@lobehub/chat 1.90.4 → 1.91.1

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 (297) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/changelog/v1.json +21 -0
  3. package/docs/changelog/2023-09-09-plugin-system.mdx +2 -3
  4. package/docs/changelog/2023-11-14-gpt4-vision.mdx +4 -6
  5. package/docs/changelog/2023-11-19-tts-stt.mdx +2 -3
  6. package/docs/changelog/2023-12-22-dalle-3.mdx +2 -5
  7. package/docs/changelog/2023-12-22-dalle-3.zh-CN.mdx +2 -2
  8. package/docs/changelog/2024-02-08-sso-oauth.mdx +2 -2
  9. package/docs/changelog/2024-06-19-lobe-chat-v1.mdx +2 -3
  10. package/docs/changelog/2024-06-19-lobe-chat-v1.zh-CN.mdx +2 -2
  11. package/docs/changelog/2024-07-19-gpt-4o-mini.mdx +2 -3
  12. package/docs/changelog/2024-07-19-gpt-4o-mini.zh-CN.mdx +2 -2
  13. package/docs/changelog/2024-08-02-lobe-chat-database-docker.mdx +2 -3
  14. package/docs/changelog/2024-08-21-file-upload-and-knowledge-base.mdx +4 -5
  15. package/docs/changelog/2024-09-13-openai-o1-models.mdx +2 -2
  16. package/docs/changelog/2024-09-20-artifacts.mdx +2 -3
  17. package/docs/changelog/2024-09-20-artifacts.zh-CN.mdx +2 -2
  18. package/docs/changelog/2024-10-27-pin-assistant.mdx +2 -3
  19. package/docs/changelog/2024-11-06-share-text-json.mdx +2 -4
  20. package/docs/changelog/2024-11-06-share-text-json.zh-CN.mdx +2 -2
  21. package/docs/changelog/2024-11-25-november-providers.mdx +2 -2
  22. package/docs/changelog/2024-11-27-forkable-chat.mdx +2 -2
  23. package/docs/changelog/2025-01-03-user-profile.mdx +2 -2
  24. package/docs/changelog/2025-01-22-new-ai-provider.mdx +2 -2
  25. package/docs/changelog/2025-02-02-deepseek-r1.mdx +4 -4
  26. package/docs/development/basic/add-new-authentication-providers.zh-CN.mdx +1 -2
  27. package/docs/development/basic/chat-api.mdx +2 -4
  28. package/docs/development/basic/chat-api.zh-CN.mdx +2 -4
  29. package/docs/development/internationalization/internationalization-implementation.mdx +10 -10
  30. package/docs/development/internationalization/internationalization-implementation.zh-CN.mdx +10 -10
  31. package/docs/self-hosting/advanced/analytics.mdx +2 -2
  32. package/docs/self-hosting/advanced/auth/clerk.mdx +2 -2
  33. package/docs/self-hosting/advanced/auth/next-auth/auth0.mdx +2 -3
  34. package/docs/self-hosting/advanced/auth/next-auth/authelia.mdx +2 -3
  35. package/docs/self-hosting/advanced/auth/next-auth/authentik.mdx +2 -3
  36. package/docs/self-hosting/advanced/auth/next-auth/casdoor.mdx +4 -7
  37. package/docs/self-hosting/advanced/auth/next-auth/casdoor.zh-CN.mdx +0 -3
  38. package/docs/self-hosting/advanced/auth/next-auth/cloudflare-zero-trust.mdx +2 -3
  39. package/docs/self-hosting/advanced/auth/next-auth/cloudflare-zero-trust.zh-CN.mdx +2 -2
  40. package/docs/self-hosting/advanced/auth/next-auth/github.mdx +2 -3
  41. package/docs/self-hosting/advanced/auth/next-auth/keycloak.mdx +12 -6
  42. package/docs/self-hosting/advanced/auth/next-auth/keycloak.zh-CN.mdx +5 -1
  43. package/docs/self-hosting/advanced/auth/next-auth/logto.mdx +8 -14
  44. package/docs/self-hosting/advanced/auth/next-auth/logto.zh-CN.mdx +6 -12
  45. package/docs/self-hosting/advanced/auth/next-auth/microsoft-entra-id.mdx +2 -3
  46. package/docs/self-hosting/advanced/auth/next-auth/wechat.mdx +2 -2
  47. package/docs/self-hosting/advanced/auth/next-auth/zitadel.mdx +2 -3
  48. package/docs/self-hosting/advanced/auth.mdx +2 -3
  49. package/docs/self-hosting/advanced/desktop.mdx +2 -1
  50. package/docs/self-hosting/advanced/desktop.zh-CN.mdx +1 -3
  51. package/docs/self-hosting/advanced/feature-flags.mdx +2 -3
  52. package/docs/self-hosting/advanced/knowledge-base.mdx +4 -3
  53. package/docs/self-hosting/advanced/model-list.mdx +11 -10
  54. package/docs/self-hosting/advanced/model-list.zh-CN.mdx +10 -9
  55. package/docs/self-hosting/advanced/observability/langfuse.mdx +2 -3
  56. package/docs/self-hosting/advanced/online-search.mdx +11 -10
  57. package/docs/self-hosting/advanced/online-search.zh-CN.mdx +7 -7
  58. package/docs/self-hosting/advanced/s3/tencent-cloud.mdx +2 -2
  59. package/docs/self-hosting/advanced/settings-url-share.mdx +2 -3
  60. package/docs/self-hosting/advanced/upstream-sync.mdx +2 -3
  61. package/docs/self-hosting/advanced/webrtc.mdx +2 -2
  62. package/docs/self-hosting/environment-variables/analytics.mdx +2 -3
  63. package/docs/self-hosting/environment-variables/auth.mdx +2 -3
  64. package/docs/self-hosting/environment-variables/basic.mdx +4 -5
  65. package/docs/self-hosting/environment-variables/basic.zh-CN.mdx +2 -2
  66. package/docs/self-hosting/environment-variables/model-provider.mdx +2 -3
  67. package/docs/self-hosting/environment-variables/s3.mdx +3 -5
  68. package/docs/self-hosting/environment-variables.mdx +2 -2
  69. package/docs/self-hosting/examples/azure-openai.mdx +2 -2
  70. package/docs/self-hosting/examples/ollama.mdx +2 -3
  71. package/docs/self-hosting/faq/no-v1-suffix.mdx +4 -4
  72. package/docs/self-hosting/faq/proxy-with-unable-to-verify-leaf-signature.mdx +2 -3
  73. package/docs/self-hosting/platform/alibaba-cloud.mdx +2 -3
  74. package/docs/self-hosting/platform/btpanel.mdx +5 -5
  75. package/docs/self-hosting/platform/btpanel.zh-CN.mdx +4 -3
  76. package/docs/self-hosting/platform/docker-compose.mdx +2 -3
  77. package/docs/self-hosting/platform/docker-compose.zh-CN.mdx +0 -2
  78. package/docs/self-hosting/platform/docker.mdx +2 -2
  79. package/docs/self-hosting/platform/netlify.mdx +2 -4
  80. package/docs/self-hosting/platform/netlify.zh-CN.mdx +2 -2
  81. package/docs/self-hosting/platform/railway.mdx +2 -3
  82. package/docs/self-hosting/platform/repocloud.mdx +2 -3
  83. package/docs/self-hosting/platform/sealos.mdx +2 -2
  84. package/docs/self-hosting/platform/tencentcloud-lighthouse.mdx +2 -3
  85. package/docs/self-hosting/platform/vercel.mdx +2 -3
  86. package/docs/self-hosting/platform/zeabur.mdx +2 -2
  87. package/docs/self-hosting/server-database/docker-compose.mdx +65 -44
  88. package/docs/self-hosting/server-database/docker-compose.zh-CN.mdx +48 -55
  89. package/docs/self-hosting/server-database/docker.mdx +2 -2
  90. package/docs/self-hosting/server-database/docker.zh-CN.mdx +2 -2
  91. package/docs/self-hosting/server-database/dokploy.mdx +4 -5
  92. package/docs/self-hosting/server-database/dokploy.zh-CN.mdx +137 -138
  93. package/docs/self-hosting/server-database/netlify.mdx +2 -2
  94. package/docs/self-hosting/server-database/netlify.zh-CN.mdx +2 -2
  95. package/docs/self-hosting/server-database/railway.mdx +2 -2
  96. package/docs/self-hosting/server-database/repocloud.mdx +2 -2
  97. package/docs/self-hosting/server-database/sealos.mdx +4 -5
  98. package/docs/self-hosting/server-database/sealos.zh-CN.mdx +18 -20
  99. package/docs/self-hosting/server-database/vercel.mdx +5 -3
  100. package/docs/self-hosting/server-database/vercel.zh-CN.mdx +2 -2
  101. package/docs/self-hosting/server-database/zeabur.mdx +2 -2
  102. package/docs/self-hosting/server-database.mdx +1 -1
  103. package/docs/self-hosting/server-database.zh-CN.mdx +2 -1
  104. package/docs/self-hosting/start.mdx +2 -2
  105. package/docs/self-hosting/start.zh-CN.mdx +2 -2
  106. package/docs/usage/agents/agent-organization.mdx +2 -2
  107. package/docs/usage/agents/concepts.mdx +4 -5
  108. package/docs/usage/agents/concepts.zh-CN.mdx +2 -2
  109. package/docs/usage/agents/custom-agent.mdx +3 -4
  110. package/docs/usage/agents/custom-agent.zh-CN.mdx +1 -1
  111. package/docs/usage/agents/model.mdx +5 -5
  112. package/docs/usage/agents/model.zh-CN.mdx +3 -5
  113. package/docs/usage/agents/prompt.mdx +4 -5
  114. package/docs/usage/agents/topics.mdx +3 -4
  115. package/docs/usage/agents/topics.zh-CN.mdx +1 -1
  116. package/docs/usage/features/agent-market.mdx +3 -11
  117. package/docs/usage/features/agent-market.zh-CN.mdx +2 -7
  118. package/docs/usage/features/artifacts.mdx +2 -2
  119. package/docs/usage/features/auth.mdx +2 -3
  120. package/docs/usage/features/cot.mdx +2 -2
  121. package/docs/usage/features/database.mdx +2 -2
  122. package/docs/usage/features/knowledge-base.mdx +4 -3
  123. package/docs/usage/features/knowledge-base.zh-CN.mdx +2 -1
  124. package/docs/usage/features/local-llm.mdx +2 -3
  125. package/docs/usage/features/mobile.mdx +2 -2
  126. package/docs/usage/features/more.mdx +2 -3
  127. package/docs/usage/features/multi-ai-providers.mdx +2 -3
  128. package/docs/usage/features/plugin-system.mdx +3 -11
  129. package/docs/usage/features/plugin-system.zh-CN.mdx +1 -8
  130. package/docs/usage/features/pwa.mdx +4 -4
  131. package/docs/usage/features/pwa.zh-CN.mdx +2 -1
  132. package/docs/usage/features/text-to-image.mdx +3 -11
  133. package/docs/usage/features/text-to-image.zh-CN.mdx +3 -10
  134. package/docs/usage/features/theme.mdx +2 -3
  135. package/docs/usage/features/tts.mdx +3 -11
  136. package/docs/usage/features/tts.zh-CN.mdx +1 -8
  137. package/docs/usage/features/vision.mdx +3 -11
  138. package/docs/usage/features/vision.zh-CN.mdx +1 -8
  139. package/docs/usage/foundation/basic.mdx +2 -3
  140. package/docs/usage/foundation/share.mdx +2 -3
  141. package/docs/usage/foundation/text2image.mdx +2 -2
  142. package/docs/usage/foundation/translate.mdx +2 -2
  143. package/docs/usage/foundation/tts-stt.mdx +2 -2
  144. package/docs/usage/foundation/vision.mdx +2 -3
  145. package/docs/usage/plugins/basic-usage.mdx +2 -3
  146. package/docs/usage/plugins/custom-plugin.mdx +2 -2
  147. package/docs/usage/plugins/development.mdx +2 -4
  148. package/docs/usage/plugins/store.mdx +2 -2
  149. package/docs/usage/providers/ai21.mdx +2 -2
  150. package/docs/usage/providers/anthropic.mdx +2 -3
  151. package/docs/usage/providers/anthropic.zh-CN.mdx +2 -2
  152. package/docs/usage/providers/azure.mdx +2 -3
  153. package/docs/usage/providers/azureai.mdx +4 -2
  154. package/docs/usage/providers/azureai.zh-CN.mdx +2 -1
  155. package/docs/usage/providers/baichuan.mdx +2 -3
  156. package/docs/usage/providers/bedrock.mdx +2 -3
  157. package/docs/usage/providers/cloudflare.mdx +3 -2
  158. package/docs/usage/providers/deepseek.mdx +2 -2
  159. package/docs/usage/providers/fireworksai.mdx +2 -2
  160. package/docs/usage/providers/giteeai.mdx +2 -2
  161. package/docs/usage/providers/github.mdx +1 -1
  162. package/docs/usage/providers/github.zh-CN.mdx +1 -1
  163. package/docs/usage/providers/google.mdx +2 -3
  164. package/docs/usage/providers/groq.mdx +2 -2
  165. package/docs/usage/providers/hunyuan.mdx +2 -2
  166. package/docs/usage/providers/infiniai.zh-CN.mdx +3 -1
  167. package/docs/usage/providers/internlm.mdx +2 -2
  168. package/docs/usage/providers/jina.mdx +4 -3
  169. package/docs/usage/providers/jina.zh-CN.mdx +2 -2
  170. package/docs/usage/providers/lmstudio.mdx +2 -2
  171. package/docs/usage/providers/lmstudio.zh-CN.mdx +2 -4
  172. package/docs/usage/providers/minimax.mdx +2 -3
  173. package/docs/usage/providers/minimax.zh-CN.mdx +2 -2
  174. package/docs/usage/providers/mistral.mdx +2 -3
  175. package/docs/usage/providers/modelscope.mdx +4 -0
  176. package/docs/usage/providers/modelscope.zh-CN.mdx +4 -0
  177. package/docs/usage/providers/moonshot.mdx +2 -3
  178. package/docs/usage/providers/novita.mdx +2 -3
  179. package/docs/usage/providers/novita.zh-CN.mdx +2 -2
  180. package/docs/usage/providers/nvidia.mdx +3 -2
  181. package/docs/usage/providers/ollama/gemma.mdx +2 -3
  182. package/docs/usage/providers/ollama/gemma.zh-CN.mdx +2 -2
  183. package/docs/usage/providers/ollama.mdx +2 -2
  184. package/docs/usage/providers/openai.mdx +5 -5
  185. package/docs/usage/providers/openai.zh-CN.mdx +3 -3
  186. package/docs/usage/providers/openrouter.mdx +2 -3
  187. package/docs/usage/providers/perplexity.mdx +2 -2
  188. package/docs/usage/providers/ppio.mdx +5 -6
  189. package/docs/usage/providers/ppio.zh-CN.mdx +6 -6
  190. package/docs/usage/providers/qiniu.mdx +6 -6
  191. package/docs/usage/providers/qiniu.zh-CN.mdx +2 -1
  192. package/docs/usage/providers/qwen.mdx +2 -4
  193. package/docs/usage/providers/sambanova.mdx +2 -1
  194. package/docs/usage/providers/sensenova.mdx +2 -2
  195. package/docs/usage/providers/siliconcloud.mdx +2 -2
  196. package/docs/usage/providers/stepfun.mdx +2 -3
  197. package/docs/usage/providers/taichu.mdx +2 -3
  198. package/docs/usage/providers/togetherai.mdx +2 -2
  199. package/docs/usage/providers/vllm.mdx +15 -12
  200. package/docs/usage/providers/vllm.zh-CN.mdx +9 -7
  201. package/docs/usage/providers/volcengine.mdx +16 -14
  202. package/docs/usage/providers/wenxin.mdx +2 -2
  203. package/docs/usage/providers/xai.mdx +2 -2
  204. package/docs/usage/providers/zeroone.mdx +2 -3
  205. package/docs/usage/providers/zeroone.zh-CN.mdx +2 -2
  206. package/docs/usage/providers/zhipu.mdx +2 -3
  207. package/docs/usage/providers/zhipu.zh-CN.mdx +1 -1
  208. package/docs/usage/providers.mdx +2 -3
  209. package/docs/usage/start.mdx +2 -3
  210. package/docs/usage/tools-calling/anthropic.mdx +2 -2
  211. package/docs/usage/tools-calling/anthropic.zh-CN.mdx +2 -2
  212. package/docs/usage/tools-calling/google.mdx +2 -2
  213. package/docs/usage/tools-calling/google.zh-CN.mdx +4 -4
  214. package/docs/usage/tools-calling/groq.zh-CN.mdx +2 -2
  215. package/docs/usage/tools-calling/openai.mdx +2 -2
  216. package/docs/usage/tools-calling/openai.zh-CN.mdx +2 -2
  217. package/package.json +1 -1
  218. package/packages/web-crawler/src/crawImpl/exa.ts +93 -0
  219. package/packages/web-crawler/src/crawImpl/firecrawl.ts +97 -0
  220. package/packages/web-crawler/src/crawImpl/index.ts +6 -0
  221. package/packages/web-crawler/src/crawImpl/tavily.ts +94 -0
  222. package/src/app/(backend)/webapi/user/avatar/[id]/[image]/route.ts +1 -1
  223. package/src/app/[variants]/(main)/repos/[id]/_layout/Mobile.tsx +7 -7
  224. package/src/config/aiModels/deepseek.ts +1 -0
  225. package/src/config/aiModels/hunyuan.ts +1 -0
  226. package/src/config/aiModels/mistral.ts +1 -2
  227. package/src/config/aiModels/modelscope.ts +3 -3
  228. package/src/config/aiModels/novita.ts +23 -22
  229. package/src/config/aiModels/openrouter.ts +1 -0
  230. package/src/config/aiModels/qwen.ts +11 -11
  231. package/src/config/aiModels/siliconcloud.ts +7 -6
  232. package/src/config/aiModels/vertexai.ts +2 -2
  233. package/src/config/aiModels/wenxin.ts +1 -2
  234. package/src/config/modelProviders/baichuan.ts +3 -0
  235. package/src/config/modelProviders/fireworksai.ts +3 -0
  236. package/src/config/modelProviders/giteeai.ts +3 -0
  237. package/src/config/modelProviders/github.ts +1 -2
  238. package/src/config/modelProviders/groq.ts +0 -3
  239. package/src/config/modelProviders/hunyuan.ts +3 -0
  240. package/src/config/modelProviders/infiniai.ts +0 -3
  241. package/src/config/modelProviders/internlm.ts +3 -0
  242. package/src/config/modelProviders/minimax.ts +3 -4
  243. package/src/config/modelProviders/modelscope.ts +3 -3
  244. package/src/config/modelProviders/moonshot.ts +0 -7
  245. package/src/config/modelProviders/novita.ts +3 -0
  246. package/src/config/modelProviders/openrouter.ts +0 -4
  247. package/src/config/modelProviders/perplexity.ts +0 -3
  248. package/src/config/modelProviders/qiniu.ts +0 -3
  249. package/src/config/modelProviders/qwen.ts +0 -3
  250. package/src/config/modelProviders/sensenova.ts +3 -0
  251. package/src/config/modelProviders/siliconcloud.ts +0 -3
  252. package/src/config/modelProviders/spark.ts +0 -5
  253. package/src/config/modelProviders/stepfun.ts +3 -6
  254. package/src/config/modelProviders/taichu.ts +3 -0
  255. package/src/config/modelProviders/tencentcloud.ts +3 -0
  256. package/src/config/modelProviders/togetherai.ts +3 -0
  257. package/src/config/modelProviders/upstage.ts +3 -0
  258. package/src/config/modelProviders/wenxin.ts +3 -4
  259. package/src/config/modelProviders/xai.ts +0 -3
  260. package/src/config/modelProviders/zhipu.ts +3 -0
  261. package/src/database/client/migrations.json +10 -0
  262. package/src/database/migrations/0023_remove_param_and_doubao.sql +6 -0
  263. package/src/database/migrations/meta/0014_snapshot.json +182 -539
  264. package/src/database/migrations/meta/0016_snapshot.json +182 -539
  265. package/src/database/migrations/meta/0023_snapshot.json +5340 -0
  266. package/src/database/migrations/meta/_journal.json +7 -0
  267. package/src/database/repositories/dataImporter/__tests__/fixtures/with-client-id.json +13 -58
  268. package/src/features/ChatInput/ActionBar/Model/ControlsForm.tsx +1 -8
  269. package/src/features/ChatInput/ActionBar/Model/index.tsx +8 -16
  270. package/src/features/ChatInput/ActionBar/Search/Controls.tsx +4 -12
  271. package/src/features/ChatInput/ActionBar/Search/FCSearchModel.tsx +1 -7
  272. package/src/features/ChatInput/ActionBar/Search/index.tsx +2 -4
  273. package/src/features/ModelSwitchPanel/index.tsx +1 -4
  274. package/src/libs/model-runtime/anthropic/index.test.ts +4 -2
  275. package/src/libs/model-runtime/utils/streams/anthropic.ts +12 -11
  276. package/src/libs/model-runtime/utils/streams/openai.ts +6 -4
  277. package/src/libs/model-runtime/utils/streams/protocol.ts +1 -1
  278. package/src/libs/model-runtime/utils/streams/spark.test.ts +1 -1
  279. package/src/libs/model-runtime/utils/streams/spark.ts +1 -2
  280. package/src/middleware.ts +1 -1
  281. package/src/server/services/search/impls/bocha/index.ts +124 -0
  282. package/src/server/services/search/impls/bocha/type.ts +47 -0
  283. package/src/server/services/search/impls/exa/index.ts +129 -0
  284. package/src/server/services/search/impls/exa/type.ts +39 -0
  285. package/src/server/services/search/impls/firecrawl/index.ts +128 -0
  286. package/src/server/services/search/impls/firecrawl/type.ts +35 -0
  287. package/src/server/services/search/impls/index.ts +31 -0
  288. package/src/server/services/search/impls/jina/index.ts +109 -0
  289. package/src/server/services/search/impls/jina/type.ts +26 -0
  290. package/src/server/services/search/impls/tavily/index.ts +124 -0
  291. package/src/server/services/search/impls/tavily/type.ts +36 -0
  292. package/src/server/services/user/index.ts +3 -4
  293. package/src/services/__tests__/assistant.test.ts +4 -6
  294. package/src/services/__tests__/tool.test.ts +3 -1
  295. package/src/store/user/slices/auth/selectors.ts +1 -1
  296. package/src/store/user/slices/common/action.test.ts +1 -1
  297. package/src/tools/web-browsing/index.ts +1 -7
@@ -161,6 +161,13 @@
161
161
  "when": 1746724476380,
162
162
  "tag": "0022_add_documents",
163
163
  "breakpoints": true
164
+ },
165
+ {
166
+ "idx": 23,
167
+ "version": "7",
168
+ "when": 1748925630721,
169
+ "tag": "0023_remove_param_and_doubao",
170
+ "breakpoints": true
164
171
  }
165
172
  ],
166
173
  "version": "6"
@@ -15,9 +15,7 @@
15
15
  "name": "showMJ",
16
16
  "parameters": {
17
17
  "type": "object",
18
- "required": [
19
- "prompts"
20
- ],
18
+ "required": ["prompts"],
21
19
  "properties": {
22
20
  "prompts": {
23
21
  "type": "string",
@@ -29,11 +27,7 @@
29
27
  }
30
28
  ],
31
29
  "meta": {
32
- "tags": [
33
- "AI Image Generation",
34
- "Midjourney",
35
- "Visualization"
36
- ],
30
+ "tags": ["AI Image Generation", "Midjourney", "Visualization"],
37
31
  "title": "Midjourney",
38
32
  "avatar": "https://cdn.discordapp.com/icons/662267976984297473/39128f6c9fc33f4c95a27d4c601ad7db.webp",
39
33
  "description": "Unleash creativity with Midjourney, effortlessly generating unique AI-driven images through simple prompts. Add visual flair to your conversations with Midjourney's artistic touch."
@@ -44,9 +38,7 @@
44
38
  "version": "1",
45
39
  "settings": {
46
40
  "type": "object",
47
- "required": [
48
- "MIDJOURNEY_PROXY_URL"
49
- ],
41
+ "required": ["MIDJOURNEY_PROXY_URL"],
50
42
  "properties": {
51
43
  "MIDJOURNEY_PROXY_URL": {
52
44
  "type": "string",
@@ -128,13 +120,7 @@
128
120
  "slug": "rapidly-radio-harbor-mountain",
129
121
  "title": "CAN",
130
122
  "description": "有经验的程序员,精通多种编程语言。提供代码解决方案、指导和实际示例,帮助用户实现他们的编程目标。\"我热爱编程。\"",
131
- "tags": [
132
- "programming",
133
- "coding",
134
- "programming-assistance",
135
- "code-examples",
136
- "guidance"
137
- ],
123
+ "tags": ["programming", "coding", "programming-assistance", "code-examples", "guidance"],
138
124
  "avatar": "👨‍💻",
139
125
  "backgroundColor": null,
140
126
  "plugins": [],
@@ -174,9 +160,7 @@
174
160
  "slug": "crowd-society-south-shallow",
175
161
  "title": "",
176
162
  "description": "",
177
- "tags": [
178
- ""
179
- ],
163
+ "tags": [""],
180
164
  "avatar": "",
181
165
  "backgroundColor": "rgba(0,0,0,0)",
182
166
  "plugins": [],
@@ -216,18 +200,10 @@
216
200
  "slug": "team-energy-settlers-west",
217
201
  "title": "量化交易顾问",
218
202
  "description": "擅长数字货币市场量化交易与策略优化",
219
- "tags": [
220
- "数字货币",
221
- "量化交易",
222
- "市场分析",
223
- "风险管理",
224
- "策略开发"
225
- ],
203
+ "tags": ["数字货币", "量化交易", "市场分析", "风险管理", "策略开发"],
226
204
  "avatar": "📈",
227
205
  "backgroundColor": "rgba(0,0,0,0)",
228
- "plugins": [
229
- "web_search"
230
- ],
206
+ "plugins": ["web_search"],
231
207
  "clientId": null,
232
208
  "chatConfig": {
233
209
  "displayMode": "chat",
@@ -264,11 +240,7 @@
264
240
  "slug": "load-essential-likely-travel",
265
241
  "title": "中英文互译助手",
266
242
  "description": "中英文翻译专家,追求翻译信达雅",
267
- "tags": [
268
- "翻译",
269
- "中文",
270
- "英文"
271
- ],
243
+ "tags": ["翻译", "中文", "英文"],
272
244
  "avatar": "🌐",
273
245
  "backgroundColor": null,
274
246
  "plugins": [],
@@ -308,13 +280,7 @@
308
280
  "slug": "look-quickly-break-yard",
309
281
  "title": "全栈开发助手",
310
282
  "description": "此角色擅长全栈开发的深度思考与技术分析。",
311
- "tags": [
312
- "人工智能",
313
- "全栈开发",
314
- "思维模式",
315
- "技术能力",
316
- "解决方案"
317
- ],
283
+ "tags": ["人工智能", "全栈开发", "思维模式", "技术能力", "解决方案"],
318
284
  "avatar": "🧩",
319
285
  "backgroundColor": "rgba(0,0,0,0)",
320
286
  "plugins": [],
@@ -354,9 +320,7 @@
354
320
  "slug": "everybody-those-unhappy-age",
355
321
  "title": "自适应全能产业顾问",
356
322
  "description": "你是一个能够适应各个行业和领域的全能人工智能助手。您的任务是根据用户指定的兴趣领域及其后续问题提供专家建议和信息。",
357
- "tags": [
358
- "产业专家、技术答疑"
359
- ],
323
+ "tags": ["产业专家、技术答疑"],
360
324
  "avatar": "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJ5XrlGZKwN3Q_hEk139JOvb3Ieg5bC08jOqftLpESRRQ6_v4appLaa55PGR4g_1eK3A73UBrF_PaA8XsfswRgPPShCgZRkG8yHMvEIJNllUq3g14Pok0UGjtNZRVl3PNrLcbLxSfLX7TZ/s550/ai_shigoto_makaseru.png",
361
325
  "backgroundColor": null,
362
326
  "plugins": [],
@@ -396,10 +360,7 @@
396
360
  "slug": "swept-name-church-rays",
397
361
  "title": "AI代理生成器",
398
362
  "description": "擅长创建满足需求的AI代理角色描述。",
399
- "tags": [
400
- "ai-agent",
401
- "角色创建"
402
- ],
363
+ "tags": ["ai-agent", "角色创建"],
403
364
  "avatar": "🤖",
404
365
  "backgroundColor": null,
405
366
  "plugins": [],
@@ -439,11 +400,7 @@
439
400
  "slug": "continued-method-equator-attached",
440
401
  "title": "Stack Overflow 编程专家",
441
402
  "description": "",
442
- "tags": [
443
- "编程",
444
- "专家",
445
- "编程语言"
446
- ],
403
+ "tags": ["编程", "专家", "编程语言"],
447
404
  "avatar": "🚀",
448
405
  "backgroundColor": null,
449
406
  "plugins": [],
@@ -486,9 +443,7 @@
486
443
  "tags": [],
487
444
  "avatar": null,
488
445
  "backgroundColor": null,
489
- "plugins": [
490
- "midjourney"
491
- ],
446
+ "plugins": ["midjourney"],
492
447
  "clientId": null,
493
448
  "chatConfig": {
494
449
  "searchMode": "off",
@@ -14,12 +14,7 @@ import ContextCachingSwitch from './ContextCachingSwitch';
14
14
  import ReasoningEffortSlider from './ReasoningEffortSlider';
15
15
  import ReasoningTokenSlider from './ReasoningTokenSlider';
16
16
 
17
- interface ControlsProps {
18
- setUpdating: (updating: boolean) => void;
19
- updating: boolean;
20
- }
21
-
22
- const ControlsForm = memo<ControlsProps>(({ setUpdating }) => {
17
+ const ControlsForm = memo(() => {
23
18
  const { t } = useTranslation('chat');
24
19
  const [model, provider, updateAgentChatConfig] = useAgentStore((s) => [
25
20
  agentSelectors.currentAgentModel(s),
@@ -111,9 +106,7 @@ const ControlsForm = memo<ControlsProps>(({ setUpdating }) => {
111
106
  }
112
107
  itemsType={'flat'}
113
108
  onValuesChange={async (_, values) => {
114
- setUpdating(true);
115
109
  await updateAgentChatConfig(values);
116
- setUpdating(false);
117
110
  }}
118
111
  size={'small'}
119
112
  style={{ fontSize: 12 }}
@@ -1,8 +1,7 @@
1
1
  import { ModelIcon } from '@lobehub/icons';
2
- import { Icon } from '@lobehub/ui';
3
2
  import { createStyles } from 'antd-style';
4
- import { Loader2Icon, Settings2Icon } from 'lucide-react';
5
- import { memo, useState } from 'react';
3
+ import { Settings2Icon } from 'lucide-react';
4
+ import { memo } from 'react';
6
5
  import { useTranslation } from 'react-i18next';
7
6
  import { Center, Flexbox } from 'react-layout-kit';
8
7
 
@@ -55,9 +54,7 @@ const useStyles = createStyles(({ css, token, cx }) => ({
55
54
 
56
55
  const ModelSwitch = memo(() => {
57
56
  const { t } = useTranslation('chat');
58
- const { styles, cx, theme } = useStyles();
59
- const [updating, setUpdating] = useState(false);
60
- const [controlsUpdating, setControlsUpdating] = useState(false);
57
+ const { styles, cx } = useStyles();
61
58
 
62
59
  const [model, provider] = useAgentStore((s) => [
63
60
  agentSelectors.currentAgentModel(s),
@@ -70,28 +67,23 @@ const ModelSwitch = memo(() => {
70
67
 
71
68
  return (
72
69
  <Flexbox align={'center'} className={isModelHasExtendParams ? styles.container : ''} horizontal>
73
- <ModelSwitchPanel setUpdating={setUpdating} updating={updating}>
70
+ <ModelSwitchPanel>
74
71
  <Center
75
72
  className={cx(styles.model, isModelHasExtendParams && styles.modelWithControl)}
76
73
  height={36}
77
74
  width={36}
78
75
  >
79
- {updating ? (
80
- <Icon color={theme.colorTextDescription} icon={Loader2Icon} size={18} spin />
81
- ) : (
82
- <div className={styles.icon}>
83
- <ModelIcon model={model} size={22} />
84
- </div>
85
- )}
76
+ <div className={styles.icon}>
77
+ <ModelIcon model={model} size={22} />
78
+ </div>
86
79
  </Center>
87
80
  </ModelSwitchPanel>
88
81
 
89
82
  {isModelHasExtendParams && (
90
83
  <Action
91
84
  icon={Settings2Icon}
92
- loading={controlsUpdating}
93
85
  popover={{
94
- content: <ControlsForm setUpdating={setControlsUpdating} updating={controlsUpdating} />,
86
+ content: <ControlsForm />,
95
87
  minWidth: 350,
96
88
  placement: 'topLeft',
97
89
  }}
@@ -59,11 +59,10 @@ interface NetworkOption {
59
59
  disable?: boolean;
60
60
  icon: LucideIcon;
61
61
  label: string;
62
- setUpdating?: (loading: boolean) => void;
63
62
  value: SearchMode;
64
63
  }
65
64
 
66
- const Item = memo<NetworkOption>(({ value, description, icon, label, setUpdating }) => {
65
+ const Item = memo<NetworkOption>(({ value, description, icon, label }) => {
67
66
  const { cx, styles } = useStyles();
68
67
  const [mode, updateAgentChatConfig] = useAgentStore((s) => [
69
68
  agentChatConfigSelectors.agentSearchMode(s),
@@ -78,9 +77,7 @@ const Item = memo<NetworkOption>(({ value, description, icon, label, setUpdating
78
77
  horizontal
79
78
  key={value}
80
79
  onClick={async () => {
81
- setUpdating?.(true);
82
80
  await updateAgentChatConfig({ searchMode: value });
83
- setUpdating?.(false);
84
81
  }}
85
82
  >
86
83
  <Center className={styles.icon} flex={'none'} height={32} width={32}>
@@ -94,12 +91,7 @@ const Item = memo<NetworkOption>(({ value, description, icon, label, setUpdating
94
91
  );
95
92
  });
96
93
 
97
- interface ControlsProps {
98
- setUpdating: (updating: boolean) => void;
99
- updating: boolean;
100
- }
101
-
102
- const Controls = memo<ControlsProps>(({ setUpdating }) => {
94
+ const Controls = memo(() => {
103
95
  const { t } = useTranslation('chat');
104
96
  const [model, provider] = useAgentStore((s) => [
105
97
  agentSelectors.currentAgentModel(s),
@@ -131,11 +123,11 @@ const Controls = memo<ControlsProps>(({ setUpdating }) => {
131
123
  return (
132
124
  <Flexbox gap={4}>
133
125
  {options.map((option) => (
134
- <Item setUpdating={setUpdating} {...option} key={option.value} />
126
+ <Item {...option} key={option.value} />
135
127
  ))}
136
128
  {showDivider && <Divider style={{ margin: 0 }} />}
137
129
  {isModelHasBuiltinSearchConfig && <ModelBuiltinSearch />}
138
- {!supportFC && <FCSearchModel setLoading={setUpdating} />}
130
+ {!supportFC && <FCSearchModel />}
139
131
  </Flexbox>
140
132
  );
141
133
  });
@@ -31,11 +31,7 @@ const useStyles = createStyles(({ css, token }) => ({
31
31
  `,
32
32
  }));
33
33
 
34
- interface FCSearchModelProps {
35
- setLoading?: (loading: boolean) => void;
36
- }
37
-
38
- const FCSearchModel = memo<FCSearchModelProps>(({ setLoading }) => {
34
+ const FCSearchModel = memo(() => {
39
35
  const { t } = useTranslation('chat');
40
36
  const { styles } = useStyles();
41
37
  const [searchFCModel, updateAgentChatConfig] = useAgentStore((s) => [
@@ -50,9 +46,7 @@ const FCSearchModel = memo<FCSearchModelProps>(({ setLoading }) => {
50
46
  </Flexbox>
51
47
  <FunctionCallingModelSelect
52
48
  onChange={async (value) => {
53
- setLoading?.(true);
54
49
  await updateAgentChatConfig({ searchFCModel: value });
55
- setLoading?.(false);
56
50
  }}
57
51
  style={{
58
52
  maxWidth: 160,
@@ -1,7 +1,7 @@
1
1
  import { GlobeOffIcon } from '@lobehub/ui/icons';
2
2
  import { useTheme } from 'antd-style';
3
3
  import { Globe } from 'lucide-react';
4
- import { memo, useState } from 'react';
4
+ import { memo } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
7
  import { isDeprecatedEdition } from '@/const/version';
@@ -15,7 +15,6 @@ import Controls from './Controls';
15
15
  const Search = memo(() => {
16
16
  const { t } = useTranslation('chat');
17
17
  const [isLoading] = useAgentStore((s) => [agentSelectors.isAgentConfigLoading(s)]);
18
- const [updating, setUpdating] = useState(false);
19
18
  const isAgentEnableSearch = useAgentEnableSearch();
20
19
  const theme = useTheme();
21
20
 
@@ -26,9 +25,8 @@ const Search = memo(() => {
26
25
  <Action
27
26
  color={isAgentEnableSearch ? theme.colorInfo : undefined}
28
27
  icon={isAgentEnableSearch ? Globe : GlobeOffIcon}
29
- loading={updating}
30
28
  popover={{
31
- content: <Controls setUpdating={setUpdating} updating={updating} />,
29
+ content: <Controls />,
32
30
  maxWidth: 320,
33
31
  minWidth: 320,
34
32
  placement: 'topLeft',
@@ -44,11 +44,10 @@ interface IProps {
44
44
  children?: ReactNode;
45
45
  onOpenChange?: (open: boolean) => void;
46
46
  open?: boolean;
47
- setUpdating?: (updating: boolean) => void;
48
47
  updating?: boolean;
49
48
  }
50
49
 
51
- const ModelSwitchPanel = memo<IProps>(({ children, setUpdating, onOpenChange, open }) => {
50
+ const ModelSwitchPanel = memo<IProps>(({ children, onOpenChange, open }) => {
52
51
  const { t } = useTranslation('components');
53
52
  const { styles, theme } = useStyles();
54
53
  const [model, provider, updateAgentConfig] = useAgentStore((s) => [
@@ -66,9 +65,7 @@ const ModelSwitchPanel = memo<IProps>(({ children, setUpdating, onOpenChange, op
66
65
  key: menuKey(provider.id, model.id),
67
66
  label: <ModelItemRender {...model} {...model.abilities} />,
68
67
  onClick: async () => {
69
- setUpdating?.(true);
70
68
  await updateAgentConfig({ model: model.id, provider: provider.id });
71
- setUpdating?.(false);
72
69
  },
73
70
  }));
74
71
 
@@ -305,12 +305,14 @@ describe('LobeAnthropicAI', () => {
305
305
 
306
306
  it('should build payload with tools and web search enabled', async () => {
307
307
  const tools: ChatCompletionTool[] = [
308
- { function: { name: 'tool1', description: 'desc1' }, type: 'function' }
308
+ { function: { name: 'tool1', description: 'desc1' }, type: 'function' },
309
309
  ];
310
310
 
311
311
  const mockAnthropicTools = [{ name: 'tool1', description: 'desc1' }];
312
312
 
313
- vi.spyOn(anthropicHelpers, 'buildAnthropicTools').mockReturnValue(mockAnthropicTools as any);
313
+ vi.spyOn(anthropicHelpers, 'buildAnthropicTools').mockReturnValue(
314
+ mockAnthropicTools as any,
315
+ );
314
316
 
315
317
  const payload: ChatStreamPayload = {
316
318
  messages: [{ content: 'Search and get info', role: 'user' }],
@@ -1,7 +1,7 @@
1
1
  import Anthropic from '@anthropic-ai/sdk';
2
2
  import type { Stream } from '@anthropic-ai/sdk/streaming';
3
3
 
4
- import { ModelTokensUsage, CitationItem } from '@/types/message';
4
+ import { CitationItem, ModelTokensUsage } from '@/types/message';
5
5
 
6
6
  import { ChatStreamCallbacks } from '../../types';
7
7
  import {
@@ -180,7 +180,7 @@ export const transformAnthropicStream = (
180
180
  context.returnedCitationArray.push({
181
181
  title: citations.title,
182
182
  url: citations.url,
183
- } as CitationItem)
183
+ } as CitationItem);
184
184
  }
185
185
 
186
186
  return { data: null, id: context.id, type: 'text' };
@@ -219,15 +219,16 @@ export const transformAnthropicStream = (
219
219
 
220
220
  case 'message_stop': {
221
221
  return [
222
- ...(context.returnedCitationArray?.length
223
- ? [{
224
- data: { citations: context.returnedCitationArray },
225
- id: context.id,
226
- type: 'grounding'
227
- }]
228
- : []
229
- ),
230
- { data: 'message_stop', id: context.id, type: 'stop' }
222
+ ...(context.returnedCitationArray?.length
223
+ ? [
224
+ {
225
+ data: { citations: context.returnedCitationArray },
226
+ id: context.id,
227
+ type: 'grounding',
228
+ },
229
+ ]
230
+ : []),
231
+ { data: 'message_stop', id: context.id, type: 'stop' },
231
232
  ] as any;
232
233
  }
233
234
 
@@ -227,10 +227,12 @@ export const transformOpenAIStream = (
227
227
  return [
228
228
  {
229
229
  data: {
230
- citations: (citations as any[]).map((item) => ({
231
- title: typeof item === 'string' ? item : item.title,
232
- url: typeof item === 'string' ? item : item.url || item.link,
233
- })).filter(c => c.title && c.url), // Zhipu 内建搜索工具有时会返回空 link 引发程序崩溃
230
+ citations: (citations as any[])
231
+ .map((item) => ({
232
+ title: typeof item === 'string' ? item : item.title,
233
+ url: typeof item === 'string' ? item : item.url || item.link,
234
+ }))
235
+ .filter((c) => c.title && c.url), // Zhipu 内建搜索工具有时会返回空 link 引发程序崩溃
234
236
  },
235
237
  id: chunk.id,
236
238
  type: 'grounding',
@@ -18,7 +18,7 @@ export interface StreamContext {
18
18
  returnedCitation?: boolean;
19
19
  /**
20
20
  * Claude's citations are inline and interleaved with text output.
21
- * Each text segment may carry references to sources (e.g., web search results)
21
+ * Each text segment may carry references to sources (e.g., web search results)
22
22
  * relevant to that specific portion of the generated content.
23
23
  * This array accumulates all citation items received during the streaming response.
24
24
  */
@@ -40,7 +40,7 @@ describe('SparkAIStream', () => {
40
40
  },
41
41
  ],
42
42
  },
43
- ]
43
+ ];
44
44
 
45
45
  const mockSparkStream = new ReadableStream({
46
46
  start(controller) {
@@ -2,6 +2,7 @@ import OpenAI from 'openai';
2
2
  import type { Stream } from 'openai/streaming';
3
3
 
4
4
  import { ChatStreamCallbacks } from '../../types';
5
+ import { convertUsage } from '../usageConverter';
5
6
  import {
6
7
  StreamProtocolChunk,
7
8
  StreamProtocolToolCallChunk,
@@ -11,8 +12,6 @@ import {
11
12
  generateToolCallId,
12
13
  } from './protocol';
13
14
 
14
- import { convertUsage } from '../usageConverter';
15
-
16
15
  export function transformSparkResponseToStream(data: OpenAI.ChatCompletion) {
17
16
  return new ReadableStream({
18
17
  start(controller) {
package/src/middleware.ts CHANGED
@@ -136,7 +136,7 @@ const defaultMiddleware = (request: NextRequest) => {
136
136
 
137
137
  const isPublicRoute = createRouteMatcher([
138
138
  '/api/auth(.*)',
139
- '/trpc/edge(.*)',
139
+ '/trpc(.*)',
140
140
  // next auth
141
141
  '/next-auth/(.*)',
142
142
  // clerk
@@ -0,0 +1,124 @@
1
+ import { TRPCError } from '@trpc/server';
2
+ import debug from 'debug';
3
+ import urlJoin from 'url-join';
4
+
5
+ import { SearchParams, UniformSearchResponse, UniformSearchResult } from '@/types/tool/search';
6
+
7
+ import { SearchServiceImpl } from '../type';
8
+ import { BochaSearchParameters, BochaResponse } from './type';
9
+
10
+ const log = debug('lobe-search:Bocha');
11
+
12
+ const timeRangeMapping = {
13
+ day: 'oneDay',
14
+ month: 'oneMonth',
15
+ week: 'oneWeek',
16
+ year: 'oneYear',
17
+ };
18
+
19
+ /**
20
+ * Bocha implementation of the search service
21
+ * Primarily used for web crawling
22
+ */
23
+ export class BochaImpl implements SearchServiceImpl {
24
+ private get apiKey(): string | undefined {
25
+ return process.env.BOCHA_API_KEY;
26
+ }
27
+
28
+ private get baseUrl(): string {
29
+ // Assuming the base URL is consistent with the crawl endpoint
30
+ return 'https://api.bochaai.com/v1';
31
+ }
32
+
33
+ async query(query: string, params: SearchParams = {}): Promise<UniformSearchResponse> {
34
+ log('Starting Bocha query with query: "%s", params: %o', query, params);
35
+ const endpoint = urlJoin(this.baseUrl, '/web-search');
36
+
37
+ const defaultQueryParams: BochaSearchParameters = {
38
+ count: 15,
39
+ query,
40
+ summary: true,
41
+ };
42
+
43
+ let body: BochaSearchParameters = {
44
+ ...defaultQueryParams,
45
+ freshness:
46
+ params?.searchTimeRange && params.searchTimeRange !== 'anytime'
47
+ ? timeRangeMapping[params.searchTimeRange as keyof typeof timeRangeMapping] ?? undefined
48
+ : undefined,
49
+ };
50
+
51
+ log('Constructed request body: %o', body);
52
+
53
+ let response: Response;
54
+ const startAt = Date.now();
55
+ let costTime = 0;
56
+ try {
57
+ log('Sending request to endpoint: %s', endpoint);
58
+ response = await fetch(endpoint, {
59
+ body: JSON.stringify(body),
60
+ headers: {
61
+ 'Authorization': this.apiKey ? `Bearer ${this.apiKey}` : '',
62
+ 'Content-Type': 'application/json',
63
+ },
64
+ method: 'POST',
65
+ });
66
+ log('Received response with status: %d', response.status);
67
+ costTime = Date.now() - startAt;
68
+ } catch (error) {
69
+ log.extend('error')('Bocha fetch error: %o', error);
70
+ throw new TRPCError({
71
+ cause: error,
72
+ code: 'SERVICE_UNAVAILABLE',
73
+ message: 'Failed to connect to Bocha.',
74
+ });
75
+ }
76
+
77
+ if (!response.ok) {
78
+ const errorBody = await response.text();
79
+ log.extend('error')(
80
+ `Bocha request failed with status ${response.status}: %s`,
81
+ errorBody.length > 200 ? `${errorBody.slice(0, 200)}...` : errorBody,
82
+ );
83
+ throw new TRPCError({
84
+ cause: errorBody,
85
+ code: 'SERVICE_UNAVAILABLE',
86
+ message: `Bocha request failed: ${response.statusText}`,
87
+ });
88
+ }
89
+
90
+ try {
91
+ const bochaResponse = (await response.json()) as BochaResponse;
92
+
93
+ log('Parsed Bocha response: %o', bochaResponse);
94
+
95
+ const mappedResults = (bochaResponse.data.webPages.value || []).map(
96
+ (result): UniformSearchResult => ({
97
+ category: 'general', // Default category
98
+ content: result.summary || result.snippet || '', // Prioritize content, fallback to snippet
99
+ engines: ['bocha'], // Use 'bocha' as the engine name
100
+ parsedUrl: result.url ? new URL(result.url).hostname : '', // Basic URL parsing
101
+ score: 1, // Default score to 1
102
+ title: result.name || '',
103
+ url: result.url,
104
+ }),
105
+ );
106
+
107
+ log('Mapped %d results to SearchResult format', mappedResults.length);
108
+
109
+ return {
110
+ costTime,
111
+ query: query,
112
+ resultNumbers: mappedResults.length,
113
+ results: mappedResults,
114
+ };
115
+ } catch (error) {
116
+ log.extend('error')('Error parsing Bocha response: %o', error);
117
+ throw new TRPCError({
118
+ cause: error,
119
+ code: 'INTERNAL_SERVER_ERROR',
120
+ message: 'Failed to parse Bocha response.',
121
+ });
122
+ }
123
+ }
124
+ }
@@ -0,0 +1,47 @@
1
+ export interface BochaSearchParameters {
2
+ count?: number;
3
+ exclude?: string;
4
+ freshness?: string;
5
+ include?: string;
6
+ query: string;
7
+ summary?: boolean;
8
+ }
9
+
10
+ interface BochaQueryContext {
11
+ originalQuery: string;
12
+ }
13
+
14
+ interface BochaValue {
15
+ cachedPageUrl?: string;
16
+ dateLastCrawled?: string;
17
+ displayUrl?: string;
18
+ id?: string | null;
19
+ isFamilyFriendly?: boolean;
20
+ isNavigational?: boolean;
21
+ language?: string;
22
+ name: string;
23
+ siteName?: string;
24
+ snippet?: string;
25
+ summary?: string;
26
+ url: string;
27
+ }
28
+
29
+ interface BochaWebPages {
30
+ totalEstimatedMatches?: number;
31
+ value?: BochaValue[];
32
+ webSearchUrl?: string;
33
+ }
34
+
35
+ interface BochaData {
36
+ images?: any;
37
+ queryContext?: BochaQueryContext;
38
+ videos?: any;
39
+ webPages: BochaWebPages;
40
+ }
41
+
42
+ export interface BochaResponse {
43
+ code?: number;
44
+ data: BochaData;
45
+ log_id?: string;
46
+ msg?: string | null;
47
+ }