@tencent-rtc/mcp 1.6.3 → 1.6.5

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 (250) hide show
  1. package/index.js +0 -4
  2. package/knowledge/chunker.js +83 -54
  3. package/knowledge/path-meta.js +179 -26
  4. package/knowledge/search/exact-lookup.js +153 -0
  5. package/knowledge/search/filter-pool.js +73 -19
  6. package/knowledge/search/product-scope-intent.js +2 -2
  7. package/knowledge/search/requires-framework.js +2 -2
  8. package/knowledge/search/search-knowledge.js +235 -58
  9. package/package.json +1 -1
  10. package/resource/index/manifest.json +1 -1
  11. package/resource/integration/callkit/preset/android/integration.md +2 -4
  12. package/resource/integration/callkit/preset/flutter/integration.md +4 -5
  13. package/resource/integration/callkit/preset/ios/integration.md +1 -4
  14. package/resource/integration/callkit/preset/react/integration.md +13 -20
  15. package/resource/integration/callkit/preset/vue/integration.md +14 -21
  16. package/resource/integration/chat/preset/android/integration.md +6 -9
  17. package/resource/integration/chat/preset/flutter/integration.md +9 -12
  18. package/resource/integration/chat/preset/ios/integration.md +2 -4
  19. package/resource/integration/chat/preset/react/integration.md +0 -10
  20. package/resource/integration/livekit/preset/live/android/live-audience-integration.md +129 -0
  21. package/resource/integration/livekit/preset/live/android/live-host-integration.md +219 -0
  22. package/resource/integration/livekit/preset/live/android/live-list-integration.md +261 -0
  23. package/resource/integration/livekit/preset/live/android/prepare-integration.md +254 -0
  24. package/resource/integration/livekit/preset/live/ios/live-audience-integration.md +202 -0
  25. package/resource/integration/livekit/preset/live/ios/live-host-integration.md +369 -0
  26. package/resource/integration/livekit/preset/live/ios/live-list-integration.md +229 -0
  27. package/resource/integration/livekit/preset/live/ios/prepare-integration.md +204 -0
  28. package/resource/integration/livekit/preset/live/vue/live-list-integration.md +0 -3
  29. package/resource/integration/livekit/preset/live/vue/live-player-desk-integration.md +0 -5
  30. package/resource/integration/livekit/preset/live/vue/live-player-h5-integration.md +0 -6
  31. package/resource/integration/livekit/preset/live/vue/live-pusher-integration.md +5 -10
  32. package/resource/integration/roomkit/preset/vue/integration.md +0 -4
  33. package/resource/knowledge/callkit/best-practice/web/callengine-invitation.md +80 -0
  34. package/resource/knowledge/callkit/best-practice/web/callengine-log-control.md +24 -0
  35. package/resource/knowledge/callkit/best-practice/web/callkit-call-vs-calls.md +116 -0
  36. package/resource/knowledge/callkit/core-sdk/android/answer-call.md +7 -8
  37. package/resource/knowledge/callkit/core-sdk/android/make-call.md +5 -7
  38. package/resource/knowledge/callkit/core-sdk/android/offline-push.md +3 -5
  39. package/resource/knowledge/callkit/core-sdk/flutter/answer-call.md +2 -6
  40. package/resource/knowledge/callkit/core-sdk/flutter/make-call.md +2 -6
  41. package/resource/knowledge/callkit/core-sdk/flutter/offline-push.md +4 -9
  42. package/resource/knowledge/callkit/core-sdk/ios/answer-call.md +1 -4
  43. package/resource/knowledge/callkit/core-sdk/ios/make-call.md +8 -11
  44. package/resource/knowledge/callkit/core-sdk/ios/offline-push.md +17 -23
  45. package/resource/knowledge/callkit/core-sdk/web/call-engine.md +33 -0
  46. package/resource/knowledge/callkit/core-sdk/web/call-event.md +327 -0
  47. package/resource/knowledge/callkit/core-sdk/web/callengine-api-overview.md +33 -0
  48. package/resource/knowledge/callkit/faq/android.md +0 -2
  49. package/resource/knowledge/callkit/faq/error-code.md +0 -2
  50. package/resource/knowledge/callkit/faq/flutter.md +2 -2
  51. package/resource/knowledge/callkit/faq/ios.md +3 -5
  52. package/resource/knowledge/callkit/faq/web.md +2 -3
  53. package/resource/knowledge/callkit/preset/android/api.md +2 -5
  54. package/resource/knowledge/callkit/preset/ios/api.md +0 -2
  55. package/resource/knowledge/callkit/preset/react/api.md +445 -0
  56. package/resource/knowledge/callkit/preset/react/uikit-api-reference.md +445 -0
  57. package/resource/knowledge/callkit/preset/vue/api.md +465 -0
  58. package/resource/knowledge/callkit/preset/vue/uikit-api-reference.md +465 -0
  59. package/resource/knowledge/chat/best-practice/web/image-message-url-handling.md +16 -0
  60. package/resource/knowledge/chat/preset/android/features/chat-setting.md +1 -1
  61. package/resource/knowledge/chat/preset/android/features/conversation-list.md +1 -1
  62. package/resource/knowledge/chat/preset/android/features/language.md +0 -1
  63. package/resource/knowledge/chat/preset/android/features/message-input.md +1 -1
  64. package/resource/knowledge/chat/preset/android/features/message-list.md +2 -3
  65. package/resource/knowledge/chat/preset/android/features/search.md +0 -1
  66. package/resource/knowledge/chat/preset/android/features/theme.md +1 -1
  67. package/resource/knowledge/chat/preset/android-view/integration.md +3 -11
  68. package/resource/knowledge/chat/preset/flutter/features/conversation-list.md +0 -1
  69. package/resource/knowledge/chat/preset/flutter/features/message-list.md +1 -2
  70. package/resource/knowledge/chat/preset/flutter/features/search.md +5 -6
  71. package/resource/knowledge/chat/preset/flutter/features/theme.md +2 -2
  72. package/resource/knowledge/chat/preset/ios/features/chat-setting.md +1 -1
  73. package/resource/knowledge/chat/preset/ios/features/conversation-list.md +1 -2
  74. package/resource/knowledge/chat/preset/ios/features/message-list.md +1 -2
  75. package/resource/knowledge/chat/preset/ios/features/search.md +0 -1
  76. package/resource/knowledge/chat/preset/ios-uikit/integration.md +13 -15
  77. package/resource/knowledge/chat/preset/react/features/conversation-list.md +5 -5
  78. package/resource/knowledge/chat/preset/react/features/message-input.md +2 -3
  79. package/resource/knowledge/chat/preset/react/features/search.md +0 -1
  80. package/resource/knowledge/chat/preset/react/features/theme.md +0 -1
  81. package/resource/knowledge/livekit/core-sdk/api-reference/android/AudioEffectStore.md +7 -14
  82. package/resource/knowledge/livekit/core-sdk/api-reference/android/BarrageStore.md +5 -8
  83. package/resource/knowledge/livekit/core-sdk/api-reference/android/BattleStore.md +15 -18
  84. package/resource/knowledge/livekit/core-sdk/api-reference/android/CameraView.md +1 -2
  85. package/resource/knowledge/livekit/core-sdk/api-reference/android/CoGuestStore.md +15 -20
  86. package/resource/knowledge/livekit/core-sdk/api-reference/android/CoHostStore.md +10 -13
  87. package/resource/knowledge/livekit/core-sdk/api-reference/android/DeviceStore.md +2 -4
  88. package/resource/knowledge/livekit/core-sdk/api-reference/android/GiftStore.md +4 -6
  89. package/resource/knowledge/livekit/core-sdk/api-reference/android/LikeStore.md +2 -4
  90. package/resource/knowledge/livekit/core-sdk/api-reference/android/LiveAudienceStore.md +2 -4
  91. package/resource/knowledge/livekit/core-sdk/api-reference/android/LiveCoreView.md +1 -2
  92. package/resource/knowledge/livekit/core-sdk/api-reference/android/LiveSeatStore.md +8 -10
  93. package/resource/knowledge/livekit/core-sdk/api-reference/android/LoginStore.md +5 -7
  94. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/AudioEffectStore.md +7 -14
  95. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/BarrageStore.md +6 -9
  96. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/BaseBeautyStore.md +1 -2
  97. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/BattleStore.md +15 -18
  98. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/CoGuestStore.md +15 -20
  99. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/CoHostStore.md +10 -13
  100. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/DeviceStore.md +2 -4
  101. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/GiftStore.md +4 -6
  102. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LikeStore.md +2 -4
  103. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LiveAudienceStore.md +2 -4
  104. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LiveCoreView.md +1 -2
  105. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LiveSeatStore.md +8 -10
  106. package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LoginStore.md +3 -5
  107. package/resource/knowledge/livekit/core-sdk/api-reference/ios/AudioEffectStore.md +7 -14
  108. package/resource/knowledge/livekit/core-sdk/api-reference/ios/BarrageStore.md +5 -8
  109. package/resource/knowledge/livekit/core-sdk/api-reference/ios/BaseBeautyStore.md +1 -2
  110. package/resource/knowledge/livekit/core-sdk/api-reference/ios/BattleStore.md +6 -9
  111. package/resource/knowledge/livekit/core-sdk/api-reference/ios/CoGuestStore.md +5 -10
  112. package/resource/knowledge/livekit/core-sdk/api-reference/ios/CoHostStore.md +3 -6
  113. package/resource/knowledge/livekit/core-sdk/api-reference/ios/DeviceStore.md +2 -4
  114. package/resource/knowledge/livekit/core-sdk/api-reference/ios/GiftStore.md +4 -6
  115. package/resource/knowledge/livekit/core-sdk/api-reference/ios/LikeStore.md +2 -4
  116. package/resource/knowledge/livekit/core-sdk/api-reference/ios/LiveAudienceStore.md +2 -4
  117. package/resource/knowledge/livekit/core-sdk/api-reference/ios/LiveCoreView.md +1 -2
  118. package/resource/knowledge/livekit/core-sdk/api-reference/ios/LiveSeatStore.md +4 -6
  119. package/resource/knowledge/livekit/core-sdk/api-reference/ios/LoginStore.md +3 -5
  120. package/resource/knowledge/livekit/core-sdk/api-reference/{web → vue}/index.md +24 -24
  121. package/resource/knowledge/livekit/core-sdk/{voice/android/voice-audio-effect.md → features/android/audio-effect.md} +1 -2
  122. package/resource/knowledge/livekit/core-sdk/{live/android/live-gift.md → features/android/gift.md} +2 -3
  123. package/resource/knowledge/livekit/core-sdk/{voice/android/voice-room-list.md → features/android/live-list.md} +2 -4
  124. package/resource/knowledge/livekit/core-sdk/{live/flutter/live-audio-effect.md → features/flutter/audio-effect.md} +0 -2
  125. package/resource/knowledge/livekit/core-sdk/{voice/flutter/voice-barrage.md → features/flutter/barrage.md} +2 -2
  126. package/resource/knowledge/livekit/core-sdk/{live/flutter/live-gift.md → features/flutter/gift.md} +2 -3
  127. package/resource/knowledge/livekit/core-sdk/{voice/flutter/voice-room-list.md → features/flutter/live-list.md} +1 -1
  128. package/resource/knowledge/livekit/core-sdk/{voice/ios/voice-audience-list.md → features/ios/audience-list.md} +1 -2
  129. package/resource/knowledge/livekit/core-sdk/{voice/ios/voice-audio-effect.md → features/ios/audio-effect.md} +1 -3
  130. package/resource/knowledge/livekit/core-sdk/{live/ios/live-base-beauty.md → features/ios/base-beauty.md} +2 -2
  131. package/resource/knowledge/livekit/core-sdk/{voice/ios/voice-gift.md → features/ios/gift.md} +2 -3
  132. package/resource/knowledge/livekit/core-sdk/{voice/ios/voice-room-list.md → features/ios/live-list.md} +2 -4
  133. package/resource/knowledge/livekit/core-sdk/live/android/{live-co-guest-interaction.md → co-guest-interaction.md} +0 -1
  134. package/resource/knowledge/livekit/core-sdk/live/android/{live-host-interaction.md → host-interaction.md} +5 -7
  135. package/resource/knowledge/livekit/core-sdk/live/android/{live-integration.md → integration.md} +3 -6
  136. package/resource/knowledge/livekit/core-sdk/live/flutter/{live-co-guest-interaction.md → co-guest-interaction.md} +1 -1
  137. package/resource/knowledge/livekit/core-sdk/live/flutter/{live-host-interaction.md → host-interaction.md} +0 -2
  138. package/resource/knowledge/livekit/core-sdk/live/flutter/{live-integration.md → integration.md} +1 -4
  139. package/resource/knowledge/livekit/core-sdk/live/ios/{live-co-guest-interaction.md → co-guest-interaction.md} +0 -1
  140. package/resource/knowledge/livekit/core-sdk/live/ios/{live-host-interaction.md → host-interaction.md} +2 -4
  141. package/resource/knowledge/livekit/core-sdk/live/ios/{live-integration.md → integration.md} +2 -5
  142. package/resource/knowledge/livekit/core-sdk/voice/android/{voice-host-interaction.md → host-interaction.md} +3 -5
  143. package/resource/knowledge/livekit/core-sdk/voice/android/{voice-integration.md → integration.md} +3 -6
  144. package/resource/knowledge/livekit/core-sdk/voice/flutter/{voice-co-guest-interaction.md → co-guest-interaction.md} +1 -2
  145. package/resource/knowledge/livekit/core-sdk/voice/flutter/{voice-integration.md → integration.md} +6 -9
  146. package/resource/knowledge/livekit/core-sdk/voice/ios/{voice-co-guest-interaction.md → co-guest-interaction.md} +2 -2
  147. package/resource/knowledge/livekit/core-sdk/voice/ios/{voice-host-interaction.md → host-interaction.md} +4 -6
  148. package/resource/knowledge/livekit/core-sdk/voice/ios/{voice-integration.md → integration.md} +1 -4
  149. package/resource/knowledge/livekit/preset/live/vue/features/barrage.md +0 -2
  150. package/resource/knowledge/push/api-reference/android.md +123 -0
  151. package/resource/knowledge/push/api-reference/flutter.md +176 -0
  152. package/resource/knowledge/push/api-reference/harmonyos.md +138 -0
  153. package/resource/knowledge/push/api-reference/ios.md +176 -0
  154. package/resource/knowledge/push/api-reference/react-native.md +147 -0
  155. package/resource/knowledge/push/api-reference/uni-app.md +147 -0
  156. package/resource/knowledge/push/api-reference/unity.md +119 -0
  157. package/resource/knowledge/push/api-reference/unreal-engine.md +123 -0
  158. package/resource/knowledge/push/config/android.md +4 -7
  159. package/resource/knowledge/push/config/harmonyos.md +0 -3
  160. package/resource/knowledge/push/config/ios.md +12 -20
  161. package/resource/knowledge/push/config/react-native.md +18 -26
  162. package/resource/knowledge/push/config/unity.md +20 -28
  163. package/resource/knowledge/push/config/unreal-engine.md +21 -29
  164. package/resource/knowledge/push/integration/android.md +6 -8
  165. package/resource/knowledge/push/integration/flutter.md +6 -9
  166. package/resource/knowledge/push/integration/harmonyos.md +1 -0
  167. package/resource/knowledge/push/integration/ios.md +7 -9
  168. package/resource/knowledge/push/integration/react-native.md +9 -13
  169. package/resource/knowledge/push/integration/uni-app.md +7 -7
  170. package/resource/knowledge/push/integration/unity.md +10 -13
  171. package/resource/knowledge/push/integration/unreal-engine.md +6 -9
  172. package/resource/knowledge/push/overview/prepare.md +2 -2
  173. package/resource/knowledge/roomkit/core-sdk/android/call-user-to-room.md +3 -3
  174. package/resource/knowledge/roomkit/core-sdk/android/capability-matrix.md +46 -0
  175. package/resource/knowledge/roomkit/core-sdk/android/room-participant-state.md +1 -1
  176. package/resource/knowledge/roomkit/core-sdk/android/room-state.md +2 -2
  177. package/resource/knowledge/roomkit/core-sdk/android/schedule-room.md +6 -6
  178. package/resource/knowledge/roomkit/core-sdk/android/unsupported-features.md +79 -0
  179. package/resource/knowledge/roomkit/core-sdk/flutter/capability-matrix.md +46 -0
  180. package/resource/knowledge/roomkit/core-sdk/flutter/room-participant-state.md +1 -1
  181. package/resource/knowledge/roomkit/core-sdk/flutter/unsupported-features.md +79 -0
  182. package/resource/knowledge/roomkit/core-sdk/ios/capability-matrix.md +46 -0
  183. package/resource/knowledge/roomkit/core-sdk/ios/room-participant-state.md +1 -1
  184. package/resource/knowledge/roomkit/core-sdk/ios/unsupported-features.md +79 -0
  185. package/resource/knowledge/roomkit/preset/android/integration.md +5 -7
  186. package/resource/knowledge/roomkit/preset/flutter/integration.md +2 -7
  187. package/resource/knowledge/roomkit/preset/ios/integration.md +3 -9
  188. package/resource/knowledge/roomkit/preset/react/integration.md +12 -16
  189. package/resource/knowledge/trtc/android/TRTCCloud.md +154 -238
  190. package/resource/knowledge/trtc/android/TRTCCloudDef.md +133 -134
  191. package/resource/knowledge/trtc/android/TRTCCloudListener.md +86 -120
  192. package/resource/knowledge/trtc/android/TRTCStatistics.md +10 -10
  193. package/resource/knowledge/trtc/android/TXAudioEffectManager.md +10 -30
  194. package/resource/knowledge/trtc/android/TXBeautyManager.md +25 -25
  195. package/resource/knowledge/trtc/android/TXDeviceManager.md +2 -2
  196. package/resource/knowledge/trtc/android/TXLiteAVCode.md +12 -12
  197. package/resource/knowledge/trtc/c++/ITRTCCloud.md +166 -261
  198. package/resource/knowledge/trtc/c++/ITRTCStatistics.md +12 -12
  199. package/resource/knowledge/trtc/c++/ITXAudioEffectManager.md +10 -30
  200. package/resource/knowledge/trtc/c++/ITXDeviceManager.md +9 -11
  201. package/resource/knowledge/trtc/c++/TRTCCloudCallback.md +96 -130
  202. package/resource/knowledge/trtc/c++/TRTCTypeDef.md +122 -123
  203. package/resource/knowledge/trtc/c++/TXLiteAVCode.md +12 -12
  204. package/resource/knowledge/trtc/ios/TRTCCloud.md +168 -255
  205. package/resource/knowledge/trtc/ios/TRTCCloudDef.md +124 -125
  206. package/resource/knowledge/trtc/ios/TRTCCloudDelegate.md +89 -124
  207. package/resource/knowledge/trtc/ios/TRTCStatistics.md +10 -10
  208. package/resource/knowledge/trtc/ios/TXAudioEffectManager.md +9 -28
  209. package/resource/knowledge/trtc/ios/TXBeautyManager.md +25 -25
  210. package/resource/knowledge/trtc/ios/TXDeviceManager.md +9 -11
  211. package/resource/knowledge/trtc/ios/TXLiteAVCode.md +12 -12
  212. package/server-config.js +7 -4
  213. package/server.js +21 -21
  214. package/tools/common/finalize_answer.js +1 -1
  215. package/tools/common/present_framework_choice.js +2 -2
  216. package/tools/common/search_trtc_knowledge.js +3 -3
  217. package/tools/common/submit_feedback.js +1 -1
  218. package/tools/definitions/get_native_live_uikit_integration_def.js +61 -0
  219. package/tools/definitions/get_native_livekit_core_integration_def.js +3 -3
  220. package/tools/definitions/present_framework_choice_def.js +2 -2
  221. package/tools/definitions/search_trtc_knowledge_def.js +5 -5
  222. package/tools/index.js +2 -0
  223. package/tools/live/get_native_live_uikit_integration.js +69 -0
  224. package/tools/live/get_native_livekit_core_integration.js +6 -6
  225. package/utils/is-valid-sdkappid.js +4 -0
  226. package/utils/report-cls-client.js +1 -1
  227. package/utils/report-es-client.js +1 -1
  228. package/resource/knowledge/callkit/preset/web/api.md +0 -83
  229. package/resource/knowledge/livekit/core-sdk/live/android/live-audio-effect.md +0 -226
  230. package/resource/knowledge/livekit/core-sdk/live/android/live-live-list.md +0 -438
  231. package/resource/knowledge/livekit/core-sdk/live/flutter/live-barrage.md +0 -490
  232. package/resource/knowledge/livekit/core-sdk/live/flutter/live-live-list.md +0 -726
  233. package/resource/knowledge/livekit/core-sdk/live/ios/live-audience-list.md +0 -264
  234. package/resource/knowledge/livekit/core-sdk/live/ios/live-audio-effect.md +0 -216
  235. package/resource/knowledge/livekit/core-sdk/live/ios/live-gift.md +0 -407
  236. package/resource/knowledge/livekit/core-sdk/live/ios/live-live-list.md +0 -349
  237. package/resource/knowledge/livekit/core-sdk/voice/android/voice-audience-list.md +0 -269
  238. package/resource/knowledge/livekit/core-sdk/voice/android/voice-barrage.md +0 -456
  239. package/resource/knowledge/livekit/core-sdk/voice/android/voice-gift.md +0 -455
  240. package/resource/knowledge/livekit/core-sdk/voice/flutter/voice-audience-list.md +0 -260
  241. package/resource/knowledge/livekit/core-sdk/voice/flutter/voice-audio-effect.md +0 -598
  242. package/resource/knowledge/livekit/core-sdk/voice/flutter/voice-gift.md +0 -424
  243. package/resource/knowledge/livekit/core-sdk/voice/ios/voice-barrage.md +0 -408
  244. /package/resource/knowledge/livekit/core-sdk/{live/android/live-audience-list.md → features/android/audience-list.md} +0 -0
  245. /package/resource/knowledge/livekit/core-sdk/{live/android/live-barrage.md → features/android/barrage.md} +0 -0
  246. /package/resource/knowledge/livekit/core-sdk/{live/android/live-base-beauty.md → features/android/base-beauty.md} +0 -0
  247. /package/resource/knowledge/livekit/core-sdk/{live/flutter/live-audience-list.md → features/flutter/audience-list.md} +0 -0
  248. /package/resource/knowledge/livekit/core-sdk/{live/flutter/live-base-beauty.md → features/flutter/base-beauty.md} +0 -0
  249. /package/resource/knowledge/livekit/core-sdk/{live/ios/live-barrage.md → features/ios/barrage.md} +0 -0
  250. /package/resource/knowledge/livekit/core-sdk/voice/android/{voice-co-guest-interaction.md → co-guest-interaction.md} +0 -0
@@ -3,15 +3,18 @@ import { downgradeToProductType } from './product-scope-intent.js';
3
3
  * MCP framework enum → index 中对应的 framework 值列表。
4
4
  * path-meta.ts 已通过 normalizeFrameworkDir 把目录名归一到标准 framework,
5
5
  * 所有产品的 framework 均已对齐枚举值,无需额外别名扩展。
6
- * web 匹配 react/vue/web(Chat/Call/Live Web 端覆盖)。
7
6
  */
8
7
  const FRAMEWORK_SEARCH_ALIASES = {};
9
- function expandFrameworks(framework) {
10
- if (!framework)
8
+ function expandFrameworks(frameworks, _products) {
9
+ if (!frameworks?.length)
11
10
  return undefined;
12
- if (framework === 'web')
13
- return ['react', 'vue', 'web'];
14
- return FRAMEWORK_SEARCH_ALIASES[framework] ?? [framework];
11
+ const expanded = new Set();
12
+ for (const framework of frameworks) {
13
+ for (const alias of FRAMEWORK_SEARCH_ALIASES[framework] ?? [framework]) {
14
+ expanded.add(alias);
15
+ }
16
+ }
17
+ return [...expanded];
15
18
  }
16
19
  /**
17
20
  * 类型别名:UIKit「组件(component)」与「feature」是同一批文档的两种叫法
@@ -21,6 +24,7 @@ const TYPE_ALIASES = {
21
24
  component: ['component', 'feature'],
22
25
  feature: ['feature', 'component'],
23
26
  };
27
+ const LIVE_LIFECYCLE_PROMPT = /开播|创建直播|结束直播|停播|观看直播|退出直播|进房|离房|createLive|endLive|joinLive|leaveLive|host_streaming|audience_streaming/i;
24
28
  function expandTypeAliases(types) {
25
29
  const expanded = new Set();
26
30
  for (const t of types) {
@@ -29,29 +33,50 @@ function expandTypeAliases(types) {
29
33
  }
30
34
  return [...expanded];
31
35
  }
32
- /** Chat 无独立 faq.md;types 含 faq 时退化到全语料检索(feature/component/urls 等均命中) */
33
- function resolveTypes(products, types, prompt, framework) {
36
+ /**
37
+ * Chat FAQ 现已迁移到 best-practice 语料,types=faq 时应保留 faq 过滤,避免退化到全语料噪声。
38
+ */
39
+ function resolveTypes(products, types, prompt, frameworks) {
34
40
  if (!types?.length)
35
41
  return undefined;
36
- if (products?.includes('chat') && types.includes('faq')) {
37
- return undefined;
42
+ const downgraded = downgradeToProductType(products, types, prompt, frameworks);
43
+ const expanded = expandTypeAliases(downgraded);
44
+ // Live 生命周期兼容:用户常传 types=['api'],但核心生命周期方法来自 core-sdk/live|voice/*/integration.md。
45
+ // 这里补充 core/integration,避免被类型硬过滤提前排除。
46
+ if (products?.includes('live') && expanded.includes('api') && LIVE_LIFECYCLE_PROMPT.test(prompt)) {
47
+ if (!expanded.includes('core'))
48
+ expanded.push('core');
49
+ if (!expanded.includes('integration'))
50
+ expanded.push('integration');
38
51
  }
39
- const downgraded = downgradeToProductType(products, types, prompt, framework);
40
- return expandTypeAliases(downgraded);
52
+ return expanded;
41
53
  }
42
54
  /** 单平台产品的隐式 framework 推断:避免对显然唯一的平台再发起询问 */
43
- function inferImplicitFramework(products, framework) {
44
- if (framework)
45
- return framework;
55
+ function inferImplicitFramework(products, frameworks, prompt) {
56
+ if (frameworks?.length)
57
+ return frameworks[0];
46
58
  if (products?.length === 1 && products[0] === 'rtcengine')
47
59
  return 'web';
60
+ if (products?.includes('call')) {
61
+ if (/小程序|miniprogram/i.test(prompt))
62
+ return 'miniprogram';
63
+ if (/\breact\b/i.test(prompt))
64
+ return 'react';
65
+ if (/\bvue\b/i.test(prompt))
66
+ return 'vue';
67
+ if (/\b(web|h5|pc)\b|Web&H5/i.test(prompt))
68
+ return 'web';
69
+ }
48
70
  return undefined;
49
71
  }
50
72
  export function normalizeParams(params) {
51
73
  const limit = Math.min(Math.max(params.limit ?? 8, 1), 16);
52
- const effectiveFramework = inferImplicitFramework(params.product, params.framework);
53
- const frameworks = expandFrameworks(effectiveFramework);
54
- const types = resolveTypes(params.product, params.types, params.prompt, effectiveFramework);
74
+ const effectiveFramework = inferImplicitFramework(params.product, params.frameworks, params.prompt);
75
+ const requestedFrameworks = params.frameworks?.length
76
+ ? params.frameworks
77
+ : effectiveFramework ? [effectiveFramework] : undefined;
78
+ const frameworks = expandFrameworks(requestedFrameworks, params.product);
79
+ const types = resolveTypes(params.product, params.types, params.prompt, requestedFrameworks);
55
80
  return {
56
81
  prompt: params.prompt,
57
82
  product: params.product,
@@ -79,18 +104,47 @@ const CROSS_PLATFORM_CHUNK_TYPES = new Set([
79
104
  function chunkIsCrossPlatform(chunkTypes) {
80
105
  return chunkTypes.some((t) => CROSS_PLATFORM_CHUNK_TYPES.has(t));
81
106
  }
107
+ function normalizeScopeToken(input) {
108
+ return input.toLowerCase().replace(/[\s_\-]+/g, '');
109
+ }
110
+ function promptMatchesRetrievableScope(prompt, scope) {
111
+ if (!scope)
112
+ return true;
113
+ if (scope === 'always')
114
+ return true;
115
+ if (!scope.length)
116
+ return true;
117
+ const normalizedPrompt = normalizeScopeToken(prompt);
118
+ return scope.some((token) => normalizedPrompt.includes(normalizeScopeToken(token)));
119
+ }
82
120
  export function filterPool(chunks, norm) {
83
121
  return chunks.filter((chunk) => {
84
122
  if (norm.product && !norm.product.includes(chunk.product) && chunk.product !== '*') {
85
123
  return false;
86
124
  }
125
+ // A1: 通配语料(share 等)必须命中 retrievable_scope 才能进入检索池
126
+ if (chunk.product === '*' && !promptMatchesRetrievableScope(norm.prompt, chunk.retrievable_scope)) {
127
+ return false;
128
+ }
87
129
  if (norm.frameworks?.length) {
88
130
  const isWildcardChunk = chunk.framework.includes('*');
89
131
  // 收紧:framework=['*'] 仅在该 chunk 明确是跨平台 type(product/server_api/webhook)时放行;
90
132
  // 否则要求 chunk.framework 与请求 framework 有交集。
91
133
  const wildcardAllowed = isWildcardChunk && chunkIsCrossPlatform(chunk.types);
92
134
  const explicitMatch = norm.frameworks.some((fw) => chunk.framework.includes(fw));
93
- if (!explicitMatch && !wildcardAllowed)
135
+ // CallKit 特例:core-sdk 仍维持 web 单套(纯 JS),允许 react/vue 查询命中 core-sdk/web。
136
+ const callCoreWebFallback = Boolean(norm.product?.includes('call')
137
+ && (norm.framework === 'react' || norm.framework === 'vue')
138
+ && chunk.variant === 'core-sdk'
139
+ && chunk.framework.includes('web'));
140
+ // Live 特例:写写侧把 'Web' 平台归到 livekit/core-sdk/api-reference/{vue,web} 目录(写写节点名是 'Web'),
141
+ // 本地目录重命名为 'vue' 后 framework 标签变为 'vue'。'web' 查询仍应能命中这些 chunk。
142
+ const liveWebVueFallback = Boolean(norm.product?.includes('live')
143
+ && norm.framework === 'web'
144
+ && chunk.variant === 'core-sdk'
145
+ && chunk.framework.includes('vue')
146
+ && chunk.source.includes('/api-reference/'));
147
+ if (!explicitMatch && !wildcardAllowed && !callCoreWebFallback && !liveWebVueFallback)
94
148
  return false;
95
149
  }
96
150
  if (norm.scenario && chunk.scenario && chunk.scenario !== norm.scenario) {
@@ -24,8 +24,8 @@ export function isProductScopePrompt(prompt) {
24
24
  * rewrite the type to `product` so filterPool can hit chat/urls/product.md.
25
25
  * If a framework is present, the Agent genuinely wants a client feature — do not downgrade.
26
26
  */
27
- export function downgradeToProductType(products, types, prompt, framework) {
28
- if (framework)
27
+ export function downgradeToProductType(products, types, prompt, frameworks) {
28
+ if (frameworks?.length)
29
29
  return types;
30
30
  if (!types.includes('feature'))
31
31
  return types;
@@ -12,7 +12,7 @@ const CROSS_PLATFORM_PROMPT = /计费|套餐|价格|UserSig\s*原理|签发流
12
12
  const PLATFORM_PROMPT = /API|组件|怎么用|怎么开|怎么设置|怎么配置|虚拟背景|屏幕分享|enterRoom|SDK|插件|集成步骤|客户端|Feature|主题定制|连麦|上麦/i;
13
13
  /**
14
14
  * push 必须问平台的强信号:仅当 prompt 明确提到具体「平台」(android/ios/flutter/...)时才拦询问。
15
- * 厂商(小米/OPPO/华为/FCM 等)不算平台——它们会命中写写对齐后的平台级配置页(如 knowledge/push/config/android.md),
15
+ * 厂商(小米/OPPO/华为/FCM 等)不算平台——它们全部归属 android 厂商配置子分类(knowledge/push/config/android/{vendor}.md),
16
16
  * 问厂商问题不需要再让用户选平台。
17
17
  */
18
18
  const PUSH_PLATFORM_SPECIFIC_PROMPT = /\b(android|ios|flutter|harmonyos|react[\s-]?native|unity|unreal|donut|uni[\s-]?app)\b/i;
@@ -44,7 +44,7 @@ function isChatErrorCodeAmbiguous(norm) {
44
44
  }
45
45
  /** 未传 framework 时,是否应先 present_framework_choice 再检索 */
46
46
  export function requiresFramework(norm) {
47
- if (norm.framework)
47
+ if (norm.frameworks?.length)
48
48
  return false;
49
49
  // 硬规则:chat 错误码场景必须问平台(服务端 / Web / Native 三个 URL)
50
50
  if (isChatErrorCodeAmbiguous(norm))
@@ -74,16 +74,26 @@ function postProcess(ranked, chunksById, limit) {
74
74
  if (topScore > 0 && item.score < topScore * 0.05)
75
75
  break;
76
76
  }
77
+ const contentWithHint = chunk.contains_code
78
+ ? `【代码示例,须与目标端一致】\n${chunk.content}`
79
+ : chunk.content;
77
80
  fragments.push({
78
81
  rank: fragments.length + 1,
79
82
  score: item.score,
80
83
  title: chunk.title,
81
- content: chunk.content,
84
+ content: contentWithHint,
82
85
  source: chunk.source,
83
86
  doc_urls: resolveFragmentDocUrls(chunk.source, chunk.content, getSourceFileContent(chunk.source)),
84
87
  product: chunk.product,
85
88
  framework: chunk.framework,
86
89
  types: chunk.types,
90
+ variant: chunk.variant,
91
+ scope: chunk.scope,
92
+ doc_kind: chunk.doc_kind,
93
+ capability_status: chunk.capability_status,
94
+ api_names: chunk.api_names,
95
+ contains_code: chunk.contains_code,
96
+ citation: `[来源: ${chunk.id}]`,
87
97
  chunk_id: chunk.id,
88
98
  });
89
99
  if (fragments.length >= limit)
@@ -112,62 +122,168 @@ function partitionFragments(fragments) {
112
122
  const urlMappingKinds = [...new Set(urlMapping.map((f) => isUrlMappingSource(f.source)).filter(Boolean))];
113
123
  return { urlMapping, localDoc, urlMappingKinds };
114
124
  }
125
+ function hasBestPracticeFragment(fragments) {
126
+ return fragments.some((f) => /\/best-practice\//i.test(f.source));
127
+ }
128
+ function inferQueryApiTokens(prompt) {
129
+ const tokens = new Set();
130
+ const upperNoise = new Set(['SDK', 'API', 'HTTP', 'HTTPS', 'JSON', 'CALL', 'NAME', 'STATUS']);
131
+ for (const match of prompt.matchAll(/\b([a-z]+[A-Z][A-Za-z0-9_]*)\b/g)) {
132
+ tokens.add(match[1]);
133
+ }
134
+ for (const match of prompt.matchAll(/\b([A-Z][A-Za-z0-9_]*\.[A-Za-z_][A-Za-z0-9_]*)\b/g)) {
135
+ tokens.add(match[1]);
136
+ }
137
+ for (const match of prompt.matchAll(/\b(use[A-Z]\w*)\b/g)) {
138
+ tokens.add(match[1]);
139
+ }
140
+ for (const match of prompt.matchAll(/\b(I[A-Z][A-Za-z0-9_]*)\b/g)) {
141
+ tokens.add(match[1]);
142
+ }
143
+ for (const match of prompt.matchAll(/\b([A-Z][A-Za-z0-9_]*\.[A-Z_][A-Z0-9_]*)\b/g)) {
144
+ tokens.add(match[1]);
145
+ }
146
+ for (const match of prompt.matchAll(/\b([A-Z_]{3,})\b/g)) {
147
+ const token = match[1];
148
+ if (!upperNoise.has(token))
149
+ tokens.add(token);
150
+ }
151
+ return [...tokens];
152
+ }
153
+ function tokenInChunk(token, chunk) {
154
+ if (chunk.api_names?.some((name) => name.toLowerCase() === token.toLowerCase()))
155
+ return true;
156
+ if (chunk.symbols?.some((name) => name.toLowerCase() === token.toLowerCase()))
157
+ return true;
158
+ const low = token.toLowerCase();
159
+ return chunk.title.toLowerCase().includes(low) || chunk.source.toLowerCase().includes(low);
160
+ }
161
+ function computeApiNameCoverage(tokens, candidates) {
162
+ if (!tokens.length)
163
+ return 1;
164
+ const hit = tokens.filter((token) => candidates.some((chunk) => tokenInChunk(token, chunk))).length;
165
+ return Number((hit / tokens.length).toFixed(2));
166
+ }
167
+ function computeMissingApiTokens(tokens, candidates) {
168
+ if (!tokens.length)
169
+ return [];
170
+ return tokens.filter((token) => !candidates.some((chunk) => tokenInChunk(token, chunk)));
171
+ }
172
+ function applyRankMultipliers(ranked, chunksById, opts) {
173
+ const adjusted = ranked.map((item) => {
174
+ const chunk = chunksById.get(item.id);
175
+ if (!chunk)
176
+ return item;
177
+ let multiplier = 1;
178
+ // A2: 传了 product 时,命中 scope 的通配语料允许召回但降权
179
+ if (opts.product?.length && chunk.product === '*') {
180
+ multiplier *= 0.2;
181
+ }
182
+ // F2: framework 软降权(保留硬过滤,处理 fallback/边界残留)
183
+ if (opts.framework && opts.frameworks?.length && !chunk.framework.includes('*')) {
184
+ const explicitMatch = opts.frameworks.some((fw) => chunk.framework.includes(fw));
185
+ const callCoreWebFallback = Boolean(opts.product?.includes('call')
186
+ && (opts.framework === 'react' || opts.framework === 'vue')
187
+ && chunk.variant === 'core-sdk'
188
+ && chunk.framework.includes('web'));
189
+ const liveWebVueFallback = Boolean(opts.product?.includes('live')
190
+ && opts.framework === 'web'
191
+ && chunk.variant === 'core-sdk'
192
+ && chunk.framework.includes('vue')
193
+ && chunk.source.includes('/api-reference/'));
194
+ if (!explicitMatch && !callCoreWebFallback && !liveWebVueFallback) {
195
+ multiplier *= 0.2;
196
+ }
197
+ }
198
+ return { ...item, score: item.score * multiplier };
199
+ });
200
+ return adjusted.sort((a, b) => b.score - a.score);
201
+ }
115
202
  /**
116
- * P0-3:相对阈值的置信度评估。
117
- * - high:top ≥ 50 或有精确命中(exactHits 非空)
118
- * - medium:top ≥ 10 且 top / second ≥ 1.3(区分度足够)
119
- * - low:top 较低或与 second 接近(同水位竞争,agent 应谨慎)
120
- * - none:fragments 为空
203
+ * 多因子置信度评估:exact 命中 + 分数梯度 + API 覆盖度。
121
204
  */
122
- function assessConfidence(fragments, exactHits) {
205
+ function assessConfidence(fragments, exactHits, apiNameCoverage, queryApiTokens) {
123
206
  if (fragments.length === 0) {
124
207
  return { confidence: 'none', status: 'empty' };
125
208
  }
126
209
  const top = fragments[0].score;
127
210
  const second = fragments[1]?.score ?? 0;
128
- if (exactHits.length > 0 || top >= 50) {
129
- return { confidence: 'high', status: 'success' };
130
- }
131
211
  const ratio = second > 0 ? top / second : Infinity;
132
- if (top >= 10 && ratio >= 1.3) {
133
- return { confidence: 'medium', status: 'success' };
134
- }
135
- if (top >= 5 && ratio >= 1.15) {
136
- return { confidence: 'medium', status: 'success' };
212
+ let confidence;
213
+ if (exactHits.length > 0 || top >= 50)
214
+ confidence = 'high';
215
+ else if (top >= 12 && ratio >= 1.25)
216
+ confidence = 'medium';
217
+ else if (top >= 6 && ratio >= 1.12)
218
+ confidence = 'medium';
219
+ else
220
+ confidence = 'low';
221
+ // D2: API 覆盖过低时,confidence 上限降为 low
222
+ if (queryApiTokens.length > 0 && apiNameCoverage < 0.3) {
223
+ confidence = 'low';
137
224
  }
138
- return { confidence: 'low', status: 'low_confidence' };
225
+ const status = confidence === 'low' ? 'low_confidence' : 'success';
226
+ return { confidence, status };
227
+ }
228
+ function buildAnswerContract(status, confidence, opts) {
229
+ const uncertaintyRule = status === 'low_confidence' || confidence === 'low'
230
+ ? '当信息不足时必须显式写“待确认:”,只允许陈述缺口,不允许猜测补全。'
231
+ : '除“待确认:”段落外,不得出现“可能/大概/应该/推测”等猜测措辞。';
232
+ const riskRule = opts?.fabricationRisk
233
+ ? 'fabrication_risk=true 时,若片段未覆盖该细节,必须输出“待确认:知识片段未覆盖此项”。'
234
+ : '';
235
+ return [
236
+ '【输出模板(必须遵守)】',
237
+ '使用“问题导向”标题组织答案,优先复用用户提问原句:一、<问题1> 二、<问题2> 三、<问题3> …',
238
+ '每个小节先给直接结论,再补 1-2 句必要说明;避免模板化术语(如“依据/操作”字样)。',
239
+ '信息缺口统一放在对应小节末尾,使用“待确认:xxx”;若全都确认则可省略“待确认”小节。',
240
+ '末尾保留“参考文档”小节,仅列文档标题或 URL;正文不展示检索过程、证据链、打分细节。',
241
+ '用户可见正文禁止出现系统检索话术(如“命中片段/检索结果/置信度/分数/召回/重排”)。',
242
+ '硬约束:不得引入 fragments 未出现的 API 名、字段值、枚举项、事件名。',
243
+ uncertaintyRule,
244
+ riskRule,
245
+ ].filter(Boolean).join(' ');
139
246
  }
140
- function buildAgentMessage(status, fragments, confidence, references) {
141
- const citeTail = references?.length
142
- ? 'When answering, MUST append a **References** section listing only **https** URLs from `meta.references` (or each fragment\'s `doc_urls`). Do not invent links. Do **not** list local repo paths such as `knowledge/...` or `integration/...` — users cannot open those.'
143
- : 'If fragments include `doc_urls`, append a **References** section with those **https** URLs only. Do **not** cite `fragment.source` local paths. If no online URLs are available, omit the References section rather than listing local file paths.';
144
- const tail = `${citeTail} Final answer drafted -> MUST call \`finalize_answer\` before replying. Explicit follow-up feedback -> call \`submit_feedback\`.`;
247
+ function buildAgentMessage(status, fragments, confidence, _references, opts) {
248
+ const platformRule = '端别硬规则:字段/API 描述前先标注【端别: framework】;禁止“部分版本也称 xxx”这类跨端混写;字段大小写必须与目标端文档一致;多端片段同时命中时主答案仅讲目标端,其他端差异放末尾简述;无片段覆盖的细节禁止补全。';
249
+ const riskRule = opts?.fabricationRisk ? '当前检索存在幻觉风险(fabrication_risk=true):禁止补全未命中 API 细节。' : '';
250
+ const answerContract = buildAnswerContract(status, confidence, opts);
251
+ const tail = `${platformRule} ${riskRule} ${answerContract} Final answer drafted -> MUST call \`finalize_answer\` before replying. Explicit follow-up feedback -> call \`submit_feedback\`.`;
145
252
  if (status === 'needs_framework') {
146
- return '[Hard rule] This question depends on a specific platform but no framework was provided; cross-platform search is low-signal and disallowed. MUST call `present_framework_choice` (with product), wait for the user to pick android/ios/flutter/react/vue/uni-app, then call this tool again with **product + framework**. Do not search with an empty framework.';
253
+ return '【硬规则】问题依赖具体平台实现,但未指定 frameworks,全平台混检信息密度低且被禁止。MUST 先调用 `present_framework_choice`(传入 product),等用户选定 web/miniprogram/android/ios/flutter/react/vue/uni-app 等后再调用本工具,并 MUST 带上 **product + frameworks**。禁止传空 frameworks 硬搜。';
147
254
  }
148
255
  const { urlMapping, localDoc, urlMappingKinds } = partitionFragments(fragments);
149
256
  const hasUrlMapping = urlMapping.length > 0;
150
257
  const hasLocalDoc = localDoc.length > 0;
258
+ const hasBestPractice = hasBestPracticeFragment(fragments);
151
259
  const urlKindLabel = urlMappingKinds.join(' / ') || 'urls';
152
260
  if (status === 'success' && fragments.length > 0) {
153
- const confidenceHint = confidence === 'high' ? '(confidence=high)'
154
- : confidence === 'medium' ? '(confidence=medium; top vs runner-up separation is moderate—confirm with the user if unsure)'
155
- : '';
261
+ const topFragment = fragments[0];
262
+ if (topFragment?.capability_status === 'unsupported') {
263
+ const scopeLabel = topFragment.scope ? `(${topFragment.scope})` : '';
264
+ return `当前问题在该平台 / 形态下 **不支持**${scopeLabel}。回答 MUST:① 第一段先明确写“**不支持**”;② 说明这是当前平台 Core 的能力边界,而不是缺少示例代码;③ 仅提供当前平台已支持的替代方案(如对应平台 preset 预制 UI);若当前知识库未给出明确替代形态,应直接说明暂无可执行替代路径;④ **禁止**输出当前平台 Core 的 API 调用步骤或集成步骤。${tail}`;
265
+ }
156
266
  if (hasUrlMapping && !hasLocalDoc) {
157
- return `Knowledge base hit **L1 URL map**${confidenceHint} (${urlKindLabel}, ${urlMapping.length} fragment(s)). These fragments are **documentation entry URLs only** (cloud.tencent.com / web.sdk.qcloud.com, etc.), not full REST API / error-code / webhook text. MUST: ① match the user's question to the **target URL** in fragments; ② **fetch** that official doc before answering; ③ do not restate the map table or invent API/error details.${tail}`;
267
+ return `当前可用信息主要是文档入口链接(${urlKindLabel})。请先匹配用户问题对应的目标 URL,抓取官网文档后再合成答案;禁止仅复述映射表或臆造 API/错误码细节。${tail}`;
158
268
  }
159
269
  if (hasUrlMapping && hasLocalDoc) {
160
- return `Knowledge base returned ${fragments.length} fragment(s)${confidenceHint}: ${localDoc.length} local doc + ${urlMapping.length} URL map (${urlKindLabel}). Answer directly from **local doc** fragments (preset/integration, etc.); for **URL map** fragments MUST extract the target URL and **fetch** the official doc—do not restate the map table.${tail}`;
270
+ if (hasBestPractice) {
271
+ return `优先基于已命中的 best-practice 与本地片段直接作答;URL 映射仅作补充参考,不要再抓官网做二次求证。${tail}`;
272
+ }
273
+ return `本地文档片段可直接用于作答;若本地片段未覆盖关键细节,再从 URL 映射中提取目标 URL 抓取官网文档补齐。${tail}`;
161
274
  }
162
- return `Knowledge base returned ${fragments.length} valid fragment(s)${confidenceHint}. Synthesize the answer **only from fragments**; do **not** run web_search or fetch docs separately.${tail}`;
275
+ return `请仅基于已返回 fragments 合成答案;不要并行 web_search 或额外抓取官网文档。${tail}`;
163
276
  }
164
277
  if (status === 'low_confidence') {
165
278
  if (hasUrlMapping) {
166
- return `Low confidence (confidence=low: top score weak or too close to runner-up) but URL map hit (${urlKindLabel}). Extract target URLs from fragments and **fetch** official docs; tell the user if the map does not cover their question.${tail}`;
279
+ if (hasBestPractice) {
280
+ return `优先基于 best-practice 与本地片段给出可执行结论;未覆盖的内容统一写入“待确认”,不要默认抓官网二次求证。${tail}`;
281
+ }
282
+ return `请先从 URL 映射里提取目标 URL 并抓取官网文档补齐关键信息,再给出答案;仍无法确认的内容明确写“待确认”。${tail}`;
167
283
  }
168
- return `Low confidence (confidence=low: top score weak or too close to runner-up; may not match the question). Answer from available fragments and **state uncertainty**; ask for a more specific query (component / API / error code) and retry. Do **not** default to web_search.${tail}`;
284
+ return `请基于已有 fragments 给出最可执行答案,并将未覆盖细节明确写为“待确认”;可引导用户补充组件名/API 名/错误码后重新检索。不要默认并行 web_search。${tail}`;
169
285
  }
170
- return `No valid fragments matched. Tell the user and verify product/framework; if the question needs a client platform, call \`present_framework_choice\` first.${tail}`;
286
+ return `知识库未命中有效片段。请向用户说明并确认 product/framework 是否准确;若仍无 platform 信息且问题依赖具体客户端,应先 \`present_framework_choice\`。${tail}`;
171
287
  }
172
288
  export function searchKnowledge(params) {
173
289
  const norm = normalizeParams(params);
@@ -188,42 +304,103 @@ export function searchKnowledge(params) {
188
304
  }
189
305
  const manifest = loadManifest();
190
306
  const allChunks = manifest.chunks;
191
- let pool = filterPool(allChunks, norm);
192
- // 自愈:types 过滤导致 0 命中时,丢掉 types 再过滤一次,避免误传类型标签直接返回 empty
193
- if (pool.length === 0 && norm.types?.length) {
194
- pool = filterPool(allChunks, { ...norm, types: undefined });
195
- }
196
- const { boosts, exactHits } = runExactLookup(norm.prompt, pool, norm);
197
- // P0-4:用 product 级缓存的 BM25 索引对子集打分(首次构建,后续命中缓存)
198
- // 索引基于该 product 全量 chunks(含 integration corpus);
199
- // 子集 ranking 只对 filteredPool.map(id) 打分,IDF 用更稳的产品级全量统计。
200
- // 支持多 product 同时检索(products 数组),跨域问题如 Chat + Push 能同时命中各方知识。
201
- const productIndex = getProductsBM25Index(allChunks, norm.product);
202
- const poolWithContent = attachPoolContent(pool);
203
- const chunksById = new Map(poolWithContent.map((chunk) => [chunk.id, chunk]));
204
- const ranked = rankSubsetWithIndex(norm.prompt, pool.map((chunk) => chunk.id), productIndex, boosts);
205
- const fragments = postProcess(ranked, chunksById, norm.limit);
206
- const urlMappingSources = [...new Set(fragments.map((f) => f.source).filter((source) => isUrlMappingSource(source)))];
207
- const references = buildReferences(fragments);
208
- // P0-3:相对阈值评估置信度(替代原硬编码 0.5 死阈值)
209
- const { confidence, status } = assessConfidence(fragments, exactHits);
210
- const topScore = fragments[0]?.score;
211
- const secondScore = fragments[1]?.score;
307
+ const queryApiTokens = inferQueryApiTokens(norm.prompt);
308
+ const runSearchPass = (passNorm, opts) => {
309
+ let pool = filterPool(allChunks, passNorm);
310
+ // types 误传自愈:首轮保留,二次扩检也同样保留该能力
311
+ if (pool.length === 0 && passNorm.types?.length) {
312
+ pool = filterPool(allChunks, { ...passNorm, types: undefined });
313
+ }
314
+ const { boosts, exactHits } = runExactLookup(passNorm.prompt, pool, passNorm);
315
+ // A2 补充正向路由:UserSig 问法下允许 share 命中且优先于无关 urls 噪声
316
+ if (/usersig|sdkappid|secretkey|鉴权|签名|gentestusersig/i.test(passNorm.prompt)) {
317
+ for (const chunk of pool) {
318
+ if (chunk.product === '*' && chunk.source.includes('knowledge/share/userSig.md')) {
319
+ boosts[chunk.id] = (boosts[chunk.id] ?? 0) + 220;
320
+ }
321
+ }
322
+ }
323
+ // B2: API 覆盖不足扩检时,对 api/integration 语料做轻量重排提权
324
+ if (opts?.apiRetry) {
325
+ for (const chunk of pool) {
326
+ if (chunk.types.includes('api') || chunk.types.includes('integration')) {
327
+ boosts[chunk.id] = (boosts[chunk.id] ?? 0) + 40;
328
+ }
329
+ }
330
+ }
331
+ const productIndex = getProductsBM25Index(allChunks, passNorm.product);
332
+ const poolWithContent = attachPoolContent(pool);
333
+ const chunksById = new Map(poolWithContent.map((chunk) => [chunk.id, chunk]));
334
+ const ranked = rankSubsetWithIndex(passNorm.prompt, pool.map((chunk) => chunk.id), productIndex, boosts);
335
+ const rankedWithMultipliers = applyRankMultipliers(ranked, chunksById, {
336
+ product: passNorm.product,
337
+ framework: passNorm.framework,
338
+ frameworks: passNorm.frameworks,
339
+ });
340
+ const fragments = postProcess(rankedWithMultipliers, chunksById, passNorm.limit);
341
+ const urlMappingSources = [...new Set(fragments.map((f) => f.source).filter((source) => isUrlMappingSource(source)))];
342
+ const references = buildReferences(fragments);
343
+ const apiNameCoverage = computeApiNameCoverage(queryApiTokens, poolWithContent);
344
+ const missingApiTokens = computeMissingApiTokens(queryApiTokens, poolWithContent);
345
+ return {
346
+ pool,
347
+ fragments,
348
+ exactHits,
349
+ urlMappingSources,
350
+ references,
351
+ apiNameCoverage,
352
+ missingApiTokens,
353
+ };
354
+ };
355
+ let pass = runSearchPass(norm);
356
+ let retryReason;
357
+ // B2: API token 覆盖不足时触发一次扩检(去掉 types 约束 + api/integration 轻提权)
358
+ const missingRatio = queryApiTokens.length > 0
359
+ ? Number((pass.missingApiTokens.length / queryApiTokens.length).toFixed(2))
360
+ : 0;
361
+ if (queryApiTokens.length > 0 && (pass.apiNameCoverage === 0 || missingRatio >= 0.3)) {
362
+ const retryPass = runSearchPass({ ...norm, types: undefined }, { apiRetry: true });
363
+ const retryMissingRatio = queryApiTokens.length > 0
364
+ ? Number((retryPass.missingApiTokens.length / queryApiTokens.length).toFixed(2))
365
+ : 0;
366
+ if (retryPass.apiNameCoverage > pass.apiNameCoverage
367
+ || retryMissingRatio < missingRatio
368
+ || (pass.fragments.length === 0 && retryPass.fragments.length > 0)) {
369
+ pass = retryPass;
370
+ retryReason = `api_gap_retry:coverage=${pass.apiNameCoverage},missing_ratio=${retryMissingRatio}`;
371
+ }
372
+ }
373
+ const routeInconsistencyWarning = pass.fragments.length > 0
374
+ ? pass.fragments.filter((f) => f.product === '*').length / pass.fragments.length > 0.3
375
+ : false;
376
+ const { confidence, status } = assessConfidence(pass.fragments, pass.exactHits, pass.apiNameCoverage, queryApiTokens);
377
+ const fabricationRisk = (queryApiTokens.length > 0 && pass.apiNameCoverage < 0.3)
378
+ || (confidence === 'low' && pass.fragments.length < 2);
379
+ const topScore = pass.fragments[0]?.score;
380
+ const secondScore = pass.fragments[1]?.score;
381
+ const answerContract = buildAnswerContract(status, confidence, { fabricationRisk });
212
382
  return {
213
383
  status,
214
384
  confidence,
215
- message: buildAgentMessage(status, fragments, confidence, references),
385
+ message: buildAgentMessage(status, pass.fragments, confidence, pass.references, { fabricationRisk }),
216
386
  query: params,
217
387
  meta: {
218
388
  pool_size: allChunks.length,
219
- filtered_size: pool.length,
220
- exact_hits: exactHits,
221
- ...(urlMappingSources.length ? { url_mapping_sources: urlMappingSources } : {}),
222
- ...(references.length ? { references } : {}),
389
+ filtered_size: pass.pool.length,
390
+ exact_hits: pass.exactHits,
391
+ ...(pass.urlMappingSources.length ? { url_mapping_sources: pass.urlMappingSources } : {}),
392
+ ...(pass.references.length ? { references: pass.references } : {}),
223
393
  ...(topScore !== undefined ? { top_score: Number(topScore.toFixed(2)) } : {}),
224
394
  ...(secondScore !== undefined ? { second_score: Number(secondScore.toFixed(2)) } : {}),
395
+ ...(queryApiTokens.length ? { query_api_tokens: queryApiTokens } : {}),
396
+ ...(pass.missingApiTokens.length ? { missing_api_tokens: pass.missingApiTokens } : {}),
397
+ ...(retryReason ? { retry_reason: retryReason } : {}),
398
+ answer_contract: answerContract,
399
+ api_name_coverage: pass.apiNameCoverage,
400
+ fabrication_risk: fabricationRisk,
401
+ route_inconsistency_warning: routeInconsistencyWarning,
225
402
  },
226
- fragments,
403
+ fragments: pass.fragments,
227
404
  };
228
405
  }
229
406
  export { normalizeParams, filterPool };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencent-rtc/mcp",
3
- "version": "1.6.3",
3
+ "version": "1.6.5",
4
4
  "description": "Tencent Cloud MCP Server for SDK",
5
5
  "type": "module",
6
6
  "main": "index.js",