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.
Files changed (463) hide show
  1. package/LICENSE +201 -21
  2. package/README.en.md +822 -0
  3. package/README.es.md +864 -0
  4. package/README.ja.md +864 -0
  5. package/README.ko.md +864 -0
  6. package/README.md +867 -320
  7. package/SKILL.md +135 -0
  8. package/assets/readme/hero.svg +121 -0
  9. package/assets/readme/made-with-beautify.svg +10 -0
  10. package/assets/readme/proof-routes.svg +73 -0
  11. package/assets/readme/settings-keys.png +0 -0
  12. package/assets/readme/settings-tools.png +0 -0
  13. package/assets/readme/why-better.svg +104 -0
  14. package/assets/readme/workflow.svg +83 -0
  15. package/backends/domain_profiles.json +2308 -96
  16. package/backends/engine_registry.yaml +3314 -503
  17. package/backends/query_synonyms_cn.json +35 -0
  18. package/backends/quota_profiles.json +2409 -161
  19. package/backends/source_types_cn.json +83 -0
  20. package/backends/text_lexicon.json +44 -0
  21. package/bin/argo +703 -0
  22. package/bin/argo.js +71 -39
  23. package/config.yaml +4976 -363
  24. package/cordis.patch.yml +21 -0
  25. package/data/countries.json +40 -0
  26. package/data/lang_matrix/lang_capability.json +842 -0
  27. package/data/lang_matrix/matrix_2026-09-10.json +11921 -0
  28. package/data/regions_cn.json +1 -0
  29. package/docs/ADDING_NEW_ENGINE.md +184 -0
  30. package/docs/ARGO_INTRO.md +124 -0
  31. package/docs/DATA_SOURCE_GAPS.md +81 -0
  32. package/docs/DESIGN_LOCAL_DATA_FUSION.md +90 -0
  33. package/docs/ENGINE_CATALOG.md +564 -0
  34. package/docs/MCP_SETUP.md +106 -0
  35. package/docs/PLATFORM_PATHS.md +111 -0
  36. package/docs/RELEASE_NOTES_v2.8.0.md +71 -0
  37. package/docs/RELEASE_NOTES_v2.8.2.md +63 -0
  38. package/docs/RELEASE_NOTES_v2.8.3.md +55 -0
  39. package/docs/RELEASE_NOTES_v2.8.4.md +79 -0
  40. package/docs/RELEASE_NOTES_v2.8.5.md +102 -0
  41. package/docs/RELEASE_NOTES_v2.8.6.md +66 -0
  42. package/docs/RELEASE_NOTES_v2.8.7.md +65 -0
  43. package/docs/RELEASE_NOTES_v2.8.8.md +67 -0
  44. package/docs/RELEASE_NOTES_v2.8.9.md +67 -0
  45. package/docs/RELEASE_NOTES_v2.9.0.md +64 -0
  46. package/docs/SEARCH_ARCHIVE.md +115 -0
  47. package/docs/assets/architecture.svg +104 -0
  48. package/docs/assets/hero.svg +98 -0
  49. package/docs/engines/bangumi.md +27 -0
  50. package/docs/engines/biorxiv.md +27 -0
  51. package/docs/engines/clawhub.md +27 -0
  52. package/docs/engines/crt_sh.md +27 -0
  53. package/docs/engines/datacite.md +27 -0
  54. package/docs/engines/deps_dev.md +27 -0
  55. package/docs/engines/douban_movie.md +27 -0
  56. package/docs/engines/endoflife.md +27 -0
  57. package/docs/engines/flk_law.md +27 -0
  58. package/docs/engines/fxtwitter.md +27 -0
  59. package/docs/engines/google_news.md +27 -0
  60. package/docs/engines/gov_regulations.md +27 -0
  61. package/docs/engines/guqian.md +27 -0
  62. package/docs/engines/hackernews.md +27 -0
  63. package/docs/engines/iplant.md +27 -0
  64. package/docs/engines/keenable.md +27 -0
  65. package/docs/engines/met_museum.md +27 -0
  66. package/docs/engines/nasa_images.md +27 -0
  67. package/docs/engines/netease_music.md +27 -0
  68. package/docs/engines/npm.md +27 -0
  69. package/docs/engines/nvd.md +27 -0
  70. package/docs/engines/openreview.md +27 -0
  71. package/docs/engines/openstd.md +27 -0
  72. package/docs/engines/parallel_free.md +27 -0
  73. package/docs/engines/people_daily.md +27 -0
  74. package/docs/engines/realtime_index.md +27 -0
  75. package/docs/engines/sec_edgar.md +27 -0
  76. package/docs/engines/seltz.md +27 -0
  77. package/docs/engines/skillsmp.md +27 -0
  78. package/docs/engines/sspai.md +27 -0
  79. package/docs/engines/std_samr.md +27 -0
  80. package/docs/engines/train.md +27 -0
  81. package/docs/engines/un_comtrade.md +27 -0
  82. package/docs/engines/wikisource.md +27 -0
  83. package/docs/engines/zdic.md +27 -0
  84. package/docs/engines/zenodo.md +27 -0
  85. package/docs/engines/zhihu_hot_app.md +27 -0
  86. package/docs//344/270/272/344/273/200/344/271/210/351/200/211/346/213/251argo.md +176 -0
  87. package/engines/README.md +10 -0
  88. package/engines/_template_cli.yaml +39 -0
  89. package/engines/_template_http.yaml +37 -0
  90. package/engines/plugins/_template_plugin.py +50 -0
  91. package/engines/specs/_cisa_kev.yaml +54 -0
  92. package/engines/specs/_osv.yaml +63 -0
  93. package/engines/specs/aljazeera.yaml +43 -0
  94. package/engines/specs/antara.yaml +43 -0
  95. package/engines/specs/artic.yaml +20 -0
  96. package/engines/specs/aviation_weather.yaml +39 -0
  97. package/engines/specs/bangumi.yaml +21 -0
  98. package/engines/specs/biorxiv.yaml +24 -0
  99. package/engines/specs/carbon_intensity.yaml +32 -0
  100. package/engines/specs/cinii.yaml +44 -0
  101. package/engines/specs/clawhub.yaml +49 -0
  102. package/engines/specs/cleveland.yaml +19 -0
  103. package/engines/specs/cn_ai_news.yaml +43 -0
  104. package/engines/specs/core.yaml +35 -0
  105. package/engines/specs/crt_sh.yaml +38 -0
  106. package/engines/specs/ct24.yaml +43 -0
  107. package/engines/specs/datacite.yaml +27 -0
  108. package/engines/specs/datagov_uk.yaml +41 -0
  109. package/engines/specs/ddgs_images.yaml +45 -0
  110. package/engines/specs/deepseek_search.yaml +74 -0
  111. package/engines/specs/deezer.yaml +20 -0
  112. package/engines/specs/deps_dev.yaml +21 -0
  113. package/engines/specs/digup.yaml +36 -0
  114. package/engines/specs/doi.yaml +39 -0
  115. package/engines/specs/douban_movie.yaml +22 -0
  116. package/engines/specs/dw_news.yaml +47 -0
  117. package/engines/specs/egov_law.yaml +21 -0
  118. package/engines/specs/elpais.yaml +43 -0
  119. package/engines/specs/endoflife.yaml +21 -0
  120. package/engines/specs/energy_charts.yaml +21 -0
  121. package/engines/specs/factcheck_org.yaml +52 -0
  122. package/engines/specs/faz.yaml +43 -0
  123. package/engines/specs/federal_register.yaml +57 -0
  124. package/engines/specs/firecrawl.yaml +53 -0
  125. package/engines/specs/flk_law.yaml +24 -0
  126. package/engines/specs/folha.yaml +43 -0
  127. package/engines/specs/france24.yaml +44 -0
  128. package/engines/specs/full_fact.yaml +47 -0
  129. package/engines/specs/fxtwitter.yaml +31 -0
  130. package/engines/specs/gbfs_nyc.yaml +32 -0
  131. package/engines/specs/gdacs.yaml +21 -0
  132. package/engines/specs/gdelt.yaml +64 -0
  133. package/engines/specs/google_news.yaml +22 -0
  134. package/engines/specs/gov_regulations.yaml +38 -0
  135. package/engines/specs/guardian_rss.yaml +59 -0
  136. package/engines/specs/hurriyet.yaml +43 -0
  137. package/engines/specs/iplant.yaml +25 -0
  138. package/engines/specs/jikan.yaml +24 -0
  139. package/engines/specs/jolpica.yaml +20 -0
  140. package/engines/specs/k10plus.yaml +20 -0
  141. package/engines/specs/keenable.yaml +44 -0
  142. package/engines/specs/lefigaro.yaml +43 -0
  143. package/engines/specs/listenbrainz.yaml +19 -0
  144. package/engines/specs/matichon.yaml +43 -0
  145. package/engines/specs/met_museum.yaml +21 -0
  146. package/engines/specs/nasa_images.yaml +45 -0
  147. package/engines/specs/netease_music.yaml +38 -0
  148. package/engines/specs/nhk.yaml +43 -0
  149. package/engines/specs/nhtsa_vpic.yaml +20 -0
  150. package/engines/specs/noaa_swpc.yaml +20 -0
  151. package/engines/specs/nvd.yaml +38 -0
  152. package/engines/specs/obis.yaml +20 -0
  153. package/engines/specs/opencitations.yaml +52 -0
  154. package/engines/specs/openf1.yaml +21 -0
  155. package/engines/specs/openfoodfacts.yaml +45 -0
  156. package/engines/specs/openligadb.yaml +20 -0
  157. package/engines/specs/openreview.yaml +37 -0
  158. package/engines/specs/openstd.yaml +21 -0
  159. package/engines/specs/people_daily.yaml +22 -0
  160. package/engines/specs/realtime_index.yaml +34 -0
  161. package/engines/specs/ror.yaml +20 -0
  162. package/engines/specs/satnogs.yaml +20 -0
  163. package/engines/specs/sec_edgar.yaml +46 -0
  164. package/engines/specs/skillsmp.yaml +50 -0
  165. package/engines/specs/sogou_weixin_browser.yaml +30 -0
  166. package/engines/specs/soilgrids.yaml +25 -0
  167. package/engines/specs/sspai.yaml +36 -0
  168. package/engines/specs/stackexchange.yaml +46 -0
  169. package/engines/specs/std_samr.yaml +21 -0
  170. package/engines/specs/tass.yaml +43 -0
  171. package/engines/specs/tle_mirror.yaml +21 -0
  172. package/engines/specs/train.yaml +37 -0
  173. package/engines/specs/tvmaze.yaml +20 -0
  174. package/engines/specs/twitter_syndication.yaml +31 -0
  175. package/engines/specs/un_comtrade.yaml +23 -0
  176. package/engines/specs/unpaywall.yaml +54 -0
  177. package/engines/specs/vnpress.yaml +43 -0
  178. package/engines/specs/weather.yaml +32 -0
  179. package/engines/specs/who_don.yaml +21 -0
  180. package/engines/specs/who_gho.yaml +20 -0
  181. package/engines/specs/wikimedia_commons.yaml +34 -0
  182. package/engines/specs/wikisource.yaml +22 -0
  183. package/engines/specs/worms.yaml +19 -0
  184. package/engines/specs/x_trending.yaml +34 -0
  185. package/engines/specs/yna.yaml +43 -0
  186. package/engines/specs/ynet.yaml +43 -0
  187. package/engines/specs/zbmath.yaml +40 -0
  188. package/engines/specs/zdic.yaml +22 -0
  189. package/engines/specs/zenodo.yaml +27 -0
  190. package/engines/specs/zhihu_hot_app.yaml +35 -0
  191. package/mcp/clients.yaml +74 -0
  192. package/package.json +51 -12
  193. package/packages/dsh-plugin/README.md +134 -0
  194. package/packages/dsh-plugin/cordis.patch.yml +48 -0
  195. package/packages/dsh-plugin/dsh/client.js +1244 -0
  196. package/packages/dsh-plugin/dsh/index.js +2290 -0
  197. package/packages/dsh-plugin/dsh/native-tools.mjs +743 -0
  198. package/packages/dsh-plugin/package.json +38 -0
  199. package/packages/dsh-plugin/test/client.test.js +232 -0
  200. package/packages/dsh-plugin/test/config.test.js +30 -0
  201. package/packages/dsh-plugin/test/index.test.js +1338 -0
  202. package/references/query-templates.md +96 -0
  203. package/references/query-templates.yaml +118 -0
  204. package/scripts/ab_eval.py +219 -0
  205. package/scripts/ab_eval_p0p1.py +266 -0
  206. package/scripts/adaptive.py +271 -70
  207. package/scripts/answer.py +154 -0
  208. package/scripts/archive_run.py +591 -0
  209. package/scripts/argo_engine_registry.py +172 -0
  210. package/scripts/argo_paths.py +728 -0
  211. package/scripts/article.py +136 -0
  212. package/scripts/arxiv_source.py +201 -0
  213. package/scripts/badcase_ledger.py +252 -0
  214. package/scripts/batch_probe.py +241 -0
  215. package/scripts/benchmark.py +19 -0
  216. package/scripts/bounded_run.py +144 -0
  217. package/scripts/browser_auth.py +323 -0
  218. package/scripts/burstiness_detector.py +147 -0
  219. package/scripts/cache.py +1078 -67
  220. package/scripts/cache_guard.py +271 -0
  221. package/scripts/cache_key_vdom.py +56 -0
  222. package/scripts/cache_similarity.py +170 -0
  223. package/scripts/caliber_isolation.py +195 -0
  224. package/scripts/calibrate_lowquality.py +210 -0
  225. package/scripts/candidate_envelope.py +366 -0
  226. package/scripts/chrome_cdp.py +871 -0
  227. package/scripts/circuit_breaker.py +389 -0
  228. package/scripts/citations.py +334 -0
  229. package/scripts/cite_cli.py +59 -0
  230. package/scripts/cjk_tokens.py +95 -0
  231. package/scripts/clarify.py +47 -24
  232. package/scripts/cli_io.py +240 -0
  233. package/scripts/config.py +683 -45
  234. package/scripts/config_cache.py +402 -0
  235. package/scripts/conn_pool.py +220 -0
  236. package/scripts/content_security.py +685 -0
  237. package/scripts/content_signals.py +730 -0
  238. package/scripts/crawl.py +74 -35
  239. package/scripts/daemon.py +866 -0
  240. package/scripts/digup_bridge.py +214 -0
  241. package/scripts/engine_admission.py +366 -0
  242. package/scripts/engine_dispatch.py +1019 -0
  243. package/scripts/engine_env.py +534 -0
  244. package/scripts/engine_failure.py +411 -0
  245. package/scripts/engine_families.py +732 -0
  246. package/scripts/engine_policy.py +218 -0
  247. package/scripts/engine_requires.py +190 -0
  248. package/scripts/engine_status.py +322 -0
  249. package/scripts/engine_validate.py +638 -0
  250. package/scripts/engines.py +778 -294
  251. package/scripts/engines_base.py +1521 -0
  252. package/scripts/engines_builders.py +298 -0
  253. package/scripts/engines_builders_batch10.py +159 -0
  254. package/scripts/engines_builders_batch11.py +174 -0
  255. package/scripts/engines_builders_batch12.py +103 -0
  256. package/scripts/engines_builders_batch13.py +340 -0
  257. package/scripts/engines_builders_batch9.py +1468 -0
  258. package/scripts/engines_builders_cn.py +2283 -0
  259. package/scripts/engines_builders_data.py +2923 -0
  260. package/scripts/engines_builders_data_macro.py +775 -0
  261. package/scripts/engines_builders_feeds.py +255 -0
  262. package/scripts/engines_builders_intl.py +1239 -0
  263. package/scripts/engines_builders_search.py +440 -0
  264. package/scripts/engines_builders_tech.py +1360 -0
  265. package/scripts/evidence.py +588 -162
  266. package/scripts/evidence_loop.py +592 -0
  267. package/scripts/evidence_tier.py +298 -0
  268. package/scripts/except_sets.py +25 -0
  269. package/scripts/extract.py +55 -16
  270. package/scripts/fact_align.py +207 -0
  271. package/scripts/fact_crosscheck.py +230 -0
  272. package/scripts/fetch.py +25 -12
  273. package/scripts/fetch_browser.py +87 -0
  274. package/scripts/fetch_jsrun.py +122 -0
  275. package/scripts/fetch_quality.py +225 -0
  276. package/scripts/fetch_render_tinyfish.py +117 -0
  277. package/scripts/fetch_v3.py +1779 -0
  278. package/scripts/focus_extract.py +350 -0
  279. package/scripts/fulltext_store.py +169 -0
  280. package/scripts/fxtwitter_api.py +325 -0
  281. package/scripts/gen_engine_catalog.py +364 -0
  282. package/scripts/gen_native_tools.py +91 -0
  283. package/scripts/gen_routing_snapshot.py +184 -0
  284. package/scripts/health_check.py +140 -402
  285. package/scripts/health_probe.py +23 -8
  286. package/scripts/hot_state.py +134 -0
  287. package/scripts/http_client.py +1053 -0
  288. package/scripts/image_ops.py +430 -0
  289. package/scripts/image_vision/vision_probe +0 -0
  290. package/scripts/image_vision/vision_probe.swift +126 -0
  291. package/scripts/install.ps1 +148 -0
  292. package/scripts/install.sh +206 -0
  293. package/scripts/job.py +1186 -0
  294. package/scripts/jump_resolver.py +235 -0
  295. package/scripts/lang_capability.py +150 -0
  296. package/scripts/lang_detect.py +289 -0
  297. package/scripts/lang_matrix_probe.py +329 -0
  298. package/scripts/lang_pref.py +311 -0
  299. package/scripts/link_source.py +340 -0
  300. package/scripts/local_engines.py +321 -0
  301. package/scripts/local_image.py +970 -0
  302. package/scripts/local_seek.py +366 -0
  303. package/scripts/macro_countries.py +82 -0
  304. package/scripts/matrix_search_eval.py +1105 -0
  305. package/scripts/mcp_diag.py +8 -3
  306. package/scripts/mcp_handlers.py +1074 -0
  307. package/scripts/mcp_handlers_surface.py +157 -0
  308. package/scripts/mcp_launch.sh +122 -0
  309. package/scripts/mcp_server.py +118 -417
  310. package/scripts/mcp_setup.py +407 -0
  311. package/scripts/mcp_tools.py +330 -0
  312. package/scripts/mcp_transport.py +191 -0
  313. package/scripts/min_version_scan.py +335 -0
  314. package/scripts/net_proxy.py +258 -0
  315. package/scripts/network_aware.py +152 -0
  316. package/scripts/paper.py +274 -0
  317. package/scripts/pdf_extract.py +518 -0
  318. package/scripts/phrase_filter.py +66 -0
  319. package/scripts/plan.py +422 -0
  320. package/scripts/postprocess_signals.py +150 -0
  321. package/scripts/pre-commit +48 -0
  322. package/scripts/query_enhance.py +157 -0
  323. package/scripts/query_operators.py +196 -0
  324. package/scripts/query_rewriter.py +116 -7
  325. package/scripts/query_signals.py +300 -0
  326. package/scripts/query_templates.py +167 -0
  327. package/scripts/query_understanding.py +411 -0
  328. package/scripts/query_variants.py +298 -0
  329. package/scripts/quota.py +488 -76
  330. package/scripts/rank_signals.py +775 -0
  331. package/scripts/ranking_eval.py +319 -0
  332. package/scripts/readability_extract.py +433 -0
  333. package/scripts/recompute.py +415 -0
  334. package/scripts/recovery.py +616 -0
  335. package/scripts/recovery_l0.py +160 -0
  336. package/scripts/redskill/redskill_engine.py +332 -0
  337. package/scripts/regression_p0p1.py +318 -0
  338. package/scripts/replay_eval.py +640 -0
  339. package/scripts/rerank_tfidf.py +225 -0
  340. package/scripts/research.py +591 -403
  341. package/scripts/research_cli.py +361 -0
  342. package/scripts/research_dossier.py +492 -0
  343. package/scripts/research_expand.py +146 -0
  344. package/scripts/research_gates.py +272 -0
  345. package/scripts/research_report.py +209 -0
  346. package/scripts/research_strategy.py +37 -0
  347. package/scripts/research_work_packages.py +195 -0
  348. package/scripts/result_lang.py +311 -0
  349. package/scripts/robots_guard.py +259 -0
  350. package/scripts/route.py +921 -254
  351. package/scripts/route_bangs.py +40 -0
  352. package/scripts/route_cache.py +225 -0
  353. package/scripts/route_combo.py +910 -0
  354. package/scripts/route_domains.py +328 -0
  355. package/scripts/route_lang.py +605 -0
  356. package/scripts/route_log.py +63 -0
  357. package/scripts/route_policy.py +250 -0
  358. package/scripts/rrf_classic.py +66 -0
  359. package/scripts/screenshot.py +73 -0
  360. package/scripts/search.py +897 -405
  361. package/scripts/search_attribution.py +88 -0
  362. package/scripts/search_benchmark.py +407 -0
  363. package/scripts/search_cli.py +627 -0
  364. package/scripts/search_entry.py +389 -0
  365. package/scripts/search_output.py +606 -0
  366. package/scripts/search_pipeline.py +1077 -0
  367. package/scripts/search_rank.py +991 -0
  368. package/scripts/search_types.py +27 -12
  369. package/scripts/seek_locator.py +68 -0
  370. package/scripts/semantic_evidence.py +215 -0
  371. package/scripts/serp_guard.py +228 -0
  372. package/scripts/serp_kill_log.py +51 -0
  373. package/scripts/single_flight.py +120 -0
  374. package/scripts/social_engines/__init__.py +10 -0
  375. package/scripts/social_engines/bilibili_engine.py +131 -0
  376. package/scripts/social_engines/hackernews_engine.py +113 -0
  377. package/scripts/social_engines/reddit_engine.py +172 -0
  378. package/scripts/social_engines/twitter_engine.py +397 -0
  379. package/scripts/social_engines/v2ex_engine.py +101 -0
  380. package/scripts/social_engines/weibo_engine.py +128 -0
  381. package/scripts/social_engines/xiaohongshu_engine.py +137 -0
  382. package/scripts/social_engines/zhihu_engine.py +139 -0
  383. package/scripts/social_research.py +201 -0
  384. package/scripts/sogou_weixin_browser.py +318 -0
  385. package/scripts/source_ledger.py +249 -0
  386. package/scripts/stage_timing.py +58 -0
  387. package/scripts/stats_cli.py +95 -0
  388. package/scripts/straggler_policy.py +60 -0
  389. package/scripts/stylometry_detector.py +231 -0
  390. package/scripts/sync_backends.py +353 -0
  391. package/scripts/sync_installs.py +29 -0
  392. package/scripts/template_cli.py +127 -0
  393. package/scripts/text_lexicon.py +72 -0
  394. package/scripts/tfidf_router.py +109 -37
  395. package/scripts/time_utils.py +233 -0
  396. package/scripts/topic_research_profiles.py +643 -0
  397. package/scripts/train.py +737 -0
  398. package/scripts/tweet.py +596 -0
  399. package/scripts/url_canon.py +217 -0
  400. package/scripts/url_optimize.py +56 -0
  401. package/scripts/url_safety.py +236 -0
  402. package/scripts/usage_log.py +116 -0
  403. package/scripts/usage_log_clean.py +113 -0
  404. package/scripts/v2ex_nodes.py +311 -0
  405. package/scripts/variant_recall.py +188 -0
  406. package/scripts/watch.py +205 -0
  407. package/scripts/wechat_article.py +258 -0
  408. package/scripts/wide_research.py +402 -0
  409. package/scripts/wx.py +349 -0
  410. package/scripts/x_article_fetch.py +141 -0
  411. package/scripts/x_search.py +234 -0
  412. package/scripts/x_trending.py +189 -0
  413. package/scripts/yaml_load.py +67 -0
  414. package/sub-skills/ego-search/SKILL.md +253 -0
  415. package/sub-skills/ego-search/references/browser-runtime.md +43 -0
  416. package/sub-skills/ego-search/references/install.md +67 -0
  417. package/sub-skills/ego-search/references/original-ego-upgrade.md +51 -0
  418. package/sub-skills/ego-search/scripts/ego_search.py +800 -0
  419. package/sub-skills/ego-search/scripts/merge.py +226 -0
  420. package/sub-skills/ego-search/scripts/quality.py +64 -0
  421. package/sub-skills/ego-search/scripts/runtime.py +172 -0
  422. package/sub-skills/ego-search/scripts/safety.py +109 -0
  423. package/sub-skills/ego-search/scripts/serp_spec.py +109 -0
  424. package/sub-skills/ego-search/scripts/webbridge_adapter.py +374 -0
  425. package/sub-skills/ego-search/tests/test_query_normalize.py +68 -0
  426. package/sub-skills/js-run/SKILL.md +67 -0
  427. package/sub-skills/js-run/scripts/jsrun.py +112 -0
  428. package/sub-skills/js-run/scripts/shim.js +188 -0
  429. package/sub-skills/js-run/tests/fixtures/challenge_like.js +27 -0
  430. package/sub-skills/js-run/tests/test_jsrun.py +165 -0
  431. package/sub-skills/local-search/SKILL.md +50 -53
  432. package/sub-skills/local-search/bm25.py +162 -0
  433. package/sub-skills/local-search/config.yaml +152 -55
  434. package/sub-skills/local-search/engine_registry.py +91 -26
  435. package/sub-skills/local-search/{health_check.py → local_health_check.py} +140 -10
  436. package/sub-skills/local-search/local_search_adapter.py +13 -2
  437. package/sub-skills/local-search/parse_maps.yaml +40 -42
  438. package/sub-skills/local-search/search_v3.py +1182 -65
  439. package/sub-skills/local-search/smart_router.py +47 -7
  440. package/sub-skills/local-seek/SKILL.md +110 -0
  441. package/sub-skills/local-seek/config/domains.yaml +20 -0
  442. package/sub-skills/local-seek/references/auto-behaviors.md +24 -0
  443. package/sub-skills/local-seek/references/fd-mdfind-recipes.md +62 -0
  444. package/sub-skills/local-seek/references/git-integration.md +54 -0
  445. package/sub-skills/local-seek/references/remote-handoff.md +46 -0
  446. package/sub-skills/local-seek/references/rg-recipes.md +96 -0
  447. package/sub-skills/local-seek/references/strategies.md +52 -0
  448. package/sub-skills/local-seek/references/structural-search.md +59 -0
  449. package/sub-skills/local-seek/scripts/eval_rank.py +216 -0
  450. package/sub-skills/local-seek/scripts/eval_seek.py +224 -0
  451. package/sub-skills/local-seek/scripts/seek.py +1465 -0
  452. package/sub-skills/local-seek/scripts/seek_frecency.py +126 -0
  453. package/sub-skills/local-seek/scripts/seek_fts.py +430 -0
  454. package/sub-skills/local-seek/scripts/seek_rank.py +193 -0
  455. package/sub-skills/local-seek/tests/test_content_rank.py +222 -0
  456. package/sub-skills/local-seek/tests/test_determinism_20261006.py +145 -0
  457. package/sub-skills/local-seek/tests/test_noise_tier.py +101 -0
  458. package/sub-skills/local-seek/tests/test_pcre2_probe.py +136 -0
  459. package/sub-skills/local-seek/tests/test_rank_pinyin.py +77 -0
  460. package/sub-skills/local-seek/tests/test_regression_20261003.py +169 -0
  461. package/sub-skills/local-seek/tests/test_regression_20261006.py +146 -0
  462. package/sub-skills/local-seek/tests/test_seek_degradation.py +111 -0
  463. package/sub-skills/local-seek/tests/test_seek_fts.py +313 -0
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env python3
2
+ """bm25.py — local-search 的相关度打分(BM25Okapi + 中英混合切词)。
3
+
4
+ 问题(第一性):local-search 此前的打分是**纯位次衰减**
5
+ (`score = max(0.7 - idx*0.05, 0.1)`)——「第 3 条结果」永远比「第 1 条
6
+ 不相关结果」分高,无论它是否真的包含查询词。位次是引擎给的先验(有价值,
7
+ 点击数据比词面匹配强),但把它当唯一依据等于宣布「词面相关度不重要」:
8
+ 实测查询词在第 3 条标题里完整出现、第 1 条只是泛相关页时,排序无动于衷。
9
+
10
+ 设计(MECE,两层信号各司其职):
11
+ - BM25 相关度:title + snippet 对查询的词面匹配(TF 饱和 + 长文档惩罚 +
12
+ IDF Rare-term 加权)。回答「这条内容是否真的关于这个查询」。
13
+ - 引擎位次先验:引擎自己的排序(它的点击/质量信号)。回答「源站认为
14
+ 谁更好」。
15
+ 两者按权重混合(默认 BM25 0.6 / 位次 0.4):任一侧无信号时另一侧兜底——
16
+ 查询词切不出 token(纯停用词)或引擎不给 snippet 时,BM25 侧为 0,
17
+ 混合分退化为旧位次序,行为与升级前逐位一致(fail-soft)。
18
+
19
+ 切词(与 local_image._tokens 同源思路,按 BM25 的需要分叉):
20
+ - ASCII 连续串 → 小写词元(python / 3.14 / node.js);
21
+ - CJK 连续串 → 字符二元组(「异步编程」→ 异步/步编/编程);
22
+ 单字 CJK 串 → 单字(「酒」→ 酒,二元无从切起)。
23
+ 为什么 CJK 用二元而非单字:单字在任何中文文档里都泛滥(的/是/了),
24
+ IDF 失去鉴别力,BM25 会退化成「文档越长分越低」。二元组是中文无分词器
25
+ 场景下的标准近似(信息检索文献的标准做法)。
26
+
27
+ BM25 口径(Okapi,k1=1.5, b=0.75,Lucene 式 IDF 保证小语料非负):
28
+ score(q,d) = Σ_t IDF(t) · f(t,d)·(k1+1) / (f(t,d) + k1·(1-b+b·|d|/avgdl))
29
+ IDF(t) = ln(1 + (N - n(t) + 0.5) / (n(t) + 0.5))
30
+ N 为语料文档数(一次搜索采集到的全部结果),n(t) 为含 t 的文档数。
31
+ """
32
+
33
+ from __future__ import annotations
34
+
35
+ import math
36
+ import re
37
+ from typing import Any, Iterable
38
+
39
+ # ASCII 词元 / CJK 连续串。CJK 必须匹配**整个串**(不是单字)——二元组在
40
+ # _tokenize 里对连续 CJK 串二次生成;正则若按单字匹配,二元逻辑永远走不到。
41
+ _TOKEN_RE = re.compile(r"[A-Za-z0-9_+\-.#]+|[\u4e00-\u9fff]+")
42
+ _CJK_RE = re.compile(r"[\u4e00-\u9fff]+")
43
+
44
+ _K1 = 1.5
45
+ _B = 0.75
46
+ # 混合权重:BM25 侧。位次先验占 1 - _W_BM25。
47
+ _W_BM25 = 0.6
48
+ # 旧位次衰减口径(max(0.7 - idx*0.05, 0.1))——先验的归一化基准。
49
+ _PRIOR_BASE = 0.7
50
+
51
+
52
+ def tokenize(text: str) -> list[str]:
53
+ """查询/文档统一切词(两侧必须同函数,否则 TF/IDF 对不上)。"""
54
+ if not text:
55
+ return []
56
+ out: list[str] = []
57
+ for m in _TOKEN_RE.finditer(text):
58
+ tok = m.group(0)
59
+ if _CJK_RE.fullmatch(tok):
60
+ # CJK 串:二元组 + (单字串时)单字本身
61
+ if len(tok) == 1:
62
+ out.append(tok)
63
+ else:
64
+ out.extend(tok[i:i + 2] for i in range(len(tok) - 1))
65
+ else:
66
+ out.append(tok.lower())
67
+ return out
68
+
69
+
70
+ def _position_prior(idx: int) -> float:
71
+ """引擎位次先验(旧打分口径,保持行为连续)。"""
72
+ return max(_PRIOR_BASE - idx * 0.05, 0.1)
73
+
74
+
75
+ class BM25:
76
+ """一次搜索语料上的 BM25 打分器。
77
+
78
+ 语料 = 本次采集到的全部结果(跨引擎池化):IDF 在池上计算比在单个
79
+ 引擎的 5 条结果上稳定得多——「含查询词的文档有多罕见」是跨源问题。
80
+ """
81
+
82
+ def __init__(self, docs: list[list[str]], k1: float = _K1, b: float = _B):
83
+ self.k1 = k1
84
+ self.b = b
85
+ self.n_docs = len(docs)
86
+ self.doc_len = [len(d) for d in docs]
87
+ self.avgdl = (sum(self.doc_len) / self.n_docs) if self.n_docs else 0.0
88
+ # term -> [doc 频次, {doc_idx: tf}]
89
+ self.tf: dict[str, dict[int, int]] = {}
90
+ for i, d in enumerate(docs):
91
+ for t in d:
92
+ self.tf.setdefault(t, {}).setdefault(i, 0)
93
+ self.tf[t][i] += 1
94
+ self._idf_cache: dict[str, float] = {}
95
+
96
+ def idf(self, term: str) -> float:
97
+ cached = self._idf_cache.get(term)
98
+ if cached is not None:
99
+ return cached
100
+ n = len(self.tf.get(term, {}))
101
+ # Lucene 式:+1 在 ln 内,n=N(语料内全含)时仍为正(小语料常见)
102
+ v = math.log(1.0 + (self.n_docs - n + 0.5) / (n + 0.5))
103
+ self._idf_cache[term] = v
104
+ return v
105
+
106
+ def score(self, query_terms: list[str], doc_idx: int) -> float:
107
+ if self.n_docs == 0 or not query_terms:
108
+ return 0.0
109
+ dl = self.doc_len[doc_idx] or 1
110
+ denom_norm = self.k1 * (1.0 - self.b + self.b * dl / (self.avgdl or 1.0))
111
+ total = 0.0
112
+ for t in query_terms:
113
+ f = self.tf.get(t, {}).get(doc_idx, 0)
114
+ if not f:
115
+ continue
116
+ total += self.idf(t) * (f * (self.k1 + 1.0)) / (f + denom_norm)
117
+ return total
118
+
119
+
120
+ def _doc_text(r: dict[str, Any]) -> str:
121
+ """参与相关度计算的文档文本:title 权重高于 snippet——做法是标题
122
+ 拼两遍(TF 加成),不引入第二套字段权重机制。"""
123
+ title = (r.get("title") or "").strip()
124
+ snippet = (r.get("snippet") or "").strip()
125
+ return f"{title} {title} {snippet}" if title else snippet
126
+
127
+
128
+ def rerank(by_engine: dict[str, list[dict[str, Any]]], query: str,
129
+ w_bm25: float = _W_BM25) -> dict[str, list[dict[str, Any]]]:
130
+ """按「BM25 相关度 × 引擎位次先验」混合分重排每个引擎的结果列表。
131
+
132
+ 原地修改(results 的 `score` 字段更新为混合分并重排),返回同一 dict。
133
+ 调用点:search_v3 采集完成后、RRF 融合前——RRF 的输入序即相关度序。
134
+
135
+ Fail-soft:查询切不出 token、或全部文档零 BM25(无任何词面重叠)时,
136
+ 混合分退化为位次先验,排序与升级前逐位一致。
137
+ """
138
+ q_terms = tokenize(query)
139
+ flat: list[tuple[str, int, dict[str, Any]]] = []
140
+ for eng, results in by_engine.items():
141
+ for i, r in enumerate(results):
142
+ if not isinstance(r, dict):
143
+ continue # 防御:单条畸形结果不应杀死整个重排
144
+ flat.append((eng, i, r))
145
+ if not flat:
146
+ return by_engine
147
+
148
+ docs = [tokenize(_doc_text(r)) for _, _, r in flat]
149
+ scorer = BM25(docs)
150
+ raw = [scorer.score(q_terms, i) for i in range(len(flat))]
151
+ max_raw = max(raw) if raw else 0.0
152
+
153
+ for (eng, idx, r), bm in zip(flat, raw):
154
+ bm25_norm = (bm / max_raw) if max_raw > 0 else 0.0
155
+ prior_norm = _position_prior(idx) / _PRIOR_BASE
156
+ r["score"] = round(w_bm25 * bm25_norm + (1.0 - w_bm25) * prior_norm, 3)
157
+
158
+ for eng in by_engine:
159
+ by_engine[eng].sort(
160
+ key=lambda r: (r.get("score", 0.0) if isinstance(r, dict) else -1.0),
161
+ reverse=True)
162
+ return by_engine
@@ -1,12 +1,13 @@
1
1
  # local-search 子技能专属配置
2
- # 与 unified-search/config.yaml 解耦,local_search_adapter.py / search_v3.py 直接读取本文件。
2
+ # 与 argo/config.yaml 解耦,local_search_adapter.py / search_v3.py 直接读取本文件。
3
3
 
4
4
  settings:
5
5
  default_timeout: 8
6
6
  default_results: 5
7
- max_parallel_engines: 5
7
+ # 27 个启用引擎 ÷ 12 ≈ 3 波串发(此前 5 并发 6 波,长尾实测可到 7s);
8
+ # ddgs 免费源瞬时 12 并发有熔断器兜底。
9
+ max_parallel_engines: 12
8
10
  user_agent: "Mozilla/5.0 (compatible; unified-search-local/1.0.1; +https://local)"
9
- request_interval_ms: 500
10
11
  health_check:
11
12
  canary_query: "test"
12
13
  ttl_minutes: 5
@@ -17,68 +18,105 @@ settings:
17
18
 
18
19
  engines:
19
20
  local_bing:
20
- type: html
21
+ type: cli
21
22
  enabled: true
22
23
  categories: [web_general]
23
- url: "https://www.bing.com/search"
24
- query_param: q
25
- method: GET
24
+ cli_command: ddgs
25
+ cli_args: ["text", "-q", "{query}", "-m", "{n}", "-b", "bing"]
26
+ key: local_bing
26
27
  timeout: 8
27
- format: html
28
- extra_params:
28
+ output_format: json
29
+ use_lang_region: true
30
+ fallback_type: html
31
+ fallback_url: "https://www.bing.com/search"
32
+ fallback_param: q
33
+ fallback_params:
29
34
  setlang: zh-Hans
30
35
 
31
- local_google:
32
- type: html
33
- enabled: false
34
- categories: [web_general]
35
- url: "https://www.google.com/search"
36
- query_param: q
37
- method: GET
36
+ local_yandex:
37
+ type: cli
38
+ enabled: true
39
+ categories: [web_general, japanese]
40
+ cli_command: ddgs
41
+ cli_args: ["text", "-q", "{query}", "-m", "{n}", "-b", "yandex"]
42
+ key: local_yandex
38
43
  timeout: 8
39
- format: html
40
- extra_params:
41
- hl: zh-CN
44
+ output_format: json
45
+ use_lang_region: true
46
+ # html fallback 已删:yandex.com 直连被 SmartCaptcha 墙(2026-09-26 实测),
47
+ # 无 selectors 可用,cli 失败即诚实空
42
48
 
43
- local_mojeek:
44
- type: html
49
+ local_duckduckgo:
50
+ type: cli
45
51
  enabled: true
46
52
  categories: [web_general]
47
- url: "https://www.mojeek.com/search"
48
- query_param: q
49
- method: GET
50
- timeout: 10
51
- format: html
53
+ cli_command: ddgs
54
+ cli_args: ["text", "-q", "{query}", "-m", "{n}"]
55
+ key: local_duckduckgo
56
+ timeout: 8
57
+ output_format: json
58
+ use_lang_region: true
59
+ fallback_type: html
60
+ fallback_url: "https://html.duckduckgo.com/html/"
61
+ fallback_param: q
52
62
 
53
- local_yandex:
54
- type: html
55
- enabled: false
63
+ # ddgs brave backend(实测 ~1.1s 稳定可用)
64
+ local_brave:
65
+ type: cli
66
+ enabled: true
56
67
  categories: [web_general]
57
- url: "https://yandex.com/search/"
58
- query_param: text
59
- method: GET
60
- timeout: 10
61
- format: html
68
+ cli_command: ddgs
69
+ cli_args: ["text", "-q", "{query}", "-m", "{n}", "-b", "brave"]
70
+ key: local_brave
71
+ timeout: 8
72
+ output_format: json
73
+ use_lang_region: true
62
74
 
63
- local_startpage:
64
- type: html
75
+ # ddgs yahoo backend(实测 ~1.1s 稳定可用)
76
+ local_yahoo:
77
+ type: cli
65
78
  enabled: true
66
79
  categories: [web_general]
67
- url: "https://www.startpage.com/do/dsearch"
68
- query_param: query
69
- method: GET
70
- timeout: 10
71
- format: html
80
+ cli_command: ddgs
81
+ cli_args: ["text", "-q", "{query}", "-m", "{n}", "-b", "yahoo"]
82
+ key: local_yahoo
83
+ timeout: 8
84
+ output_format: json
85
+ use_lang_region: true
72
86
 
73
- local_duckduckgo:
74
- type: html
87
+ # ddgs CLI 增强版引擎(支持 news/images/videos)
88
+ local_ddgs_news:
89
+ type: cli
75
90
  enabled: true
76
- categories: [web_general]
77
- url: "https://html.duckduckgo.com/html/"
78
- query_param: q
79
- method: GET
91
+ categories: [news]
92
+ cli_command: ddgs
93
+ cli_args: ["news", "-q", "{query}", "-m", "{n}"]
94
+ key: local_ddgs_news
80
95
  timeout: 8
81
- format: html
96
+ output_format: json
97
+ use_lang_region: true
98
+
99
+ local_ddgs_images:
100
+ type: cli
101
+ enabled: true
102
+ categories: [images]
103
+ cli_command: ddgs
104
+ cli_args: ["images", "-q", "{query}", "-m", "{n}"]
105
+ key: local_ddgs_images
106
+ timeout: 8
107
+ output_format: json
108
+ use_lang_region: true
109
+
110
+ local_ddgs_videos:
111
+ type: cli
112
+ enabled: true
113
+ categories: [videos]
114
+ cli_command: ddgs
115
+ cli_args: ["videos", "-q", "{query}", "-m", "{n}"]
116
+ key: local_ddgs_videos
117
+ timeout: 8
118
+ output_format: json
119
+ use_lang_region: true
82
120
 
83
121
  local_baidu:
84
122
  type: html
@@ -89,6 +127,10 @@ engines:
89
127
  method: GET
90
128
  timeout: 8
91
129
  format: html
130
+ # 结果链接走 baidu.com/link 跳转壳:与主链 baidu 引擎同契约(engines_base
131
+ # 同名同义),不解析会在主链 serp_guard 整批被杀。解不开的按不可核验
132
+ # 信源丢弃。
133
+ resolve_redirects: true
92
134
  extra_params:
93
135
  ie: utf-8
94
136
 
@@ -101,6 +143,36 @@ engines:
101
143
  method: GET
102
144
  timeout: 8
103
145
  format: html
146
+ # 结果链接走 sogou.com/link 会话型跳转壳:Chrome 指纹下是 200 小页 +
147
+ # window.location.replace(真实URL),可无会话解析(2026-10-06 实测);
148
+ # 不解析会在主链 serp_guard 整批被杀(returned 10 → kept 1 的根因)。
149
+ resolve_redirects: true
150
+
151
+ local_360:
152
+ type: html
153
+ enabled: true
154
+ categories: [chinese]
155
+ family: web_general
156
+ url: "https://www.so.com/s"
157
+ query_param: q
158
+ method: GET
159
+ timeout: 8
160
+ format: html
161
+ # 不声明 resolve_redirects(2026-10-06 实测):so.com/link 需 QiHoo GUID
162
+ # cookie 链,chrome131 指纹直连仍 400,声明了只会把结果整条丢弃。
163
+ extra_params:
164
+ ie: utf-8
165
+
166
+ local_jisilu:
167
+ type: html
168
+ enabled: true
169
+ categories: [finance, chinese]
170
+ family: social
171
+ url: "https://www.jisilu.cn/explore/"
172
+ query_param: keyword
173
+ method: GET
174
+ timeout: 8
175
+ format: html
104
176
 
105
177
  local_arxiv:
106
178
  type: xml
@@ -128,6 +200,11 @@ engines:
128
200
  db: pubmed
129
201
  retmode: json
130
202
  retmax: "{n}"
203
+ datetype: pdat
204
+ # 时间窗下推:mindate/maxdate + datetype=pdat(出版日期)
205
+ filter_args:
206
+ since: [[mindate, "{since_iso}"]]
207
+ until: [[maxdate, "{until_iso}"]]
131
208
 
132
209
  local_crossref:
133
210
  type: json
@@ -166,6 +243,7 @@ engines:
166
243
  format: rss
167
244
  extra_params:
168
245
  format: rss
246
+ note: ddgs bing news backend unreliable, use RSS directly
169
247
 
170
248
  local_google_news:
171
249
  type: rss
@@ -176,16 +254,20 @@ engines:
176
254
  method: GET
177
255
  timeout: 8
178
256
  format: rss
257
+ note: ddgs google news backend unreliable, use RSS directly
179
258
 
180
259
  local_duckduckgo_news:
181
- type: rss
182
- enabled: false
260
+ type: cli
261
+ enabled: true
183
262
  categories: [news]
184
- url: "https://duckduckgo.com/html/"
185
- query_param: q
186
- method: GET
187
- timeout: 8
188
- format: html
263
+ cli_command: ddgs
264
+ cli_args: ["news", "-q", "{query}", "-m", "{n}"]
265
+ key: local_duckduckgo_news
266
+ timeout: 15
267
+ output_format: json
268
+ fallback_type: html
269
+ fallback_url: "https://duckduckgo.com/html/"
270
+ fallback_param: q
189
271
 
190
272
  local_github:
191
273
  type: json
@@ -201,6 +283,10 @@ engines:
201
283
  headers:
202
284
  Accept: application/vnd.github.v3+json
203
285
  User-Agent: unified-search-local/1.0.1
286
+ # 时间窗下推:created 限定符追加进 q(参数名与 query_param 相同时自动追加,不重复 query)
287
+ filter_args:
288
+ since: [[q, "created:>={since_iso}"]]
289
+ until: [[q, "created:<={until_iso}"]]
204
290
 
205
291
  local_stackoverflow:
206
292
  type: json
@@ -216,6 +302,10 @@ engines:
216
302
  pagesize: "{n}"
217
303
  order: desc
218
304
  sort: relevance
305
+ # 时间窗下推:fromdate/todate(unix 时间戳)
306
+ filter_args:
307
+ since: [[fromdate, "{since_epoch}"]]
308
+ until: [[todate, "{until_epoch}"]]
219
309
 
220
310
  local_gitlab:
221
311
  type: json
@@ -229,6 +319,10 @@ engines:
229
319
  extra_params:
230
320
  per_page: "{n}"
231
321
  scope: projects
322
+ # 时间窗下推:created_after/created_before(ISO 日期)
323
+ filter_args:
324
+ since: [[created_after, "{since_iso}"]]
325
+ until: [[created_before, "{until_iso}"]]
232
326
 
233
327
  local_npm:
234
328
  type: json
@@ -256,6 +350,7 @@ engines:
256
350
  list: search
257
351
  format: json
258
352
  srlimit: "{n}"
353
+ note: ddgs wikipedia backend unreliable, use MediaWiki API directly
259
354
 
260
355
  local_wiktionary:
261
356
  type: json
@@ -288,6 +383,8 @@ engines:
288
383
  srlimit: "{n}"
289
384
 
290
385
  local_imdb:
386
+ # 与主仓 imdb 同源:suggestion API(由 argo 主引擎 type=imdb 实现;
387
+ # local-search 内 html 路径已弃用,保留条目供垂直分类与健康探测)
291
388
  type: html
292
389
  enabled: false
293
390
  categories: [vertical]