@konbakuyomu/smart-search-linux-x64 0.1.27 → 0.1.29

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 (30) hide show
  1. package/package.json +1 -1
  2. package/runtime/smart-search/_internal/base_library.zip +0 -0
  3. package/runtime/smart-search/_internal/certifi/cacert.pem +0 -104
  4. package/runtime/smart-search/_internal/smart_search/assets/i18n/messages.json +108 -0
  5. package/runtime/smart-search/_internal/smart_search/assets/skills/smart-search-cli/references/cli-core.md +1 -1
  6. package/runtime/smart-search/_internal/smart_search/assets/skills/smart-search-cli/references/command-patterns.md +2 -0
  7. package/runtime/smart-search/_internal/smart_search/assets/skills/smart-search-cli/references/provider-routing.md +11 -3
  8. package/runtime/smart-search/_internal/smart_search/assets/skills/smart-search-cli/references/setup-config.md +2 -0
  9. package/runtime/smart-search/_internal/smart_search/assets/ui/index.html +1 -1
  10. package/runtime/smart-search/_internal/smart_search/cli.py +35 -3
  11. package/runtime/smart-search/_internal/smart_search/config.py +20 -1
  12. package/runtime/smart-search/_internal/smart_search/jev_search.py +9 -1
  13. package/runtime/smart-search/_internal/smart_search/provider_descriptions.py +14 -0
  14. package/runtime/smart-search/_internal/smart_search/providers/__init__.py +2 -0
  15. package/runtime/smart-search/_internal/smart_search/providers/deepseek.py +110 -0
  16. package/runtime/smart-search/_internal/smart_search/service.py +84 -10
  17. package/runtime/smart-search/_internal/smart_search/skill_maintenance.py +30 -6
  18. package/runtime/smart-search/_internal/smart_search/ui_metadata.py +18 -0
  19. package/runtime/smart-search/_internal/smart_search/ui_server.py +44 -3
  20. package/runtime/smart-search/_internal/{smart_search-0.1.27.dist-info → smart_search-0.1.29.dist-info}/METADATA +1 -1
  21. package/runtime/smart-search/_internal/{smart_search-0.1.27.dist-info → smart_search-0.1.29.dist-info}/RECORD +26 -24
  22. package/runtime/smart-search/package.json +7 -7
  23. package/runtime/smart-search/smart-search +0 -0
  24. /package/runtime/smart-search/_internal/{smart_search-0.1.27.dist-info → smart_search-0.1.29.dist-info}/INSTALLER +0 -0
  25. /package/runtime/smart-search/_internal/{smart_search-0.1.27.dist-info → smart_search-0.1.29.dist-info}/REQUESTED +0 -0
  26. /package/runtime/smart-search/_internal/{smart_search-0.1.27.dist-info → smart_search-0.1.29.dist-info}/WHEEL +0 -0
  27. /package/runtime/smart-search/_internal/{smart_search-0.1.27.dist-info → smart_search-0.1.29.dist-info}/direct_url.json +0 -0
  28. /package/runtime/smart-search/_internal/{smart_search-0.1.27.dist-info → smart_search-0.1.29.dist-info}/entry_points.txt +0 -0
  29. /package/runtime/smart-search/_internal/{smart_search-0.1.27.dist-info → smart_search-0.1.29.dist-info}/licenses/LICENSE +0 -0
  30. /package/runtime/smart-search/_internal/{smart_search-0.1.27.dist-info → smart_search-0.1.29.dist-info}/top_level.txt +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konbakuyomu/smart-search-linux-x64",
3
- "version": "0.1.27",
3
+ "version": "0.1.29",
4
4
  "description": "Self-contained Smart Search CLI for linux/x64",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1975,110 +1975,6 @@ jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw
1975
1975
  3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
1976
1976
  -----END CERTIFICATE-----
1977
1977
 
1978
- # Issuer: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI
1979
- # Subject: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI
1980
- # Label: "emSign Root CA - G1"
1981
- # Serial: 235931866688319308814040
1982
- # MD5 Fingerprint: 9c:42:84:57:dd:cb:0b:a7:2e:95:ad:b6:f3:da:bc:ac
1983
- # SHA1 Fingerprint: 8a:c7:ad:8f:73:ac:4e:c1:b5:75:4d:a5:40:f4:fc:cf:7c:b5:8e:8c
1984
- # SHA256 Fingerprint: 40:f6:af:03:46:a9:9a:a1:cd:1d:55:5a:4e:9c:ce:62:c7:f9:63:46:03:ee:40:66:15:83:3d:c8:c8:d0:03:67
1985
- -----BEGIN CERTIFICATE-----
1986
- MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD
1987
- VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU
1988
- ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH
1989
- MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO
1990
- MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv
1991
- Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN
1992
- BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz
1993
- f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO
1994
- 8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq
1995
- d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM
1996
- tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt
1997
- Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB
1998
- o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD
1999
- AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x
2000
- PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM
2001
- wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d
2002
- GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH
2003
- 6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby
2004
- RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
2005
- iN66zB+Afko=
2006
- -----END CERTIFICATE-----
2007
-
2008
- # Issuer: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI
2009
- # Subject: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI
2010
- # Label: "emSign ECC Root CA - G3"
2011
- # Serial: 287880440101571086945156
2012
- # MD5 Fingerprint: ce:0b:72:d1:9f:88:8e:d0:50:03:e8:e3:b8:8b:67:40
2013
- # SHA1 Fingerprint: 30:43:fa:4f:f2:57:dc:a0:c3:80:ee:2e:58:ea:78:b2:3f:e6:bb:c1
2014
- # SHA256 Fingerprint: 86:a1:ec:ba:08:9c:4a:8d:3b:be:27:34:c6:12:ba:34:1d:81:3e:04:3c:f9:e8:a8:62:cd:5c:57:a3:6b:be:6b
2015
- -----BEGIN CERTIFICATE-----
2016
- MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG
2017
- EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo
2018
- bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
2019
- RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ
2020
- TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s
2021
- b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw
2022
- djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0
2023
- WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS
2024
- fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB
2025
- zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq
2026
- hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB
2027
- CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD
2028
- +JbNR6iC8hZVdyR+EhCVBCyj
2029
- -----END CERTIFICATE-----
2030
-
2031
- # Issuer: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI
2032
- # Subject: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI
2033
- # Label: "emSign Root CA - C1"
2034
- # Serial: 825510296613316004955058
2035
- # MD5 Fingerprint: d8:e3:5d:01:21:fa:78:5a:b0:df:ba:d2:ee:2a:5f:68
2036
- # SHA1 Fingerprint: e7:2e:f1:df:fc:b2:09:28:cf:5d:d4:d5:67:37:b1:51:cb:86:4f:01
2037
- # SHA256 Fingerprint: 12:56:09:aa:30:1d:a0:a2:49:b9:7a:82:39:cb:6a:34:21:6f:44:dc:ac:9f:39:54:b1:42:92:f2:e8:c8:60:8f
2038
- -----BEGIN CERTIFICATE-----
2039
- MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG
2040
- A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg
2041
- SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw
2042
- MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln
2043
- biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v
2044
- dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ
2045
- BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ
2046
- HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH
2047
- 3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH
2048
- GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c
2049
- xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1
2050
- aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq
2051
- TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
2052
- BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87
2053
- /kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4
2054
- kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG
2055
- YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT
2056
- +xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo
2057
- WXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
2058
- -----END CERTIFICATE-----
2059
-
2060
- # Issuer: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI
2061
- # Subject: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI
2062
- # Label: "emSign ECC Root CA - C3"
2063
- # Serial: 582948710642506000014504
2064
- # MD5 Fingerprint: 3e:53:b3:a3:81:ee:d7:10:f8:d3:b0:1d:17:92:f5:d5
2065
- # SHA1 Fingerprint: b6:af:43:c2:9b:81:53:7d:f6:ef:6b:c3:1f:1f:60:15:0c:ee:48:66
2066
- # SHA256 Fingerprint: bc:4d:80:9b:15:18:9d:78:db:3e:1d:8c:f4:f9:72:6a:79:5d:a1:64:3c:a5:f1:35:8e:1d:db:0e:dc:0d:7e:b3
2067
- -----BEGIN CERTIFICATE-----
2068
- MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG
2069
- EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx
2070
- IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw
2071
- MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln
2072
- biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND
2073
- IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci
2074
- MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti
2075
- sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O
2076
- BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
2077
- Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c
2078
- 3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J
2079
- 0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
2080
- -----END CERTIFICATE-----
2081
-
2082
1978
  # Issuer: CN=Hongkong Post Root CA 3 O=Hongkong Post
2083
1979
  # Subject: CN=Hongkong Post Root CA 3 O=Hongkong Post
2084
1980
  # Label: "Hongkong Post Root CA 3"
@@ -17858,5 +17858,113 @@
17858
17858
  "{0} 另外,联网搜索能力检查未通过:{1}。OpenAI-compatible 不会发送搜索工具;如果该模型只能通过 Responses 的 web_search 工具联网,请把 XAI_API_URL、XAI_API_KEY、XAI_MODEL 指向支持 /v1/responses 的中转站。": [
17859
17859
  "{0} 另外,联网搜索能力检查未通过:{1}。OpenAI-compatible 不会发送搜索工具;如果该模型只能通过 Responses 的 web_search 工具联网,请把 XAI_API_URL、XAI_API_KEY、XAI_MODEL 指向支持 /v1/responses 的中转站。",
17860
17860
  "{0} Also, the web search capability check did not pass: {1}. OpenAI-compatible sends no search tool; if this model can only search through the Responses web_search tool, point XAI_API_URL, XAI_API_KEY and XAI_MODEL at a relay that supports /v1/responses."
17861
+ ],
17862
+ "DeepSeek search response is not a JSON object": [
17863
+ "DeepSeek 搜索响应不是 JSON 对象",
17864
+ "DeepSeek search response is not a JSON object"
17865
+ ],
17866
+ "DeepSeek search response is missing results": [
17867
+ "DeepSeek 搜索响应缺少 results",
17868
+ "DeepSeek search response is missing results"
17869
+ ],
17870
+ "DeepSeek fetch response is not a JSON object": [
17871
+ "DeepSeek 抓取响应不是 JSON 对象",
17872
+ "DeepSeek fetch response is not a JSON object"
17873
+ ],
17874
+ "DeepSeek fetch content is not text": [
17875
+ "DeepSeek 抓取内容不是文本",
17876
+ "DeepSeek fetch content is not text"
17877
+ ],
17878
+ "DeepSeek search: {0}": [
17879
+ "DeepSeek 搜索:{0}",
17880
+ "DeepSeek search: {0}"
17881
+ ],
17882
+ "DeepSeek fetch: {0}": [
17883
+ "DeepSeek 抓取:{0}",
17884
+ "DeepSeek fetch: {0}"
17885
+ ],
17886
+ "DeepSeek fetch returned no content for {0}": [
17887
+ "DeepSeek 抓取 {0} 没有返回正文",
17888
+ "DeepSeek fetch returned no content for {0}"
17889
+ ],
17890
+ "DEEPSEEK_API_KEY is not set. DeepSeek search and fetch are unavailable.": [
17891
+ "DEEPSEEK_API_KEY 未设置,DeepSeek 搜索与抓取不可用",
17892
+ "DEEPSEEK_API_KEY is not set. DeepSeek search and fetch are unavailable."
17893
+ ],
17894
+ "DEEPSEEK_API_KEY 未设置,DeepSeek 搜索与抓取不可用": [
17895
+ "DEEPSEEK_API_KEY 未设置,DeepSeek 搜索与抓取不可用",
17896
+ "DEEPSEEK_API_KEY is not set. DeepSeek search and fetch are unavailable."
17897
+ ],
17898
+ "Both DeepSeek search and fetch APIs are available": [
17899
+ "DeepSeek 搜索与抓取 API 均可用",
17900
+ "Both DeepSeek search and fetch APIs are available"
17901
+ ],
17902
+ "DeepSeek 搜索与抓取 API 均可用": [
17903
+ "DeepSeek 搜索与抓取 API 均可用",
17904
+ "Both DeepSeek search and fetch APIs are available"
17905
+ ],
17906
+ "DeepSeek API request timed out": [
17907
+ "DeepSeek API 请求超时",
17908
+ "DeepSeek API request timed out"
17909
+ ],
17910
+ "DeepSeek API 请求超时": [
17911
+ "DeepSeek API 请求超时",
17912
+ "DeepSeek API request timed out"
17913
+ ],
17914
+ "Save DEEPSEEK_API_KEY.": [
17915
+ "保存 DEEPSEEK_API_KEY。",
17916
+ "Save DEEPSEEK_API_KEY."
17917
+ ],
17918
+ "Save DEEPSEEK_API_URL.": [
17919
+ "保存 DEEPSEEK_API_URL。",
17920
+ "Save DEEPSEEK_API_URL."
17921
+ ],
17922
+ "Save DEEPSEEK_TIMEOUT_SECONDS.": [
17923
+ "保存 DEEPSEEK_TIMEOUT_SECONDS。",
17924
+ "Save DEEPSEEK_TIMEOUT_SECONDS."
17925
+ ],
17926
+ "没有找到 WSL 发行版。": [
17927
+ "没有找到 WSL 发行版。",
17928
+ "No WSL distribution was found."
17929
+ ],
17930
+ "没有在 WSL 中找到 smart-search。请先在 WSL 中安装 CLI,并确认 bash 能直接运行 smart-search。": [
17931
+ "没有在 WSL 中找到 smart-search。请先在 WSL 中安装 CLI,并确认 bash 能直接运行 smart-search。",
17932
+ "smart-search was not found in WSL. Install the CLI in WSL first and make sure bash can run smart-search directly."
17933
+ ],
17934
+ "位于 WSL {0},使用该发行版中的配置和 Skills。请在 WSL 终端用原安装方式更新 CLI。": [
17935
+ "位于 WSL {0},使用该发行版中的配置和 Skills。请在 WSL 终端用原安装方式更新 CLI。",
17936
+ "Installed in WSL {0}; it uses that distribution's configuration and Skills. Update the CLI from a WSL terminal with the tool you installed it with."
17937
+ ],
17938
+ "WSL {0} 中的 CLI 版本过旧,App 无法连接。请在 WSL 终端更新:npm install -g @konbakuyomu/smart-search@latest": [
17939
+ "WSL {0} 中的 CLI 版本过旧,App 无法连接。请在 WSL 终端更新:npm install -g @konbakuyomu/smart-search@latest",
17940
+ "The CLI in WSL {0} is too old for the App to connect. Update it from a WSL terminal: npm install -g @konbakuyomu/smart-search@latest"
17941
+ ],
17942
+ "旧版": [
17943
+ "旧版",
17944
+ "old version"
17945
+ ],
17946
+ "当前连接的是 WSL 中的 CLI,只观察它自己的配置目录。": [
17947
+ "当前连接的是 WSL 中的 CLI,只观察它自己的配置目录。",
17948
+ "Connected to a CLI in WSL; only its own configuration directory is observed."
17949
+ ],
17950
+ "这是 WSL 中的目录。需要更换时,在 WSL 中设置 SMART_SEARCH_CONFIG_DIR。": [
17951
+ "这是 WSL 中的目录。需要更换时,在 WSL 中设置 SMART_SEARCH_CONFIG_DIR。",
17952
+ "This directory is inside WSL. To use another one, set SMART_SEARCH_CONFIG_DIR in WSL."
17953
+ ],
17954
+ "WSL 中的 CLI 使用该发行版自己的配置和 Skills。未运行的发行版不会自动启动。": [
17955
+ "WSL 中的 CLI 使用该发行版自己的配置和 Skills。未运行的发行版不会自动启动。",
17956
+ "A CLI in WSL uses that distribution's own configuration and Skills. Stopped distributions are not started automatically."
17957
+ ],
17958
+ "未运行:{0}。“检测 WSL”会启动这些发行版并查找 CLI。": [
17959
+ "未运行:{0}。“检测 WSL”会启动这些发行版并查找 CLI。",
17960
+ "Not running: {0}. Detect WSL starts them to look for the CLI."
17961
+ ],
17962
+ "检测 WSL": [
17963
+ "检测 WSL",
17964
+ "Detect WSL"
17965
+ ],
17966
+ "{0} · 需要更新": [
17967
+ "{0} · 需要更新",
17968
+ "{0} · update needed"
17861
17969
  ]
17862
17970
  }
@@ -48,7 +48,7 @@
48
48
  - `smart-search map URL [--instructions TEXT] [--max-depth N] [--max-breadth N] [--limit N] [--timeout SECONDS] [--format json|markdown|content] [--output PATH]`
49
49
  - `smart-search doctor [--format json|markdown|content] [--output PATH]`
50
50
  - `smart-search diagnose openai-compatible [--timeout SECONDS] [--format json|markdown] [--output PATH]`
51
- - `smart-search setup [--lang zh|en] [--advanced] [--non-interactive] [--skip-skills] [--install-skills CSV] [--skills-root PATH] [--xai-api-url URL] [--xai-api-key KEY] [--xai-model ID] [--xai-tools-explicit CSV] [--openai-compatible-api-url URL] [--openai-compatible-api-key KEY] [--openai-compatible-model ID] [--openai-compatible-fallback-models CSV] [--openai-compatible-api-mode chat-completions|responses] [--openai-compatible-stream true|false] [--validation-level fast|balanced|strict] [--fallback-mode auto|off] [--minimum-profile standard|off] [--intent-router jev|local] [--search-timeout SECONDS] [--provider-cooldown SECONDS] [--provider-failure-threshold N] [--exa-key KEY] [--context7-key KEY] [--zhipu-key KEY] [--zhipu-api-url URL] [--zhipu-search-engine ENGINE] [--zhipu-mcp-key KEY] [--zhipu-mcp-search-api-url URL] [--zhipu-mcp-reader-api-url URL] [--zhipu-mcp-zread-api-url URL] [--zhipu-mcp-timeout SECONDS] [--jina-key KEY] [--jina-reader-api-url URL] [--jina-respond-with MODE] [--jina-timeout SECONDS] [--tavily-api-url URL] [--tavily-key KEY] [--firecrawl-api-url URL] [--firecrawl-key KEY] [--tinyfish-key KEY] [--tinyfish-search-api-url URL] [--tinyfish-fetch-api-url URL] [--tinyfish-timeout SECONDS] [--anysearch-api-url URL] [--anysearch-key KEY] [--anysearch-timeout SECONDS] [--sciverse-api-url URL] [--sciverse-token TOKEN] [--sciverse-timeout SECONDS] [--format json|markdown|content] [--output PATH]`
51
+ - `smart-search setup [--lang zh|en] [--advanced] [--non-interactive] [--skip-skills] [--install-skills CSV] [--skills-root PATH] [--xai-api-url URL] [--xai-api-key KEY] [--xai-model ID] [--xai-tools-explicit CSV] [--openai-compatible-api-url URL] [--openai-compatible-api-key KEY] [--openai-compatible-model ID] [--openai-compatible-fallback-models CSV] [--openai-compatible-api-mode chat-completions|responses] [--openai-compatible-stream true|false] [--validation-level fast|balanced|strict] [--fallback-mode auto|off] [--minimum-profile standard|off] [--intent-router jev|local] [--search-timeout SECONDS] [--provider-cooldown SECONDS] [--provider-failure-threshold N] [--exa-key KEY] [--context7-key KEY] [--zhipu-key KEY] [--zhipu-api-url URL] [--zhipu-search-engine ENGINE] [--zhipu-mcp-key KEY] [--zhipu-mcp-search-api-url URL] [--zhipu-mcp-reader-api-url URL] [--zhipu-mcp-zread-api-url URL] [--zhipu-mcp-timeout SECONDS] [--jina-key KEY] [--jina-reader-api-url URL] [--jina-respond-with MODE] [--jina-timeout SECONDS] [--tavily-api-url URL] [--tavily-key KEY] [--firecrawl-api-url URL] [--firecrawl-key KEY] [--tinyfish-key KEY] [--tinyfish-search-api-url URL] [--tinyfish-fetch-api-url URL] [--tinyfish-timeout SECONDS] [--deepseek-key KEY] [--deepseek-api-url URL] [--deepseek-timeout SECONDS] [--anysearch-api-url URL] [--anysearch-key KEY] [--anysearch-timeout SECONDS] [--sciverse-api-url URL] [--sciverse-token TOKEN] [--sciverse-timeout SECONDS] [--format json|markdown|content] [--output PATH]`
52
52
  - `smart-search config path|list|set|unset ... [--format json|markdown|content] [--output PATH]`
53
53
  - `smart-search model set MODEL [--format json|markdown|content] [--output PATH]`
54
54
  - `smart-search model current [--format json|markdown|content] [--output PATH]`
@@ -96,6 +96,8 @@ smart-search config set FIRECRAWL_API_URL "https://api.firecrawl.dev/v2" --forma
96
96
  smart-search config set TINYFISH_API_KEY "key" --format json
97
97
  smart-search config set TINYFISH_SEARCH_API_URL "https://api.search.tinyfish.ai" --format json
98
98
  smart-search config set TINYFISH_FETCH_API_URL "https://api.fetch.tinyfish.ai" --format json
99
+ smart-search config set DEEPSEEK_API_KEY "key" --format json
100
+ smart-search config set DEEPSEEK_API_URL "https://api.deepseek.com" --format json
99
101
  smart-search model current --format json
100
102
  smart-search doctor --format json
101
103
  smart-search doctor --format markdown
@@ -32,11 +32,11 @@ For research, `SMART_SEARCH_JEV_SYNTHESIZE` accepts `true`, `false`, and `auto`.
32
32
  - Jina Reader is `web_fetch` only, not a general search provider. `JINA_API_KEY` is required before Jina satisfies the standard minimum profile; anonymous `r.jina.ai` is explicit/experimental fetch behavior.
33
33
  - Same-capability fallback is allowed; model answers and web search are mutual fallbacks in ordinary search. Context7 is not used for unrelated broad web queries, and page extraction providers are not used as docs search providers.
34
34
  - `TAVILY_ENABLED=false` removes Tavily from registered `web_search` and `web_fetch` routes even when its key is present. Direct Tavily search/extract calls, `map`, `doctor`, and smoke must make no Tavily network request; `map` reports a local configuration error. Firecrawl remains independently configured and all fallback stays within its capability.
35
- - In Jev mode, Jev chooses among allowed capabilities and providers for the question; there is no mandatory main-model call or fixed global provider order. Local routing prioritizes suitable capabilities and configured preferences.
36
- - `main_search` contains xAI Responses and OpenAI-compatible model channels; `web_search` contains Zhipu REST/MCP, Tavily, Firecrawl and TinyFish; `docs_search` contains Context7 and Exa. Failure fallback stays within the selected capability family; model answers and web search are mutual fallbacks in ordinary search.
35
+ - In Jev mode, Jev chooses among allowed capabilities and providers for the question; there is no mandatory main-model call or fixed global provider order. Local routing prioritizes suitable capabilities and configured preferences; a docs question with no docs channel configured uses web search instead of no channel.
36
+ - `main_search` contains xAI Responses and OpenAI-compatible model channels; `web_search` contains Zhipu REST/MCP, Tavily, Firecrawl, TinyFish and DeepSeek; `docs_search` contains Context7 and Exa. Failure fallback stays within the selected capability family; model answers and web search are mutual fallbacks in ordinary search.
37
37
  - Ordinary Context7 uses the first library in Context7's ranked candidates, without a second Jev call. Research may use Jev to select the matching library, using the first candidate if Jev fails or no score reaches its threshold. Empty results may fall through to same-capability Exa; explicit Context7 commands remain unchanged.
38
38
  - `--extra-sources N` controls the selected channel's result count. It does not add channels, split a budget between providers, or make Tavily/Firecrawl a required extra stage. A known-URL search follows the configured Jev/local routing; local routing prefers page reading.
39
- - `fetch` tries Tavily first, then Jina with `JINA_API_KEY`, then Zhipu Coding Plan MCP Reader, then Firecrawl, then TinyFish.
39
+ - `fetch` tries Tavily first, then Jina with `JINA_API_KEY`, then Zhipu Coding Plan MCP Reader, then Firecrawl, then TinyFish, then DeepSeek.
40
40
 
41
41
  TinyFish:
42
42
 
@@ -47,6 +47,14 @@ TinyFish:
47
47
  - Fetch reads `results[0].text`; `errors[]` entries are surfaced as `provider_error` with the upstream message. A payload with neither results nor errors is `provider_error`, and a non-object payload is `parse_error`.
48
48
  - Challenge pages such as `Checking if the site connection is secure` are reported as `quality_error` so same-capability fallback can continue.
49
49
  - `401`/403 map to `auth_error`, `408` to `timeout`, `429` to `rate_limited`, `5xx` to `network_error`, and `400`/422 to `parameter_error`.
50
+ DeepSeek:
51
+
52
+ - `DEEPSEEK_API_KEY` is optional and registers DeepSeek for both `web_search` and `web_fetch`; it is the same key as the DeepSeek model API. It never satisfies `main_search` or `docs_search`. Jev may select it directly; the direct `fetch` fallback order remains as listed above.
53
+ - `DEEPSEEK_API_URL` defaults to `https://api.deepseek.com`; search calls `POST /v1/tools/search` with `{"query", "count"}` and fetch calls `POST /v1/tools/fetch` with `{"url"}`, both with `Authorization: Bearer`. A trailing `/v1` in the base URL is accepted. Never log or echo the key.
54
+ - DeepSeek accepts queries of at most 128 characters, so longer queries are shortened at a word boundary. `site:`, `-site:`, `lang:`, `after:`/`before:` and quoted phrases in the query pass through unchanged.
55
+ - Search results normalize `summary` (falling back to `snippet`) to `description`, `site_name` to `source`, and `date` to `published_date`. Summaries are not page text: fetch a key page before citing it. An empty result set is a successful empty response.
56
+ - Fetch returns the page Markdown. HTTP 403 (URL refused by DeepSeek's safety policy) and 404 (no usable page content, which currently includes PDF links and private network addresses) mean that page has nothing to read: the attempt is `empty`, fallback continues, and the provider is not cooled down. `401` maps to `auth_error`, `402` (insufficient balance) to `provider_error`, `429` to `rate_limited`, `5xx` to `network_error`.
57
+ - DeepSeek bills each successful search or fetch request. `doctor` and `providers test deepseek` send one real request to each.
50
58
  - `map` currently uses Tavily only.
51
59
  - `exa-search` and `exa-similar` use Exa only.
52
60
  - `context7-library` and `context7-docs` use Context7 only.
@@ -98,6 +98,8 @@
98
98
  - Use `smart-search setup --non-interactive --tinyfish-key "key"` to add TinyFish to `web_search` and `web_fetch`. It never satisfies `main_search` or `docs_search`; Jev can select it among the allowed channels.
99
99
  - `TINYFISH_SEARCH_API_URL` defaults to `https://api.search.tinyfish.ai`, and `TINYFISH_FETCH_API_URL` defaults to `https://api.fetch.tinyfish.ai`. Both authenticate with the `X-API-Key` header, not a bearer token.
100
100
  - `TINYFISH_TIMEOUT_SECONDS` defaults to `60` and covers both TinyFish search and fetch reads.
101
+ - Use `smart-search setup --non-interactive --deepseek-key "key"` to add DeepSeek to `web_search` and `web_fetch` with the same key as the DeepSeek model API. It never satisfies `main_search` or `docs_search`; Jev can select it among the allowed channels.
102
+ - `DEEPSEEK_API_URL` defaults to `https://api.deepseek.com`, and `DEEPSEEK_TIMEOUT_SECONDS` defaults to `60` and covers both DeepSeek search and fetch reads. Each successful DeepSeek request is billed.
101
103
 
102
104
  ## Provider Failure Cooldown
103
105
 
@@ -691,7 +691,7 @@ details.more[open] > summary::before { content: "▾ "; }
691
691
  { capability: "docs_search", title: "stepDocs",
692
692
  providers: ["context7", "exa"] },
693
693
  { capability: "web_fetch", title: "stepFetch",
694
- providers: ["tavily", "jina", "zhipu-mcp-reader", "zhipu-mcp", "firecrawl"] }
694
+ providers: ["tavily", "jina", "zhipu-mcp-reader", "zhipu-mcp", "firecrawl", "deepseek"] }
695
695
  ];
696
696
 
697
697
  function viewGettingStarted() {
@@ -627,6 +627,7 @@ def _format_doctor_markdown(data: dict[str, Any]) -> str:
627
627
  ("jina", data.get("jina_connection_test") or {}),
628
628
  ("firecrawl", data.get("firecrawl_connection_test") or {}),
629
629
  ("tinyfish", data.get("tinyfish_connection_test") or {}),
630
+ ("deepseek", data.get("deepseek_connection_test") or {}),
630
631
  ("zhipu", data.get("zhipu_connection_test") or {}),
631
632
  ("zhipu-mcp", data.get("zhipu_mcp_connection_test") or {}),
632
633
  ("context7", data.get("context7_connection_test") or {}),
@@ -1478,6 +1479,7 @@ def _display_provider(provider: str, lang: str) -> str:
1478
1479
  "tavily": "Tavily",
1479
1480
  "firecrawl": "Firecrawl",
1480
1481
  "tinyfish": "TinyFish",
1482
+ "deepseek": "DeepSeek",
1481
1483
  "anysearch": "AnySearch",
1482
1484
  "sciverse": "Sciverse",
1483
1485
  }
@@ -2078,7 +2080,7 @@ def _prompt_web_fetch(values: dict[str, str], current: dict[str, str], lang: str
2078
2080
  "选择 web_fetch provider",
2079
2081
  "Choose web_fetch providers",
2080
2082
  ),
2081
- ["tavily", "jina", "firecrawl", "tinyfish"],
2083
+ ["tavily", "jina", "firecrawl", "tinyfish", "deepseek"],
2082
2084
  default_selected,
2083
2085
  lang,
2084
2086
  )
@@ -2110,6 +2112,13 @@ def _prompt_web_fetch(values: dict[str, str], current: dict[str, str], lang: str
2110
2112
  current.get("TINYFISH_API_KEY", ""),
2111
2113
  lang=lang,
2112
2114
  )
2115
+ if "deepseek" in selected:
2116
+ values["DEEPSEEK_API_KEY"] = _prompt_value(
2117
+ "DEEPSEEK_API_KEY",
2118
+ "DeepSeek API key",
2119
+ current.get("DEEPSEEK_API_KEY", ""),
2120
+ lang=lang,
2121
+ )
2113
2122
 
2114
2123
 
2115
2124
  def _prompt_optional_enhancements(values: dict[str, str], current: dict[str, str], lang: str) -> None:
@@ -2347,6 +2356,9 @@ def _run_advanced_setup_prompts(values: dict[str, str], current: dict[str, str],
2347
2356
  ("TINYFISH_SEARCH_API_URL", "TinyFish Search API URL", True),
2348
2357
  ("TINYFISH_FETCH_API_URL", "TinyFish Fetch API URL", True),
2349
2358
  ("TINYFISH_TIMEOUT_SECONDS", "TinyFish timeout seconds", True),
2359
+ ("DEEPSEEK_API_KEY", "DeepSeek API key", True),
2360
+ ("DEEPSEEK_API_URL", "DeepSeek API URL", True),
2361
+ ("DEEPSEEK_TIMEOUT_SECONDS", "DeepSeek timeout seconds", True),
2350
2362
  ("ANYSEARCH_API_URL", "AnySearch MCP API URL", True),
2351
2363
  ("ANYSEARCH_API_KEY", "AnySearch API key", True),
2352
2364
  ("ANYSEARCH_TIMEOUT_SECONDS", "AnySearch timeout seconds", True),
@@ -2370,7 +2382,7 @@ def _run_advanced_setup_prompts(values: dict[str, str], current: dict[str, str],
2370
2382
  value = _normalize_custom_base_url(value)
2371
2383
  elif key == "SCIVERSE_API_URL":
2372
2384
  value = _normalize_custom_base_url(value)
2373
- elif key in {"TINYFISH_SEARCH_API_URL", "TINYFISH_FETCH_API_URL"}:
2385
+ elif key in {"TINYFISH_SEARCH_API_URL", "TINYFISH_FETCH_API_URL", "DEEPSEEK_API_URL"}:
2374
2386
  value = _normalize_custom_base_url(value)
2375
2387
  values[key] = value
2376
2388
 
@@ -2775,6 +2787,9 @@ def _run_setup(args: argparse.Namespace) -> int:
2775
2787
  "TINYFISH_SEARCH_API_URL": _normalize_custom_base_url(args.tinyfish_search_api_url),
2776
2788
  "TINYFISH_FETCH_API_URL": _normalize_custom_base_url(args.tinyfish_fetch_api_url),
2777
2789
  "TINYFISH_TIMEOUT_SECONDS": args.tinyfish_timeout,
2790
+ "DEEPSEEK_API_KEY": args.deepseek_key,
2791
+ "DEEPSEEK_API_URL": _normalize_custom_base_url(args.deepseek_api_url),
2792
+ "DEEPSEEK_TIMEOUT_SECONDS": args.deepseek_timeout,
2778
2793
  "ANYSEARCH_API_URL": _normalize_custom_base_url(args.anysearch_api_url),
2779
2794
  "ANYSEARCH_API_KEY": args.anysearch_key,
2780
2795
  "ANYSEARCH_TIMEOUT_SECONDS": args.anysearch_timeout,
@@ -2885,6 +2900,7 @@ def _run_regression() -> int:
2885
2900
  "tests/test_jina_provider.py",
2886
2901
  "tests/test_tinyfish_provider.py",
2887
2902
  "tests/test_tinyfish_service.py",
2903
+ "tests/test_deepseek_provider.py",
2888
2904
  "tests/test_zhipu_mcp_provider.py",
2889
2905
  "tests/test_smoke.py",
2890
2906
  "tests/test_intent_router.py",
@@ -3484,6 +3500,9 @@ def build_parser() -> argparse.ArgumentParser:
3484
3500
  setup_parser.add_argument("--tinyfish-search-api-url", default="", help="Save TINYFISH_SEARCH_API_URL.")
3485
3501
  setup_parser.add_argument("--tinyfish-fetch-api-url", default="", help="Save TINYFISH_FETCH_API_URL.")
3486
3502
  setup_parser.add_argument("--tinyfish-timeout", default="", help="Save TINYFISH_TIMEOUT_SECONDS.")
3503
+ setup_parser.add_argument("--deepseek-key", default="", help="Save DEEPSEEK_API_KEY.")
3504
+ setup_parser.add_argument("--deepseek-api-url", default="", help="Save DEEPSEEK_API_URL.")
3505
+ setup_parser.add_argument("--deepseek-timeout", default="", help="Save DEEPSEEK_TIMEOUT_SECONDS.")
3487
3506
  setup_parser.add_argument("--anysearch-api-url", default="", help="Save ANYSEARCH_API_URL.")
3488
3507
  setup_parser.add_argument("--anysearch-key", default="", help="Save ANYSEARCH_API_KEY.")
3489
3508
  setup_parser.add_argument("--anysearch-timeout", default="", help="Save ANYSEARCH_TIMEOUT_SECONDS.")
@@ -3562,6 +3581,18 @@ def _main(argv: list[str] | None = None) -> int:
3562
3581
  return EXIT_RUNTIME_ERROR
3563
3582
 
3564
3583
 
3584
+ def _desktop_launch_command() -> list[str]:
3585
+ """Argv that starts this same CLI without a shell, e.g. inside WSL from the Windows App."""
3586
+ package_root = os.environ.get("SMART_SEARCH_PACKAGE_ROOT", "")
3587
+ node = os.environ.get("SMART_SEARCH_NODE_PATH", "")
3588
+ wrapper = Path(package_root) / "npm" / "bin" / "smart-search.js"
3589
+ if package_root and node and wrapper.is_file():
3590
+ return [node, str(wrapper)]
3591
+ if getattr(sys, "frozen", False):
3592
+ return [sys.executable]
3593
+ return [sys.executable, "-m", "smart_search.cli"]
3594
+
3595
+
3565
3596
  def main(argv: list[str] | None = None) -> int:
3566
3597
  arguments = list(sys.argv[1:] if argv is None else argv)
3567
3598
  if arguments == ["--desktop-backend"]:
@@ -3569,7 +3600,8 @@ def main(argv: list[str] | None = None) -> int:
3569
3600
  return desktop_main()
3570
3601
  if arguments == ["--desktop-capabilities"]:
3571
3602
  print(json.dumps({"product": "smart-search", "version": _get_version(), "activity_protocol_version": 1,
3572
- "desktop_protocol_version": 1, "skills_protocol_version": 1}))
3603
+ "desktop_protocol_version": 1, "skills_protocol_version": 1,
3604
+ "launch_command": _desktop_launch_command()}))
3573
3605
  return EXIT_OK
3574
3606
  try:
3575
3607
  arguments, language, warning = _command_language(arguments)
@@ -58,6 +58,7 @@ class Config:
58
58
  "tavily": "TAVILY_ENABLED",
59
59
  "firecrawl": "FIRECRAWL_ENABLED",
60
60
  "tinyfish": "TINYFISH_ENABLED",
61
+ "deepseek": "DEEPSEEK_ENABLED",
61
62
  "jina": "JINA_ENABLED",
62
63
  "anysearch": "ANYSEARCH_ENABLED",
63
64
  "sciverse": "SCIVERSE_ENABLED",
@@ -122,6 +123,9 @@ class Config:
122
123
  "TINYFISH_SEARCH_API_URL",
123
124
  "TINYFISH_FETCH_API_URL",
124
125
  "TINYFISH_TIMEOUT_SECONDS",
126
+ "DEEPSEEK_API_KEY",
127
+ "DEEPSEEK_API_URL",
128
+ "DEEPSEEK_TIMEOUT_SECONDS",
125
129
  "ANYSEARCH_API_KEY",
126
130
  "ANYSEARCH_API_URL",
127
131
  "ANYSEARCH_TIMEOUT_SECONDS",
@@ -712,7 +716,7 @@ class Config:
712
716
  if key in JEV_DEFAULTS:
713
717
  validate_jev_value(key, value)
714
718
  return
715
- if key in {"SMART_SEARCH_TIMEOUT_SECONDS", "TINYFISH_TIMEOUT_SECONDS"}:
719
+ if key in {"SMART_SEARCH_TIMEOUT_SECONDS", "TINYFISH_TIMEOUT_SECONDS", "DEEPSEEK_TIMEOUT_SECONDS"}:
716
720
  self._parse_positive_float_value(key, value)
717
721
  return
718
722
  if key == "SMART_SEARCH_PROVIDER_COOLDOWN_SECONDS":
@@ -970,6 +974,18 @@ class Config:
970
974
  def tinyfish_timeout(self) -> float:
971
975
  return self._parse_positive_float_value("TINYFISH_TIMEOUT_SECONDS", self._get_config_value("TINYFISH_TIMEOUT_SECONDS", "150") or "150")
972
976
 
977
+ @property
978
+ def deepseek_api_key(self) -> str | None:
979
+ return self._get_config_value("DEEPSEEK_API_KEY")
980
+
981
+ @property
982
+ def deepseek_api_url(self) -> str:
983
+ return self._get_config_value("DEEPSEEK_API_URL", "https://api.deepseek.com") or "https://api.deepseek.com"
984
+
985
+ @property
986
+ def deepseek_timeout(self) -> float:
987
+ return self._parse_positive_float_value("DEEPSEEK_TIMEOUT_SECONDS", self._get_config_value("DEEPSEEK_TIMEOUT_SECONDS", "60") or "60")
988
+
973
989
  @property
974
990
  def anysearch_api_url(self) -> str:
975
991
  return self._get_config_value("ANYSEARCH_API_URL", "https://api.anysearch.com/mcp") or "https://api.anysearch.com/mcp"
@@ -1253,6 +1269,9 @@ class Config:
1253
1269
  "TINYFISH_FETCH_API_URL": self.tinyfish_fetch_api_url,
1254
1270
  "TINYFISH_API_KEY": self._mask_api_key(self.tinyfish_api_key) if self.tinyfish_api_key else tr('未配置'),
1255
1271
  "TINYFISH_TIMEOUT_SECONDS": self.tinyfish_timeout,
1272
+ "DEEPSEEK_API_URL": self.deepseek_api_url,
1273
+ "DEEPSEEK_API_KEY": self._mask_api_key(self.deepseek_api_key) if self.deepseek_api_key else tr('未配置'),
1274
+ "DEEPSEEK_TIMEOUT_SECONDS": self.deepseek_timeout,
1256
1275
  "ANYSEARCH_API_URL": self.anysearch_api_url,
1257
1276
  "ANYSEARCH_API_KEY": self._mask_api_key(self.anysearch_api_key) if self.anysearch_api_key else tr('未配置'),
1258
1277
  "ANYSEARCH_TIMEOUT_SECONDS": self.anysearch_timeout,
@@ -89,9 +89,13 @@ def fallback_channels(svc: Any, query: str, candidates: list[dict], limit: int,
89
89
  if reading:
90
90
  order = svc._research_fetch_order(query, reading[0]["url"])
91
91
  return sorted(reading, key=lambda item: order.index(item["provider"]) if item["provider"] in order else len(order))[:limit]
92
+ allowed = []
92
93
  if rule.docs_intent:
93
94
  allowed = [item for item in candidates if item["operation"] == "search" and item["capability"] == "docs_search"]
94
- else:
95
+ # With no docs channel configured, a docs question still gets general web
96
+ # discovery instead of no channel at all. Failure fallback passes only
97
+ # same-family candidates, so this cannot cross a capability boundary.
98
+ if not allowed:
95
99
  allowed = [item for item in candidates if item["operation"] == "search" and
96
100
  (item["capability"] in {"main_search", "web_search"} or item["provider"] == "exa" or
97
101
  item["capability"] in rule.required_capabilities)]
@@ -162,6 +166,8 @@ class ChannelExecutor:
162
166
  content = _check_data(await svc.zhipu_mcp_reader(url)).get("content")
163
167
  elif provider == "tinyfish":
164
168
  content = _check_data(await svc.call_tinyfish_fetch(url)).get("content")
169
+ elif provider == "deepseek":
170
+ content = await svc.call_deepseek_fetch(url)
165
171
  else:
166
172
  raise ProviderCallError("parameter_error", source_message('Unsupported fetch channel'))
167
173
  results = [{"url": url, "content": content}]
@@ -177,6 +183,8 @@ class ChannelExecutor:
177
183
  results = await svc.call_firecrawl_search(query, self.count) or []
178
184
  elif provider == "tinyfish":
179
185
  results = await svc.call_tinyfish_search(query, self.count) or []
186
+ elif provider == "deepseek":
187
+ results = await svc.call_deepseek_search(query, self.count) or []
180
188
  elif provider == "anysearch":
181
189
  results = _check_data(await svc.anysearch_search(query, max_results=self.count)).get("results", [])
182
190
  elif provider == "context7":
@@ -113,6 +113,20 @@ PROVIDER_DESCRIPTIONS: dict[str, dict[str, dict[str, str]]] = {
113
113
  "guidance_zh": "擅长读取已找到的页面;不适合发现新来源或执行浏览器自动化。",
114
114
  },
115
115
  },
116
+ "deepseek": {
117
+ "search": {
118
+ "en": "Searches the web with DeepSeek's own search engine and returns linked results with long query-focused summaries.",
119
+ "zh": "通过 DeepSeek 自研搜索引擎检索网页,返回链接和与问题相关的长摘要。",
120
+ "guidance_en": "Best for broad web and Chinese-language source discovery; summaries are not full page text, so read key pages before citing them. Queries longer than 128 characters are shortened.",
121
+ "guidance_zh": "擅长广泛发现网页和中文来源;摘要不是网页全文,引用关键结论前应读取原页。超过 128 个字符的查询会被截短。",
122
+ },
123
+ "fetch": {
124
+ "en": "Fetches a known URL as markdown through DeepSeek Fetch.",
125
+ "zh": "通过 DeepSeek Fetch 将已知链接读取为 Markdown。",
126
+ "guidance_en": "Best for reading public web pages already found; unsuitable for source discovery, PDF files, login-only pages or private network addresses.",
127
+ "guidance_zh": "擅长读取已找到的公开网页;不适合发现新来源,也读不了 PDF、需登录的页面或内网地址。",
128
+ },
129
+ },
116
130
  "anysearch": {
117
131
  "search": {
118
132
  "en": "Searches AnySearch's available domains with a plain query.",
@@ -1,6 +1,7 @@
1
1
  from .base import BaseSearchProvider, SearchResult
2
2
  from .anysearch import AnySearchProvider
3
3
  from .context7 import Context7Provider
4
+ from .deepseek import DeepSeekToolsProvider
4
5
  from .openai_compatible import OpenAICompatibleSearchProvider
5
6
  from .xai_responses import XAIResponsesSearchProvider
6
7
  from .exa import ExaSearchProvider
@@ -15,6 +16,7 @@ __all__ = [
15
16
  "SearchResult",
16
17
  "AnySearchProvider",
17
18
  "Context7Provider",
19
+ "DeepSeekToolsProvider",
18
20
  "OpenAICompatibleSearchProvider",
19
21
  "XAIResponsesSearchProvider",
20
22
  "ExaSearchProvider",