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/runtime/lsp.py
ADDED
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
"""Minimal Language Server Protocol (LSP) client for on-demand diagnostics.
|
|
2
|
+
|
|
3
|
+
This is the "biggest gap" vs Claude Code's architecture: real diagnostics from
|
|
4
|
+
a language server (type errors, undefined names, unused imports) rather than
|
|
5
|
+
just a syntax compile check.
|
|
6
|
+
|
|
7
|
+
Design — deliberately one-shot, not a persistent server:
|
|
8
|
+
spawn language server → initialize → didOpen → collect publishDiagnostics →
|
|
9
|
+
shutdown. Each call is self-contained with strict timeouts so it never hangs
|
|
10
|
+
the REPL, and degrades gracefully (returns []) when no server is installed.
|
|
11
|
+
|
|
12
|
+
Supported servers (auto-detected on PATH):
|
|
13
|
+
Python → pylsp (pip install python-lsp-server)
|
|
14
|
+
TS / JS → typescript-language-server --stdio (npm i -g …)
|
|
15
|
+
|
|
16
|
+
Exposed to the LLM as the `lsp_diagnostics` tool and to users via /lsp.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import json
|
|
22
|
+
import os
|
|
23
|
+
import queue
|
|
24
|
+
import shutil
|
|
25
|
+
import subprocess
|
|
26
|
+
import threading
|
|
27
|
+
import time
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import Optional
|
|
30
|
+
|
|
31
|
+
# ── Server registry ──────────────────────────────────────────────────────────
|
|
32
|
+
# suffix → (command argv, LSP languageId)
|
|
33
|
+
_SERVERS: dict[str, tuple[list[str], str]] = {
|
|
34
|
+
".py": (["pylsp"], "python"),
|
|
35
|
+
".ts": (["typescript-language-server", "--stdio"], "typescript"),
|
|
36
|
+
".tsx": (["typescript-language-server", "--stdio"], "typescriptreact"),
|
|
37
|
+
".js": (["typescript-language-server", "--stdio"], "javascript"),
|
|
38
|
+
".jsx": (["typescript-language-server", "--stdio"], "javascriptreact"),
|
|
39
|
+
".mjs": (["typescript-language-server", "--stdio"], "javascript"),
|
|
40
|
+
".cjs": (["typescript-language-server", "--stdio"], "javascript"),
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
_SEVERITY = {1: "error", 2: "warning", 3: "info", 4: "hint"}
|
|
44
|
+
|
|
45
|
+
# Cache PATH lookups so repeated edits don't re-stat the filesystem each time.
|
|
46
|
+
_AVAILABILITY: dict[str, bool] = {}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def server_for(path) -> Optional[tuple[list[str], str]]:
|
|
50
|
+
"""Return (argv, languageId) if a language server is installed for this
|
|
51
|
+
file's type, else None."""
|
|
52
|
+
suffix = Path(path).suffix.lower()
|
|
53
|
+
entry = _SERVERS.get(suffix)
|
|
54
|
+
if not entry:
|
|
55
|
+
return None
|
|
56
|
+
cmd, lang = entry
|
|
57
|
+
exe = cmd[0]
|
|
58
|
+
if exe not in _AVAILABILITY:
|
|
59
|
+
_AVAILABILITY[exe] = shutil.which(exe) is not None
|
|
60
|
+
if not _AVAILABILITY[exe]:
|
|
61
|
+
return None
|
|
62
|
+
return cmd, lang
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def available_servers() -> dict[str, bool]:
|
|
66
|
+
"""Report which known language servers are installed (for /lsp status)."""
|
|
67
|
+
out: dict[str, bool] = {}
|
|
68
|
+
for cmd, _ in _SERVERS.values():
|
|
69
|
+
exe = cmd[0]
|
|
70
|
+
if exe not in out:
|
|
71
|
+
out[exe] = shutil.which(exe) is not None
|
|
72
|
+
return out
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# ── JSON-RPC framing ──────────────────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
def _encode(msg: dict) -> bytes:
|
|
78
|
+
body = json.dumps(msg).encode("utf-8")
|
|
79
|
+
return f"Content-Length: {len(body)}\r\n\r\n".encode("ascii") + body
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _read_message(stdout) -> Optional[dict]:
|
|
83
|
+
"""Read one LSP message (headers + body) from a blocking stream."""
|
|
84
|
+
headers: dict[bytes, bytes] = {}
|
|
85
|
+
while True:
|
|
86
|
+
line = stdout.readline()
|
|
87
|
+
if not line:
|
|
88
|
+
return None
|
|
89
|
+
line = line.strip()
|
|
90
|
+
if not line:
|
|
91
|
+
break # blank line terminates headers
|
|
92
|
+
if b":" in line:
|
|
93
|
+
k, v = line.split(b":", 1)
|
|
94
|
+
headers[k.strip().lower()] = v.strip()
|
|
95
|
+
length = int(headers.get(b"content-length", b"0") or 0)
|
|
96
|
+
if length <= 0:
|
|
97
|
+
return None
|
|
98
|
+
body = stdout.read(length)
|
|
99
|
+
if not body:
|
|
100
|
+
return None
|
|
101
|
+
try:
|
|
102
|
+
return json.loads(body.decode("utf-8"))
|
|
103
|
+
except Exception:
|
|
104
|
+
return None
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _format_diagnostics(raw: list) -> list[dict]:
|
|
108
|
+
out = []
|
|
109
|
+
for d in raw or []:
|
|
110
|
+
start = (d.get("range") or {}).get("start") or {}
|
|
111
|
+
code = d.get("code", "")
|
|
112
|
+
out.append({
|
|
113
|
+
"line": int(start.get("line", 0)) + 1, # LSP is 0-based
|
|
114
|
+
"col": int(start.get("character", 0)) + 1,
|
|
115
|
+
"severity": _SEVERITY.get(d.get("severity", 1), "info"),
|
|
116
|
+
"message": str(d.get("message", "")).strip(),
|
|
117
|
+
"source": d.get("source", "") or "",
|
|
118
|
+
"code": str(code) if code != "" else "",
|
|
119
|
+
})
|
|
120
|
+
out.sort(key=lambda x: (x["line"], x["col"]))
|
|
121
|
+
return out
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# ── Core: one-shot diagnostics ────────────────────────────────────────────────
|
|
125
|
+
|
|
126
|
+
def get_diagnostics(path, timeout: float = 8.0) -> list[dict]:
|
|
127
|
+
"""Spawn a language server, open `path`, and return its diagnostics.
|
|
128
|
+
|
|
129
|
+
Returns [] if no server is available, the file can't be read, or the
|
|
130
|
+
handshake times out. Never raises.
|
|
131
|
+
"""
|
|
132
|
+
resolved = server_for(path)
|
|
133
|
+
if not resolved:
|
|
134
|
+
return []
|
|
135
|
+
cmd, lang_id = resolved
|
|
136
|
+
|
|
137
|
+
p = Path(path).expanduser().resolve()
|
|
138
|
+
try:
|
|
139
|
+
text = p.read_text(errors="replace")
|
|
140
|
+
except Exception:
|
|
141
|
+
return []
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
proc = subprocess.Popen(
|
|
145
|
+
cmd,
|
|
146
|
+
stdin=subprocess.PIPE,
|
|
147
|
+
stdout=subprocess.PIPE,
|
|
148
|
+
stderr=subprocess.DEVNULL,
|
|
149
|
+
cwd=str(p.parent),
|
|
150
|
+
)
|
|
151
|
+
except Exception:
|
|
152
|
+
return []
|
|
153
|
+
|
|
154
|
+
msg_queue: "queue.Queue[dict]" = queue.Queue()
|
|
155
|
+
|
|
156
|
+
def _reader():
|
|
157
|
+
try:
|
|
158
|
+
while True:
|
|
159
|
+
msg = _read_message(proc.stdout)
|
|
160
|
+
if msg is None:
|
|
161
|
+
break
|
|
162
|
+
msg_queue.put(msg)
|
|
163
|
+
except Exception:
|
|
164
|
+
pass
|
|
165
|
+
|
|
166
|
+
reader = threading.Thread(target=_reader, daemon=True)
|
|
167
|
+
reader.start()
|
|
168
|
+
|
|
169
|
+
def _send(msg: dict) -> None:
|
|
170
|
+
try:
|
|
171
|
+
proc.stdin.write(_encode(msg))
|
|
172
|
+
proc.stdin.flush()
|
|
173
|
+
except Exception:
|
|
174
|
+
pass
|
|
175
|
+
|
|
176
|
+
def _cleanup() -> None:
|
|
177
|
+
try:
|
|
178
|
+
_send({"jsonrpc": "2.0", "id": 9999, "method": "shutdown", "params": None})
|
|
179
|
+
_send({"jsonrpc": "2.0", "method": "exit"})
|
|
180
|
+
except Exception:
|
|
181
|
+
pass
|
|
182
|
+
try:
|
|
183
|
+
proc.terminate()
|
|
184
|
+
proc.wait(timeout=1.0)
|
|
185
|
+
except Exception:
|
|
186
|
+
try:
|
|
187
|
+
proc.kill()
|
|
188
|
+
except Exception:
|
|
189
|
+
pass
|
|
190
|
+
|
|
191
|
+
file_uri = p.as_uri()
|
|
192
|
+
deadline = time.time() + timeout
|
|
193
|
+
|
|
194
|
+
# 1) initialize
|
|
195
|
+
_send({
|
|
196
|
+
"jsonrpc": "2.0", "id": 1, "method": "initialize",
|
|
197
|
+
"params": {
|
|
198
|
+
"processId": os.getpid(),
|
|
199
|
+
"rootUri": p.parent.as_uri(),
|
|
200
|
+
"workspaceFolders": [{"uri": p.parent.as_uri(), "name": p.parent.name}],
|
|
201
|
+
"capabilities": {
|
|
202
|
+
"textDocument": {
|
|
203
|
+
"publishDiagnostics": {"relatedInformation": True},
|
|
204
|
+
"synchronization": {"didSave": True},
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
initialized = False
|
|
211
|
+
while time.time() < deadline:
|
|
212
|
+
try:
|
|
213
|
+
msg = msg_queue.get(timeout=0.2)
|
|
214
|
+
except queue.Empty:
|
|
215
|
+
if proc.poll() is not None:
|
|
216
|
+
_cleanup()
|
|
217
|
+
return []
|
|
218
|
+
continue
|
|
219
|
+
if msg.get("id") == 1 and "result" in msg:
|
|
220
|
+
initialized = True
|
|
221
|
+
break
|
|
222
|
+
if not initialized:
|
|
223
|
+
_cleanup()
|
|
224
|
+
return []
|
|
225
|
+
|
|
226
|
+
# 2) initialized + didOpen
|
|
227
|
+
_send({"jsonrpc": "2.0", "method": "initialized", "params": {}})
|
|
228
|
+
_send({
|
|
229
|
+
"jsonrpc": "2.0", "method": "textDocument/didOpen",
|
|
230
|
+
"params": {
|
|
231
|
+
"textDocument": {
|
|
232
|
+
"uri": file_uri, "languageId": lang_id,
|
|
233
|
+
"version": 1, "text": text,
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
# 3) collect publishDiagnostics for our file. Some servers emit an empty
|
|
239
|
+
# set first, then a populated one after analysis — so once we see a
|
|
240
|
+
# matching notification we keep a short grace window for a better one.
|
|
241
|
+
diagnostics: list = []
|
|
242
|
+
got_one = False
|
|
243
|
+
grace_deadline = None
|
|
244
|
+
while time.time() < deadline:
|
|
245
|
+
remaining = deadline - time.time()
|
|
246
|
+
if grace_deadline is not None:
|
|
247
|
+
remaining = min(remaining, grace_deadline - time.time())
|
|
248
|
+
if remaining <= 0:
|
|
249
|
+
break
|
|
250
|
+
try:
|
|
251
|
+
msg = msg_queue.get(timeout=max(0.05, min(0.2, remaining)))
|
|
252
|
+
except queue.Empty:
|
|
253
|
+
if proc.poll() is not None:
|
|
254
|
+
break
|
|
255
|
+
continue
|
|
256
|
+
if msg.get("method") == "textDocument/publishDiagnostics":
|
|
257
|
+
params = msg.get("params", {})
|
|
258
|
+
if _same_uri(params.get("uri", ""), file_uri, p):
|
|
259
|
+
diags = params.get("diagnostics", [])
|
|
260
|
+
if diags:
|
|
261
|
+
diagnostics = diags
|
|
262
|
+
got_one = True
|
|
263
|
+
break # populated result — done
|
|
264
|
+
if not got_one:
|
|
265
|
+
diagnostics = diags # remember the empty result
|
|
266
|
+
got_one = True
|
|
267
|
+
grace_deadline = time.time() + 1.5 # wait briefly for more
|
|
268
|
+
|
|
269
|
+
_cleanup()
|
|
270
|
+
return _format_diagnostics(diagnostics)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def _same_uri(a: str, b: str, path: Path) -> bool:
|
|
274
|
+
if not a:
|
|
275
|
+
return False
|
|
276
|
+
if a == b:
|
|
277
|
+
return True
|
|
278
|
+
# Tolerate trailing-slash / encoding differences by comparing resolved paths
|
|
279
|
+
try:
|
|
280
|
+
return Path(a.replace("file://", "")).resolve() == path
|
|
281
|
+
except Exception:
|
|
282
|
+
return False
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
# ── Tool wrapper ──────────────────────────────────────────────────────────────
|
|
286
|
+
|
|
287
|
+
def tool_lsp_diagnostics(params: dict) -> dict:
|
|
288
|
+
"""LLM-callable: run language-server diagnostics on a single file."""
|
|
289
|
+
path = params.get("path", "")
|
|
290
|
+
if not path:
|
|
291
|
+
return {"success": False, "error": "Missing 'path' parameter"}
|
|
292
|
+
p = Path(path).expanduser()
|
|
293
|
+
if not p.exists():
|
|
294
|
+
return {"success": False, "error": f"File not found: {p}"}
|
|
295
|
+
|
|
296
|
+
resolved = server_for(p)
|
|
297
|
+
if not resolved:
|
|
298
|
+
return {"success": True, "data": {
|
|
299
|
+
"path": str(p), "diagnostics": [], "available": False,
|
|
300
|
+
"note": f"No language server installed for '{p.suffix}' files. "
|
|
301
|
+
f"Python: pip install 'python-lsp-server[all]' (the [all] extra "
|
|
302
|
+
f"pulls in pyflakes/pycodestyle — without it pylsp reports nothing) · "
|
|
303
|
+
f"TS/JS: npm i -g typescript-language-server typescript",
|
|
304
|
+
}}
|
|
305
|
+
|
|
306
|
+
cmd, _ = resolved
|
|
307
|
+
diags = get_diagnostics(p)
|
|
308
|
+
errors = sum(1 for d in diags if d["severity"] == "error")
|
|
309
|
+
warnings = sum(1 for d in diags if d["severity"] == "warning")
|
|
310
|
+
return {"success": True, "data": {
|
|
311
|
+
"path": str(p),
|
|
312
|
+
"server": cmd[0],
|
|
313
|
+
"available": True,
|
|
314
|
+
"diagnostics": diags,
|
|
315
|
+
"errors": errors,
|
|
316
|
+
"warnings": warnings,
|
|
317
|
+
"total": len(diags),
|
|
318
|
+
}}
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
# ── Registry (merged into LOCAL_TOOLS in aria_cli.py) ─────────────────────────
|
|
322
|
+
|
|
323
|
+
LSP_TOOLS = {
|
|
324
|
+
"lsp_diagnostics": (tool_lsp_diagnostics,
|
|
325
|
+
"Run language-server diagnostics (errors/warnings) on a code file"),
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
LSP_SCHEMAS = [
|
|
329
|
+
{
|
|
330
|
+
"name": "lsp_diagnostics",
|
|
331
|
+
"description": (
|
|
332
|
+
"Run a language server (pylsp / typescript-language-server) on a single "
|
|
333
|
+
"file and return its diagnostics: type errors, undefined names, unused "
|
|
334
|
+
"imports, lint warnings. Use this after editing code to catch problems a "
|
|
335
|
+
"plain syntax check misses. Returns [] if no server is installed for the "
|
|
336
|
+
"file type."
|
|
337
|
+
),
|
|
338
|
+
"parameters": {
|
|
339
|
+
"type": "object",
|
|
340
|
+
"properties": {
|
|
341
|
+
"path": {"type": "string", "description": "Path to the code file to analyze"},
|
|
342
|
+
},
|
|
343
|
+
"required": ["path"],
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
]
|
|
347
|
+
|
|
348
|
+
def _lsp_query(path: str, method: str, params: dict, timeout: float = 6.0) -> dict | None:
|
|
349
|
+
resolved = server_for(path)
|
|
350
|
+
if not resolved: return None
|
|
351
|
+
cmd, lang_id = resolved
|
|
352
|
+
p = Path(path).expanduser().resolve()
|
|
353
|
+
try: text_content = p.read_text(errors="replace")
|
|
354
|
+
except Exception: return None
|
|
355
|
+
try:
|
|
356
|
+
proc = subprocess.Popen(
|
|
357
|
+
cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, cwd=str(p.parent)
|
|
358
|
+
)
|
|
359
|
+
except Exception: return None
|
|
360
|
+
|
|
361
|
+
msg_queue = queue.Queue()
|
|
362
|
+
def _reader():
|
|
363
|
+
try:
|
|
364
|
+
while True:
|
|
365
|
+
m = _read_message(proc.stdout)
|
|
366
|
+
if not m: break
|
|
367
|
+
msg_queue.put(m)
|
|
368
|
+
except Exception: pass
|
|
369
|
+
t = threading.Thread(target=_reader, daemon=True)
|
|
370
|
+
t.start()
|
|
371
|
+
|
|
372
|
+
def _send(m):
|
|
373
|
+
try:
|
|
374
|
+
proc.stdin.write(_encode(m))
|
|
375
|
+
proc.stdin.flush()
|
|
376
|
+
except Exception: pass
|
|
377
|
+
|
|
378
|
+
def _cleanup():
|
|
379
|
+
try:
|
|
380
|
+
_send({"jsonrpc": "2.0", "id": 99, "method": "shutdown", "params": None})
|
|
381
|
+
_send({"jsonrpc": "2.0", "method": "exit"})
|
|
382
|
+
except Exception: pass
|
|
383
|
+
try: proc.terminate(); proc.wait(1.0)
|
|
384
|
+
except Exception: pass
|
|
385
|
+
|
|
386
|
+
file_uri = p.as_uri()
|
|
387
|
+
deadline = time.time() + timeout
|
|
388
|
+
_send({
|
|
389
|
+
"jsonrpc": "2.0", "id": 1, "method": "initialize",
|
|
390
|
+
"params": {
|
|
391
|
+
"processId": os.getpid(),
|
|
392
|
+
"rootUri": p.parent.as_uri(),
|
|
393
|
+
"capabilities": {}
|
|
394
|
+
}
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
initialized = False
|
|
398
|
+
while time.time() < deadline:
|
|
399
|
+
try:
|
|
400
|
+
m = msg_queue.get(timeout=0.2)
|
|
401
|
+
if m.get("id") == 1 and "result" in m:
|
|
402
|
+
initialized = True
|
|
403
|
+
break
|
|
404
|
+
except queue.Empty:
|
|
405
|
+
if proc.poll() is not None:
|
|
406
|
+
_cleanup()
|
|
407
|
+
return None
|
|
408
|
+
|
|
409
|
+
if not initialized:
|
|
410
|
+
_cleanup()
|
|
411
|
+
return None
|
|
412
|
+
|
|
413
|
+
_send({"jsonrpc": "2.0", "method": "initialized", "params": {}})
|
|
414
|
+
_send({
|
|
415
|
+
"jsonrpc": "2.0", "method": "textDocument/didOpen",
|
|
416
|
+
"params": {"textDocument": {"uri": file_uri, "languageId": lang_id, "version": 1, "text": text_content}}
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
req_id = 2
|
|
420
|
+
params["textDocument"] = {"uri": file_uri}
|
|
421
|
+
_send({"jsonrpc": "2.0", "id": req_id, "method": method, "params": params})
|
|
422
|
+
|
|
423
|
+
result = None
|
|
424
|
+
while time.time() < deadline:
|
|
425
|
+
try:
|
|
426
|
+
m = msg_queue.get(timeout=0.2)
|
|
427
|
+
if m.get("id") == req_id:
|
|
428
|
+
if "result" in m:
|
|
429
|
+
result = m["result"]
|
|
430
|
+
break
|
|
431
|
+
except queue.Empty:
|
|
432
|
+
if proc.poll() is not None:
|
|
433
|
+
break
|
|
434
|
+
|
|
435
|
+
_cleanup()
|
|
436
|
+
return result
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def get_hover(path: str, line: int, col: int) -> str | None:
|
|
440
|
+
res = _lsp_query(path, "textDocument/hover", {"position": {"line": line - 1, "character": col - 1}})
|
|
441
|
+
if not res or not res.get("contents"):
|
|
442
|
+
return None
|
|
443
|
+
contents = res["contents"]
|
|
444
|
+
if isinstance(contents, dict) and "value" in contents:
|
|
445
|
+
return contents["value"]
|
|
446
|
+
if isinstance(contents, list):
|
|
447
|
+
return "\n".join(c.get("value", c) if isinstance(c, dict) else c for c in contents)
|
|
448
|
+
return str(contents)
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
def get_definition(path: str, line: int, col: int) -> list[dict]:
|
|
452
|
+
res = _lsp_query(path, "textDocument/definition", {"position": {"line": line - 1, "character": col - 1}})
|
|
453
|
+
if not res: return []
|
|
454
|
+
if isinstance(res, dict): res = [res]
|
|
455
|
+
out = []
|
|
456
|
+
for loc in res:
|
|
457
|
+
uri = loc.get("uri") or loc.get("targetUri")
|
|
458
|
+
if not uri: continue
|
|
459
|
+
rng = loc.get("range") or loc.get("targetRange") or {}
|
|
460
|
+
st = rng.get("start", {})
|
|
461
|
+
if str(uri).startswith("file://"):
|
|
462
|
+
from urllib.parse import unquote
|
|
463
|
+
file_path = unquote(str(uri)[7:])
|
|
464
|
+
out.append({"path": file_path, "line": st.get("line", 0) + 1, "col": st.get("character", 0) + 1})
|
|
465
|
+
return out
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def get_references(path: str, line: int, col: int) -> list[dict]:
|
|
469
|
+
res = _lsp_query(path, "textDocument/references", {
|
|
470
|
+
"position": {"line": line - 1, "character": col - 1},
|
|
471
|
+
"context": {"includeDeclaration": True}
|
|
472
|
+
})
|
|
473
|
+
if not res: return []
|
|
474
|
+
out = []
|
|
475
|
+
for loc in res:
|
|
476
|
+
uri = loc.get("uri")
|
|
477
|
+
if not uri: continue
|
|
478
|
+
rng = loc.get("range", {})
|
|
479
|
+
st = rng.get("start", {})
|
|
480
|
+
if str(uri).startswith("file://"):
|
|
481
|
+
from urllib.parse import unquote
|
|
482
|
+
file_path = unquote(str(uri)[7:])
|
|
483
|
+
out.append({"path": file_path, "line": st.get("line", 0) + 1, "col": st.get("character", 0) + 1})
|
|
484
|
+
return out
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from typing import List, Dict, Any
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
from aria_code.agents.registry import get_registry
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
async def dynamic_agent_orchestration(user_query: str, provider: Any) -> Dict[str, Any]:
|
|
9
|
+
"""
|
|
10
|
+
Dynamic routing to pick the best agents for the user's query.
|
|
11
|
+
"""
|
|
12
|
+
registry = get_registry()
|
|
13
|
+
agents = registry.list()
|
|
14
|
+
|
|
15
|
+
# Filter out orchestrator or core infrastructure agents that shouldn't be dynamically routed
|
|
16
|
+
agents = [a for a in agents if a["name"] not in {"orchestrator", "supervisor"}]
|
|
17
|
+
|
|
18
|
+
agents_info = "\n".join([f"- {a['name']}: {a.get('description', '')}" for a in agents])
|
|
19
|
+
|
|
20
|
+
prompt = (
|
|
21
|
+
f"你是一个高级的智能体编排中心 (Orchestrator)。\n"
|
|
22
|
+
f"用户请求:\n{user_query}\n\n"
|
|
23
|
+
f"可用智能体库:\n{agents_info}\n\n"
|
|
24
|
+
f"请直接输出一段合法的 JSON,选择最合适的智能体来解决用户请求(最多选3个)。\n"
|
|
25
|
+
f"JSON 结构必须是:\n"
|
|
26
|
+
f"{{\n"
|
|
27
|
+
f" \"plan\": \"解释为什么选择这些智能体\",\n"
|
|
28
|
+
f" \"agents\": [\"agent_name_1\", \"agent_name_2\"]\n"
|
|
29
|
+
f"}}\n"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
# We assume provider is an async function or object that can generate text
|
|
34
|
+
# But we'll just try to use a simple completion if available
|
|
35
|
+
messages = [{"role": "user", "content": prompt}]
|
|
36
|
+
|
|
37
|
+
# Use provider to generate
|
|
38
|
+
full_response = ""
|
|
39
|
+
async for chunk in provider.stream(messages=messages, tools=[]):
|
|
40
|
+
if hasattr(chunk, 'text') and chunk.text:
|
|
41
|
+
full_response += chunk.text
|
|
42
|
+
|
|
43
|
+
# Parse JSON
|
|
44
|
+
start_idx = full_response.find("{")
|
|
45
|
+
end_idx = full_response.rfind("}")
|
|
46
|
+
if start_idx != -1 and end_idx != -1:
|
|
47
|
+
json_str = full_response[start_idx:end_idx+1]
|
|
48
|
+
return json.loads(json_str)
|
|
49
|
+
else:
|
|
50
|
+
return {"plan": "未能解析 JSON", "agents": ["technical"]}
|
|
51
|
+
except Exception as e:
|
|
52
|
+
logger.error(f"Orchestration failed: {e}")
|
|
53
|
+
# Default fallback
|
|
54
|
+
return {"plan": "降级路由", "agents": ["technical", "fundamental"]}
|
|
55
|
+
|