argo-search 1.0.1 → 2.9.7
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 +822 -0
- package/README.es.md +864 -0
- package/README.ja.md +864 -0
- package/README.ko.md +864 -0
- package/README.md +867 -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/settings-keys.png +0 -0
- package/assets/readme/settings-tools.png +0 -0
- package/assets/readme/why-better.svg +104 -0
- package/assets/readme/workflow.svg +83 -0
- package/backends/domain_profiles.json +2308 -96
- package/backends/engine_registry.yaml +3314 -503
- package/backends/query_synonyms_cn.json +35 -0
- package/backends/quota_profiles.json +2409 -161
- package/backends/source_types_cn.json +83 -0
- package/backends/text_lexicon.json +44 -0
- package/bin/argo +703 -0
- package/bin/argo.js +71 -39
- package/config.yaml +4976 -363
- 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 +564 -0
- package/docs/MCP_SETUP.md +106 -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/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/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/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 +31 -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/google_news.yaml +22 -0
- package/engines/specs/gov_regulations.yaml +38 -0
- package/engines/specs/guardian_rss.yaml +59 -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/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/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/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/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 +74 -0
- package/package.json +51 -12
- package/packages/dsh-plugin/README.md +134 -0
- package/packages/dsh-plugin/cordis.patch.yml +48 -0
- package/packages/dsh-plugin/dsh/client.js +1244 -0
- package/packages/dsh-plugin/dsh/index.js +2290 -0
- package/packages/dsh-plugin/dsh/native-tools.mjs +743 -0
- package/packages/dsh-plugin/package.json +38 -0
- package/packages/dsh-plugin/test/client.test.js +232 -0
- package/packages/dsh-plugin/test/config.test.js +30 -0
- package/packages/dsh-plugin/test/index.test.js +1338 -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 +271 -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/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/burstiness_detector.py +147 -0
- package/scripts/cache.py +1078 -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/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_security.py +685 -0
- package/scripts/content_signals.py +730 -0
- package/scripts/crawl.py +74 -35
- package/scripts/daemon.py +866 -0
- package/scripts/digup_bridge.py +214 -0
- package/scripts/engine_admission.py +366 -0
- package/scripts/engine_dispatch.py +1019 -0
- package/scripts/engine_env.py +534 -0
- package/scripts/engine_failure.py +411 -0
- package/scripts/engine_families.py +732 -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 +778 -294
- package/scripts/engines_base.py +1521 -0
- package/scripts/engines_builders.py +298 -0
- package/scripts/engines_builders_batch10.py +159 -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_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_search.py +440 -0
- package/scripts/engines_builders_tech.py +1360 -0
- package/scripts/evidence.py +588 -162
- package/scripts/evidence_loop.py +592 -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 +1779 -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 +184 -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 +0 -0
- package/scripts/image_vision/vision_probe.swift +126 -0
- package/scripts/install.ps1 +148 -0
- package/scripts/install.sh +206 -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_engines.py +321 -0
- package/scripts/local_image.py +970 -0
- package/scripts/local_seek.py +366 -0
- package/scripts/macro_countries.py +82 -0
- package/scripts/matrix_search_eval.py +1105 -0
- package/scripts/mcp_diag.py +8 -3
- package/scripts/mcp_handlers.py +1074 -0
- package/scripts/mcp_handlers_surface.py +157 -0
- package/scripts/mcp_launch.sh +122 -0
- package/scripts/mcp_server.py +118 -417
- package/scripts/mcp_setup.py +407 -0
- package/scripts/mcp_tools.py +330 -0
- package/scripts/mcp_transport.py +191 -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/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 +488 -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/redskill/redskill_engine.py +332 -0
- package/scripts/regression_p0p1.py +318 -0
- package/scripts/replay_eval.py +640 -0
- package/scripts/rerank_tfidf.py +225 -0
- package/scripts/research.py +591 -403
- package/scripts/research_cli.py +361 -0
- package/scripts/research_dossier.py +492 -0
- package/scripts/research_expand.py +146 -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/robots_guard.py +259 -0
- package/scripts/route.py +921 -254
- package/scripts/route_bangs.py +40 -0
- package/scripts/route_cache.py +225 -0
- package/scripts/route_combo.py +910 -0
- package/scripts/route_domains.py +328 -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 +897 -405
- package/scripts/search_attribution.py +88 -0
- package/scripts/search_benchmark.py +407 -0
- package/scripts/search_cli.py +627 -0
- package/scripts/search_entry.py +389 -0
- package/scripts/search_output.py +606 -0
- package/scripts/search_pipeline.py +1077 -0
- package/scripts/search_rank.py +991 -0
- package/scripts/search_types.py +27 -12
- package/scripts/seek_locator.py +68 -0
- package/scripts/semantic_evidence.py +215 -0
- package/scripts/serp_guard.py +228 -0
- package/scripts/serp_kill_log.py +51 -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 +95 -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 +402 -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/sub-skills/ego-search/SKILL.md +253 -0
- package/sub-skills/ego-search/references/browser-runtime.md +43 -0
- package/sub-skills/ego-search/references/install.md +67 -0
- package/sub-skills/ego-search/references/original-ego-upgrade.md +51 -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/ego-search/tests/test_query_normalize.py +68 -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/js-run/tests/fixtures/challenge_like.js +27 -0
- package/sub-skills/js-run/tests/test_jsrun.py +165 -0
- package/sub-skills/local-search/SKILL.md +50 -53
- package/sub-skills/local-search/bm25.py +162 -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/search_v3.py +1182 -65
- 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/references/auto-behaviors.md +24 -0
- package/sub-skills/local-seek/references/fd-mdfind-recipes.md +62 -0
- package/sub-skills/local-seek/references/git-integration.md +54 -0
- package/sub-skills/local-seek/references/remote-handoff.md +46 -0
- package/sub-skills/local-seek/references/rg-recipes.md +96 -0
- package/sub-skills/local-seek/references/strategies.md +52 -0
- package/sub-skills/local-seek/references/structural-search.md +59 -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 +193 -0
- package/sub-skills/local-seek/tests/test_content_rank.py +222 -0
- package/sub-skills/local-seek/tests/test_determinism_20261006.py +145 -0
- package/sub-skills/local-seek/tests/test_noise_tier.py +101 -0
- package/sub-skills/local-seek/tests/test_pcre2_probe.py +136 -0
- package/sub-skills/local-seek/tests/test_rank_pinyin.py +77 -0
- package/sub-skills/local-seek/tests/test_regression_20261003.py +169 -0
- package/sub-skills/local-seek/tests/test_regression_20261006.py +146 -0
- package/sub-skills/local-seek/tests/test_seek_degradation.py +111 -0
- package/sub-skills/local-seek/tests/test_seek_fts.py +313 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""mcp_handlers_surface — 2026-09-26 补齐 CLI 面的五工具 handler。
|
|
2
|
+
|
|
3
|
+
extract/preflight/answer/watch/cite 的执行体独立成模块:mcp_handlers.py
|
|
4
|
+
涨破 1000 行硬上限(门禁),按 route_* 先例拆分。handle_surface_tool
|
|
5
|
+
返回 None 表示非本模块工具,调用方继续走未知工具分支。
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from mcp_handlers import (
|
|
13
|
+
_cap_extract_output,
|
|
14
|
+
_clamp_int,
|
|
15
|
+
_dumps,
|
|
16
|
+
_err_is,
|
|
17
|
+
_lazy_cached,
|
|
18
|
+
_ok,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# 本模块五工具的必填参数,**从 mcp_tools 的 schema 真读**而不是另抄一份。
|
|
22
|
+
# 抄一份的后果实测过:拆分本模块时五个新工具全都没进 mcp_handlers 的
|
|
23
|
+
# _required 表,于是 execute_tool("argo_answer", {}) 走到 arguments["query"]
|
|
24
|
+
# 抛 KeyError,被兜底的 except Exception 变成 -32000 KeyError: 'query'——
|
|
25
|
+
# 而不是契约要求的 -32602 Missing required parameter(s)。schema 里
|
|
26
|
+
# "required" 本来就写对了,只是没人去读;读它还顺带让 schema 与执行层
|
|
27
|
+
# 不可能再漂移(新增参数只改 schema 一处)。
|
|
28
|
+
def _required_params(name: str) -> tuple[str, ...]:
|
|
29
|
+
"""该工具的必填参数名;读不到 schema 时保守返回空(不误拒合法调用)。"""
|
|
30
|
+
try:
|
|
31
|
+
from mcp_tools import TOOLS as _TOOLS
|
|
32
|
+
except Exception:
|
|
33
|
+
return ()
|
|
34
|
+
for entry in _TOOLS or ():
|
|
35
|
+
if isinstance(entry, dict) and entry.get("name") == name:
|
|
36
|
+
req = (entry.get("inputSchema") or {}).get("required")
|
|
37
|
+
return tuple(req) if isinstance(req, list) else ()
|
|
38
|
+
return ()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _check_required(name: str, arguments: dict[str, Any]) -> list[str]:
|
|
42
|
+
"""返回缺失的必填参数名;空 list = 通过。"""
|
|
43
|
+
return [p for p in _required_params(name) if not arguments.get(p)]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# 本模块承接的工具名。放在这里而不是靠 if 链自然落空:新增一个工具时
|
|
47
|
+
# 「忘了加进这个集合」会立刻表现为返回 None(被调用方当成未知工具),
|
|
48
|
+
# 比静默走进某个分支更容易发现。
|
|
49
|
+
_SURFACE_TOOLS = frozenset({
|
|
50
|
+
"argo_extract", "argo_preflight", "argo_answer", "argo_watch", "argo_cite",
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def handle_surface_tool(name: str, arguments: dict[str, Any],
|
|
55
|
+
pretty: bool = False) -> dict[str, Any] | None:
|
|
56
|
+
"""五工具(extract/preflight/answer/watch/cite)分发;None=非本模块工具。"""
|
|
57
|
+
if name not in _SURFACE_TOOLS:
|
|
58
|
+
return None
|
|
59
|
+
# 必填校验放在分发之后、任何 arguments[...] 取值之前:缺参数要报
|
|
60
|
+
# -32602(契约规定的「Invalid params」),而不是让 arguments["query"]
|
|
61
|
+
# 抛 KeyError 后被兜底 except 变成 -32000 —— 后者对调用方毫无信息量,
|
|
62
|
+
# 也不知道该补哪个参数。
|
|
63
|
+
_missing = _check_required(name, arguments)
|
|
64
|
+
if _missing:
|
|
65
|
+
return {
|
|
66
|
+
"content": [{"type": "text", "text": _dumps({
|
|
67
|
+
"error": {
|
|
68
|
+
"code": -32602,
|
|
69
|
+
"message": "Missing required parameter(s): "
|
|
70
|
+
+ ", ".join(_missing),
|
|
71
|
+
},
|
|
72
|
+
})}],
|
|
73
|
+
"isError": True,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if name == "argo_extract":
|
|
77
|
+
extract_mod = _lazy_cached("extract")
|
|
78
|
+
max_chars = _clamp_int(arguments.get("max_chars", 50000), 50000, 1000, 200000)
|
|
79
|
+
fetched = extract_mod._extract_fetch(arguments["url"], max_chars, 15)
|
|
80
|
+
if not fetched.get("success"):
|
|
81
|
+
return {"content": [{"type": "text", "text": _dumps(
|
|
82
|
+
{"error": fetched.get("error") or "抓取失败"})}], "isError": True}
|
|
83
|
+
html = fetched.get("html") or fetched.get("content") or ""
|
|
84
|
+
mode = arguments.get("mode", "all")
|
|
85
|
+
out = {}
|
|
86
|
+
if mode in ("tables", "all"):
|
|
87
|
+
out["tables"] = extract_mod.extract_tables(html)
|
|
88
|
+
if mode in ("metadata", "all"):
|
|
89
|
+
out["metadata"] = extract_mod.extract_metadata(html)
|
|
90
|
+
if mode in ("jsonld", "all"):
|
|
91
|
+
out["jsonld"] = extract_mod.extract_jsonld(html)
|
|
92
|
+
# 输出上限不是可选优化:表格数/单元格、metadata 值、jsonld 体积各自
|
|
93
|
+
# 设限并在超限时打 *_truncated 标记。拆分本模块时这行曾被漏掉,
|
|
94
|
+
# 于是 _cap_extract_output 成了孤儿函数、argo_extract 变成唯一一条
|
|
95
|
+
# 没有上限的正文抽取路径——恰好是它最需要的那个(表格多的页面)。
|
|
96
|
+
return _ok(_cap_extract_output(out), pretty=pretty)
|
|
97
|
+
|
|
98
|
+
if name == "argo_preflight":
|
|
99
|
+
probe_mod = _lazy_cached("batch_probe")
|
|
100
|
+
urls = [str(u).strip() for u in arguments.get("urls") or [] if str(u).strip()]
|
|
101
|
+
if not urls:
|
|
102
|
+
return {"content": [{"type": "text", "text": _dumps(
|
|
103
|
+
{"error": "urls 为空"})}], "isError": True}
|
|
104
|
+
report = probe_mod.probe_batch(urls, do_probe=bool(arguments.get("probe", False)))
|
|
105
|
+
return _ok(report, pretty=pretty)
|
|
106
|
+
|
|
107
|
+
if name == "argo_answer":
|
|
108
|
+
answer_mod = _lazy_cached("answer")
|
|
109
|
+
resp, err = answer_mod.seltz_answer(
|
|
110
|
+
arguments["query"], timeout=40.0,
|
|
111
|
+
scope=arguments.get("scope") or None,
|
|
112
|
+
model=arguments.get("model") or None)
|
|
113
|
+
if err or resp is None:
|
|
114
|
+
return {"content": [{"type": "text", "text": _dumps(
|
|
115
|
+
{"error": err or "直答无响应"})}], "isError": True}
|
|
116
|
+
return _ok(resp, pretty=pretty)
|
|
117
|
+
|
|
118
|
+
if name == "argo_watch":
|
|
119
|
+
watch_mod = _lazy_cached("watch")
|
|
120
|
+
action = arguments.get("action", "")
|
|
121
|
+
url = arguments.get("url") or ""
|
|
122
|
+
if action == "add":
|
|
123
|
+
if not url:
|
|
124
|
+
return _err_is("add 需要 url")
|
|
125
|
+
return _ok(watch_mod.cmd_add(url, arguments.get("note", "")), pretty=pretty)
|
|
126
|
+
if action == "check":
|
|
127
|
+
return _ok(watch_mod.cmd_check(url or None), pretty=pretty)
|
|
128
|
+
if action == "list":
|
|
129
|
+
return _ok(watch_mod.cmd_list(), pretty=pretty)
|
|
130
|
+
if action == "remove":
|
|
131
|
+
if not url:
|
|
132
|
+
return _err_is("remove 需要 url")
|
|
133
|
+
removed = watch_mod.cmd_remove(url)
|
|
134
|
+
return _ok({"removed": bool(removed), "url": url}, pretty=pretty)
|
|
135
|
+
return _err_is(f"未知 action: {action}")
|
|
136
|
+
|
|
137
|
+
if name == "argo_cite":
|
|
138
|
+
cite_mod = _lazy_cached("citations")
|
|
139
|
+
style = arguments.get("style", "gbt7714")
|
|
140
|
+
dois = [str(d).strip() for d in arguments.get("dois") or [] if str(d).strip()]
|
|
141
|
+
if not dois:
|
|
142
|
+
return {"content": [{"type": "text", "text": _dumps(
|
|
143
|
+
{"error": "dois 为空"})}], "isError": True}
|
|
144
|
+
citations_out = []
|
|
145
|
+
used_keys: set = set()
|
|
146
|
+
for doi in dois:
|
|
147
|
+
try:
|
|
148
|
+
meta = cite_mod.fetch_metadata(doi)
|
|
149
|
+
citations_out.append({
|
|
150
|
+
"doi": doi,
|
|
151
|
+
"citation": cite_mod.format_citation(meta, style, used_keys),
|
|
152
|
+
})
|
|
153
|
+
except Exception as e:
|
|
154
|
+
citations_out.append({"doi": doi, "error": f"{type(e).__name__}: {e}"})
|
|
155
|
+
return _ok({"style": style, "citations": citations_out}, pretty=pretty)
|
|
156
|
+
|
|
157
|
+
return None
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# argo MCP 启动器 —— 保证任何客户端、任何启动上下文都拿到引擎密钥。
|
|
3
|
+
#
|
|
4
|
+
# 背景(2026-08-29):各客户端 server 的密钥来自「宿主 app 启动时的环境」,
|
|
5
|
+
# 上下文不同密钥就不同(有的 8 个全有、有的全无),且 launchctl setenv
|
|
6
|
+
# 重启即失效。此启动器把密钥收敛到唯一真源文件,启动时注入:
|
|
7
|
+
# 1. ~/.config/argo/env(chmod 600,勿入库勿分享)——唯一真源
|
|
8
|
+
# 2. 系统域兜底:macOS 走 launchctl getenv,其它平台无此层、直接跳过
|
|
9
|
+
# 提前恢复配额/换 key:改 env 文件后重启对应客户端即可,零配置分散维护。
|
|
10
|
+
#
|
|
11
|
+
# 跨平台(2026-09-15):原版是 `#!/bin/zsh` + `dscl` + `${(P)k}` + `${0:A:h}`
|
|
12
|
+
# + 写死 `/opt/homebrew/bin/python3`,只在装了 Homebrew 的 macOS 上成立。
|
|
13
|
+
# 而 `mcp_setup.py` 把本脚本路径写成 MCP 客户端的 command(10 处引用),
|
|
14
|
+
# 于是 Linux / Windows-WSL 用户接 MCP 的第一步就是
|
|
15
|
+
# `bad interpreter: /bin/zsh`——不是配置错,是脚本根本起不来。
|
|
16
|
+
# 改用 POSIX sh + 解释器探测后,macOS 本机行为不变(同一个 env 文件、同一层
|
|
17
|
+
# launchctl 兜底、同一批透传名单),其余平台从「拉不起来」变成「能起」。
|
|
18
|
+
|
|
19
|
+
# 某些宿主(如 dsh web)以净化环境 spawn MCP,HOME 可能缺失——先兜底
|
|
20
|
+
if [ -z "$HOME" ]; then
|
|
21
|
+
if command -v dscl >/dev/null 2>&1; then # macOS
|
|
22
|
+
HOME="$(dscl . -read "/Users/$(id -un)" NFSHomeDirectory 2>/dev/null | awk '{print $2}')"
|
|
23
|
+
elif command -v getent >/dev/null 2>&1; then # Linux
|
|
24
|
+
HOME="$(getent passwd "$(id -un)" | cut -d: -f6)"
|
|
25
|
+
fi
|
|
26
|
+
[ -n "$HOME" ] && export HOME
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
ENV_FILE="${HOME}/.config/argo/env"
|
|
30
|
+
# set -a 仅覆盖 env 文件加载这一行,内部变量不导出
|
|
31
|
+
set -a
|
|
32
|
+
[ -f "$ENV_FILE" ] && . "$ENV_FILE"
|
|
33
|
+
set +a
|
|
34
|
+
|
|
35
|
+
# 透传名单单一真源:launchctl print 批量路径与 getenv 回退路径共用这一份
|
|
36
|
+
# (与 engine_env.KNOWN_ENV_ALIASES 展开 + 代理变量对齐,
|
|
37
|
+
# tests/test_launch_passthrough_alignment.py 锁两表一致,改名单两处同步)
|
|
38
|
+
_ARGO_PASSTHROUGH_KEYS="ALL_PROXY ANYSEARCH_API_KEY ARGO_ANYSEARCH_API_KEY ARGO_BOCHA_API_KEY\
|
|
39
|
+
ARGO_BRAVE_API_KEY ARGO_BYTED_API_KEY ARGO_EASTMONEY_APIKEY\
|
|
40
|
+
ARGO_EXA_API_KEY ARGO_FELO_API_KEY ARGO_FIRECRAWL_API_KEY\
|
|
41
|
+
ARGO_GITHUB_TOKEN ARGO_METASO_API_KEY ARGO_OCTEN_API_KEY\
|
|
42
|
+
ARGO_PROXY ARGO_QWEATHER_KEY ARGO_TAVILY_API_KEY\
|
|
43
|
+
ARGO_WEB_SEARCH_API_KEY ARGO_WEREAD_API_KEY\
|
|
44
|
+
ARGO_WOLFRAM_APPID ARGO_ZHIHU_ACCESS_SECRET BOCHA_API_KEY\
|
|
45
|
+
BRAVE_API_KEY EASTMONEY_APIKEY EXA_API_KEY FELO_API_KEY\
|
|
46
|
+
FIRECRAWL_API_KEY GITHUB_TOKEN HTTPS_PROXY HTTP_PROXY\
|
|
47
|
+
METASO_API_KEY NO_PROXY OCTEN_API_KEY QWEATHER_KEY\
|
|
48
|
+
TAVILY_API_KEY WEB_SEARCH_API_KEY WEREAD_API_KEY\
|
|
49
|
+
WOLFRAM_APPID ZHIHU_ACCESS_SECRET"
|
|
50
|
+
|
|
51
|
+
# launchctl 兜底(macOS):旧实现逐键 spawn `launchctl getenv`——实测每次
|
|
52
|
+
# 4-20ms,名单里 ~30 个未设键让每个宿主会话白付百毫秒级纯开销。改为一次
|
|
53
|
+
# `launchctl print gui/$UID` 读整个域环境(实测热态 ~30ms):environment 段
|
|
54
|
+
# 的 "KEY => value" 行与 getenv 同源(setenv 探针实测,含空格值一致)。
|
|
55
|
+
# print 不可用(非 macOS / 特殊上下文)时回退旧逐键 getenv,行为同 08-29 版。
|
|
56
|
+
_lc_vals=""
|
|
57
|
+
if command -v launchctl >/dev/null 2>&1; then
|
|
58
|
+
_lc_vals="$(launchctl print "gui/$(id -u)" 2>/dev/null | LC_ALL=C awk -v keys="$_ARGO_PASSTHROUGH_KEYS" '
|
|
59
|
+
BEGIN { n = split(keys, a, " "); for (i = 1; i <= n; i++) want[a[i]] = 1 }
|
|
60
|
+
/^[[:space:]]*environment[[:space:]]*=[[:space:]]*\{/ { e = 1; next }
|
|
61
|
+
e && /^[[:space:]]*\}/ { exit }
|
|
62
|
+
e && / => / {
|
|
63
|
+
i = index($0, " => ")
|
|
64
|
+
k = substr($0, 1, i - 1)
|
|
65
|
+
sub(/^[[:space:]]+/, "", k)
|
|
66
|
+
if (k in want) print k "\t" substr($0, i + 4)
|
|
67
|
+
}')"
|
|
68
|
+
fi
|
|
69
|
+
if [ -n "$_lc_vals" ]; then
|
|
70
|
+
# 名单内已设的键逐条导出;env 文件/父环境已给的键不覆盖(语义同旧循环)
|
|
71
|
+
while IFS=" " read -r k v; do
|
|
72
|
+
eval "cur=\${$k}"
|
|
73
|
+
if [ -z "$cur" ] && [ -n "$v" ]; then
|
|
74
|
+
export "$k=$v"
|
|
75
|
+
fi
|
|
76
|
+
done <<_ARGO_LC_EOF
|
|
77
|
+
$_lc_vals
|
|
78
|
+
_ARGO_LC_EOF
|
|
79
|
+
else
|
|
80
|
+
for k in $_ARGO_PASSTHROUGH_KEYS; do
|
|
81
|
+
if command -v launchctl >/dev/null 2>&1; then
|
|
82
|
+
# POSIX 间接展开(zsh 的 ${(P)k} 在 sh 下不存在,eval 是等价写法)
|
|
83
|
+
eval "cur=\${$k}"
|
|
84
|
+
if [ -z "$cur" ]; then
|
|
85
|
+
v="$(launchctl getenv "$k" 2>/dev/null)"
|
|
86
|
+
[ -n "$v" ] && export "$k=$v"
|
|
87
|
+
fi
|
|
88
|
+
fi
|
|
89
|
+
done
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# 脚本所在目录的绝对路径(POSIX 写法,替代 zsh 的 ${0:A:h})
|
|
93
|
+
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
|
|
94
|
+
|
|
95
|
+
# 解释器:ARGO_PYTHON 显式指定优先(客户端配置可覆盖);否则自动探测,取第一个
|
|
96
|
+
# 同时满足「版本 ≥3.9」且「能导入 PyYAML」的——版本下限与 bin/argo 的 MIN_PYTHON
|
|
97
|
+
# 一致(改一处就要改另一处)。为什么不是更高的版本:早期这里写 3.10,理由是
|
|
98
|
+
# 「脚本用了 `X | None`」,但实测全仓 0 处该写法。而配置/引擎声明都靠 PyYAML
|
|
99
|
+
# 解析,版本够却没装 yaml 的解释器选了也只能用残缺的内置默认配置——所以这两点
|
|
100
|
+
# 必须**同时**判,少判一个就会选到跑不动的解释器(bin/argo 曾因此把 3.9 选中
|
|
101
|
+
# 并写进缓存)。报错最终都落在客户端日志里,用户看到的是「MCP server 未就绪」,
|
|
102
|
+
# 所以探测阶段就把不可用的解释器跳过。
|
|
103
|
+
# 全都不达标时回落 python3:宁可让错误信息可读,也不抛「找不到解释器」。
|
|
104
|
+
# ARGO_PYTHON 显式指定同样要过「版本 + PyYAML」双判据(2026-10-02 补齐):
|
|
105
|
+
# 此前只查存在性,把无 yaml 的解释器写进 env 文件会带着残缺配置起服务,
|
|
106
|
+
# 宿主只看到「MCP server 未就绪」——与下方自动探测同一条判据。
|
|
107
|
+
if [ -n "$ARGO_PYTHON" ] && command -v "$ARGO_PYTHON" >/dev/null 2>&1 \
|
|
108
|
+
&& "$ARGO_PYTHON" -c 'import sys, yaml; sys.exit(0 if sys.version_info >= (3, 9) else 1)' >/dev/null 2>&1; then
|
|
109
|
+
PY="$ARGO_PYTHON"
|
|
110
|
+
else
|
|
111
|
+
PY=""
|
|
112
|
+
for c in python3 python3.14 python3.13 python3.12 python3.11 python3.10 python3.9 python; do
|
|
113
|
+
p="$(command -v "$c" 2>/dev/null)" || continue
|
|
114
|
+
if "$p" -c 'import sys, yaml; sys.exit(0 if sys.version_info >= (3, 9) else 1)' >/dev/null 2>&1; then
|
|
115
|
+
PY="$p"
|
|
116
|
+
break
|
|
117
|
+
fi
|
|
118
|
+
done
|
|
119
|
+
[ -n "$PY" ] || PY="python3"
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
exec "$PY" -u "${SCRIPT_DIR}/mcp_server.py" "$@"
|