argo-search 1.0.1 → 2.9.8
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.
- package/LICENSE +201 -21
- package/README.en.md +735 -0
- package/README.es.md +777 -0
- package/README.ja.md +777 -0
- package/README.ko.md +777 -0
- package/README.md +778 -320
- package/SKILL.md +135 -0
- package/assets/readme/hero.svg +121 -0
- package/assets/readme/made-with-beautify.svg +10 -0
- package/assets/readme/proof-routes.svg +73 -0
- package/assets/readme/why-better.svg +104 -0
- package/assets/readme/workflow.svg +83 -0
- package/backends/domain_profiles.json +2356 -96
- package/backends/engine_registry.yaml +3428 -503
- package/backends/query_synonyms_cn.json +35 -0
- package/backends/quota_profiles.json +2488 -160
- package/backends/source_types_cn.json +109 -0
- package/backends/text_lexicon.json +44 -0
- package/bin/argo +772 -0
- package/bin/argo.js +102 -39
- package/config.yaml +5139 -367
- package/cordis.patch.yml +21 -0
- package/data/countries.json +40 -0
- package/data/lang_matrix/lang_capability.json +842 -0
- package/data/lang_matrix/matrix_2026-09-10.json +11921 -0
- package/data/regions_cn.json +1 -0
- package/docs/ADDING_NEW_ENGINE.md +184 -0
- package/docs/ARGO_INTRO.md +124 -0
- package/docs/DATA_SOURCE_GAPS.md +81 -0
- package/docs/DESIGN_LOCAL_DATA_FUSION.md +90 -0
- package/docs/ENGINE_CATALOG.md +575 -0
- package/docs/MCP_SETUP.md +108 -0
- package/docs/PLATFORM_PATHS.md +111 -0
- package/docs/RELEASE_NOTES_v2.8.0.md +71 -0
- package/docs/RELEASE_NOTES_v2.8.2.md +63 -0
- package/docs/RELEASE_NOTES_v2.8.3.md +55 -0
- package/docs/RELEASE_NOTES_v2.8.4.md +79 -0
- package/docs/RELEASE_NOTES_v2.8.5.md +102 -0
- package/docs/RELEASE_NOTES_v2.8.6.md +66 -0
- package/docs/RELEASE_NOTES_v2.8.7.md +65 -0
- package/docs/RELEASE_NOTES_v2.8.8.md +67 -0
- package/docs/RELEASE_NOTES_v2.8.9.md +67 -0
- package/docs/RELEASE_NOTES_v2.9.0.md +64 -0
- package/docs/RELEASE_NOTES_v2.9.8.md +73 -0
- package/docs/SEARCH_ARCHIVE.md +115 -0
- package/docs/assets/architecture.svg +104 -0
- package/docs/assets/hero.svg +98 -0
- package/docs/engines/bangumi.md +27 -0
- package/docs/engines/biorxiv.md +27 -0
- package/docs/engines/clawhub.md +27 -0
- package/docs/engines/crt_sh.md +27 -0
- package/docs/engines/datacite.md +27 -0
- package/docs/engines/deps_dev.md +27 -0
- package/docs/engines/douban_movie.md +27 -0
- package/docs/engines/endoflife.md +27 -0
- package/docs/engines/flk_law.md +27 -0
- package/docs/engines/fxtwitter.md +27 -0
- package/docs/engines/google_news.md +27 -0
- package/docs/engines/gov_regulations.md +27 -0
- package/docs/engines/guqian.md +27 -0
- package/docs/engines/hackernews.md +27 -0
- package/docs/engines/iplant.md +27 -0
- package/docs/engines/keenable.md +27 -0
- package/docs/engines/met_museum.md +27 -0
- package/docs/engines/nasa_images.md +27 -0
- package/docs/engines/netease_music.md +27 -0
- package/docs/engines/npm.md +27 -0
- package/docs/engines/nvd.md +27 -0
- package/docs/engines/openreview.md +27 -0
- package/docs/engines/openstd.md +27 -0
- package/docs/engines/parallel_free.md +27 -0
- package/docs/engines/people_daily.md +27 -0
- package/docs/engines/realtime_index.md +27 -0
- package/docs/engines/sec_edgar.md +27 -0
- package/docs/engines/seltz.md +27 -0
- package/docs/engines/skillsmp.md +27 -0
- package/docs/engines/sspai.md +27 -0
- package/docs/engines/std_samr.md +27 -0
- package/docs/engines/train.md +27 -0
- package/docs/engines/un_comtrade.md +27 -0
- package/docs/engines/wikisource.md +27 -0
- package/docs/engines/zdic.md +27 -0
- package/docs/engines/zenodo.md +27 -0
- package/docs/engines/zhihu_hot_app.md +27 -0
- package/docs//344/270/272/344/273/200/344/271/210/351/200/211/346/213/251argo.md +176 -0
- package/engines/README.md +10 -0
- package/engines/_template_cli.yaml +39 -0
- package/engines/_template_http.yaml +37 -0
- package/engines/plugins/_template_plugin.py +50 -0
- package/engines/specs/_cisa_kev.yaml +54 -0
- package/engines/specs/_osv.yaml +63 -0
- package/engines/specs/aljazeera.yaml +43 -0
- package/engines/specs/antara.yaml +43 -0
- package/engines/specs/artic.yaml +20 -0
- package/engines/specs/aviation_weather.yaml +39 -0
- package/engines/specs/bangumi.yaml +21 -0
- package/engines/specs/biorxiv.yaml +24 -0
- package/engines/specs/carbon_intensity.yaml +32 -0
- package/engines/specs/cfets.yaml +41 -0
- package/engines/specs/cinii.yaml +44 -0
- package/engines/specs/clawhub.yaml +49 -0
- package/engines/specs/cleveland.yaml +19 -0
- package/engines/specs/cn_ai_news.yaml +43 -0
- package/engines/specs/core.yaml +35 -0
- package/engines/specs/crt_sh.yaml +38 -0
- package/engines/specs/ct24.yaml +43 -0
- package/engines/specs/datacite.yaml +27 -0
- package/engines/specs/datagov_uk.yaml +41 -0
- package/engines/specs/ddgs_images.yaml +45 -0
- package/engines/specs/deepseek_search.yaml +74 -0
- package/engines/specs/deezer.yaml +20 -0
- package/engines/specs/defillama.yaml +38 -0
- package/engines/specs/deps_dev.yaml +21 -0
- package/engines/specs/digup.yaml +36 -0
- package/engines/specs/doi.yaml +39 -0
- package/engines/specs/douban_movie.yaml +22 -0
- package/engines/specs/dw_news.yaml +47 -0
- package/engines/specs/egov_law.yaml +21 -0
- package/engines/specs/elpais.yaml +43 -0
- package/engines/specs/endoflife.yaml +21 -0
- package/engines/specs/energy_charts.yaml +21 -0
- package/engines/specs/factcheck_org.yaml +52 -0
- package/engines/specs/faz.yaml +43 -0
- package/engines/specs/federal_register.yaml +57 -0
- package/engines/specs/firecrawl.yaml +53 -0
- package/engines/specs/flk_law.yaml +24 -0
- package/engines/specs/folha.yaml +43 -0
- package/engines/specs/france24.yaml +44 -0
- package/engines/specs/full_fact.yaml +47 -0
- package/engines/specs/fxtwitter.yaml +36 -0
- package/engines/specs/gbfs_nyc.yaml +32 -0
- package/engines/specs/gdacs.yaml +21 -0
- package/engines/specs/gdelt.yaml +64 -0
- package/engines/specs/gleif.yaml +55 -0
- package/engines/specs/google_news.yaml +22 -0
- package/engines/specs/gov_regulations.yaml +38 -0
- package/engines/specs/guardian_rss.yaml +59 -0
- package/engines/specs/hkex.yaml +40 -0
- package/engines/specs/hurriyet.yaml +43 -0
- package/engines/specs/iplant.yaml +25 -0
- package/engines/specs/jikan.yaml +24 -0
- package/engines/specs/jolpica.yaml +20 -0
- package/engines/specs/k10plus.yaml +20 -0
- package/engines/specs/keenable.yaml +44 -0
- package/engines/specs/keenable_free.yaml +36 -0
- package/engines/specs/lefigaro.yaml +43 -0
- package/engines/specs/listenbrainz.yaml +19 -0
- package/engines/specs/matichon.yaml +43 -0
- package/engines/specs/met_museum.yaml +21 -0
- package/engines/specs/nasa_images.yaml +45 -0
- package/engines/specs/netease_music.yaml +38 -0
- package/engines/specs/nhk.yaml +43 -0
- package/engines/specs/nhtsa_vpic.yaml +20 -0
- package/engines/specs/noaa_swpc.yaml +20 -0
- package/engines/specs/nvd.yaml +38 -0
- package/engines/specs/obis.yaml +20 -0
- package/engines/specs/opencitations.yaml +52 -0
- package/engines/specs/openf1.yaml +21 -0
- package/engines/specs/openfoodfacts.yaml +45 -0
- package/engines/specs/openligadb.yaml +20 -0
- package/engines/specs/openreview.yaml +37 -0
- package/engines/specs/openstd.yaml +21 -0
- package/engines/specs/people_daily.yaml +22 -0
- package/engines/specs/realtime_index.yaml +34 -0
- package/engines/specs/ror.yaml +20 -0
- package/engines/specs/satnogs.yaml +20 -0
- package/engines/specs/sec_edgar.yaml +46 -0
- package/engines/specs/shfe.yaml +39 -0
- package/engines/specs/skillsmp.yaml +50 -0
- package/engines/specs/sogou_weixin_browser.yaml +30 -0
- package/engines/specs/soilgrids.yaml +25 -0
- package/engines/specs/sspai.yaml +36 -0
- package/engines/specs/stackexchange.yaml +46 -0
- package/engines/specs/std_samr.yaml +21 -0
- package/engines/specs/tass.yaml +43 -0
- package/engines/specs/tavily_free.yaml +56 -0
- package/engines/specs/tle_mirror.yaml +21 -0
- package/engines/specs/train.yaml +37 -0
- package/engines/specs/tvmaze.yaml +20 -0
- package/engines/specs/twitter_syndication.yaml +31 -0
- package/engines/specs/un_comtrade.yaml +23 -0
- package/engines/specs/unpaywall.yaml +54 -0
- package/engines/specs/vnpress.yaml +43 -0
- package/engines/specs/weather.yaml +32 -0
- package/engines/specs/who_don.yaml +21 -0
- package/engines/specs/who_gho.yaml +20 -0
- package/engines/specs/wikimedia_commons.yaml +34 -0
- package/engines/specs/wikisource.yaml +22 -0
- package/engines/specs/worms.yaml +19 -0
- package/engines/specs/x_trending.yaml +34 -0
- package/engines/specs/yna.yaml +43 -0
- package/engines/specs/ynet.yaml +43 -0
- package/engines/specs/yuanbao.yaml +93 -0
- package/engines/specs/zbmath.yaml +40 -0
- package/engines/specs/zdic.yaml +22 -0
- package/engines/specs/zenodo.yaml +27 -0
- package/engines/specs/zhihu_hot_app.yaml +35 -0
- package/mcp/clients.yaml +106 -0
- package/package.json +55 -12
- package/packages/dsh-plugin/README.md +152 -0
- package/packages/dsh-plugin/cordis.patch.yml +48 -0
- package/packages/dsh-plugin/dsh/client.js +1533 -0
- package/packages/dsh-plugin/dsh/diagnostics.js +54 -0
- package/packages/dsh-plugin/dsh/index.js +527 -0
- package/packages/dsh-plugin/dsh/native-tools.mjs +749 -0
- package/packages/dsh-plugin/dsh/runner.js +666 -0
- package/packages/dsh-plugin/dsh/wide-research.js +878 -0
- package/packages/dsh-plugin/package.json +38 -0
- package/packages/dsh-plugin/scripts/sync-local.sh +70 -0
- package/packages/dsh-plugin/test/client.test.js +406 -0
- package/packages/dsh-plugin/test/config.test.js +30 -0
- package/packages/dsh-plugin/test/diagnostics.test.js +28 -0
- package/packages/dsh-plugin/test/index.test.js +1382 -0
- package/references/query-templates.md +96 -0
- package/references/query-templates.yaml +118 -0
- package/scripts/ab_eval.py +219 -0
- package/scripts/ab_eval_p0p1.py +266 -0
- package/scripts/adaptive.py +294 -70
- package/scripts/answer.py +154 -0
- package/scripts/archive_run.py +591 -0
- package/scripts/argo_engine_registry.py +172 -0
- package/scripts/argo_paths.py +728 -0
- package/scripts/article.py +136 -0
- package/scripts/article_meta.py +131 -0
- package/scripts/arxiv_source.py +201 -0
- package/scripts/badcase_ledger.py +252 -0
- package/scripts/batch_probe.py +241 -0
- package/scripts/benchmark.py +19 -0
- package/scripts/bounded_run.py +144 -0
- package/scripts/browser_auth.py +323 -0
- package/scripts/budget.py +247 -0
- package/scripts/budget_cli.py +93 -0
- package/scripts/build_release_assets.sh +65 -0
- package/scripts/burstiness_detector.py +147 -0
- package/scripts/cache.py +1066 -67
- package/scripts/cache_guard.py +271 -0
- package/scripts/cache_key_vdom.py +56 -0
- package/scripts/cache_similarity.py +170 -0
- package/scripts/caliber_isolation.py +195 -0
- package/scripts/calibrate_lowquality.py +210 -0
- package/scripts/candidate_envelope.py +366 -0
- package/scripts/chrome_cdp.py +871 -0
- package/scripts/ci_drift_gate.py +90 -0
- package/scripts/circuit_breaker.py +389 -0
- package/scripts/citations.py +334 -0
- package/scripts/cite_cli.py +59 -0
- package/scripts/cjk_tokens.py +95 -0
- package/scripts/clarify.py +47 -24
- package/scripts/cli_io.py +240 -0
- package/scripts/config.py +683 -45
- package/scripts/config_cache.py +402 -0
- package/scripts/conn_pool.py +220 -0
- package/scripts/content_boundary.py +46 -0
- package/scripts/content_security.py +685 -0
- package/scripts/content_signals.py +751 -0
- package/scripts/crawl.py +74 -35
- package/scripts/cross_lingual_trace.py +293 -0
- package/scripts/daemon.py +866 -0
- package/scripts/digup_bridge.py +214 -0
- package/scripts/dispatch_result.py +98 -0
- package/scripts/engine_admission.py +366 -0
- package/scripts/engine_dispatch.py +982 -0
- package/scripts/engine_env.py +539 -0
- package/scripts/engine_failure.py +411 -0
- package/scripts/engine_families.py +738 -0
- package/scripts/engine_policy.py +218 -0
- package/scripts/engine_requires.py +190 -0
- package/scripts/engine_status.py +322 -0
- package/scripts/engine_validate.py +638 -0
- package/scripts/engines.py +799 -294
- package/scripts/engines_base.py +1521 -0
- package/scripts/engines_builders.py +310 -0
- package/scripts/engines_builders_batch10.py +204 -0
- package/scripts/engines_builders_batch11.py +174 -0
- package/scripts/engines_builders_batch12.py +103 -0
- package/scripts/engines_builders_batch13.py +340 -0
- package/scripts/engines_builders_batch14.py +656 -0
- package/scripts/engines_builders_batch15.py +249 -0
- package/scripts/engines_builders_batch9.py +1468 -0
- package/scripts/engines_builders_cn.py +2283 -0
- package/scripts/engines_builders_data.py +2923 -0
- package/scripts/engines_builders_data_macro.py +775 -0
- package/scripts/engines_builders_feeds.py +255 -0
- package/scripts/engines_builders_intl.py +1239 -0
- package/scripts/engines_builders_keyless.py +111 -0
- package/scripts/engines_builders_search.py +440 -0
- package/scripts/engines_builders_tech.py +1359 -0
- package/scripts/evidence.py +620 -166
- package/scripts/evidence_loop.py +624 -0
- package/scripts/evidence_tier.py +298 -0
- package/scripts/except_sets.py +25 -0
- package/scripts/extract.py +55 -16
- package/scripts/fact_align.py +207 -0
- package/scripts/fact_crosscheck.py +230 -0
- package/scripts/fetch.py +25 -12
- package/scripts/fetch_browser.py +87 -0
- package/scripts/fetch_jsrun.py +122 -0
- package/scripts/fetch_quality.py +225 -0
- package/scripts/fetch_render_tinyfish.py +117 -0
- package/scripts/fetch_v3.py +1804 -0
- package/scripts/focus_extract.py +350 -0
- package/scripts/fulltext_store.py +169 -0
- package/scripts/fxtwitter_api.py +325 -0
- package/scripts/gen_engine_catalog.py +364 -0
- package/scripts/gen_native_tools.py +91 -0
- package/scripts/gen_routing_snapshot.py +195 -0
- package/scripts/health_check.py +140 -402
- package/scripts/health_probe.py +23 -8
- package/scripts/hot_state.py +134 -0
- package/scripts/http_client.py +1053 -0
- package/scripts/image_ops.py +430 -0
- package/scripts/image_vision/vision_probe.swift +126 -0
- package/scripts/install.ps1 +166 -0
- package/scripts/install.sh +221 -0
- package/scripts/job.py +1186 -0
- package/scripts/jump_resolver.py +235 -0
- package/scripts/lang_capability.py +150 -0
- package/scripts/lang_detect.py +289 -0
- package/scripts/lang_matrix_probe.py +329 -0
- package/scripts/lang_pref.py +311 -0
- package/scripts/link_source.py +340 -0
- package/scripts/local_image.py +970 -0
- package/scripts/local_seek.py +402 -0
- package/scripts/macro_countries.py +97 -0
- package/scripts/matrix_search_eval.py +1187 -0
- package/scripts/mcp_compact.py +234 -0
- package/scripts/mcp_diag.py +8 -3
- package/scripts/mcp_handlers.py +492 -0
- package/scripts/mcp_handlers_surface.py +157 -0
- package/scripts/mcp_launch.sh +124 -0
- package/scripts/mcp_local.py +241 -0
- package/scripts/mcp_server.py +125 -419
- package/scripts/mcp_setup.py +431 -0
- package/scripts/mcp_tools.py +331 -0
- package/scripts/mcp_transport.py +191 -0
- package/scripts/mcp_warm.py +127 -0
- package/scripts/min_version_scan.py +335 -0
- package/scripts/net_proxy.py +258 -0
- package/scripts/network_aware.py +152 -0
- package/scripts/output_transparency.py +200 -0
- package/scripts/paid_policy.py +98 -0
- package/scripts/paper.py +274 -0
- package/scripts/pdf_extract.py +518 -0
- package/scripts/phrase_filter.py +66 -0
- package/scripts/plan.py +422 -0
- package/scripts/postprocess_signals.py +150 -0
- package/scripts/pre-commit +48 -0
- package/scripts/query_enhance.py +157 -0
- package/scripts/query_operators.py +196 -0
- package/scripts/query_rewriter.py +116 -7
- package/scripts/query_signals.py +300 -0
- package/scripts/query_templates.py +167 -0
- package/scripts/query_understanding.py +411 -0
- package/scripts/query_variants.py +298 -0
- package/scripts/quota.py +633 -76
- package/scripts/rank_signals.py +775 -0
- package/scripts/ranking_eval.py +319 -0
- package/scripts/readability_extract.py +433 -0
- package/scripts/recompute.py +415 -0
- package/scripts/recovery.py +616 -0
- package/scripts/recovery_l0.py +160 -0
- package/scripts/recovery_runner.py +150 -0
- package/scripts/redskill/redskill_engine.py +332 -0
- package/scripts/regression_p0p1.py +318 -0
- package/scripts/replay_eval.py +658 -0
- package/scripts/rerank_tfidf.py +225 -0
- package/scripts/research.py +607 -403
- package/scripts/research_cli.py +361 -0
- package/scripts/research_dossier.py +492 -0
- package/scripts/research_expand.py +169 -0
- package/scripts/research_gates.py +272 -0
- package/scripts/research_report.py +209 -0
- package/scripts/research_strategy.py +37 -0
- package/scripts/research_work_packages.py +195 -0
- package/scripts/result_lang.py +311 -0
- package/scripts/retry_policy.py +76 -0
- package/scripts/robots_guard.py +259 -0
- package/scripts/route.py +921 -254
- package/scripts/route_bangs.py +40 -0
- package/scripts/route_cache.py +243 -0
- package/scripts/route_combo.py +917 -0
- package/scripts/route_domains.py +341 -0
- package/scripts/route_lang.py +605 -0
- package/scripts/route_log.py +63 -0
- package/scripts/route_policy.py +250 -0
- package/scripts/rrf_classic.py +66 -0
- package/scripts/screenshot.py +73 -0
- package/scripts/search.py +886 -406
- package/scripts/search_attribution.py +185 -0
- package/scripts/search_benchmark.py +407 -0
- package/scripts/search_cli.py +640 -0
- package/scripts/search_entry.py +395 -0
- package/scripts/search_output.py +690 -0
- package/scripts/search_pipeline.py +926 -0
- package/scripts/search_rank.py +991 -0
- package/scripts/search_types.py +129 -16
- package/scripts/seek_locator.py +68 -0
- package/scripts/semantic_evidence.py +391 -0
- package/scripts/serp_guard.py +336 -0
- package/scripts/serp_kill_log.py +74 -0
- package/scripts/single_flight.py +120 -0
- package/scripts/social_engines/__init__.py +10 -0
- package/scripts/social_engines/bilibili_engine.py +131 -0
- package/scripts/social_engines/hackernews_engine.py +113 -0
- package/scripts/social_engines/reddit_engine.py +172 -0
- package/scripts/social_engines/twitter_engine.py +397 -0
- package/scripts/social_engines/v2ex_engine.py +101 -0
- package/scripts/social_engines/weibo_engine.py +128 -0
- package/scripts/social_engines/xiaohongshu_engine.py +137 -0
- package/scripts/social_engines/zhihu_engine.py +139 -0
- package/scripts/social_research.py +201 -0
- package/scripts/sogou_weixin_browser.py +318 -0
- package/scripts/source_ledger.py +249 -0
- package/scripts/stage_timing.py +58 -0
- package/scripts/stats_cli.py +107 -0
- package/scripts/straggler_policy.py +60 -0
- package/scripts/stylometry_detector.py +231 -0
- package/scripts/sync_backends.py +353 -0
- package/scripts/sync_installs.py +29 -0
- package/scripts/template_cli.py +127 -0
- package/scripts/text_lexicon.py +72 -0
- package/scripts/tfidf_router.py +109 -37
- package/scripts/time_utils.py +233 -0
- package/scripts/topic_research_profiles.py +643 -0
- package/scripts/train.py +737 -0
- package/scripts/tweet.py +596 -0
- package/scripts/url_canon.py +217 -0
- package/scripts/url_optimize.py +56 -0
- package/scripts/url_safety.py +236 -0
- package/scripts/usage_log.py +116 -0
- package/scripts/usage_log_clean.py +113 -0
- package/scripts/v2ex_nodes.py +311 -0
- package/scripts/variant_recall.py +188 -0
- package/scripts/watch.py +205 -0
- package/scripts/wechat_article.py +258 -0
- package/scripts/wide_research.py +447 -0
- package/scripts/wx.py +349 -0
- package/scripts/x_article_fetch.py +141 -0
- package/scripts/x_search.py +234 -0
- package/scripts/x_trending.py +189 -0
- package/scripts/yaml_load.py +67 -0
- package/scripts/zhihu_quota.py +139 -0
- package/sub-skills/ego-search/SKILL.md +253 -0
- package/sub-skills/ego-search/scripts/ego_search.py +800 -0
- package/sub-skills/ego-search/scripts/merge.py +226 -0
- package/sub-skills/ego-search/scripts/quality.py +64 -0
- package/sub-skills/ego-search/scripts/runtime.py +172 -0
- package/sub-skills/ego-search/scripts/safety.py +109 -0
- package/sub-skills/ego-search/scripts/serp_spec.py +109 -0
- package/sub-skills/ego-search/scripts/webbridge_adapter.py +374 -0
- package/sub-skills/js-run/SKILL.md +67 -0
- package/sub-skills/js-run/scripts/jsrun.py +112 -0
- package/sub-skills/js-run/scripts/shim.js +188 -0
- package/sub-skills/local-search/SKILL.md +50 -53
- package/sub-skills/local-search/bm25.py +186 -0
- package/sub-skills/local-search/cli_runner.py +331 -0
- package/sub-skills/local-search/config.yaml +152 -55
- package/sub-skills/local-search/engine_registry.py +91 -26
- package/sub-skills/local-search/{health_check.py → local_health_check.py} +140 -10
- package/sub-skills/local-search/local_search_adapter.py +13 -2
- package/sub-skills/local-search/parse_maps.yaml +40 -42
- package/sub-skills/local-search/parsers.py +328 -0
- package/sub-skills/local-search/search_v3.py +716 -242
- package/sub-skills/local-search/smart_router.py +47 -7
- package/sub-skills/local-seek/SKILL.md +110 -0
- package/sub-skills/local-seek/config/domains.yaml +20 -0
- package/sub-skills/local-seek/scripts/eval_rank.py +216 -0
- package/sub-skills/local-seek/scripts/eval_seek.py +224 -0
- package/sub-skills/local-seek/scripts/seek.py +1465 -0
- package/sub-skills/local-seek/scripts/seek_frecency.py +126 -0
- package/sub-skills/local-seek/scripts/seek_fts.py +430 -0
- package/sub-skills/local-seek/scripts/seek_rank.py +197 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""engine_status.py — 引擎状态聚合(list-engines --detail)
|
|
3
|
+
|
|
4
|
+
输出每引擎:
|
|
5
|
+
enabled / type / cost_tier / env_ready / missing_env /
|
|
6
|
+
allowed_by_env / blocked / admitted / routable / health summary
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Any, Iterable
|
|
14
|
+
|
|
15
|
+
SCRIPT_DIR = Path(__file__).resolve().parent
|
|
16
|
+
if str(SCRIPT_DIR) not in sys.path:
|
|
17
|
+
sys.path.insert(0, str(SCRIPT_DIR))
|
|
18
|
+
|
|
19
|
+
from config import load_config, get_cost_tiers # noqa: E402
|
|
20
|
+
from engine_env import env_status_for, is_engine_allowed_by_env # noqa: E402
|
|
21
|
+
from engine_requires import requires_status # noqa: E402
|
|
22
|
+
from engine_admission import load_admission, is_blocked, is_admitted # noqa: E402
|
|
23
|
+
from cli_io import dumps
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _cost_tier_of(engine_id: str, tiers: dict[str, list[str]]) -> str:
|
|
27
|
+
for tier in ("paid", "api", "low", "free"):
|
|
28
|
+
if engine_id in (tiers.get(tier) or []):
|
|
29
|
+
return tier
|
|
30
|
+
return "free"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _all_engine_specs(cfg: dict[str, Any] | None = None) -> dict[str, dict[str, Any]]:
|
|
34
|
+
cfg = cfg if cfg is not None else load_config()
|
|
35
|
+
engines = cfg.get("engines") or {}
|
|
36
|
+
return {k: v for k, v in engines.items() if isinstance(v, dict)}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _adaptive_scores_snapshot() -> dict[str, float]:
|
|
40
|
+
"""一次取全部引擎学习分(get_ranking 单查询),避免 120+ 引擎逐个开 sqlite。"""
|
|
41
|
+
try:
|
|
42
|
+
from adaptive import get_learner
|
|
43
|
+
return dict(get_learner().get_ranking())
|
|
44
|
+
except Exception:
|
|
45
|
+
return {}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _runtime_status(engine_id: str,
|
|
49
|
+
adaptive_scores: dict[str, float] | None = None,
|
|
50
|
+
spec: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
51
|
+
"""运行时状态聚合(统一健康度视图):熔断 + 学习分。
|
|
52
|
+
|
|
53
|
+
被动读取、无网络副作用:breaker 状态读进程内存(构造时已 load 磁盘态);
|
|
54
|
+
adaptive 分数用调用方传入的全表快照,缺失时按中性分 0.5。
|
|
55
|
+
与主动探针(health_check.check_engine)互补:本函数是「当前可用性」快照,
|
|
56
|
+
探针是「立即连通性」验证,二者计算方式不同、各自保留。
|
|
57
|
+
"""
|
|
58
|
+
out: dict[str, Any] = {"breaker": None, "adaptive_score": None,
|
|
59
|
+
"failure": None}
|
|
60
|
+
try:
|
|
61
|
+
from circuit_breaker import get_breaker
|
|
62
|
+
st = get_breaker().status(engine_id)
|
|
63
|
+
out["breaker"] = {
|
|
64
|
+
"state": st.get("state", "closed"),
|
|
65
|
+
"failures": st.get("failures", 0),
|
|
66
|
+
"cooldown_remain": st.get("cooldown_remain", 0),
|
|
67
|
+
"last_kind": st.get("last_kind"),
|
|
68
|
+
}
|
|
69
|
+
# 失败归因:熔断只回答「要不要继续用」,这里补「为什么坏」。
|
|
70
|
+
# 仅在确有失败记录时输出,避免给健康引擎塞噪音字段。
|
|
71
|
+
# 优先用失败现场记录的归因(真实 category/evidence);旧数据没有该字段
|
|
72
|
+
# 时才回落按 kind 文本归类(信息量有限,可能落 unknown)。
|
|
73
|
+
if st.get("last_kind") and int(st.get("failures") or 0) > 0:
|
|
74
|
+
persisted = st.get("last_attribution")
|
|
75
|
+
if isinstance(persisted, dict) and persisted.get("category"):
|
|
76
|
+
out["failure"] = persisted
|
|
77
|
+
else:
|
|
78
|
+
from engine_failure import explain as _explain_failure
|
|
79
|
+
out["failure"] = _explain_failure(
|
|
80
|
+
engine_id, spec=spec, output=str(st.get("last_kind") or ""),
|
|
81
|
+
)
|
|
82
|
+
except Exception:
|
|
83
|
+
pass
|
|
84
|
+
if adaptive_scores is not None:
|
|
85
|
+
out["adaptive_score"] = adaptive_scores.get(engine_id, 0.5)
|
|
86
|
+
elif adaptive_scores is None:
|
|
87
|
+
# 单引擎查询:只查一次 sqlite(批量场景必须传快照避免 N 次连接)
|
|
88
|
+
try:
|
|
89
|
+
from adaptive import get_learner
|
|
90
|
+
out["adaptive_score"] = get_learner().get_score(engine_id)
|
|
91
|
+
except Exception:
|
|
92
|
+
pass
|
|
93
|
+
return out
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _quota_exhausted_marks() -> dict[str, dict[str, Any]]:
|
|
97
|
+
"""一次取全部「远端配额耗尽」标记,避免逐引擎查询。失败返回空。"""
|
|
98
|
+
try:
|
|
99
|
+
from quota import get_quota_manager
|
|
100
|
+
return get_quota_manager().remote_exhausted_marks()
|
|
101
|
+
except Exception:
|
|
102
|
+
return {}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def engine_detail(engine_id: str, spec: dict[str, Any] | None = None,
|
|
106
|
+
tiers: dict[str, list[str]] | None = None,
|
|
107
|
+
adaptive_scores: dict[str, float] | None = None,
|
|
108
|
+
quota_marks: dict[str, dict[str, Any]] | None = None) -> dict[str, Any]:
|
|
109
|
+
if spec is None:
|
|
110
|
+
specs = _all_engine_specs()
|
|
111
|
+
spec = specs.get(engine_id) or {}
|
|
112
|
+
tiers = tiers if tiers is not None else get_cost_tiers()
|
|
113
|
+
env = env_status_for(engine_id, spec)
|
|
114
|
+
deps = requires_status(spec)
|
|
115
|
+
adm = load_admission(engine_id)
|
|
116
|
+
blocked = is_blocked(engine_id)
|
|
117
|
+
admitted = is_admitted(engine_id)
|
|
118
|
+
config_enabled = bool(spec.get("enabled", True))
|
|
119
|
+
allowed = env["allowed_by_env"]
|
|
120
|
+
env_ok = env["env_ready"]
|
|
121
|
+
dep_ok = deps["dep_ready"]
|
|
122
|
+
# 远端配额耗尽(如博查 AI Search 403 套餐额度不足):这是源端的「现在别打」,
|
|
123
|
+
# 与密钥/依赖无关,也不是引擎故障。此前这类引擎一律显示 ready、
|
|
124
|
+
# routable=True,直到 lookup 才发现打不动——配额状态机已记下它,这里读出来。
|
|
125
|
+
if quota_marks is None:
|
|
126
|
+
quota_marks = _quota_exhausted_marks()
|
|
127
|
+
quota_mark = quota_marks.get(engine_id)
|
|
128
|
+
quota_exhausted = bool(quota_mark)
|
|
129
|
+
# 自动路由可用条件(含后端依赖:缺 xhs/yt-dlp 这类工具时不该进路由)
|
|
130
|
+
# explicit_only 排除在外:声明即「不进自动路由,只等显式 --engine」
|
|
131
|
+
# (--routable-only 的帮助文案与 available_engines 同一口径)。此前漏判,
|
|
132
|
+
# 旧显式源恰好被 env/dep 门挡住没暴露;toutiao(免 key 免依赖)把它炸出。
|
|
133
|
+
routable = (
|
|
134
|
+
config_enabled
|
|
135
|
+
and allowed
|
|
136
|
+
and env_ok
|
|
137
|
+
and dep_ok
|
|
138
|
+
and not blocked
|
|
139
|
+
and not quota_exhausted
|
|
140
|
+
and not bool(spec.get("explicit_only"))
|
|
141
|
+
)
|
|
142
|
+
status = "ready"
|
|
143
|
+
if not config_enabled:
|
|
144
|
+
status = "disabled"
|
|
145
|
+
elif not allowed:
|
|
146
|
+
status = "env_filtered"
|
|
147
|
+
elif not env_ok:
|
|
148
|
+
status = "missing_key"
|
|
149
|
+
elif not dep_ok:
|
|
150
|
+
# 后端工具缺失:密钥齐全、脚本存在,但真正干活的外部命令没有。
|
|
151
|
+
# 此前这类引擎一律显示 ready,调用后静默返回空,无从定位。
|
|
152
|
+
status = "missing_dep"
|
|
153
|
+
elif quota_exhausted:
|
|
154
|
+
status = "quota_exhausted"
|
|
155
|
+
elif blocked:
|
|
156
|
+
status = "blocked"
|
|
157
|
+
elif admitted:
|
|
158
|
+
status = "admitted"
|
|
159
|
+
else:
|
|
160
|
+
status = "ready" # 未验证但可用(兼容)
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
"engine_id": engine_id,
|
|
164
|
+
"enabled": config_enabled,
|
|
165
|
+
"type": spec.get("type", "cli"),
|
|
166
|
+
"cost_tier": _cost_tier_of(engine_id, tiers),
|
|
167
|
+
"status": status,
|
|
168
|
+
# 设计上不进自动路由(需密钥的付费源 / 输入形态特殊),按 --engine 显式调用;
|
|
169
|
+
# 可达性检查据此区分「有意显式」与「忘了接线」。
|
|
170
|
+
"explicit_only": bool(spec.get("explicit_only")),
|
|
171
|
+
"env_ready": env_ok,
|
|
172
|
+
"required_env": env["required_env"],
|
|
173
|
+
"missing_env": env["missing_env"],
|
|
174
|
+
"allowed_by_env": allowed,
|
|
175
|
+
"blocked": blocked,
|
|
176
|
+
"admitted": admitted,
|
|
177
|
+
"routable": routable,
|
|
178
|
+
# 远端配额耗尽(源端明示)。配额问题既不是引擎健康问题、也不是密钥问题,
|
|
179
|
+
# 单列出来,到周期边界惰性自愈。
|
|
180
|
+
"quota_exhausted": quota_exhausted,
|
|
181
|
+
"quota_exhausted_until": (quota_mark or {}).get("until"),
|
|
182
|
+
"quota_exhausted_reason": (quota_mark or {}).get("reason") or "",
|
|
183
|
+
# 后端依赖(requires 声明):缺什么、怎么装。与 missing_env(密钥)互不相干。
|
|
184
|
+
"dep_ready": dep_ok,
|
|
185
|
+
"requires": deps["requires"],
|
|
186
|
+
"missing_deps": deps["missing_deps"],
|
|
187
|
+
"dep_fixes": deps["dep_fixes"],
|
|
188
|
+
"admission": {
|
|
189
|
+
"admitted_at": (adm or {}).get("admitted_at"),
|
|
190
|
+
"stages_passed": (adm or {}).get("stages_passed") or [],
|
|
191
|
+
"quality_score": (adm or {}).get("quality_score"),
|
|
192
|
+
"avg_latency_ms": (adm or {}).get("avg_latency_ms"),
|
|
193
|
+
"reason": (adm or {}).get("reason") or "",
|
|
194
|
+
} if adm else None,
|
|
195
|
+
# 统一健康度视图:熔断状态 + 学习分(被动快照,见 _runtime_status)
|
|
196
|
+
"runtime": _runtime_status(engine_id, adaptive_scores, spec),
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def compact_engine_row(row: dict[str, Any]) -> dict[str, Any]:
|
|
201
|
+
"""全量清单的瘦身投影:剥掉嵌套转储(runtime/admission),留判定面。
|
|
202
|
+
|
|
203
|
+
为什么要压缩:--list-engines --detail 不带过滤是 232 行 × 全字段的
|
|
204
|
+
诊断转储,实测 151 KB(runtime 24% + admission 7% 是大头)——Agent
|
|
205
|
+
一旦把它拉进上下文就是 ~50k token。而全量清单要回答的通常只有
|
|
206
|
+
「哪些源可用/为什么不可用」,判定只需要标量旗标 + 条件性细节:
|
|
207
|
+
failure/配额原因/缺 env 缺依赖在**非空时**才出现,健康源一行 ~150B。
|
|
208
|
+
要单引擎的全量诊断(含 admission 里程碑、runtime 学习分),用
|
|
209
|
+
`--engine <名>` 过滤后拿完整行——按需付全量的代价。
|
|
210
|
+
|
|
211
|
+
降级契约:本函数只做「删键」,不改任何值;未来新增顶层字段默认
|
|
212
|
+
不进瘦身面(显式登记才带),宁可瘦也不要悄悄膨胀。
|
|
213
|
+
"""
|
|
214
|
+
slim: dict[str, Any] = {
|
|
215
|
+
"engine_id": row.get("engine_id"),
|
|
216
|
+
"enabled": row.get("enabled"),
|
|
217
|
+
"type": row.get("type"),
|
|
218
|
+
"cost_tier": row.get("cost_tier"),
|
|
219
|
+
"status": row.get("status"),
|
|
220
|
+
"explicit_only": row.get("explicit_only"),
|
|
221
|
+
"env_ready": row.get("env_ready"),
|
|
222
|
+
"routable": row.get("routable"),
|
|
223
|
+
"quota_exhausted": row.get("quota_exhausted"),
|
|
224
|
+
"dep_ready": row.get("dep_ready"),
|
|
225
|
+
}
|
|
226
|
+
# 条件性细节:非空才出现(健康源不带这些键,输出不随异常源膨胀)
|
|
227
|
+
for key in ("missing_env", "missing_deps"):
|
|
228
|
+
if row.get(key):
|
|
229
|
+
slim[key] = row[key]
|
|
230
|
+
if row.get("quota_exhausted") and row.get("quota_exhausted_reason"):
|
|
231
|
+
slim["quota_exhausted_reason"] = row["quota_exhausted_reason"]
|
|
232
|
+
failure = (row.get("runtime") or {}).get("failure") or {}
|
|
233
|
+
if failure:
|
|
234
|
+
slim["failure"] = {"category": failure.get("category"),
|
|
235
|
+
"evidence": failure.get("evidence")}
|
|
236
|
+
return slim
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def list_engines_detail(
|
|
240
|
+
*,
|
|
241
|
+
routable_only: bool = False,
|
|
242
|
+
include_disabled: bool = True,
|
|
243
|
+
engines: Iterable[str] | None = None,
|
|
244
|
+
) -> list[dict[str, Any]]:
|
|
245
|
+
"""引擎详细状态行。
|
|
246
|
+
|
|
247
|
+
engines:只保留这些 engine_id(None = 全量)。单引擎的详细行约 0.9 KB;
|
|
248
|
+
全量诊断转储 2026-09-16 实测 151 KB(runtime 24% + admission 7% 是大头,
|
|
249
|
+
此前误记 22 KB)——CLI 在不带 `--engine` 过滤时改出 compact_engine_row
|
|
250
|
+
瘦身投影(约 1/4 体积),要全量就按引擎过滤,别把转储拉进上下文。
|
|
251
|
+
"""
|
|
252
|
+
wanted = set(engines) if engines else None
|
|
253
|
+
cfg = load_config()
|
|
254
|
+
tiers = get_cost_tiers(cfg)
|
|
255
|
+
specs = _all_engine_specs(cfg)
|
|
256
|
+
adaptive_scores = _adaptive_scores_snapshot()
|
|
257
|
+
quota_marks = _quota_exhausted_marks()
|
|
258
|
+
rows = []
|
|
259
|
+
for name in sorted(specs.keys()):
|
|
260
|
+
if wanted is not None and name not in wanted:
|
|
261
|
+
continue
|
|
262
|
+
row = engine_detail(name, specs[name], tiers, adaptive_scores, quota_marks)
|
|
263
|
+
if not include_disabled and not row["enabled"]:
|
|
264
|
+
continue
|
|
265
|
+
if routable_only and not row["routable"]:
|
|
266
|
+
continue
|
|
267
|
+
rows.append(row)
|
|
268
|
+
return rows
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def list_routable_engine_ids() -> list[str]:
|
|
272
|
+
return [r["engine_id"] for r in list_engines_detail(routable_only=True, include_disabled=False)]
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def format_engines_table(rows: list[dict[str, Any]]) -> str:
|
|
276
|
+
lines = [
|
|
277
|
+
f"{'ENGINE':<22} {'STATUS':<14} {'TIER':<6} {'TYPE':<14} {'ROUTABLE':<8} {'ENV':<28} FAILURE",
|
|
278
|
+
"-" * 120,
|
|
279
|
+
]
|
|
280
|
+
for r in rows:
|
|
281
|
+
env_note = "ok" if r["env_ready"] else ",".join(r["missing_env"][:2]) or "missing"
|
|
282
|
+
# 失败归因:熔断只回答「要不要继续用」,这一列补「为什么坏」。
|
|
283
|
+
# 归因来自引擎内失败现场记录的寄存器(engines_base.http_open /
|
|
284
|
+
# _http_get_raw → note_failure → 熔断持久化),此前只出现在 --json 里。
|
|
285
|
+
failure = r.get("runtime", {}).get("failure") or {}
|
|
286
|
+
fail_note = ""
|
|
287
|
+
# 配额耗尽优先:它是由配额状态机确认过的「源端明示额度不足」,比熔断里
|
|
288
|
+
# 可能陈旧的归因(旧版落的 unknown/empty)更可信,也更可行动。
|
|
289
|
+
if r.get("quota_exhausted"):
|
|
290
|
+
reason = (r.get("quota_exhausted_reason") or "").replace("\n", " ")
|
|
291
|
+
fail_note = f"quota_exhausted: {reason[:40]}".strip(": ")
|
|
292
|
+
elif failure:
|
|
293
|
+
cat = failure.get("category") or ""
|
|
294
|
+
ev = (failure.get("evidence") or "").replace("\n", " ")[:40]
|
|
295
|
+
fail_note = f"{cat}: {ev}".strip(": ")
|
|
296
|
+
lines.append(
|
|
297
|
+
f"{r['engine_id']:<22} {r['status']:<14} {r['cost_tier']:<6} "
|
|
298
|
+
f"{str(r['type']):<14} {str(r['routable']):<8} {env_note:<28} {fail_note}"
|
|
299
|
+
)
|
|
300
|
+
lines.append(f"\n总计 {len(rows)} · routable={sum(1 for r in rows if r['routable'])}")
|
|
301
|
+
return "\n".join(lines)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def _cli() -> None:
|
|
305
|
+
import argparse
|
|
306
|
+
parser = argparse.ArgumentParser(description="Argo 引擎状态")
|
|
307
|
+
parser.add_argument("--json", action="store_true")
|
|
308
|
+
parser.add_argument("--routable-only", action="store_true")
|
|
309
|
+
parser.add_argument("--engine", help="只看单个引擎")
|
|
310
|
+
args = parser.parse_args()
|
|
311
|
+
if args.engine:
|
|
312
|
+
rows = [engine_detail(args.engine)]
|
|
313
|
+
else:
|
|
314
|
+
rows = list_engines_detail(routable_only=args.routable_only)
|
|
315
|
+
if args.json:
|
|
316
|
+
print(dumps(rows if len(rows) != 1 else rows[0]))
|
|
317
|
+
else:
|
|
318
|
+
print(format_engines_table(rows))
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
if __name__ == "__main__":
|
|
322
|
+
_cli()
|