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.
Files changed (472) hide show
  1. package/LICENSE +201 -21
  2. package/README.en.md +735 -0
  3. package/README.es.md +777 -0
  4. package/README.ja.md +777 -0
  5. package/README.ko.md +777 -0
  6. package/README.md +778 -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/why-better.svg +104 -0
  12. package/assets/readme/workflow.svg +83 -0
  13. package/backends/domain_profiles.json +2356 -96
  14. package/backends/engine_registry.yaml +3428 -503
  15. package/backends/query_synonyms_cn.json +35 -0
  16. package/backends/quota_profiles.json +2488 -160
  17. package/backends/source_types_cn.json +109 -0
  18. package/backends/text_lexicon.json +44 -0
  19. package/bin/argo +772 -0
  20. package/bin/argo.js +102 -39
  21. package/config.yaml +5139 -367
  22. package/cordis.patch.yml +21 -0
  23. package/data/countries.json +40 -0
  24. package/data/lang_matrix/lang_capability.json +842 -0
  25. package/data/lang_matrix/matrix_2026-09-10.json +11921 -0
  26. package/data/regions_cn.json +1 -0
  27. package/docs/ADDING_NEW_ENGINE.md +184 -0
  28. package/docs/ARGO_INTRO.md +124 -0
  29. package/docs/DATA_SOURCE_GAPS.md +81 -0
  30. package/docs/DESIGN_LOCAL_DATA_FUSION.md +90 -0
  31. package/docs/ENGINE_CATALOG.md +575 -0
  32. package/docs/MCP_SETUP.md +108 -0
  33. package/docs/PLATFORM_PATHS.md +111 -0
  34. package/docs/RELEASE_NOTES_v2.8.0.md +71 -0
  35. package/docs/RELEASE_NOTES_v2.8.2.md +63 -0
  36. package/docs/RELEASE_NOTES_v2.8.3.md +55 -0
  37. package/docs/RELEASE_NOTES_v2.8.4.md +79 -0
  38. package/docs/RELEASE_NOTES_v2.8.5.md +102 -0
  39. package/docs/RELEASE_NOTES_v2.8.6.md +66 -0
  40. package/docs/RELEASE_NOTES_v2.8.7.md +65 -0
  41. package/docs/RELEASE_NOTES_v2.8.8.md +67 -0
  42. package/docs/RELEASE_NOTES_v2.8.9.md +67 -0
  43. package/docs/RELEASE_NOTES_v2.9.0.md +64 -0
  44. package/docs/RELEASE_NOTES_v2.9.8.md +73 -0
  45. package/docs/SEARCH_ARCHIVE.md +115 -0
  46. package/docs/assets/architecture.svg +104 -0
  47. package/docs/assets/hero.svg +98 -0
  48. package/docs/engines/bangumi.md +27 -0
  49. package/docs/engines/biorxiv.md +27 -0
  50. package/docs/engines/clawhub.md +27 -0
  51. package/docs/engines/crt_sh.md +27 -0
  52. package/docs/engines/datacite.md +27 -0
  53. package/docs/engines/deps_dev.md +27 -0
  54. package/docs/engines/douban_movie.md +27 -0
  55. package/docs/engines/endoflife.md +27 -0
  56. package/docs/engines/flk_law.md +27 -0
  57. package/docs/engines/fxtwitter.md +27 -0
  58. package/docs/engines/google_news.md +27 -0
  59. package/docs/engines/gov_regulations.md +27 -0
  60. package/docs/engines/guqian.md +27 -0
  61. package/docs/engines/hackernews.md +27 -0
  62. package/docs/engines/iplant.md +27 -0
  63. package/docs/engines/keenable.md +27 -0
  64. package/docs/engines/met_museum.md +27 -0
  65. package/docs/engines/nasa_images.md +27 -0
  66. package/docs/engines/netease_music.md +27 -0
  67. package/docs/engines/npm.md +27 -0
  68. package/docs/engines/nvd.md +27 -0
  69. package/docs/engines/openreview.md +27 -0
  70. package/docs/engines/openstd.md +27 -0
  71. package/docs/engines/parallel_free.md +27 -0
  72. package/docs/engines/people_daily.md +27 -0
  73. package/docs/engines/realtime_index.md +27 -0
  74. package/docs/engines/sec_edgar.md +27 -0
  75. package/docs/engines/seltz.md +27 -0
  76. package/docs/engines/skillsmp.md +27 -0
  77. package/docs/engines/sspai.md +27 -0
  78. package/docs/engines/std_samr.md +27 -0
  79. package/docs/engines/train.md +27 -0
  80. package/docs/engines/un_comtrade.md +27 -0
  81. package/docs/engines/wikisource.md +27 -0
  82. package/docs/engines/zdic.md +27 -0
  83. package/docs/engines/zenodo.md +27 -0
  84. package/docs/engines/zhihu_hot_app.md +27 -0
  85. package/docs//344/270/272/344/273/200/344/271/210/351/200/211/346/213/251argo.md +176 -0
  86. package/engines/README.md +10 -0
  87. package/engines/_template_cli.yaml +39 -0
  88. package/engines/_template_http.yaml +37 -0
  89. package/engines/plugins/_template_plugin.py +50 -0
  90. package/engines/specs/_cisa_kev.yaml +54 -0
  91. package/engines/specs/_osv.yaml +63 -0
  92. package/engines/specs/aljazeera.yaml +43 -0
  93. package/engines/specs/antara.yaml +43 -0
  94. package/engines/specs/artic.yaml +20 -0
  95. package/engines/specs/aviation_weather.yaml +39 -0
  96. package/engines/specs/bangumi.yaml +21 -0
  97. package/engines/specs/biorxiv.yaml +24 -0
  98. package/engines/specs/carbon_intensity.yaml +32 -0
  99. package/engines/specs/cfets.yaml +41 -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/defillama.yaml +38 -0
  113. package/engines/specs/deps_dev.yaml +21 -0
  114. package/engines/specs/digup.yaml +36 -0
  115. package/engines/specs/doi.yaml +39 -0
  116. package/engines/specs/douban_movie.yaml +22 -0
  117. package/engines/specs/dw_news.yaml +47 -0
  118. package/engines/specs/egov_law.yaml +21 -0
  119. package/engines/specs/elpais.yaml +43 -0
  120. package/engines/specs/endoflife.yaml +21 -0
  121. package/engines/specs/energy_charts.yaml +21 -0
  122. package/engines/specs/factcheck_org.yaml +52 -0
  123. package/engines/specs/faz.yaml +43 -0
  124. package/engines/specs/federal_register.yaml +57 -0
  125. package/engines/specs/firecrawl.yaml +53 -0
  126. package/engines/specs/flk_law.yaml +24 -0
  127. package/engines/specs/folha.yaml +43 -0
  128. package/engines/specs/france24.yaml +44 -0
  129. package/engines/specs/full_fact.yaml +47 -0
  130. package/engines/specs/fxtwitter.yaml +36 -0
  131. package/engines/specs/gbfs_nyc.yaml +32 -0
  132. package/engines/specs/gdacs.yaml +21 -0
  133. package/engines/specs/gdelt.yaml +64 -0
  134. package/engines/specs/gleif.yaml +55 -0
  135. package/engines/specs/google_news.yaml +22 -0
  136. package/engines/specs/gov_regulations.yaml +38 -0
  137. package/engines/specs/guardian_rss.yaml +59 -0
  138. package/engines/specs/hkex.yaml +40 -0
  139. package/engines/specs/hurriyet.yaml +43 -0
  140. package/engines/specs/iplant.yaml +25 -0
  141. package/engines/specs/jikan.yaml +24 -0
  142. package/engines/specs/jolpica.yaml +20 -0
  143. package/engines/specs/k10plus.yaml +20 -0
  144. package/engines/specs/keenable.yaml +44 -0
  145. package/engines/specs/keenable_free.yaml +36 -0
  146. package/engines/specs/lefigaro.yaml +43 -0
  147. package/engines/specs/listenbrainz.yaml +19 -0
  148. package/engines/specs/matichon.yaml +43 -0
  149. package/engines/specs/met_museum.yaml +21 -0
  150. package/engines/specs/nasa_images.yaml +45 -0
  151. package/engines/specs/netease_music.yaml +38 -0
  152. package/engines/specs/nhk.yaml +43 -0
  153. package/engines/specs/nhtsa_vpic.yaml +20 -0
  154. package/engines/specs/noaa_swpc.yaml +20 -0
  155. package/engines/specs/nvd.yaml +38 -0
  156. package/engines/specs/obis.yaml +20 -0
  157. package/engines/specs/opencitations.yaml +52 -0
  158. package/engines/specs/openf1.yaml +21 -0
  159. package/engines/specs/openfoodfacts.yaml +45 -0
  160. package/engines/specs/openligadb.yaml +20 -0
  161. package/engines/specs/openreview.yaml +37 -0
  162. package/engines/specs/openstd.yaml +21 -0
  163. package/engines/specs/people_daily.yaml +22 -0
  164. package/engines/specs/realtime_index.yaml +34 -0
  165. package/engines/specs/ror.yaml +20 -0
  166. package/engines/specs/satnogs.yaml +20 -0
  167. package/engines/specs/sec_edgar.yaml +46 -0
  168. package/engines/specs/shfe.yaml +39 -0
  169. package/engines/specs/skillsmp.yaml +50 -0
  170. package/engines/specs/sogou_weixin_browser.yaml +30 -0
  171. package/engines/specs/soilgrids.yaml +25 -0
  172. package/engines/specs/sspai.yaml +36 -0
  173. package/engines/specs/stackexchange.yaml +46 -0
  174. package/engines/specs/std_samr.yaml +21 -0
  175. package/engines/specs/tass.yaml +43 -0
  176. package/engines/specs/tavily_free.yaml +56 -0
  177. package/engines/specs/tle_mirror.yaml +21 -0
  178. package/engines/specs/train.yaml +37 -0
  179. package/engines/specs/tvmaze.yaml +20 -0
  180. package/engines/specs/twitter_syndication.yaml +31 -0
  181. package/engines/specs/un_comtrade.yaml +23 -0
  182. package/engines/specs/unpaywall.yaml +54 -0
  183. package/engines/specs/vnpress.yaml +43 -0
  184. package/engines/specs/weather.yaml +32 -0
  185. package/engines/specs/who_don.yaml +21 -0
  186. package/engines/specs/who_gho.yaml +20 -0
  187. package/engines/specs/wikimedia_commons.yaml +34 -0
  188. package/engines/specs/wikisource.yaml +22 -0
  189. package/engines/specs/worms.yaml +19 -0
  190. package/engines/specs/x_trending.yaml +34 -0
  191. package/engines/specs/yna.yaml +43 -0
  192. package/engines/specs/ynet.yaml +43 -0
  193. package/engines/specs/yuanbao.yaml +93 -0
  194. package/engines/specs/zbmath.yaml +40 -0
  195. package/engines/specs/zdic.yaml +22 -0
  196. package/engines/specs/zenodo.yaml +27 -0
  197. package/engines/specs/zhihu_hot_app.yaml +35 -0
  198. package/mcp/clients.yaml +106 -0
  199. package/package.json +55 -12
  200. package/packages/dsh-plugin/README.md +152 -0
  201. package/packages/dsh-plugin/cordis.patch.yml +48 -0
  202. package/packages/dsh-plugin/dsh/client.js +1533 -0
  203. package/packages/dsh-plugin/dsh/diagnostics.js +54 -0
  204. package/packages/dsh-plugin/dsh/index.js +527 -0
  205. package/packages/dsh-plugin/dsh/native-tools.mjs +749 -0
  206. package/packages/dsh-plugin/dsh/runner.js +666 -0
  207. package/packages/dsh-plugin/dsh/wide-research.js +878 -0
  208. package/packages/dsh-plugin/package.json +38 -0
  209. package/packages/dsh-plugin/scripts/sync-local.sh +70 -0
  210. package/packages/dsh-plugin/test/client.test.js +406 -0
  211. package/packages/dsh-plugin/test/config.test.js +30 -0
  212. package/packages/dsh-plugin/test/diagnostics.test.js +28 -0
  213. package/packages/dsh-plugin/test/index.test.js +1382 -0
  214. package/references/query-templates.md +96 -0
  215. package/references/query-templates.yaml +118 -0
  216. package/scripts/ab_eval.py +219 -0
  217. package/scripts/ab_eval_p0p1.py +266 -0
  218. package/scripts/adaptive.py +294 -70
  219. package/scripts/answer.py +154 -0
  220. package/scripts/archive_run.py +591 -0
  221. package/scripts/argo_engine_registry.py +172 -0
  222. package/scripts/argo_paths.py +728 -0
  223. package/scripts/article.py +136 -0
  224. package/scripts/article_meta.py +131 -0
  225. package/scripts/arxiv_source.py +201 -0
  226. package/scripts/badcase_ledger.py +252 -0
  227. package/scripts/batch_probe.py +241 -0
  228. package/scripts/benchmark.py +19 -0
  229. package/scripts/bounded_run.py +144 -0
  230. package/scripts/browser_auth.py +323 -0
  231. package/scripts/budget.py +247 -0
  232. package/scripts/budget_cli.py +93 -0
  233. package/scripts/build_release_assets.sh +65 -0
  234. package/scripts/burstiness_detector.py +147 -0
  235. package/scripts/cache.py +1066 -67
  236. package/scripts/cache_guard.py +271 -0
  237. package/scripts/cache_key_vdom.py +56 -0
  238. package/scripts/cache_similarity.py +170 -0
  239. package/scripts/caliber_isolation.py +195 -0
  240. package/scripts/calibrate_lowquality.py +210 -0
  241. package/scripts/candidate_envelope.py +366 -0
  242. package/scripts/chrome_cdp.py +871 -0
  243. package/scripts/ci_drift_gate.py +90 -0
  244. package/scripts/circuit_breaker.py +389 -0
  245. package/scripts/citations.py +334 -0
  246. package/scripts/cite_cli.py +59 -0
  247. package/scripts/cjk_tokens.py +95 -0
  248. package/scripts/clarify.py +47 -24
  249. package/scripts/cli_io.py +240 -0
  250. package/scripts/config.py +683 -45
  251. package/scripts/config_cache.py +402 -0
  252. package/scripts/conn_pool.py +220 -0
  253. package/scripts/content_boundary.py +46 -0
  254. package/scripts/content_security.py +685 -0
  255. package/scripts/content_signals.py +751 -0
  256. package/scripts/crawl.py +74 -35
  257. package/scripts/cross_lingual_trace.py +293 -0
  258. package/scripts/daemon.py +866 -0
  259. package/scripts/digup_bridge.py +214 -0
  260. package/scripts/dispatch_result.py +98 -0
  261. package/scripts/engine_admission.py +366 -0
  262. package/scripts/engine_dispatch.py +982 -0
  263. package/scripts/engine_env.py +539 -0
  264. package/scripts/engine_failure.py +411 -0
  265. package/scripts/engine_families.py +738 -0
  266. package/scripts/engine_policy.py +218 -0
  267. package/scripts/engine_requires.py +190 -0
  268. package/scripts/engine_status.py +322 -0
  269. package/scripts/engine_validate.py +638 -0
  270. package/scripts/engines.py +799 -294
  271. package/scripts/engines_base.py +1521 -0
  272. package/scripts/engines_builders.py +310 -0
  273. package/scripts/engines_builders_batch10.py +204 -0
  274. package/scripts/engines_builders_batch11.py +174 -0
  275. package/scripts/engines_builders_batch12.py +103 -0
  276. package/scripts/engines_builders_batch13.py +340 -0
  277. package/scripts/engines_builders_batch14.py +656 -0
  278. package/scripts/engines_builders_batch15.py +249 -0
  279. package/scripts/engines_builders_batch9.py +1468 -0
  280. package/scripts/engines_builders_cn.py +2283 -0
  281. package/scripts/engines_builders_data.py +2923 -0
  282. package/scripts/engines_builders_data_macro.py +775 -0
  283. package/scripts/engines_builders_feeds.py +255 -0
  284. package/scripts/engines_builders_intl.py +1239 -0
  285. package/scripts/engines_builders_keyless.py +111 -0
  286. package/scripts/engines_builders_search.py +440 -0
  287. package/scripts/engines_builders_tech.py +1359 -0
  288. package/scripts/evidence.py +620 -166
  289. package/scripts/evidence_loop.py +624 -0
  290. package/scripts/evidence_tier.py +298 -0
  291. package/scripts/except_sets.py +25 -0
  292. package/scripts/extract.py +55 -16
  293. package/scripts/fact_align.py +207 -0
  294. package/scripts/fact_crosscheck.py +230 -0
  295. package/scripts/fetch.py +25 -12
  296. package/scripts/fetch_browser.py +87 -0
  297. package/scripts/fetch_jsrun.py +122 -0
  298. package/scripts/fetch_quality.py +225 -0
  299. package/scripts/fetch_render_tinyfish.py +117 -0
  300. package/scripts/fetch_v3.py +1804 -0
  301. package/scripts/focus_extract.py +350 -0
  302. package/scripts/fulltext_store.py +169 -0
  303. package/scripts/fxtwitter_api.py +325 -0
  304. package/scripts/gen_engine_catalog.py +364 -0
  305. package/scripts/gen_native_tools.py +91 -0
  306. package/scripts/gen_routing_snapshot.py +195 -0
  307. package/scripts/health_check.py +140 -402
  308. package/scripts/health_probe.py +23 -8
  309. package/scripts/hot_state.py +134 -0
  310. package/scripts/http_client.py +1053 -0
  311. package/scripts/image_ops.py +430 -0
  312. package/scripts/image_vision/vision_probe.swift +126 -0
  313. package/scripts/install.ps1 +166 -0
  314. package/scripts/install.sh +221 -0
  315. package/scripts/job.py +1186 -0
  316. package/scripts/jump_resolver.py +235 -0
  317. package/scripts/lang_capability.py +150 -0
  318. package/scripts/lang_detect.py +289 -0
  319. package/scripts/lang_matrix_probe.py +329 -0
  320. package/scripts/lang_pref.py +311 -0
  321. package/scripts/link_source.py +340 -0
  322. package/scripts/local_image.py +970 -0
  323. package/scripts/local_seek.py +402 -0
  324. package/scripts/macro_countries.py +97 -0
  325. package/scripts/matrix_search_eval.py +1187 -0
  326. package/scripts/mcp_compact.py +234 -0
  327. package/scripts/mcp_diag.py +8 -3
  328. package/scripts/mcp_handlers.py +492 -0
  329. package/scripts/mcp_handlers_surface.py +157 -0
  330. package/scripts/mcp_launch.sh +124 -0
  331. package/scripts/mcp_local.py +241 -0
  332. package/scripts/mcp_server.py +125 -419
  333. package/scripts/mcp_setup.py +431 -0
  334. package/scripts/mcp_tools.py +331 -0
  335. package/scripts/mcp_transport.py +191 -0
  336. package/scripts/mcp_warm.py +127 -0
  337. package/scripts/min_version_scan.py +335 -0
  338. package/scripts/net_proxy.py +258 -0
  339. package/scripts/network_aware.py +152 -0
  340. package/scripts/output_transparency.py +200 -0
  341. package/scripts/paid_policy.py +98 -0
  342. package/scripts/paper.py +274 -0
  343. package/scripts/pdf_extract.py +518 -0
  344. package/scripts/phrase_filter.py +66 -0
  345. package/scripts/plan.py +422 -0
  346. package/scripts/postprocess_signals.py +150 -0
  347. package/scripts/pre-commit +48 -0
  348. package/scripts/query_enhance.py +157 -0
  349. package/scripts/query_operators.py +196 -0
  350. package/scripts/query_rewriter.py +116 -7
  351. package/scripts/query_signals.py +300 -0
  352. package/scripts/query_templates.py +167 -0
  353. package/scripts/query_understanding.py +411 -0
  354. package/scripts/query_variants.py +298 -0
  355. package/scripts/quota.py +633 -76
  356. package/scripts/rank_signals.py +775 -0
  357. package/scripts/ranking_eval.py +319 -0
  358. package/scripts/readability_extract.py +433 -0
  359. package/scripts/recompute.py +415 -0
  360. package/scripts/recovery.py +616 -0
  361. package/scripts/recovery_l0.py +160 -0
  362. package/scripts/recovery_runner.py +150 -0
  363. package/scripts/redskill/redskill_engine.py +332 -0
  364. package/scripts/regression_p0p1.py +318 -0
  365. package/scripts/replay_eval.py +658 -0
  366. package/scripts/rerank_tfidf.py +225 -0
  367. package/scripts/research.py +607 -403
  368. package/scripts/research_cli.py +361 -0
  369. package/scripts/research_dossier.py +492 -0
  370. package/scripts/research_expand.py +169 -0
  371. package/scripts/research_gates.py +272 -0
  372. package/scripts/research_report.py +209 -0
  373. package/scripts/research_strategy.py +37 -0
  374. package/scripts/research_work_packages.py +195 -0
  375. package/scripts/result_lang.py +311 -0
  376. package/scripts/retry_policy.py +76 -0
  377. package/scripts/robots_guard.py +259 -0
  378. package/scripts/route.py +921 -254
  379. package/scripts/route_bangs.py +40 -0
  380. package/scripts/route_cache.py +243 -0
  381. package/scripts/route_combo.py +917 -0
  382. package/scripts/route_domains.py +341 -0
  383. package/scripts/route_lang.py +605 -0
  384. package/scripts/route_log.py +63 -0
  385. package/scripts/route_policy.py +250 -0
  386. package/scripts/rrf_classic.py +66 -0
  387. package/scripts/screenshot.py +73 -0
  388. package/scripts/search.py +886 -406
  389. package/scripts/search_attribution.py +185 -0
  390. package/scripts/search_benchmark.py +407 -0
  391. package/scripts/search_cli.py +640 -0
  392. package/scripts/search_entry.py +395 -0
  393. package/scripts/search_output.py +690 -0
  394. package/scripts/search_pipeline.py +926 -0
  395. package/scripts/search_rank.py +991 -0
  396. package/scripts/search_types.py +129 -16
  397. package/scripts/seek_locator.py +68 -0
  398. package/scripts/semantic_evidence.py +391 -0
  399. package/scripts/serp_guard.py +336 -0
  400. package/scripts/serp_kill_log.py +74 -0
  401. package/scripts/single_flight.py +120 -0
  402. package/scripts/social_engines/__init__.py +10 -0
  403. package/scripts/social_engines/bilibili_engine.py +131 -0
  404. package/scripts/social_engines/hackernews_engine.py +113 -0
  405. package/scripts/social_engines/reddit_engine.py +172 -0
  406. package/scripts/social_engines/twitter_engine.py +397 -0
  407. package/scripts/social_engines/v2ex_engine.py +101 -0
  408. package/scripts/social_engines/weibo_engine.py +128 -0
  409. package/scripts/social_engines/xiaohongshu_engine.py +137 -0
  410. package/scripts/social_engines/zhihu_engine.py +139 -0
  411. package/scripts/social_research.py +201 -0
  412. package/scripts/sogou_weixin_browser.py +318 -0
  413. package/scripts/source_ledger.py +249 -0
  414. package/scripts/stage_timing.py +58 -0
  415. package/scripts/stats_cli.py +107 -0
  416. package/scripts/straggler_policy.py +60 -0
  417. package/scripts/stylometry_detector.py +231 -0
  418. package/scripts/sync_backends.py +353 -0
  419. package/scripts/sync_installs.py +29 -0
  420. package/scripts/template_cli.py +127 -0
  421. package/scripts/text_lexicon.py +72 -0
  422. package/scripts/tfidf_router.py +109 -37
  423. package/scripts/time_utils.py +233 -0
  424. package/scripts/topic_research_profiles.py +643 -0
  425. package/scripts/train.py +737 -0
  426. package/scripts/tweet.py +596 -0
  427. package/scripts/url_canon.py +217 -0
  428. package/scripts/url_optimize.py +56 -0
  429. package/scripts/url_safety.py +236 -0
  430. package/scripts/usage_log.py +116 -0
  431. package/scripts/usage_log_clean.py +113 -0
  432. package/scripts/v2ex_nodes.py +311 -0
  433. package/scripts/variant_recall.py +188 -0
  434. package/scripts/watch.py +205 -0
  435. package/scripts/wechat_article.py +258 -0
  436. package/scripts/wide_research.py +447 -0
  437. package/scripts/wx.py +349 -0
  438. package/scripts/x_article_fetch.py +141 -0
  439. package/scripts/x_search.py +234 -0
  440. package/scripts/x_trending.py +189 -0
  441. package/scripts/yaml_load.py +67 -0
  442. package/scripts/zhihu_quota.py +139 -0
  443. package/sub-skills/ego-search/SKILL.md +253 -0
  444. package/sub-skills/ego-search/scripts/ego_search.py +800 -0
  445. package/sub-skills/ego-search/scripts/merge.py +226 -0
  446. package/sub-skills/ego-search/scripts/quality.py +64 -0
  447. package/sub-skills/ego-search/scripts/runtime.py +172 -0
  448. package/sub-skills/ego-search/scripts/safety.py +109 -0
  449. package/sub-skills/ego-search/scripts/serp_spec.py +109 -0
  450. package/sub-skills/ego-search/scripts/webbridge_adapter.py +374 -0
  451. package/sub-skills/js-run/SKILL.md +67 -0
  452. package/sub-skills/js-run/scripts/jsrun.py +112 -0
  453. package/sub-skills/js-run/scripts/shim.js +188 -0
  454. package/sub-skills/local-search/SKILL.md +50 -53
  455. package/sub-skills/local-search/bm25.py +186 -0
  456. package/sub-skills/local-search/cli_runner.py +331 -0
  457. package/sub-skills/local-search/config.yaml +152 -55
  458. package/sub-skills/local-search/engine_registry.py +91 -26
  459. package/sub-skills/local-search/{health_check.py → local_health_check.py} +140 -10
  460. package/sub-skills/local-search/local_search_adapter.py +13 -2
  461. package/sub-skills/local-search/parse_maps.yaml +40 -42
  462. package/sub-skills/local-search/parsers.py +328 -0
  463. package/sub-skills/local-search/search_v3.py +716 -242
  464. package/sub-skills/local-search/smart_router.py +47 -7
  465. package/sub-skills/local-seek/SKILL.md +110 -0
  466. package/sub-skills/local-seek/config/domains.yaml +20 -0
  467. package/sub-skills/local-seek/scripts/eval_rank.py +216 -0
  468. package/sub-skills/local-seek/scripts/eval_seek.py +224 -0
  469. package/sub-skills/local-seek/scripts/seek.py +1465 -0
  470. package/sub-skills/local-seek/scripts/seek_frecency.py +126 -0
  471. package/sub-skills/local-seek/scripts/seek_fts.py +430 -0
  472. package/sub-skills/local-seek/scripts/seek_rank.py +197 -0
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env python3
2
+ """engine_policy.py — 引擎分层与 combo 预算(日常 vs 深度研究)
3
+
4
+ 单一策略层,避免 route/search/research 各自 if 分叉。
5
+
6
+ tier(引擎 config 可覆写 engines.<id>.tier):
7
+ daily_core 默认;意图命中即可跑
8
+ daily_support 同 daily,但优先被 budget 截断掉(靠 combo 后排)
9
+ research_only 仅 context=research / depth=deep / mode=deep
10
+
11
+ combo 预算:
12
+ fast / budget / depth=fast → 最多 2
13
+ auto / balanced → 最多 3
14
+ deep / research → 不截断(全 combo + research_only)
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from typing import Any, Callable, Iterable
20
+
21
+ # 默认 research_only:长尾/慢/脆,日常窄域主源不要标这里
22
+ DEFAULT_RESEARCH_ONLY: frozenset[str] = frozenset({
23
+ "wayback_cdx",
24
+ "archive_org",
25
+ "gutenberg",
26
+ "seeking_alpha",
27
+ "courtlistener",
28
+ "nasa_cmr",
29
+ "usgs", # earth_science 双源时 daily 只留 usgs 需 domain 有别的 core;见 filter 保底
30
+ "rcsb_pdb", # protein 以 uniprot 为主
31
+ })
32
+
33
+ # 明确 daily 答案源,永不标 research_only(防误配)
34
+ FORCE_DAILY_CORE: frozenset[str] = frozenset({
35
+ "sina_quote", "tencent_quote", "em_flow", "eastmoney",
36
+ "fred", "worldbank", "fx_rate", "nbs_stats", "eurostat",
37
+ "pubchem", "rfc_editor", "gbif", "clinicaltrials",
38
+ "finviz", "anysearch", "byted", "octen",
39
+ "arxiv", "github", "wikipedia",
40
+ "zhihu", "zhihu_hot",
41
+ })
42
+
43
+ # 通用免费保底源(唯一来源):route 保底 / 域内引擎全过滤 / recovery L3 共用。
44
+ # 顺序 = 通用检索优先(anysearch),本地零成本引擎居中(供语言引擎展开),
45
+ # 百科殿后(knowledge 族,最后保底)。route 侧本地优先时以 ["local_search"] 前缀
46
+ # 再引用本清单;recovery 直接按本顺序遍历。预算截断由调用方完成。
47
+ # 2026-09-07:duckduckgo 移出——本地使用日志 45% 错误率 + 实测 11.1s 0 条(本机网络
48
+ # 限流),串行保底链里它是最大死重;uapi 顶入(免 key 聚合,历史 521 次 0% 错)。
49
+ # 2026-09-12:firecrawl 顶入(免 key 云搜索,JS 渲染/PDF/学术垂直)——它的声明
50
+ # 一直写着「免费池可路由(daily_support)」,但没有接进任何分发路径,属死源;
51
+ # 排在通用检索源末位 + spec 的 tier=daily_support,日常 fast/auto 的 combo 预算
52
+ # (2/3 个)够不到它,只在 deep/research 无截断时参战,共享免费层不被烧穿。
53
+ GENERAL_FREE_FALLBACK: tuple[str, ...] = (
54
+ # 2026-10-21 A/B:octen 顶到第一位。交错对拍(ab_eval,4 对/查询、
55
+ # --no-cache)里 octen 对 anysearch 8:0 全胜:露营 天幕 p90 6313→835ms、
56
+ # asyncio p90 2769→963ms,结果数中位同为 8。生产日志同向:general_search
57
+ # 346 条查询里 324 条的最后一棒是 anysearch(p50 1932ms),octen 同域
58
+ # p50 776ms。anysearch 退到对冲位,能力面不变(仍在 combo 内)。
59
+ "octen", "anysearch", "local_bing", "uapi", "local_baidu", "firecrawl",
60
+ "parallel_free", "tavily_free", "keenable_free", "wikipedia",
61
+ )
62
+
63
+
64
+ def is_research_context(
65
+ *,
66
+ mode: str = "auto",
67
+ depth: str = "fast",
68
+ context: str = "search",
69
+ ) -> bool:
70
+ """是否允许 research_only 引擎与全量 combo。"""
71
+ if (context or "search") == "research":
72
+ return True
73
+ if (depth or "fast") == "deep":
74
+ return True
75
+ if (mode or "auto") == "deep":
76
+ return True
77
+ return False
78
+
79
+
80
+ def combo_budget(
81
+ *,
82
+ mode: str = "auto",
83
+ depth: str = "fast",
84
+ context: str = "search",
85
+ extra: int = 0,
86
+ ) -> int | None:
87
+ """combo 最大引擎数;None = 不截断。
88
+
89
+ extra:垂直域的「新专源加成」。批次九的 11 个新源声明在 combo 后排
90
+ (位次 3~6),而日常预算只有 2~3 —— 截断后它们永不参与自动路由。
91
+ 直接调大全局预算会拖慢所有查询,用 must_keep 顶位又会挤掉既有可用源
92
+ (实测会把 open_library/douban_movie/musicbrainz 挤出)。故只给
93
+ 「确有新专源待接」的垂直域加固定额度,其余域预算不变。
94
+ """
95
+ if is_research_context(mode=mode, depth=depth, context=context):
96
+ return None
97
+ base = 2 if ((mode or "auto") in ("fast", "budget")
98
+ or (depth or "fast") == "fast") else 3
99
+ return base + max(0, int(extra or 0))
100
+
101
+
102
+ def get_engine_tier(engine_id: str, spec: dict[str, Any] | None = None) -> str:
103
+ """解析引擎 tier。"""
104
+ if engine_id in FORCE_DAILY_CORE:
105
+ return "daily_core"
106
+ if spec:
107
+ t = (spec.get("tier") or "").strip().lower()
108
+ if t in ("daily_core", "daily_support", "research_only"):
109
+ return t
110
+ if engine_id in DEFAULT_RESEARCH_ONLY:
111
+ return "research_only"
112
+ return "daily_core"
113
+
114
+
115
+ def _tier_lookup() -> Callable[[str], str]:
116
+ try:
117
+ from config import get_engines, load_config
118
+ engines = get_engines(load_config())
119
+ except Exception:
120
+ engines = {} # 配置加载失败:退回空引擎表,tier 查询退化为默认值
121
+
122
+ def _t(eid: str) -> str:
123
+ return get_engine_tier(eid, engines.get(eid) if isinstance(engines, dict) else None)
124
+
125
+ return _t
126
+
127
+
128
+ def filter_combo_by_policy(
129
+ combo: list[str],
130
+ *,
131
+ mode: str = "auto",
132
+ depth: str = "fast",
133
+ context: str = "search",
134
+ tier_of: Callable[[str], str] | None = None,
135
+ budget_extra: int = 0,
136
+ ) -> list[str]:
137
+ """按 tier + budget 过滤 combo。
138
+
139
+ 若 research_only 过滤后为空(域内全是研究源),保留原 combo 再截断预算,
140
+ 避免「问蛋白质却一个引擎都没有」。
141
+
142
+ budget_extra:垂直域新专源加成,见 `combo_budget` 的 extra 说明。
143
+ """
144
+ if not combo:
145
+ return []
146
+ tier_of = tier_of or _tier_lookup()
147
+ allow_ro = is_research_context(mode=mode, depth=depth, context=context)
148
+
149
+ if allow_ro:
150
+ filtered = list(combo)
151
+ else:
152
+ kept = [e for e in combo if tier_of(e) != "research_only"]
153
+ filtered = kept if kept else list(combo)
154
+
155
+ budget = combo_budget(mode=mode, depth=depth, context=context,
156
+ extra=budget_extra)
157
+ if budget is not None and len(filtered) > budget:
158
+ filtered = filtered[:budget]
159
+ return filtered
160
+
161
+
162
+ def boost_into_combo(
163
+ combo: list[str],
164
+ boosts: Iterable[str] | None,
165
+ *,
166
+ enabled: set[str] | None = None,
167
+ max_total: int | None = None,
168
+ ) -> list[str]:
169
+ """将 boost 引擎插入 combo 前部(去重,可选 enabled 过滤)。
170
+
171
+ 用于研究子查询:不锁死单引擎,而是抬高垂直源优先级后仍走 auto 融合。
172
+ """
173
+ base = list(combo or [])
174
+ if not boosts:
175
+ out = base
176
+ else:
177
+ head: list[str] = []
178
+ for e in boosts:
179
+ if not e or e == "auto":
180
+ continue
181
+ if enabled is not None and e not in enabled:
182
+ continue
183
+ if e not in head:
184
+ head.append(e)
185
+ tail = [e for e in base if e not in head]
186
+ out = head + tail
187
+ if max_total is not None and max_total > 0:
188
+ out = out[:max_total]
189
+ return out
190
+
191
+
192
+ def research_engine_hints(
193
+ profile: dict[str, Any] | None,
194
+ sub_index: int,
195
+ ) -> list[str]:
196
+ """从选题 profile 生成子查询引擎 boost 列表。
197
+
198
+ 子查询 0:vertical + priority 前 2(广度)
199
+ 子查询 k>0:轮转 priority/vertical
200
+ """
201
+ if not profile:
202
+ return []
203
+ vertical = list(profile.get("vertical_engines") or [])
204
+ priority = list(profile.get("engines_priority") or [])
205
+ # 合并去重,vertical 优先
206
+ merged: list[str] = []
207
+ for e in vertical + priority:
208
+ if e and e not in merged:
209
+ merged.append(e)
210
+ if not merged:
211
+ return []
212
+ if sub_index <= 0:
213
+ return merged[:3]
214
+ # 轮转:每次取 2 个从 offset 起
215
+ n = len(merged)
216
+ start = (sub_index - 1) % n
217
+ picked = [merged[(start + i) % n] for i in range(min(2, n))]
218
+ return picked
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env python3
2
+ """engine_requires.py — 引擎后端依赖声明的解析、检查与修复指引。
3
+
4
+ 背景(v2.4.2):argo 的 CLI 引擎此前只校验 `cmd[-1]` 指向的脚本文件是否存在
5
+ (见 config._validate_engine_paths)。这对「壳脚本」型引擎完全无效:例如
6
+ xiaohongshu 引擎的 cmd 是 `python3 scripts/social_engines/xiaohongshu_engine.py`,
7
+ 脚本文件当然存在,于是状态显示 ready;但该脚本内部真正调用的 `xhs` 二进制
8
+ 依赖外部 CLI(xhs-cli),用户没装时它只是静默返回空列表——`--list-engines
9
+ --detail` 仍报 ready,调用后白等到超时、拿到 0 条,且无从知道「缺什么、怎么装」。
10
+
11
+ 本模块引入声明式依赖:
12
+
13
+ engines:
14
+ xiaohongshu:
15
+ requires:
16
+ - bin: xhs # 必需的 PATH 可执行文件
17
+ fix: npm i -g xiaohongshu-cli # 缺失时的修复指引
18
+ optional: false # true 时缺失只降级不报 missing_dep
19
+ - bin: yt-dlp
20
+ min_version: "2024.01.01" # 可选:最低版本(尽力检查)
21
+
22
+ 设计原则(与既有 required_env / engine_env.py 同构,属扩展而非外来物):
23
+ - 只声明「后端工具」,不声明「密钥」(密钥仍归 required_env)
24
+ - 检查是只读的:`shutil.which` + 一次 `--version` 调用,绝不自动安装
25
+ - 缺失必须给出可执行 fix 指令,否则声明即无意义
26
+ - 检查结果可缓存(同进程内),避免 list-engines 对 168 引擎反复起子进程
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import shutil
32
+ import subprocess
33
+ import threading
34
+ from typing import Any
35
+
36
+ # 进程内缓存:{(bin, min_version): (ok, actual_version, reason)}
37
+ _cache: dict[tuple[str, str | None], tuple[bool, str | None, str | None]] = {}
38
+ _cache_lock = threading.Lock()
39
+
40
+ # version 探测的候选参数(不同工具约定不同)
41
+ _VERSION_ARGS = ("--version", "-version", "-V", "version")
42
+
43
+
44
+ def _probe_version(bin_path: str, timeout: float = 3.0) -> str | None:
45
+ """尽力探测可执行文件的版本串;失败返回 None(不作为失败依据)。"""
46
+ for arg in _VERSION_ARGS:
47
+ try:
48
+ r = subprocess.run(
49
+ [bin_path, arg],
50
+ capture_output=True, text=True,
51
+ encoding="utf-8", errors="replace", # Windows GBK 下防乱码/崩溃
52
+ timeout=timeout,
53
+ )
54
+ out = (r.stdout or "") + (r.stderr or "")
55
+ out = out.strip()
56
+ if out:
57
+ return out.splitlines()[0][:120]
58
+ except Exception:
59
+ continue
60
+ return None
61
+
62
+
63
+ def _parse_version_numbers(text: str | None) -> tuple[int, ...]:
64
+ """从版本串里抽出数字段,用于比较。抽不到返回空元组。"""
65
+ if not text:
66
+ return ()
67
+ nums: list[int] = []
68
+ cur = ""
69
+ for ch in text:
70
+ if ch.isdigit():
71
+ cur += ch
72
+ else:
73
+ if cur:
74
+ nums.append(int(cur))
75
+ cur = ""
76
+ if cur:
77
+ nums.append(int(cur))
78
+ return tuple(nums[:4])
79
+
80
+
81
+ def _version_ok(actual: str | None, minimum: str | None) -> bool:
82
+ """actual >= minimum?任一解析不出数字则视为通过(不误报缺失)。"""
83
+ if not minimum:
84
+ return True
85
+ a, b = _parse_version_numbers(actual), _parse_version_numbers(minimum)
86
+ if not a or not b:
87
+ return True
88
+ n = max(len(a), len(b))
89
+ a = a + (0,) * (n - len(a))
90
+ b = b + (0,) * (n - len(b))
91
+ return a >= b
92
+
93
+
94
+ def check_requirement(req: dict[str, Any]) -> dict[str, Any]:
95
+ """检查单条依赖声明,返回结构化结果。
96
+
97
+ 返回 {bin, ok, actual_version, required_version, reason, fix, optional}
98
+ """
99
+ bin_name = str(req.get("bin") or "").strip()
100
+ minimum = req.get("min_version")
101
+ optional = bool(req.get("optional", False))
102
+ fix = str(req.get("fix") or "").strip()
103
+ out = {
104
+ "bin": bin_name,
105
+ "ok": False,
106
+ "actual_version": None,
107
+ "required_version": minimum,
108
+ "reason": None,
109
+ "fix": fix,
110
+ "optional": optional,
111
+ }
112
+ if not bin_name:
113
+ out["reason"] = "invalid-requirement"
114
+ return out
115
+
116
+ key = (bin_name, minimum)
117
+ with _cache_lock:
118
+ cached = _cache.get(key)
119
+ if cached is not None:
120
+ ok, actual, reason = cached
121
+ out.update({"ok": ok, "actual_version": actual, "reason": reason})
122
+ return out
123
+
124
+ path = shutil.which(bin_name)
125
+ if not path:
126
+ ok, actual, reason = False, None, "bin-not-found"
127
+ else:
128
+ actual = _probe_version(path)
129
+ if _version_ok(actual, minimum):
130
+ ok, reason = True, None
131
+ else:
132
+ ok, reason = False, "version-too-old"
133
+ with _cache_lock:
134
+ _cache[key] = (ok, actual, reason)
135
+ out.update({"ok": ok, "actual_version": actual, "reason": reason})
136
+ return out
137
+
138
+
139
+ def requirements_of(spec: dict[str, Any] | None) -> list[dict[str, Any]]:
140
+ """从 engine spec 取出 requires 声明(规范化成 list[dict])。
141
+
142
+ 容错:允许简写 `requires: [{bin: xhs}]`,也允许字符串简写
143
+ `requires: ["xhs"]`(等价 {bin: xhs}),便于手写 config。
144
+ """
145
+ spec = spec or {}
146
+ raw = spec.get("requires")
147
+ if not raw:
148
+ return []
149
+ if isinstance(raw, str):
150
+ raw = [raw]
151
+ if not isinstance(raw, list):
152
+ return []
153
+ out: list[dict[str, Any]] = []
154
+ for item in raw:
155
+ if isinstance(item, str) and item.strip():
156
+ out.append({"bin": item.strip()})
157
+ elif isinstance(item, dict) and item.get("bin"):
158
+ out.append(dict(item))
159
+ return out
160
+
161
+
162
+ def requires_status(spec: dict[str, Any] | None) -> dict[str, Any]:
163
+ """引擎依赖总览:缺失的必需项 + 全部检查明细。
164
+
165
+ missing_deps 只含必需项(optional 缺失不算),保证状态机
166
+ `missing_dep` 只反映「真的跑不了」,不把可选增强算成故障。
167
+ """
168
+ reqs = requirements_of(spec)
169
+ if not reqs:
170
+ return {"requires": [], "missing_deps": [], "dep_ready": True,
171
+ "dep_fixes": []}
172
+ checked = [check_requirement(r) for r in reqs]
173
+ missing = [c for c in checked if not c["ok"] and not c["optional"]]
174
+ return {
175
+ "requires": checked,
176
+ "missing_deps": [{"bin": c["bin"], "reason": c["reason"],
177
+ "fix": c["fix"]} for c in missing],
178
+ "dep_ready": not missing,
179
+ # 修复指引:缺失项自带 fix;未声明 fix 的给通用保底提示
180
+ "dep_fixes": [
181
+ c["fix"] or f"安装 {c['bin']} 并确保其在 PATH 上"
182
+ for c in missing
183
+ ],
184
+ }
185
+
186
+
187
+ def clear_cache() -> None:
188
+ """清空探测缓存(测试与配置热更新用)。"""
189
+ with _cache_lock:
190
+ _cache.clear()