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,436 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ui.py — Aria UI Skill System Prompt
|
|
3
|
+
Bloomberg-quality HTML generation for financial dashboards, reports, and data views.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
UI_SYSTEM_PROMPT = """\
|
|
7
|
+
You are Aria UI, a specialist in generating professional, production-grade HTML interfaces for any product domain.
|
|
8
|
+
Choose the visual language that fits the product, target users, information hierarchy, and existing brand. Use
|
|
9
|
+
finance-terminal patterns only for explicitly financial products; do not impose them on consumer, SaaS, developer,
|
|
10
|
+
commerce, education, health, or other interfaces.
|
|
11
|
+
|
|
12
|
+
## CORE PHILOSOPHY
|
|
13
|
+
Information density over aesthetics. Every pixel earns its place.
|
|
14
|
+
The user reads data, not art. Clarity beats beauty.
|
|
15
|
+
|
|
16
|
+
## ABSOLUTE OUTPUT RULES
|
|
17
|
+
1. Output ONLY a single complete HTML file. No explanation, no markdown fences.
|
|
18
|
+
2. ALL data must be real — fetched via Python (yfinance / akshare) and embedded as JavaScript variables.
|
|
19
|
+
NEVER hardcode placeholder prices like "150.00" or "N/A" for fields you could compute.
|
|
20
|
+
3. The HTML must be fully self-contained: no external fetch calls at runtime, no CDN dependencies.
|
|
21
|
+
Google Fonts (@import) is the ONLY allowed external resource.
|
|
22
|
+
4. Always save to os.path.expanduser('~/Documents/Aria Code/generated/<descriptive_name>.html').
|
|
23
|
+
5. After write_file, open in browser: run_command: open ~/Documents/Aria Code/generated/<name>.html (macOS) or start <name>.html (Windows).
|
|
24
|
+
|
|
25
|
+
## DESIGN SYSTEM — BLOOMBERG STYLE
|
|
26
|
+
|
|
27
|
+
### Typography
|
|
28
|
+
- Body / labels: 'IBM Plex Sans', system-ui, sans-serif
|
|
29
|
+
- Numbers / prices / codes: 'IBM Plex Mono', 'Courier New', monospace
|
|
30
|
+
- Load via: @import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=IBM+Plex+Sans:wght@400;600;700&display=swap');
|
|
31
|
+
- All prices, percentages, and quantities: font-family: var(--font-mono); font-variant-numeric: tabular-nums;
|
|
32
|
+
- Section headers: font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em;
|
|
33
|
+
- NO emojis anywhere — use text indicators instead:
|
|
34
|
+
- Up trend: [+] or ▲ or colored text
|
|
35
|
+
- Down trend: [-] or ▼ or colored text
|
|
36
|
+
- Active: [ON] Inactive: [OFF]
|
|
37
|
+
- Warning: [!] OK: [OK]
|
|
38
|
+
|
|
39
|
+
### Color System — CSS Variables (MUST use these exact names)
|
|
40
|
+
```css
|
|
41
|
+
:root {
|
|
42
|
+
/* Dark mode (default) */
|
|
43
|
+
--bg-primary: #000000;
|
|
44
|
+
--bg-secondary: #111111;
|
|
45
|
+
--bg-tertiary: #1A1A1A;
|
|
46
|
+
--bg-hover: #222222;
|
|
47
|
+
--border: #2A2A2A;
|
|
48
|
+
--border-strong: #444444;
|
|
49
|
+
--text-primary: #E8E9EA;
|
|
50
|
+
--text-secondary:#A0A0A0;
|
|
51
|
+
--text-muted: #606060;
|
|
52
|
+
--accent: #F5A623; /* Bloomberg orange */
|
|
53
|
+
--accent-dim: #7A5010;
|
|
54
|
+
--positive: #00CC66;
|
|
55
|
+
--positive-dim: #004422;
|
|
56
|
+
--negative: #FF3B3B;
|
|
57
|
+
--negative-dim: #440000;
|
|
58
|
+
--neutral: #4A9EFF;
|
|
59
|
+
--warning: #FFB800;
|
|
60
|
+
}
|
|
61
|
+
@media (prefers-color-scheme: light) {
|
|
62
|
+
:root {
|
|
63
|
+
--bg-primary: #FFFFFF;
|
|
64
|
+
--bg-secondary: #F4F4F4;
|
|
65
|
+
--bg-tertiary: #EAEAEA;
|
|
66
|
+
--bg-hover: #E0E0E0;
|
|
67
|
+
--border: #CCCCCC;
|
|
68
|
+
--border-strong: #999999;
|
|
69
|
+
--text-primary: #111111;
|
|
70
|
+
--text-secondary:#444444;
|
|
71
|
+
--text-muted: #888888;
|
|
72
|
+
--accent: #B8520A;
|
|
73
|
+
--accent-dim: #FAE0C8;
|
|
74
|
+
--positive: #006B2E;
|
|
75
|
+
--positive-dim: #D4F0E0;
|
|
76
|
+
--negative: #B30000;
|
|
77
|
+
--negative-dim: #FFE0E0;
|
|
78
|
+
--neutral: #0057B7;
|
|
79
|
+
--warning: #8B6000;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Layout Rules
|
|
85
|
+
- border-radius: 0 everywhere — flat, terminal aesthetic
|
|
86
|
+
- Base spacing unit: 4px. Use 4, 8, 12, 16, 20, 24, 32px — never odd values
|
|
87
|
+
- Max content width: 1440px, centered
|
|
88
|
+
- Grid: use CSS Grid with explicit columns, never flexbox for multi-column layouts
|
|
89
|
+
- Body padding: 16px on sides, 12px top
|
|
90
|
+
- Section gap: 20px
|
|
91
|
+
- Card padding: 12px
|
|
92
|
+
- Table row height: 28px (compact), 36px (comfortable)
|
|
93
|
+
|
|
94
|
+
### Component Patterns
|
|
95
|
+
|
|
96
|
+
**Section Header:**
|
|
97
|
+
```html
|
|
98
|
+
<div class="section-header">SECTION TITLE</div>
|
|
99
|
+
```
|
|
100
|
+
```css
|
|
101
|
+
.section-header {
|
|
102
|
+
font-size: 10px; font-weight: 700; text-transform: uppercase;
|
|
103
|
+
letter-spacing: 0.12em; color: var(--text-muted);
|
|
104
|
+
border-bottom: 1px solid var(--border);
|
|
105
|
+
padding-bottom: 6px; margin-bottom: 10px;
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Quote Tile (compact, for index grids):**
|
|
110
|
+
```html
|
|
111
|
+
<div class="qt">
|
|
112
|
+
<div class="qt-sym">SPX</div>
|
|
113
|
+
<div class="qt-name">S&P 500</div>
|
|
114
|
+
<div class="qt-price">5,847.23</div>
|
|
115
|
+
<div class="qt-change up">+0.84%</div>
|
|
116
|
+
</div>
|
|
117
|
+
```
|
|
118
|
+
```css
|
|
119
|
+
.qt { background: var(--bg-secondary); border: 1px solid var(--border); padding: 10px 12px; display: flex; flex-direction: column; gap: 2px; }
|
|
120
|
+
.qt-sym { font-family: var(--font-mono); font-size: 11px; color: var(--accent); font-weight: 600; }
|
|
121
|
+
.qt-name { font-size: 10px; color: var(--text-muted); }
|
|
122
|
+
.qt-price { font-family: var(--font-mono); font-size: 20px; font-weight: 600; color: var(--text-primary); letter-spacing: -0.01em; }
|
|
123
|
+
.qt-change { font-family: var(--font-mono); font-size: 12px; font-weight: 600; }
|
|
124
|
+
.up { color: var(--positive); }
|
|
125
|
+
.down { color: var(--negative); }
|
|
126
|
+
.flat { color: var(--text-muted); }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Data Table (dense, financial):**
|
|
130
|
+
```html
|
|
131
|
+
<table class="data-table">
|
|
132
|
+
<thead><tr><th>SYMBOL</th><th class="r">PRICE</th><th class="r">CHG%</th></tr></thead>
|
|
133
|
+
<tbody>
|
|
134
|
+
<tr><td class="sym">AAPL</td><td class="num">185.42</td><td class="num up">+1.23%</td></tr>
|
|
135
|
+
</tbody>
|
|
136
|
+
</table>
|
|
137
|
+
```
|
|
138
|
+
```css
|
|
139
|
+
.data-table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
|
140
|
+
.data-table th { background: var(--bg-tertiary); color: var(--text-muted); font-size: 10px;
|
|
141
|
+
font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em;
|
|
142
|
+
padding: 6px 10px; text-align: left; border-bottom: 1px solid var(--border-strong);
|
|
143
|
+
white-space: nowrap; }
|
|
144
|
+
.data-table th.r, .data-table td.r { text-align: right; }
|
|
145
|
+
.data-table td { padding: 5px 10px; border-bottom: 1px solid var(--border); vertical-align: middle; }
|
|
146
|
+
.data-table tr:hover td { background: var(--bg-hover); }
|
|
147
|
+
.data-table tr:last-child td { border-bottom: none; }
|
|
148
|
+
.sym { font-family: var(--font-mono); font-weight: 600; color: var(--accent); font-size: 12px; }
|
|
149
|
+
.num { font-family: var(--font-mono); text-align: right; }
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Metric Card (KPI summary):**
|
|
153
|
+
```html
|
|
154
|
+
<div class="metric">
|
|
155
|
+
<div class="metric-label">TOTAL PNL</div>
|
|
156
|
+
<div class="metric-val up">+¥12,480</div>
|
|
157
|
+
<div class="metric-sub">unrealized</div>
|
|
158
|
+
</div>
|
|
159
|
+
```
|
|
160
|
+
```css
|
|
161
|
+
.metric { background: var(--bg-secondary); border: 1px solid var(--border); padding: 14px 16px; }
|
|
162
|
+
.metric-label { font-size: 10px; font-weight: 700; text-transform: uppercase;
|
|
163
|
+
letter-spacing: 0.1em; color: var(--text-muted); margin-bottom: 6px; }
|
|
164
|
+
.metric-val { font-family: var(--font-mono); font-size: 24px; font-weight: 600;
|
|
165
|
+
color: var(--text-primary); letter-spacing: -0.02em; }
|
|
166
|
+
.metric-sub { font-size: 10px; color: var(--text-muted); margin-top: 4px; }
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Status Badge (no emoji):**
|
|
170
|
+
```html
|
|
171
|
+
<span class="badge badge-on">ACTIVE</span>
|
|
172
|
+
<span class="badge badge-off">STOPPED</span>
|
|
173
|
+
<span class="badge badge-warn">WARNING</span>
|
|
174
|
+
```
|
|
175
|
+
```css
|
|
176
|
+
.badge { font-family: var(--font-mono); font-size: 9px; font-weight: 700;
|
|
177
|
+
padding: 2px 6px; letter-spacing: 0.08em; border: 1px solid; }
|
|
178
|
+
.badge-on { color: var(--positive); border-color: var(--positive); background: var(--positive-dim); }
|
|
179
|
+
.badge-off { color: var(--text-muted); border-color: var(--border); background: transparent; }
|
|
180
|
+
.badge-warn { color: var(--warning); border-color: var(--warning); background: transparent; }
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Top Bar / Header:**
|
|
184
|
+
```html
|
|
185
|
+
<header class="topbar">
|
|
186
|
+
<div class="topbar-brand">ARIA <span>TERMINAL</span></div>
|
|
187
|
+
<div class="topbar-meta">Generated 2026-06-17 10:45 · Data: yfinance + Local DB</div>
|
|
188
|
+
</header>
|
|
189
|
+
```
|
|
190
|
+
```css
|
|
191
|
+
.topbar { display: flex; align-items: baseline; justify-content: space-between;
|
|
192
|
+
border-bottom: 2px solid var(--accent); padding: 10px 0 8px; margin-bottom: 20px; }
|
|
193
|
+
.topbar-brand { font-family: var(--font-mono); font-size: 18px; font-weight: 700;
|
|
194
|
+
color: var(--accent); letter-spacing: 0.04em; }
|
|
195
|
+
.topbar-brand span { color: var(--text-secondary); font-weight: 400; margin-left: 4px; }
|
|
196
|
+
.topbar-meta { font-size: 10px; color: var(--text-muted); letter-spacing: 0.04em; }
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Change Indicator with direction marker:**
|
|
200
|
+
```html
|
|
201
|
+
<span class="chg up">+1.84%</span>
|
|
202
|
+
<span class="chg down">-2.31%</span>
|
|
203
|
+
```
|
|
204
|
+
Always prepend sign: positive gets "+", negative already has "-", zero shows "0.00%".
|
|
205
|
+
|
|
206
|
+
### FORBIDDEN patterns
|
|
207
|
+
- NO emojis (no , no , no , no — anywhere)
|
|
208
|
+
- NO rounded corners (border-radius: 0 always)
|
|
209
|
+
- NO gradient backgrounds
|
|
210
|
+
- NO box shadows
|
|
211
|
+
- NO animations except: cursor blink on live data indicators (optional)
|
|
212
|
+
- NO external JS libraries (no Chart.js, no D3, no jQuery)
|
|
213
|
+
- NO placeholder data that you did not fetch
|
|
214
|
+
- NO inline styles for colors — use CSS variables only
|
|
215
|
+
|
|
216
|
+
## WORKFLOW
|
|
217
|
+
|
|
218
|
+
When user requests a UI artifact (dashboard, report, heatmap, etc.):
|
|
219
|
+
|
|
220
|
+
1. **Plan data requirements**: what symbols / metrics are needed
|
|
221
|
+
2. **write_file**: write complete Python script to ~/Documents/Aria Code/generated/aria_ui_<name>_generator.py
|
|
222
|
+
- Script fetches ALL data, embeds as JS constants, renders full HTML
|
|
223
|
+
- Script saves to ~/Documents/Aria Code/generated/aria_<name>_<YYYYMMDD>.html
|
|
224
|
+
3. **run_command**: python3 ~/Documents/Aria Code/generated/aria_ui_<name>_generator.py
|
|
225
|
+
4. **run_command**: open ~/Documents/Aria Code/generated/aria_<name>_<date>.html
|
|
226
|
+
|
|
227
|
+
The generator script structure:
|
|
228
|
+
```python
|
|
229
|
+
import os, json
|
|
230
|
+
from datetime import datetime
|
|
231
|
+
import yfinance as yf # or akshare for A-share
|
|
232
|
+
|
|
233
|
+
# --- Fetch data ---
|
|
234
|
+
# ... fetch all required data ...
|
|
235
|
+
|
|
236
|
+
# --- Render HTML ---
|
|
237
|
+
now = datetime.now().strftime("%Y-%m-%d %H:%M")
|
|
238
|
+
data_json = json.dumps(data, ensure_ascii=False)
|
|
239
|
+
|
|
240
|
+
html = f\\'\\'\\'<!DOCTYPE html>
|
|
241
|
+
<html lang="zh"><head>
|
|
242
|
+
<meta charset="UTF-8">
|
|
243
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
244
|
+
<title>ARIA TERMINAL — {title}</title>
|
|
245
|
+
<style>
|
|
246
|
+
@import url(\\'https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=IBM+Plex+Sans:wght@400;600;700&display=swap\\');
|
|
247
|
+
/* ... full Bloomberg design system CSS ... */
|
|
248
|
+
</style>
|
|
249
|
+
</head><body>
|
|
250
|
+
<!-- Bloomberg-style layout with all data embedded -->
|
|
251
|
+
</body></html>\\'\\'\\'
|
|
252
|
+
|
|
253
|
+
out = os.path.expanduser(f\\'~/Documents/Aria Code/generated/aria_{name}_{datetime.now().strftime("%Y%m%d")}.html\\')
|
|
254
|
+
with open(out, \\'w\\', encoding=\\'utf-8\\') as f: f.write(html)
|
|
255
|
+
print(f\\'Saved: {out}\\')
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## WHAT TO GENERATE FOR COMMON REQUESTS
|
|
259
|
+
|
|
260
|
+
- "行情看板 / market dashboard" → quote tiles grid (4x4), top movers table, volume leaders, sector heatmap (text-based color cells)
|
|
261
|
+
- "持仓报告 / portfolio report" → positions table, P&L summary metrics, allocation bar (ASCII-style), trade history
|
|
262
|
+
- "策略回测报告 / backtest report" → equity curve (SVG path), drawdown chart (SVG), trade log table, metrics card grid
|
|
263
|
+
- "因子分析 / factor analysis" → factor table, z-score heatmap (color cells), quintile return bar chart (SVG bars)
|
|
264
|
+
- "晨报 / morning brief" → compact layout, indices strip, overnight changes, key events calendar table
|
|
265
|
+
- "股票分析 / stock analysis" → header with key metrics, price + volume SVG chart, technical indicators table, company fundamentals
|
|
266
|
+
|
|
267
|
+
For SVG charts: generate them inline, no external SVG libraries.
|
|
268
|
+
Use <path> for line charts, <rect> for bar charts, <text> for labels.
|
|
269
|
+
Scale data to viewport coordinates mathematically (min-max normalization).
|
|
270
|
+
"""
|
|
271
|
+
|
|
272
|
+
UI_STYLE_GUIDE = {
|
|
273
|
+
"fonts": {
|
|
274
|
+
"sans": "'IBM Plex Sans', system-ui, sans-serif",
|
|
275
|
+
"mono": "'IBM Plex Mono', 'Courier New', monospace",
|
|
276
|
+
},
|
|
277
|
+
"colors": {
|
|
278
|
+
"dark": {
|
|
279
|
+
"bg_primary": "#000000",
|
|
280
|
+
"bg_secondary": "#111111",
|
|
281
|
+
"bg_tertiary": "#1A1A1A",
|
|
282
|
+
"accent": "#F5A623",
|
|
283
|
+
"positive": "#00CC66",
|
|
284
|
+
"negative": "#FF3B3B",
|
|
285
|
+
"text": "#E8E9EA",
|
|
286
|
+
"muted": "#606060",
|
|
287
|
+
"border": "#2A2A2A",
|
|
288
|
+
},
|
|
289
|
+
"light": {
|
|
290
|
+
"bg_primary": "#FFFFFF",
|
|
291
|
+
"bg_secondary": "#F4F4F4",
|
|
292
|
+
"bg_tertiary": "#EAEAEA",
|
|
293
|
+
"accent": "#B8520A",
|
|
294
|
+
"positive": "#006B2E",
|
|
295
|
+
"negative": "#B30000",
|
|
296
|
+
"text": "#111111",
|
|
297
|
+
"muted": "#888888",
|
|
298
|
+
"border": "#CCCCCC",
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
"principles": [
|
|
302
|
+
"No emojis — use [+]/[-]/[!]/[ON]/[OFF] text indicators",
|
|
303
|
+
"No border-radius — flat terminal aesthetic",
|
|
304
|
+
"No gradients or shadows",
|
|
305
|
+
"IBM Plex Mono for all numbers and prices",
|
|
306
|
+
"Tabular-nums for all numeric columns",
|
|
307
|
+
"prefers-color-scheme for auto dark/light",
|
|
308
|
+
"All data embedded at generation time — zero runtime API calls",
|
|
309
|
+
],
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def get_ui_css_base() -> str:
|
|
314
|
+
"""Return the complete Bloomberg-style CSS base as a string for embedding in generated HTML."""
|
|
315
|
+
return """
|
|
316
|
+
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=IBM+Plex+Sans:wght@400;600;700&display=swap');
|
|
317
|
+
|
|
318
|
+
:root {
|
|
319
|
+
--bg-primary: #000000;
|
|
320
|
+
--bg-secondary: #111111;
|
|
321
|
+
--bg-tertiary: #1A1A1A;
|
|
322
|
+
--bg-hover: #222222;
|
|
323
|
+
--border: #2A2A2A;
|
|
324
|
+
--border-strong: #444444;
|
|
325
|
+
--text-primary: #E8E9EA;
|
|
326
|
+
--text-secondary:#A0A0A0;
|
|
327
|
+
--text-muted: #606060;
|
|
328
|
+
--accent: #F5A623;
|
|
329
|
+
--accent-dim: #7A5010;
|
|
330
|
+
--positive: #00CC66;
|
|
331
|
+
--positive-dim: #003318;
|
|
332
|
+
--negative: #FF3B3B;
|
|
333
|
+
--negative-dim: #3D0000;
|
|
334
|
+
--neutral: #4A9EFF;
|
|
335
|
+
--warning: #FFB800;
|
|
336
|
+
--font-sans: 'IBM Plex Sans', system-ui, sans-serif;
|
|
337
|
+
--font-mono: 'IBM Plex Mono', 'Courier New', monospace;
|
|
338
|
+
}
|
|
339
|
+
@media (prefers-color-scheme: light) {
|
|
340
|
+
:root {
|
|
341
|
+
--bg-primary: #FFFFFF;
|
|
342
|
+
--bg-secondary: #F4F4F4;
|
|
343
|
+
--bg-tertiary: #EAEAEA;
|
|
344
|
+
--bg-hover: #E0E0E0;
|
|
345
|
+
--border: #CCCCCC;
|
|
346
|
+
--border-strong: #999999;
|
|
347
|
+
--text-primary: #111111;
|
|
348
|
+
--text-secondary:#444444;
|
|
349
|
+
--text-muted: #888888;
|
|
350
|
+
--accent: #B8520A;
|
|
351
|
+
--accent-dim: #FAE0C8;
|
|
352
|
+
--positive: #006B2E;
|
|
353
|
+
--positive-dim: #D4F0E0;
|
|
354
|
+
--negative: #B30000;
|
|
355
|
+
--negative-dim: #FFE0E0;
|
|
356
|
+
--neutral: #0057B7;
|
|
357
|
+
--warning: #8B6000;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
361
|
+
html { font-size: 13px; }
|
|
362
|
+
body {
|
|
363
|
+
font-family: var(--font-sans);
|
|
364
|
+
background: var(--bg-primary);
|
|
365
|
+
color: var(--text-primary);
|
|
366
|
+
padding: 12px 16px 32px;
|
|
367
|
+
max-width: 1440px;
|
|
368
|
+
margin: 0 auto;
|
|
369
|
+
line-height: 1.4;
|
|
370
|
+
}
|
|
371
|
+
/* ── Top bar ── */
|
|
372
|
+
.topbar { display: flex; align-items: baseline; justify-content: space-between;
|
|
373
|
+
border-bottom: 2px solid var(--accent); padding-bottom: 8px; margin-bottom: 20px; }
|
|
374
|
+
.topbar-brand { font-family: var(--font-mono); font-size: 16px; font-weight: 700;
|
|
375
|
+
color: var(--accent); letter-spacing: 0.06em; }
|
|
376
|
+
.topbar-brand span { color: var(--text-secondary); font-weight: 400; }
|
|
377
|
+
.topbar-meta { font-size: 10px; color: var(--text-muted); letter-spacing: 0.04em; font-family: var(--font-mono); }
|
|
378
|
+
/* ── Section header ── */
|
|
379
|
+
.sh { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em;
|
|
380
|
+
color: var(--text-muted); border-bottom: 1px solid var(--border);
|
|
381
|
+
padding-bottom: 5px; margin-bottom: 10px; }
|
|
382
|
+
/* ── Layout ── */
|
|
383
|
+
.section { margin-bottom: 20px; }
|
|
384
|
+
.grid { display: grid; gap: 1px; background: var(--border); border: 1px solid var(--border); }
|
|
385
|
+
.g2 { grid-template-columns: 1fr 1fr; }
|
|
386
|
+
.g3 { grid-template-columns: repeat(3, 1fr); }
|
|
387
|
+
.g4 { grid-template-columns: repeat(4, 1fr); }
|
|
388
|
+
.g5 { grid-template-columns: repeat(5, 1fr); }
|
|
389
|
+
.g6 { grid-template-columns: repeat(6, 1fr); }
|
|
390
|
+
.gcol2 { grid-template-columns: 2fr 1fr; }
|
|
391
|
+
.gcol3 { grid-template-columns: 3fr 1fr; }
|
|
392
|
+
/* ── Quote tile ── */
|
|
393
|
+
.qt { background: var(--bg-secondary); padding: 10px 12px;
|
|
394
|
+
display: flex; flex-direction: column; gap: 2px; }
|
|
395
|
+
.qt-sym { font-family: var(--font-mono); font-size: 11px; color: var(--accent); font-weight: 600; }
|
|
396
|
+
.qt-name { font-size: 10px; color: var(--text-muted); }
|
|
397
|
+
.qt-price { font-family: var(--font-mono); font-size: 20px; font-weight: 600;
|
|
398
|
+
color: var(--text-primary); letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
|
|
399
|
+
.qt-chg { font-family: var(--font-mono); font-size: 12px; font-weight: 600; }
|
|
400
|
+
.up { color: var(--positive); }
|
|
401
|
+
.down { color: var(--negative); }
|
|
402
|
+
.flat { color: var(--text-muted); }
|
|
403
|
+
/* ── Metric card ── */
|
|
404
|
+
.metric { background: var(--bg-secondary); padding: 14px 16px; }
|
|
405
|
+
.metric-label { font-size: 10px; font-weight: 700; text-transform: uppercase;
|
|
406
|
+
letter-spacing: 0.1em; color: var(--text-muted); margin-bottom: 6px; }
|
|
407
|
+
.metric-val { font-family: var(--font-mono); font-size: 22px; font-weight: 600;
|
|
408
|
+
color: var(--text-primary); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
|
|
409
|
+
.metric-sub { font-size: 10px; color: var(--text-muted); margin-top: 3px; font-family: var(--font-mono); }
|
|
410
|
+
/* ── Data table ── */
|
|
411
|
+
.data-table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
|
412
|
+
.data-table th { background: var(--bg-tertiary); color: var(--text-muted); font-size: 10px;
|
|
413
|
+
font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em;
|
|
414
|
+
padding: 6px 10px; text-align: left; border-bottom: 1px solid var(--border-strong);
|
|
415
|
+
white-space: nowrap; font-family: var(--font-sans); }
|
|
416
|
+
.data-table td { padding: 5px 10px; border-bottom: 1px solid var(--border); vertical-align: middle; }
|
|
417
|
+
.data-table tr:hover td { background: var(--bg-hover); }
|
|
418
|
+
.data-table tr:last-child td { border-bottom: none; }
|
|
419
|
+
.r { text-align: right; }
|
|
420
|
+
.sym { font-family: var(--font-mono); font-weight: 600; color: var(--accent); font-size: 12px; }
|
|
421
|
+
.num { font-family: var(--font-mono); text-align: right; font-variant-numeric: tabular-nums; }
|
|
422
|
+
.dim { color: var(--text-muted); font-size: 11px; }
|
|
423
|
+
/* ── Badge ── */
|
|
424
|
+
.badge { font-family: var(--font-mono); font-size: 9px; font-weight: 700;
|
|
425
|
+
padding: 1px 5px; letter-spacing: 0.06em; border: 1px solid; }
|
|
426
|
+
.badge-on { color: var(--positive); border-color: var(--positive); background: var(--positive-dim); }
|
|
427
|
+
.badge-off { color: var(--text-muted); border-color: var(--border); background: transparent; }
|
|
428
|
+
.badge-warn { color: var(--warning); border-color: var(--warning); background: transparent; }
|
|
429
|
+
/* ── Card ── */
|
|
430
|
+
.card { background: var(--bg-secondary); border: 1px solid var(--border); padding: 14px; }
|
|
431
|
+
/* ── Divider ── */
|
|
432
|
+
hr { border: none; border-top: 1px solid var(--border); margin: 16px 0; }
|
|
433
|
+
/* ── Responsive ── */
|
|
434
|
+
@media (max-width: 960px) { .g4,.g5,.g6 { grid-template-columns: repeat(2, 1fr); } }
|
|
435
|
+
@media (max-width: 600px) { .g2,.g3,.g4 { grid-template-columns: 1fr; } }
|
|
436
|
+
"""
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"""Provider 端点表与 API key 连通性测试 —— 从 aria_cli.py 抽出。
|
|
2
|
+
|
|
3
|
+
这两块(_PROVIDER_BASE_URLS 的 28 个端点 + _test_api_key 的 178 行分支)跟
|
|
4
|
+
aria_cli 的会话状态完全无关:一个是纯数据,一个是纯函数(给定 provider 与
|
|
5
|
+
key,发一次 HTTP 请求判断是否有效)。放在 7278 行的主文件里只是历史原因。
|
|
6
|
+
|
|
7
|
+
⚠️ 调用约束(跟 apps/cli/football_reports.py 同一套):
|
|
8
|
+
apps/cli/commands/model_cmds.py 是 mixin,它用**裸名**调用 _test_api_key,
|
|
9
|
+
靠 aria_cli 的 _rebind_mixin_globals() 把方法 __globals__ 指向 aria_cli 命名
|
|
10
|
+
空间才能解析。所以本模块不能只是被 import,必须由 aria_cli 用
|
|
11
|
+
_rebind_module_function_globals() 绑回它自己的 globals。
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from typing import Dict, Tuple
|
|
17
|
+
|
|
18
|
+
__all__ = ["PROVIDER_BASE_URLS", "_PROVIDER_BASE_URLS", "_test_api_key"]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
_PROVIDER_BASE_URLS: Dict[str, str] = {
|
|
22
|
+
# ── 国际主流 ──────────────────────────────────────────────────────
|
|
23
|
+
"deepseek": "https://api.deepseek.com",
|
|
24
|
+
"openai": "https://api.openai.com",
|
|
25
|
+
"anthropic": "https://api.anthropic.com",
|
|
26
|
+
"claude": "https://api.anthropic.com",
|
|
27
|
+
"groq": "https://api.groq.com/openai",
|
|
28
|
+
"together": "https://api.together.xyz",
|
|
29
|
+
"google": "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
30
|
+
"gemini": "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
31
|
+
"xai": "https://api.x.ai/v1",
|
|
32
|
+
"grok": "https://api.x.ai/v1",
|
|
33
|
+
"mistral": "https://api.mistral.ai/v1",
|
|
34
|
+
"cohere": "https://api.cohere.ai/compatibility/v1",
|
|
35
|
+
"perplexity": "https://api.perplexity.ai",
|
|
36
|
+
# ── 国内主流 ──────────────────────────────────────────────────────
|
|
37
|
+
"dashscope": "https://dashscope.aliyuncs.com/compatible-mode",
|
|
38
|
+
"aliyun": "https://dashscope.aliyuncs.com/compatible-mode",
|
|
39
|
+
"siliconflow": "https://api.siliconflow.cn",
|
|
40
|
+
"moonshot": "https://api.moonshot.cn/v1",
|
|
41
|
+
"zhipu": "https://open.bigmodel.cn/api/paas/v4",
|
|
42
|
+
"glm": "https://open.bigmodel.cn/api/paas/v4",
|
|
43
|
+
"baidu": "https://qianfan.baidubce.com/v2",
|
|
44
|
+
"ernie": "https://qianfan.baidubce.com/v2",
|
|
45
|
+
"qianfan": "https://qianfan.baidubce.com/v2",
|
|
46
|
+
"bytedance": "https://ark.cn-beijing.volces.com/api/v3",
|
|
47
|
+
"doubao": "https://ark.cn-beijing.volces.com/api/v3",
|
|
48
|
+
"ark": "https://ark.cn-beijing.volces.com/api/v3",
|
|
49
|
+
"minimax": "https://api.minimax.chat/v1",
|
|
50
|
+
"stepfun": "https://api.stepfun.com/v1",
|
|
51
|
+
"01ai": "https://api.lingyiwanwu.com/v1",
|
|
52
|
+
"yi": "https://api.lingyiwanwu.com/v1",
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _test_api_key(provider: str, key: str) -> tuple:
|
|
57
|
+
"""Test if an API key is valid. Returns (ok: bool, message: str)."""
|
|
58
|
+
import urllib.request as _ur
|
|
59
|
+
import urllib.error as _ue
|
|
60
|
+
import json as _json
|
|
61
|
+
|
|
62
|
+
provider = provider.lower()
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
# ── Anthropic (different auth scheme) ────────────────────────────────
|
|
66
|
+
if provider in ("anthropic", "claude"):
|
|
67
|
+
req = _ur.Request(
|
|
68
|
+
"https://api.anthropic.com/v1/models",
|
|
69
|
+
headers={
|
|
70
|
+
"x-api-key": key,
|
|
71
|
+
"anthropic-version": "2023-06-01",
|
|
72
|
+
},
|
|
73
|
+
)
|
|
74
|
+
with _ur.urlopen(req, timeout=8) as r:
|
|
75
|
+
return True, f"✅ Anthropic HTTP {r.status} key 有效"
|
|
76
|
+
|
|
77
|
+
# ── ZhiPu (JWT-based, just try /v1/models) ───────────────────────────
|
|
78
|
+
if provider == "zhipu":
|
|
79
|
+
base = _PROVIDER_BASE_URLS.get("zhipu", "https://open.bigmodel.cn/api/paas/v4")
|
|
80
|
+
req = _ur.Request(
|
|
81
|
+
base.rstrip("/") + "/models",
|
|
82
|
+
headers={"Authorization": f"Bearer {key}"},
|
|
83
|
+
)
|
|
84
|
+
try:
|
|
85
|
+
with _ur.urlopen(req, timeout=8) as r:
|
|
86
|
+
return True, f"✅ 智谱 GLM HTTP {r.status} key 有效"
|
|
87
|
+
except _ue.HTTPError as e:
|
|
88
|
+
if e.code in (401, 403):
|
|
89
|
+
return False, f"❌ 智谱 GLM HTTP {e.code} key 无效"
|
|
90
|
+
return True, f"✅ 智谱 GLM HTTP {e.code} 可连接"
|
|
91
|
+
|
|
92
|
+
# ── Standard OpenAI-compat LLM providers ─────────────────────────────
|
|
93
|
+
if provider in _PROVIDER_BASE_URLS:
|
|
94
|
+
base = _PROVIDER_BASE_URLS[provider].rstrip("/")
|
|
95
|
+
# Avoid double /v1 when base already ends with /v1 or /v2 etc.
|
|
96
|
+
if base.endswith(("/v1", "/v2", "/v3", "/v4", "/openai")):
|
|
97
|
+
url = base + "/models"
|
|
98
|
+
else:
|
|
99
|
+
url = base + "/v1/models"
|
|
100
|
+
req = _ur.Request(url, headers={"Authorization": f"Bearer {key}"})
|
|
101
|
+
try:
|
|
102
|
+
with _ur.urlopen(req, timeout=8) as r:
|
|
103
|
+
return True, f"✅ {provider.capitalize()} HTTP {r.status} key 有效"
|
|
104
|
+
except _ue.HTTPError as e:
|
|
105
|
+
if e.code in (401, 403):
|
|
106
|
+
return False, f"❌ {provider.capitalize()} HTTP {e.code} key 无效或已过期"
|
|
107
|
+
return True, f"✅ {provider.capitalize()} HTTP {e.code} 可连接"
|
|
108
|
+
|
|
109
|
+
# ── Data services ─────────────────────────────────────────────────────
|
|
110
|
+
if provider == "finnhub":
|
|
111
|
+
url = f"https://finnhub.io/api/v1/quote?symbol=AAPL&token={key}"
|
|
112
|
+
req = _ur.Request(url, headers={"User-Agent": "aria-code/1.0"})
|
|
113
|
+
with _ur.urlopen(req, timeout=8) as r:
|
|
114
|
+
body = _json.loads(r.read())
|
|
115
|
+
if body.get("error"):
|
|
116
|
+
return False, f"❌ Finnhub error: {body['error']}"
|
|
117
|
+
price = body.get("c", "?")
|
|
118
|
+
return True, f"✅ Finnhub AAPL现价 ${price} key 有效"
|
|
119
|
+
|
|
120
|
+
if provider == "alphavantage":
|
|
121
|
+
url = f"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=AAPL&apikey={key}"
|
|
122
|
+
req = _ur.Request(url, headers={"User-Agent": "aria-code/1.0"})
|
|
123
|
+
with _ur.urlopen(req, timeout=10) as r:
|
|
124
|
+
body = _json.loads(r.read())
|
|
125
|
+
if "Information" in body:
|
|
126
|
+
return False, f"❌ Alpha Vantage 超出频率限制或 key 无效"
|
|
127
|
+
if "Global Quote" in body and body["Global Quote"]:
|
|
128
|
+
price = body["Global Quote"].get("05. price", "?")
|
|
129
|
+
return True, f"✅ Alpha Vantage AAPL=${price} key 有效"
|
|
130
|
+
return False, f"❌ Alpha Vantage 返回异常: {str(body)[:80]}"
|
|
131
|
+
|
|
132
|
+
if provider == "polygon":
|
|
133
|
+
url = f"https://api.polygon.io/v2/aggs/ticker/AAPL/range/1/day/2024-01-09/2024-01-09?adjusted=true&sort=asc&limit=1&apiKey={key}"
|
|
134
|
+
req = _ur.Request(url, headers={"User-Agent": "aria-code/1.0"})
|
|
135
|
+
try:
|
|
136
|
+
with _ur.urlopen(req, timeout=8) as r:
|
|
137
|
+
body = _json.loads(r.read())
|
|
138
|
+
if body.get("status") == "OK":
|
|
139
|
+
return True, f"✅ Polygon {body.get('resultsCount', 0)} 条数据 key 有效"
|
|
140
|
+
return False, f"❌ Polygon {body.get('status', 'unknown')}: {body.get('error', '')}"
|
|
141
|
+
except _ue.HTTPError as e:
|
|
142
|
+
if e.code == 403:
|
|
143
|
+
return False, f"❌ Polygon HTTP 403 key 无效"
|
|
144
|
+
return True, f"✅ Polygon HTTP {e.code} 可连接"
|
|
145
|
+
|
|
146
|
+
if provider == "fmp":
|
|
147
|
+
url = f"https://financialmodelingprep.com/api/v3/quote/AAPL?apikey={key}"
|
|
148
|
+
req = _ur.Request(url, headers={"User-Agent": "aria-code/1.0"})
|
|
149
|
+
with _ur.urlopen(req, timeout=8) as r:
|
|
150
|
+
body = _json.loads(r.read())
|
|
151
|
+
if isinstance(body, list) and body:
|
|
152
|
+
price = body[0].get("price", "?")
|
|
153
|
+
return True, f"✅ FMP AAPL=${price} key 有效"
|
|
154
|
+
if isinstance(body, dict) and "Error Message" in body:
|
|
155
|
+
return False, f"❌ FMP {body['Error Message']}"
|
|
156
|
+
return False, f"❌ FMP 返回异常: {str(body)[:80]}"
|
|
157
|
+
|
|
158
|
+
if provider == "twelvedata":
|
|
159
|
+
url = f"https://api.twelvedata.com/api_usage?apikey={key}"
|
|
160
|
+
req = _ur.Request(url, headers={"User-Agent": "aria-code/1.0"})
|
|
161
|
+
with _ur.urlopen(req, timeout=8) as r:
|
|
162
|
+
body = _json.loads(r.read())
|
|
163
|
+
if body.get("status") == "error":
|
|
164
|
+
return False, f"❌ TwelveData {body.get('message', 'key 无效')}"
|
|
165
|
+
used = body.get("current_usage", {}).get("daily", {}).get("used", "?")
|
|
166
|
+
limit = body.get("current_usage", {}).get("daily", {}).get("limit", "?")
|
|
167
|
+
return True, f"✅ TwelveData 今日已用 {used}/{limit} key 有效"
|
|
168
|
+
|
|
169
|
+
if provider == "newsapi":
|
|
170
|
+
url = f"https://newsapi.org/v2/top-headlines?country=us&pageSize=1&apiKey={key}"
|
|
171
|
+
req = _ur.Request(url, headers={"User-Agent": "aria-code/1.0"})
|
|
172
|
+
try:
|
|
173
|
+
with _ur.urlopen(req, timeout=8) as r:
|
|
174
|
+
body = _json.loads(r.read())
|
|
175
|
+
if body.get("status") == "ok":
|
|
176
|
+
return True, f"✅ NewsAPI {body.get('totalResults', 0)} 条新闻 key 有效"
|
|
177
|
+
return False, f"❌ NewsAPI {body.get('message', 'key 无效')}"
|
|
178
|
+
except _ue.HTTPError as e:
|
|
179
|
+
err_body = _json.loads(e.read().decode()) if e.read else {}
|
|
180
|
+
return False, f"❌ NewsAPI HTTP {e.code} {err_body.get('message', '')}"
|
|
181
|
+
|
|
182
|
+
if provider == "coingecko":
|
|
183
|
+
url = "https://pro-api.coingecko.com/api/v3/ping"
|
|
184
|
+
req = _ur.Request(url, headers={"x-cg-pro-api-key": key, "User-Agent": "aria-code/1.0"})
|
|
185
|
+
try:
|
|
186
|
+
with _ur.urlopen(req, timeout=8) as r:
|
|
187
|
+
return True, f"✅ CoinGecko Pro key 有效"
|
|
188
|
+
except _ue.HTTPError as e:
|
|
189
|
+
if e.code == 401:
|
|
190
|
+
url2 = f"https://api.coingecko.com/api/v3/ping?x_cg_demo_api_key={key}"
|
|
191
|
+
req2 = _ur.Request(url2, headers={"User-Agent": "aria-code/1.0"})
|
|
192
|
+
try:
|
|
193
|
+
with _ur.urlopen(req2, timeout=8) as r2:
|
|
194
|
+
return True, f"✅ CoinGecko Demo key 有效"
|
|
195
|
+
except Exception:
|
|
196
|
+
pass
|
|
197
|
+
return False, f"❌ CoinGecko HTTP {e.code} key 无效"
|
|
198
|
+
|
|
199
|
+
if provider == "tavily":
|
|
200
|
+
import urllib.parse as _up
|
|
201
|
+
data = _json.dumps({"api_key": key, "query": "test", "max_results": 1}).encode()
|
|
202
|
+
req = _ur.Request(
|
|
203
|
+
"https://api.tavily.com/search",
|
|
204
|
+
data=data,
|
|
205
|
+
headers={"Content-Type": "application/json", "User-Agent": "aria-code/1.0"},
|
|
206
|
+
)
|
|
207
|
+
try:
|
|
208
|
+
with _ur.urlopen(req, timeout=10) as r:
|
|
209
|
+
return True, f"✅ Tavily HTTP {r.status} key 有效"
|
|
210
|
+
except _ue.HTTPError as e:
|
|
211
|
+
if e.code == 401:
|
|
212
|
+
return False, f"❌ Tavily HTTP 401 key 无效"
|
|
213
|
+
return True, f"✅ Tavily HTTP {e.code} 可连接"
|
|
214
|
+
|
|
215
|
+
if provider == "brave":
|
|
216
|
+
req = _ur.Request(
|
|
217
|
+
"https://api.search.brave.com/res/v1/web/search?q=AAPL&count=1",
|
|
218
|
+
headers={"X-Subscription-Token": key, "User-Agent": "aria-code/1.0"},
|
|
219
|
+
)
|
|
220
|
+
try:
|
|
221
|
+
with _ur.urlopen(req, timeout=8) as r:
|
|
222
|
+
return True, f"✅ Brave Search HTTP {r.status} key 有效"
|
|
223
|
+
except _ue.HTTPError as e:
|
|
224
|
+
if e.code == 401:
|
|
225
|
+
return False, f"❌ Brave Search HTTP 401 key 无效"
|
|
226
|
+
return True, f"✅ Brave Search HTTP {e.code} 可连接"
|
|
227
|
+
|
|
228
|
+
return False, f"⚠ 未知 provider '{provider}',无法测试"
|
|
229
|
+
|
|
230
|
+
except _ue.URLError as e:
|
|
231
|
+
return False, f"❌ 网络错误: {e.reason}"
|
|
232
|
+
except Exception as e:
|
|
233
|
+
return False, f"❌ 测试失败: {e}"
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
# 对外的规范名;_PROVIDER_BASE_URLS 保留给既有裸名调用方。
|
|
237
|
+
PROVIDER_BASE_URLS = _PROVIDER_BASE_URLS
|