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
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Reading API keys from the environment and providers.json.
|
|
2
|
+
|
|
3
|
+
Both functions lived in aria_cli.py, so five mixins reached into it for them.
|
|
4
|
+
Neither touches CLI state — they read two constant maps and one file.
|
|
5
|
+
|
|
6
|
+
The file path is resolved on each call rather than snapshotted at import, and
|
|
7
|
+
that is deliberate. resolve_config_dir() reads ARIA_CONFIG_DIR when it runs, so
|
|
8
|
+
a module-level snapshot taken while this module is imported would be taken
|
|
9
|
+
before initialize_cli_environment() — these mixins are imported at aria_cli.py
|
|
10
|
+
line 31, that call happens at 106. config_paths.py records what that class of
|
|
11
|
+
mistake cost before: config landing in ~/.aria-code while credentials went to
|
|
12
|
+
~/.arthera. Resolving at call time is always after the environment is set up.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
import os
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Dict
|
|
21
|
+
|
|
22
|
+
from aria_code.apps.cli.constants import _DATA_KEY_MAP, _PROVIDER_KEY_MAP
|
|
23
|
+
|
|
24
|
+
__all__ = ["get_provider_key", "load_data_keys", "providers_file"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def providers_file() -> Path:
|
|
28
|
+
"""Where providers.json lives, resolved now rather than at import."""
|
|
29
|
+
from aria_code.apps.cli.bootstrap import runtime_paths
|
|
30
|
+
|
|
31
|
+
return runtime_paths().providers_file
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def get_provider_key(provider: str) -> str:
|
|
35
|
+
"""Return the configured API key for a provider (env var takes priority)."""
|
|
36
|
+
env_var = (_PROVIDER_KEY_MAP.get(provider.lower())
|
|
37
|
+
or _DATA_KEY_MAP.get(provider.lower(), ""))
|
|
38
|
+
if env_var:
|
|
39
|
+
val = os.getenv(env_var, "")
|
|
40
|
+
if val:
|
|
41
|
+
return val
|
|
42
|
+
# Check providers.json under both "llm" and "data" sections
|
|
43
|
+
try:
|
|
44
|
+
if providers_file().exists():
|
|
45
|
+
raw = json.loads(providers_file().read_text(encoding="utf-8"))
|
|
46
|
+
for section in ("llm", "data"):
|
|
47
|
+
entry = raw.get(section, {}).get(provider.lower(), {})
|
|
48
|
+
if entry.get("api_key"):
|
|
49
|
+
return entry["api_key"]
|
|
50
|
+
except Exception:
|
|
51
|
+
pass
|
|
52
|
+
return ""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def load_data_keys() -> Dict[str, str]:
|
|
56
|
+
"""Return a dict of {service: api_key} for all configured data services.
|
|
57
|
+
Merges environment variables (priority) and providers.json."""
|
|
58
|
+
result: Dict[str, str] = {}
|
|
59
|
+
# 1. Environment variables
|
|
60
|
+
for svc, env_var in _DATA_KEY_MAP.items():
|
|
61
|
+
val = os.getenv(env_var, "")
|
|
62
|
+
if val:
|
|
63
|
+
result[svc] = val
|
|
64
|
+
# 2. providers.json "data" section
|
|
65
|
+
try:
|
|
66
|
+
if providers_file().exists():
|
|
67
|
+
raw = json.loads(providers_file().read_text(encoding="utf-8"))
|
|
68
|
+
for svc, entry in raw.get("data", {}).items():
|
|
69
|
+
if svc not in result and entry.get("api_key"):
|
|
70
|
+
result[svc] = entry["api_key"]
|
|
71
|
+
except Exception:
|
|
72
|
+
pass
|
|
73
|
+
return result
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""apps/cli/providers — LLM provider utilities."""
|
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
"""LLM provider abstraction layer.
|
|
2
|
+
|
|
3
|
+
Defines the minimal Protocol that every provider must satisfy so the
|
|
4
|
+
agent loop can call any backend (Ollama, AriaSSE, DeepSeek, etc.)
|
|
5
|
+
without importing provider-specific code.
|
|
6
|
+
|
|
7
|
+
Usage
|
|
8
|
+
-----
|
|
9
|
+
Implement the protocol on any class or pass a coroutine that matches
|
|
10
|
+
``stream()``'s signature as a bare ``provider_fn`` callable.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import asyncio
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from typing import AsyncGenerator, Optional, Protocol, runtime_checkable
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# ── Event types emitted by LLMProvider.stream() ──────────────────────────────
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True)
|
|
22
|
+
class LLMToken:
|
|
23
|
+
"""A single text token from the model."""
|
|
24
|
+
text: str
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True)
|
|
28
|
+
class LLMThinking:
|
|
29
|
+
"""One thinking/reasoning token (extended-thinking models)."""
|
|
30
|
+
content: str
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True)
|
|
34
|
+
class LLMToolCall:
|
|
35
|
+
"""Model requested a tool call."""
|
|
36
|
+
tool: str
|
|
37
|
+
params: dict
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass(frozen=True)
|
|
41
|
+
class LLMToolResult:
|
|
42
|
+
"""Provider reported a tool execution result summary."""
|
|
43
|
+
tool: str
|
|
44
|
+
summary: str
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
class LLMStatus:
|
|
49
|
+
"""Provider emitted a streaming status update."""
|
|
50
|
+
state: str
|
|
51
|
+
message: str
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclass(frozen=True)
|
|
55
|
+
class LLMDone:
|
|
56
|
+
"""Stream finished. Carries the aggregated result."""
|
|
57
|
+
response: str
|
|
58
|
+
tool_calls_pending: list = field(default_factory=list)
|
|
59
|
+
usage: dict = field(default_factory=dict)
|
|
60
|
+
provider: str = "unknown"
|
|
61
|
+
success: bool = True
|
|
62
|
+
cancelled: bool = False
|
|
63
|
+
error: str = ""
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# Union type for type-checkers
|
|
67
|
+
LLMEvent = LLMToken | LLMThinking | LLMToolCall | LLMToolResult | LLMStatus | LLMDone
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _resolve_ollama_stream():
|
|
71
|
+
"""Prefer the aria_cli rebound stream_ollama when available."""
|
|
72
|
+
import sys
|
|
73
|
+
|
|
74
|
+
# Console entry points import ``aria_cli``; direct execution
|
|
75
|
+
# (``python aria_cli.py`` and the npm launcher) registers it as
|
|
76
|
+
# ``__main__``. Both own the rebound function whose globals include the
|
|
77
|
+
# CLI tool registry and cache helpers.
|
|
78
|
+
#
|
|
79
|
+
# ``aria_code.aria_cli`` is the same file reached through the package root
|
|
80
|
+
# rather than as a bare top-level module — the import the SDK and daemon
|
|
81
|
+
# use. Without it here they fell through to the raw extracted function,
|
|
82
|
+
# whose globals lack the borrowed CLI helpers, and the first cache-eligible
|
|
83
|
+
# turn died with ``NameError: name '_cache_key' is not defined``.
|
|
84
|
+
for module_name in ("aria_cli", "aria_code.aria_cli", "__main__"):
|
|
85
|
+
module = sys.modules.get(module_name)
|
|
86
|
+
rebound = getattr(module, "stream_ollama", None) if module else None
|
|
87
|
+
if callable(rebound):
|
|
88
|
+
return rebound
|
|
89
|
+
from aria_code.apps.cli.providers.llm.ollama_stream import stream_ollama
|
|
90
|
+
|
|
91
|
+
return stream_ollama
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
async def _stream_callback_provider(invoke, *, done_provider: str) -> AsyncGenerator[LLMEvent, None]:
|
|
95
|
+
"""Convert a callback-based provider coroutine into a real async event stream."""
|
|
96
|
+
|
|
97
|
+
queue: asyncio.Queue[LLMEvent] = asyncio.Queue()
|
|
98
|
+
|
|
99
|
+
def _on_token(tok: str) -> None:
|
|
100
|
+
queue.put_nowait(LLMToken(text=tok))
|
|
101
|
+
|
|
102
|
+
def _on_thinking(content: str) -> None:
|
|
103
|
+
queue.put_nowait(LLMThinking(content=content))
|
|
104
|
+
|
|
105
|
+
def _on_tool_call(tool: str, params: dict) -> None:
|
|
106
|
+
queue.put_nowait(LLMToolCall(tool=tool, params=params))
|
|
107
|
+
|
|
108
|
+
def _on_tool_result(tool: str, summary: str) -> None:
|
|
109
|
+
queue.put_nowait(LLMToolResult(tool=tool, summary=summary))
|
|
110
|
+
|
|
111
|
+
def _on_status(state: str, message: str) -> None:
|
|
112
|
+
queue.put_nowait(LLMStatus(state=state, message=message))
|
|
113
|
+
|
|
114
|
+
task = asyncio.create_task(
|
|
115
|
+
invoke(_on_token, _on_thinking, _on_tool_call, _on_tool_result, _on_status)
|
|
116
|
+
)
|
|
117
|
+
while not task.done() or not queue.empty():
|
|
118
|
+
try:
|
|
119
|
+
yield await asyncio.wait_for(queue.get(), timeout=0.05)
|
|
120
|
+
except asyncio.TimeoutError:
|
|
121
|
+
continue
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
result = await task
|
|
125
|
+
except Exception as exc:
|
|
126
|
+
yield LLMDone(response="", provider=done_provider, success=False, error=str(exc))
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
yield LLMDone(
|
|
130
|
+
response=result.get("response", ""),
|
|
131
|
+
tool_calls_pending=result.get("tool_calls_pending", []),
|
|
132
|
+
usage=result.get("usage", {}),
|
|
133
|
+
provider=result.get("provider", done_provider),
|
|
134
|
+
success=result.get("success", False),
|
|
135
|
+
cancelled=result.get("cancelled", False),
|
|
136
|
+
error=result.get("error", ""),
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# ── Protocol ─────────────────────────────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
@runtime_checkable
|
|
143
|
+
class LLMProvider(Protocol):
|
|
144
|
+
"""Minimal interface every LLM backend must implement.
|
|
145
|
+
|
|
146
|
+
``stream()`` is an async generator that yields ``LLMEvent`` objects.
|
|
147
|
+
The final event is always ``LLMDone``; callers may break early on
|
|
148
|
+
``LLMDone`` or consume the full stream.
|
|
149
|
+
|
|
150
|
+
Parameters
|
|
151
|
+
----------
|
|
152
|
+
messages:
|
|
153
|
+
Full conversation history (list of {"role": …, "content": …} dicts).
|
|
154
|
+
tools:
|
|
155
|
+
OpenAI-format function schema list; empty list disables tool calls.
|
|
156
|
+
cancel_event:
|
|
157
|
+
asyncio.Event that, when set, signals the provider to stop.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
async def stream(
|
|
161
|
+
self,
|
|
162
|
+
messages: list,
|
|
163
|
+
tools: list,
|
|
164
|
+
*,
|
|
165
|
+
cancel_event: Optional[asyncio.Event] = None,
|
|
166
|
+
) -> AsyncGenerator[LLMEvent, None]:
|
|
167
|
+
...
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
# ── Thin adapters (wrap existing callables as LLMProvider) ───────────────────
|
|
171
|
+
|
|
172
|
+
class OllamaProvider:
|
|
173
|
+
"""Wraps ``stream_ollama`` as an ``LLMProvider``.
|
|
174
|
+
|
|
175
|
+
Import lazily to avoid circular dependencies — ``stream_ollama`` lives in
|
|
176
|
+
the same providers package and rebinds globals from aria_cli at startup.
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
def __init__(
|
|
180
|
+
self,
|
|
181
|
+
ollama_url: str,
|
|
182
|
+
model: str,
|
|
183
|
+
*,
|
|
184
|
+
system_override: Optional[str] = None,
|
|
185
|
+
show_market_prefetch_status: bool = True,
|
|
186
|
+
) -> None:
|
|
187
|
+
self.ollama_url = ollama_url
|
|
188
|
+
self.model = model
|
|
189
|
+
self.system_override = system_override
|
|
190
|
+
self.show_market_prefetch_status = show_market_prefetch_status
|
|
191
|
+
|
|
192
|
+
async def stream(
|
|
193
|
+
self,
|
|
194
|
+
messages: list,
|
|
195
|
+
tools: list,
|
|
196
|
+
*,
|
|
197
|
+
cancel_event: Optional[asyncio.Event] = None,
|
|
198
|
+
) -> AsyncGenerator[LLMEvent, None]:
|
|
199
|
+
stream_ollama = _resolve_ollama_stream()
|
|
200
|
+
|
|
201
|
+
# Extract last user message as the prompt; the rest is history
|
|
202
|
+
history = [m for m in messages if not (m.get("role") == "user" and m is messages[-1])]
|
|
203
|
+
prompt = messages[-1].get("content", "") if messages else ""
|
|
204
|
+
|
|
205
|
+
async def _invoke(on_token, on_thinking, on_tool_call, on_tool_result, _on_status):
|
|
206
|
+
return await stream_ollama(
|
|
207
|
+
self.ollama_url,
|
|
208
|
+
prompt,
|
|
209
|
+
history,
|
|
210
|
+
model=self.model,
|
|
211
|
+
on_token=on_token,
|
|
212
|
+
on_thinking=on_thinking,
|
|
213
|
+
on_tool_call=on_tool_call,
|
|
214
|
+
on_tool_result=on_tool_result,
|
|
215
|
+
cancel_event=cancel_event,
|
|
216
|
+
enable_tools=bool(tools),
|
|
217
|
+
tool_schemas=list(tools or []),
|
|
218
|
+
defer_tool_execution=True,
|
|
219
|
+
system_override=self.system_override,
|
|
220
|
+
show_market_prefetch_status=self.show_market_prefetch_status,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
async for event in _stream_callback_provider(_invoke, done_provider="ollama"):
|
|
224
|
+
yield event
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class AriaSSEProvider:
|
|
228
|
+
"""Wraps ``stream_chat`` (Aria cloud SSE) as an ``LLMProvider``."""
|
|
229
|
+
|
|
230
|
+
def __init__(
|
|
231
|
+
self,
|
|
232
|
+
api_url: str,
|
|
233
|
+
model: str,
|
|
234
|
+
*,
|
|
235
|
+
auth_token: Optional[str] = None,
|
|
236
|
+
thinking_mode: str = "auto",
|
|
237
|
+
user_context: Optional[dict] = None,
|
|
238
|
+
system_override: Optional[str] = None,
|
|
239
|
+
project_context: str = "",
|
|
240
|
+
use_react_gateway: bool = False,
|
|
241
|
+
) -> None:
|
|
242
|
+
self.api_url = api_url
|
|
243
|
+
self.model = model
|
|
244
|
+
self.auth_token = auth_token
|
|
245
|
+
self.thinking_mode = thinking_mode
|
|
246
|
+
self.user_context = user_context or {}
|
|
247
|
+
self.system_override = system_override
|
|
248
|
+
self.project_context = project_context
|
|
249
|
+
self.use_react_gateway = use_react_gateway
|
|
250
|
+
|
|
251
|
+
async def stream(
|
|
252
|
+
self,
|
|
253
|
+
messages: list,
|
|
254
|
+
tools: list,
|
|
255
|
+
*,
|
|
256
|
+
cancel_event: Optional[asyncio.Event] = None,
|
|
257
|
+
) -> AsyncGenerator[LLMEvent, None]:
|
|
258
|
+
from aria_code.apps.cli.providers.llm.sse_stream import stream_chat
|
|
259
|
+
|
|
260
|
+
history = [m for m in messages if not (m.get("role") == "user" and m is messages[-1])]
|
|
261
|
+
prompt = messages[-1].get("content", "") if messages else ""
|
|
262
|
+
|
|
263
|
+
uctx = dict(self.user_context)
|
|
264
|
+
if self.system_override:
|
|
265
|
+
uctx["system_role_override"] = self.system_override
|
|
266
|
+
|
|
267
|
+
async def _invoke(on_token, on_thinking, on_tool_call, on_tool_result, on_status):
|
|
268
|
+
return await stream_chat(
|
|
269
|
+
self.api_url,
|
|
270
|
+
prompt,
|
|
271
|
+
history,
|
|
272
|
+
model=self.model,
|
|
273
|
+
thinking_mode=self.thinking_mode,
|
|
274
|
+
user_context=uctx or None,
|
|
275
|
+
auth_token=self.auth_token,
|
|
276
|
+
on_token=on_token,
|
|
277
|
+
on_thinking=on_thinking,
|
|
278
|
+
on_tool_call=on_tool_call,
|
|
279
|
+
on_tool_result=on_tool_result,
|
|
280
|
+
on_status=on_status,
|
|
281
|
+
cancel_event=cancel_event,
|
|
282
|
+
project_context=self.project_context,
|
|
283
|
+
use_react_gateway=self.use_react_gateway,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
async for event in _stream_callback_provider(_invoke, done_provider="aria_sse"):
|
|
287
|
+
yield event
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def _opt_in(config: dict, key: str, default: bool = True) -> bool:
|
|
291
|
+
"""Read a tri-state boolean setting where "unset" means *default*.
|
|
292
|
+
|
|
293
|
+
``config.get(key, default)`` is the wrong tool here and produced a real
|
|
294
|
+
failure: a config holding ``"use_vertexai": null`` returns None — the
|
|
295
|
+
stored value, not the default — so a Google model silently opted out of
|
|
296
|
+
Vertex and went down the OpenAI-compatible path instead. Settings that are
|
|
297
|
+
written as null by a config round-trip have to mean "not configured".
|
|
298
|
+
"""
|
|
299
|
+
value = config.get(key)
|
|
300
|
+
return default if value is None else bool(value)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
class ConfiguredProvider:
|
|
304
|
+
"""Adapter for the provider selected by ``/model provider/model``.
|
|
305
|
+
|
|
306
|
+
Ollama keeps its dedicated CLI adapter because that path owns Aria's local
|
|
307
|
+
intent and tool orchestration. Other local runtimes use the shared
|
|
308
|
+
``LocalLLMProvider`` OpenAI-compatible transport, while cloud APIs use the
|
|
309
|
+
provider registry (including Anthropic's native protocol).
|
|
310
|
+
"""
|
|
311
|
+
|
|
312
|
+
LOCAL_OPENAI_BACKENDS = {"lmstudio", "vllm", "llamacpp", "jan", "custom"}
|
|
313
|
+
GENERIC_OPENAI_BACKENDS = {
|
|
314
|
+
"google", "gemini", "xai", "grok", "mistral", "cohere",
|
|
315
|
+
"perplexity", "baidu", "ernie", "qianfan", "bytedance",
|
|
316
|
+
"doubao", "ark", "minimax", "stepfun", "01ai", "yi",
|
|
317
|
+
}
|
|
318
|
+
GENERIC_ENV_KEYS = {
|
|
319
|
+
"google": "GOOGLE_API_KEY", "gemini": "GOOGLE_API_KEY",
|
|
320
|
+
"xai": "XAI_API_KEY", "grok": "XAI_API_KEY",
|
|
321
|
+
"mistral": "MISTRAL_API_KEY", "cohere": "COHERE_API_KEY",
|
|
322
|
+
"perplexity": "PERPLEXITY_API_KEY", "baidu": "QIANFAN_ACCESS_KEY",
|
|
323
|
+
"ernie": "QIANFAN_ACCESS_KEY", "qianfan": "QIANFAN_ACCESS_KEY",
|
|
324
|
+
"bytedance": "ARK_API_KEY", "doubao": "ARK_API_KEY",
|
|
325
|
+
"ark": "ARK_API_KEY", "minimax": "MINIMAX_API_KEY",
|
|
326
|
+
"stepfun": "STEPFUN_API_KEY", "01ai": "ONEAI_API_KEY",
|
|
327
|
+
"yi": "ONEAI_API_KEY",
|
|
328
|
+
}
|
|
329
|
+
GENERIC_BASE_URLS = {
|
|
330
|
+
"google": "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
331
|
+
"gemini": "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
332
|
+
"xai": "https://api.x.ai/v1", "grok": "https://api.x.ai/v1",
|
|
333
|
+
"mistral": "https://api.mistral.ai/v1",
|
|
334
|
+
"cohere": "https://api.cohere.ai/compatibility/v1",
|
|
335
|
+
"perplexity": "https://api.perplexity.ai",
|
|
336
|
+
"baidu": "https://qianfan.baidubce.com/v2",
|
|
337
|
+
"ernie": "https://qianfan.baidubce.com/v2",
|
|
338
|
+
"qianfan": "https://qianfan.baidubce.com/v2",
|
|
339
|
+
"bytedance": "https://ark.cn-beijing.volces.com/api/v3",
|
|
340
|
+
"doubao": "https://ark.cn-beijing.volces.com/api/v3",
|
|
341
|
+
"ark": "https://ark.cn-beijing.volces.com/api/v3",
|
|
342
|
+
"minimax": "https://api.minimax.chat/v1",
|
|
343
|
+
"stepfun": "https://api.stepfun.com/v1",
|
|
344
|
+
"01ai": "https://api.lingyiwanwu.com/v1",
|
|
345
|
+
"yi": "https://api.lingyiwanwu.com/v1",
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
def __init__(
|
|
349
|
+
self,
|
|
350
|
+
config: dict,
|
|
351
|
+
model: str,
|
|
352
|
+
*,
|
|
353
|
+
system_override: Optional[str] = None,
|
|
354
|
+
) -> None:
|
|
355
|
+
self.config = dict(config or {})
|
|
356
|
+
from aria_code.apps.cli.providers.chat_routing import (
|
|
357
|
+
model_provider,
|
|
358
|
+
normalize_provider_name,
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
# A provider-qualified model id names its own backend and wins over
|
|
362
|
+
# local_provider — the default config pairs model="gemini-pro" with
|
|
363
|
+
# local_provider="ollama", so deriving the backend from local_provider
|
|
364
|
+
# alone sent every Gemini request to Ollama.
|
|
365
|
+
declared = model_provider(model)
|
|
366
|
+
self.backend = declared or normalize_provider_name(
|
|
367
|
+
self.config.get("local_provider") or "ollama"
|
|
368
|
+
)
|
|
369
|
+
# Downstream APIs expect the bare model name; "google/gemini-2.5-pro"
|
|
370
|
+
# would 404 against Google's endpoint and would be re-prefixed into
|
|
371
|
+
# "google/google/gemini-2.5-pro" by the registry path below.
|
|
372
|
+
self.model = model.split("/", 1)[1] if declared else model
|
|
373
|
+
self.config["local_provider"] = self.backend
|
|
374
|
+
self.system_override = system_override
|
|
375
|
+
|
|
376
|
+
def _messages(self, messages: list) -> list:
|
|
377
|
+
prepared = [dict(message) for message in messages]
|
|
378
|
+
if not self.system_override:
|
|
379
|
+
return prepared
|
|
380
|
+
if prepared and prepared[0].get("role") == "system":
|
|
381
|
+
prepared[0]["content"] = (
|
|
382
|
+
self.system_override + "\n\n" + str(prepared[0].get("content", ""))
|
|
383
|
+
)
|
|
384
|
+
else:
|
|
385
|
+
prepared.insert(0, {"role": "system", "content": self.system_override})
|
|
386
|
+
return prepared
|
|
387
|
+
|
|
388
|
+
async def stream(
|
|
389
|
+
self,
|
|
390
|
+
messages: list,
|
|
391
|
+
tools: list,
|
|
392
|
+
*,
|
|
393
|
+
cancel_event: Optional[asyncio.Event] = None,
|
|
394
|
+
) -> AsyncGenerator[LLMEvent, None]:
|
|
395
|
+
prepared = self._messages(messages)
|
|
396
|
+
|
|
397
|
+
if self.backend in ("vertexai", "vertex-ai", "google-genai") or (
|
|
398
|
+
self.backend in ("google", "gemini") and _opt_in(self.config, "use_vertexai")
|
|
399
|
+
):
|
|
400
|
+
from aria_code.apps.cli.providers.vertexai_stream import VertexAIProvider
|
|
401
|
+
provider = VertexAIProvider(
|
|
402
|
+
model=self.model,
|
|
403
|
+
config=self.config,
|
|
404
|
+
system_override=self.system_override,
|
|
405
|
+
)
|
|
406
|
+
async for evt in provider.stream(prepared, tools=tools, cancel_event=cancel_event):
|
|
407
|
+
yield evt
|
|
408
|
+
return
|
|
409
|
+
|
|
410
|
+
if self.backend in self.LOCAL_OPENAI_BACKENDS | self.GENERIC_OPENAI_BACKENDS:
|
|
411
|
+
from aria_code.local_llm_provider import LocalLLMProvider
|
|
412
|
+
|
|
413
|
+
cfg = dict(self.config)
|
|
414
|
+
cfg["model"] = self.model
|
|
415
|
+
if self.backend in self.GENERIC_OPENAI_BACKENDS:
|
|
416
|
+
import os
|
|
417
|
+
from aria_code.providers.llm.registry import _load_provider_cfg_from_file
|
|
418
|
+
|
|
419
|
+
file_cfg = _load_provider_cfg_from_file(self.backend)
|
|
420
|
+
api_key = (
|
|
421
|
+
os.getenv(self.GENERIC_ENV_KEYS[self.backend], "")
|
|
422
|
+
or str(file_cfg.get("api_key") or "")
|
|
423
|
+
)
|
|
424
|
+
base_url = file_cfg.get("base_url") or self.GENERIC_BASE_URLS[self.backend]
|
|
425
|
+
model_name = self.model
|
|
426
|
+
|
|
427
|
+
if not api_key and self.backend in ("google", "gemini"):
|
|
428
|
+
import subprocess
|
|
429
|
+
try:
|
|
430
|
+
api_key = subprocess.check_output(["gcloud", "auth", "print-access-token"], text=True).strip()
|
|
431
|
+
project = subprocess.check_output(["gcloud", "config", "get-value", "project"], text=True).strip()
|
|
432
|
+
region = "us-central1"
|
|
433
|
+
base_url = f"https://{region}-aiplatform.googleapis.com/v1beta1/projects/{project}/locations/{region}/endpoints/openapi"
|
|
434
|
+
|
|
435
|
+
if not model_name.startswith("google/"):
|
|
436
|
+
model_name = f"google/{model_name}"
|
|
437
|
+
except Exception:
|
|
438
|
+
pass
|
|
439
|
+
|
|
440
|
+
if not api_key:
|
|
441
|
+
yield LLMDone(
|
|
442
|
+
response="", provider=self.backend, success=False,
|
|
443
|
+
error=f"missing_api_key:{self.backend}",
|
|
444
|
+
)
|
|
445
|
+
return
|
|
446
|
+
cfg.update({
|
|
447
|
+
"local_provider": "custom",
|
|
448
|
+
"custom_endpoint": base_url,
|
|
449
|
+
"custom_model": model_name,
|
|
450
|
+
"local_api_key": api_key,
|
|
451
|
+
})
|
|
452
|
+
provider = LocalLLMProvider.from_config(cfg)
|
|
453
|
+
source = self.backend
|
|
454
|
+
event_stream = provider.stream(prepared, tools=tools, cancel_event=cancel_event)
|
|
455
|
+
else:
|
|
456
|
+
from aria_code.providers.llm.base import Message
|
|
457
|
+
from aria_code.providers.llm.registry import get_provider
|
|
458
|
+
|
|
459
|
+
try:
|
|
460
|
+
provider = get_provider(f"{self.backend}/{self.model}")
|
|
461
|
+
except Exception as exc:
|
|
462
|
+
yield LLMDone(
|
|
463
|
+
response="", provider=self.backend, success=False,
|
|
464
|
+
error=f"{self.backend}: {exc}",
|
|
465
|
+
)
|
|
466
|
+
return
|
|
467
|
+
source = self.backend
|
|
468
|
+
registry_messages = [
|
|
469
|
+
Message(
|
|
470
|
+
role=str(message.get("role", "user")),
|
|
471
|
+
content=str(message.get("content", "")),
|
|
472
|
+
name=message.get("name"),
|
|
473
|
+
tool_call_id=message.get("tool_call_id"),
|
|
474
|
+
)
|
|
475
|
+
for message in prepared
|
|
476
|
+
]
|
|
477
|
+
# providers.llm accepts bare function schemas, while the CLI owns
|
|
478
|
+
# OpenAI envelopes. Normalize once at this adapter boundary.
|
|
479
|
+
registry_tools = [
|
|
480
|
+
item.get("function", item)
|
|
481
|
+
if isinstance(item, dict) and item.get("type") == "function"
|
|
482
|
+
else item
|
|
483
|
+
for item in tools
|
|
484
|
+
]
|
|
485
|
+
event_stream = provider.stream(
|
|
486
|
+
registry_messages, tools=registry_tools, cancel_event=cancel_event
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
async for event in event_stream:
|
|
490
|
+
kind = event.get("type")
|
|
491
|
+
if kind == "token":
|
|
492
|
+
yield LLMToken(text=str(event.get("text", "")))
|
|
493
|
+
elif kind == "thinking":
|
|
494
|
+
yield LLMThinking(content=str(event.get("text", "")))
|
|
495
|
+
elif kind == "tool_call":
|
|
496
|
+
yield LLMToolCall(
|
|
497
|
+
tool=str(event.get("name", "")),
|
|
498
|
+
params=dict(event.get("arguments") or {}),
|
|
499
|
+
)
|
|
500
|
+
elif kind == "error":
|
|
501
|
+
yield LLMDone(
|
|
502
|
+
response="",
|
|
503
|
+
provider=source,
|
|
504
|
+
success=False,
|
|
505
|
+
error=str(event.get("message") or "provider_error"),
|
|
506
|
+
)
|
|
507
|
+
return
|
|
508
|
+
elif kind == "done":
|
|
509
|
+
stop_reason = str(event.get("stop_reason") or "")
|
|
510
|
+
yield LLMDone(
|
|
511
|
+
response=str(event.get("text") or ""),
|
|
512
|
+
usage=dict(event.get("usage") or {}),
|
|
513
|
+
provider=source,
|
|
514
|
+
success=True,
|
|
515
|
+
cancelled=stop_reason == "cancelled",
|
|
516
|
+
)
|
|
517
|
+
return
|
|
518
|
+
|
|
519
|
+
yield LLMDone(
|
|
520
|
+
response="", provider=source, success=False, error="empty_response"
|
|
521
|
+
)
|