@tencentcloud/sdk-mcp 1.7.2 → 1.7.4

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 (135) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +25 -17
  3. package/knowledge/bm25.js +20 -11
  4. package/knowledge/path-meta.js +23 -1
  5. package/knowledge/search/generic-rerank.js +123 -0
  6. package/knowledge/search/search-pass.js +8 -1
  7. package/package.json +1 -1
  8. package/resource/_schema/query-normalization.yaml +6 -0
  9. package/resource/index/manifest.json +1 -1
  10. package/resource/integration/callkit/preset/android/integration.md +4 -0
  11. package/resource/integration/callkit/preset/flutter/integration.md +4 -0
  12. package/resource/integration/callkit/preset/ios/integration.md +14 -13
  13. package/resource/integration/callkit/preset/vue/integration.md +0 -3
  14. package/resource/integration/chat/preset/android/integration.md +35 -173
  15. package/resource/integration/chat/preset/flutter/integration.md +113 -220
  16. package/resource/integration/chat/preset/ios/integration.md +2 -269
  17. package/resource/integration/chat/preset/react/integration.md +27 -1
  18. package/resource/integration/chat/preset/uni-app/integration.md +5 -1
  19. package/resource/integration/chat/preset/vue/integration.md +21 -31
  20. package/resource/integration/livekit/preset/live/android/live-host-integration.md +4 -0
  21. package/resource/integration/livekit/preset/live/ios/live-host-integration.md +4 -0
  22. package/resource/integration/livekit/preset/live/vue/live-list-integration.md +3 -4
  23. package/resource/integration/livekit/preset/live/vue/live-player-desk-integration.md +0 -1
  24. package/resource/integration/livekit/preset/live/vue/live-player-h5-integration.md +0 -1
  25. package/resource/integration/livekit/preset/live/vue/live-pusher-integration.md +4 -9
  26. package/resource/integration/roomkit/preset/vue/integration.md +0 -213
  27. package/resource/knowledge/callkit/best-practice/android/video-chat-dating.md +490 -0
  28. package/resource/knowledge/callkit/best-practice/flutter/android-keep-call-alive-background.md +79 -0
  29. package/resource/knowledge/callkit/best-practice/flutter/background-incoming-call-no-notification.md +99 -0
  30. package/resource/knowledge/callkit/best-practice/flutter/ios-keep-call-alive-background.md +93 -0
  31. package/resource/knowledge/callkit/best-practice/flutter/ios-startup-crash-version-voip.md +68 -0
  32. package/resource/knowledge/callkit/core-sdk/flutter/offline-push.md +1 -1
  33. package/resource/knowledge/callkit/core-sdk/ios/answer-call.md +9 -7
  34. package/resource/knowledge/callkit/core-sdk/ios/make-call.md +10 -7
  35. package/resource/knowledge/callkit/core-sdk/ios/offline-push.md +1 -1
  36. package/resource/knowledge/callkit/core-sdk/miniprogram/call-engine.md +19 -19
  37. package/resource/knowledge/callkit/core-sdk/miniprogram/call-event.md +16 -16
  38. package/resource/knowledge/callkit/core-sdk/uni-app/answer-call.md +0 -84
  39. package/resource/knowledge/callkit/core-sdk/uni-app/make-call.md +0 -102
  40. package/resource/knowledge/callkit/core-sdk/web/call-event.md +2 -2
  41. package/resource/knowledge/callkit/faq/error-code.md +62 -36
  42. package/resource/knowledge/callkit/faq/uniapp-miniprogram.md +1 -1
  43. package/resource/knowledge/callkit/preset/android/api.md +10 -10
  44. package/resource/knowledge/callkit/preset/harmonyos/api.md +362 -0
  45. package/resource/knowledge/callkit/preset/harmonyos/integration.md +322 -0
  46. package/resource/knowledge/callkit/preset/ios/api.md +9 -9
  47. package/resource/knowledge/callkit/preset/miniprogram/api-uniapp.md +293 -0
  48. package/resource/knowledge/callkit/preset/miniprogram/api.md +19 -19
  49. package/resource/knowledge/callkit/preset/miniprogram/integration.md +292 -0
  50. package/resource/knowledge/callkit/preset/miniprogram/uniapp-integration.md +521 -0
  51. package/resource/knowledge/callkit/preset/uni-app/api.md +49 -0
  52. package/resource/knowledge/callkit/preset/uni-app/integration.md +353 -0
  53. package/resource/knowledge/chat/best-practice/common/web-sdk-log-level.md +76 -0
  54. package/resource/knowledge/chat/best-practice/miniprogram/desktop-wechat-miniprogram-error.md +79 -0
  55. package/resource/knowledge/chat/best-practice/miniprogram/login-timeout-2801-diagnosis.md +1 -1
  56. package/resource/knowledge/chat/preset/android-view/integration.md +84 -124
  57. package/resource/knowledge/chat/preset/ios/features/language.md +5 -5
  58. package/resource/knowledge/chat/preset/ios-uikit/integration.md +184 -923
  59. package/resource/knowledge/chat/preset/react/features/search.md +9 -214
  60. package/resource/knowledge/chat/preset/react/h5/integration.md +965 -0
  61. package/resource/knowledge/chat/preset/vue/features/chat-header.md +0 -36
  62. package/resource/knowledge/chat/preset/vue/features/contact-list.md +0 -34
  63. package/resource/knowledge/chat/preset/vue/features/conversation-list.md +0 -39
  64. package/resource/knowledge/chat/preset/vue/features/conversation-preview.md +0 -74
  65. package/resource/knowledge/chat/preset/vue/features/search.md +9 -790
  66. package/resource/knowledge/chat/preset/vue/h5/integration.md +724 -0
  67. package/resource/knowledge/livekit/core-sdk/features/uni-app/live-list.md +0 -167
  68. package/resource/knowledge/livekit/core-sdk/live/android/co-guest-interaction.md +1 -1
  69. package/resource/knowledge/livekit/core-sdk/live/android/host-interaction.md +1 -1
  70. package/resource/knowledge/livekit/core-sdk/live/flutter/co-guest-interaction.md +1 -1
  71. package/resource/knowledge/livekit/core-sdk/live/flutter/host-interaction.md +1 -1
  72. package/resource/knowledge/livekit/core-sdk/live/flutter/integration.md +1 -1
  73. package/resource/knowledge/livekit/core-sdk/live/ios/co-guest-interaction.md +1 -1
  74. package/resource/knowledge/livekit/core-sdk/live/ios/host-interaction.md +1 -1
  75. package/resource/knowledge/livekit/core-sdk/live/ios/integration.md +2 -2
  76. package/resource/knowledge/livekit/core-sdk/live/uni-app/co-guest-interaction.md +1 -66
  77. package/resource/knowledge/livekit/core-sdk/live/uni-app/host-interaction.md +1 -66
  78. package/resource/knowledge/livekit/core-sdk/live/uni-app/integration.md +1 -1
  79. package/resource/knowledge/livekit/core-sdk/voice/android/co-guest-interaction.md +1 -1
  80. package/resource/knowledge/livekit/core-sdk/voice/android/host-interaction.md +2 -2
  81. package/resource/knowledge/livekit/core-sdk/voice/flutter/co-guest-interaction.md +1 -1
  82. package/resource/knowledge/livekit/core-sdk/voice/ios/co-guest-interaction.md +1 -1
  83. package/resource/knowledge/livekit/core-sdk/voice/ios/host-interaction.md +2 -2
  84. package/resource/knowledge/livekit/core-sdk/voice/uni-app/integration.md +2 -2
  85. package/resource/knowledge/livekit/preset/live/vue/features/barrage.md +1 -24
  86. package/resource/knowledge/livekit/preset/live/vue/features/live-audience-list.md +0 -3
  87. package/resource/knowledge/livekit/preset/live/vue/features/live-view.md +0 -5
  88. package/resource/knowledge/push/api-reference/harmonyos.md +9 -9
  89. package/resource/knowledge/push/api-reference/unity.md +10 -10
  90. package/resource/knowledge/push/api-reference/unreal-engine.md +11 -11
  91. package/resource/knowledge/push/config/android/fcm.md +2 -6
  92. package/resource/knowledge/push/integration/android.md +824 -428
  93. package/resource/knowledge/push/integration/donut.md +57 -74
  94. package/resource/knowledge/push/integration/flutter.md +208 -63
  95. package/resource/knowledge/push/integration/harmonyos.md +6 -11
  96. package/resource/knowledge/push/integration/ios.md +44 -99
  97. package/resource/knowledge/push/integration/react-native.md +3 -2
  98. package/resource/knowledge/push/integration/uni-app.md +29 -107
  99. package/resource/knowledge/push/integration/unity.md +3 -2
  100. package/resource/knowledge/push/integration/unreal-engine.md +4 -3
  101. package/resource/knowledge/roomkit/best-practice/vue/screen-share-auto-stop-on-leave.md +62 -0
  102. package/resource/knowledge/roomkit/core-sdk/android/room-state.md +3 -3
  103. package/resource/knowledge/roomkit/core-sdk/android/schedule-room.md +4 -4
  104. package/resource/knowledge/roomkit/core-sdk/flutter/room-state.md +2 -2
  105. package/resource/knowledge/roomkit/core-sdk/flutter/schedule-room.md +4 -4
  106. package/resource/knowledge/roomkit/core-sdk/ios/room-state.md +3 -3
  107. package/resource/knowledge/roomkit/core-sdk/ios/schedule-room.md +4 -4
  108. package/resource/knowledge/roomkit/core-sdk/react/network-proxy.md +84 -0
  109. package/resource/knowledge/roomkit/core-sdk/vue/device-detection.md +0 -9
  110. package/resource/knowledge/roomkit/core-sdk/vue/free-beauty-panel.md +0 -9
  111. package/resource/knowledge/roomkit/core-sdk/vue/network-proxy.md +84 -0
  112. package/resource/knowledge/roomkit/core-sdk/vue/recording.md +245 -0
  113. package/resource/knowledge/roomkit/core-sdk/vue/room-chat.md +0 -3
  114. package/resource/knowledge/roomkit/core-sdk/vue/room-view.md +0 -16
  115. package/resource/knowledge/roomkit/core-sdk/vue/schedule-room.md +0 -3
  116. package/resource/knowledge/roomkit/core-sdk/vue/virtual-background.md +0 -3
  117. package/resource/knowledge/roomkit/core-sdk/vue/whiteboard-annotation.md +181 -0
  118. package/resource/knowledge/roomkit/faq/error-code.md +103 -0
  119. package/resource/knowledge/roomkit/preset/android/integration.md +1 -202
  120. package/resource/knowledge/roomkit/preset/flutter/integration.md +13 -13
  121. package/resource/knowledge/roomkit/preset/harmonyos/integration.md +465 -0
  122. package/resource/knowledge/roomkit/preset/ios/integration.md +0 -201
  123. package/resource/knowledge/roomkit/preset/react/features/network-proxy.md +80 -0
  124. package/resource/knowledge/roomkit/preset/react/integration.md +0 -202
  125. package/resource/knowledge/roomkit/preset/uniapp-app/integration.md +279 -0
  126. package/resource/knowledge/roomkit/preset/vue/features/ai-caption-translation.md +69 -0
  127. package/resource/knowledge/roomkit/preset/vue/features/ai-denoiser.md +67 -0
  128. package/resource/knowledge/roomkit/preset/vue/features/network-proxy.md +80 -0
  129. package/resource/knowledge/roomkit/preset/vue/features/recording.md +85 -0
  130. package/resource/knowledge/roomkit/preset/vue/features/whiteboard-annotation.md +86 -0
  131. package/resource/knowledge/rtcengine/web/plugin/42-advanced-realtime-transcriber.md +25 -6
  132. package/server.js +1 -1
  133. package/utils/preflight-route.js +18 -6
  134. package/utils/report-cls-client.js +1 -1
  135. package/utils/report-es-client.js +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## Version 1.7.4 @2026.08.31
4
+
5
+ ### 新增
6
+ - 新增 CallKit Flutter 最佳实践文档 4 篇:Android 后台通话保活、iOS 后台音频保活、iOS 启动崩溃排查、后台来电无通知排查。
7
+ - 新增 CallKit Android 视频交友场景(VideoChat Demo)最佳实践文档,覆盖 Demo 跑通与组件快速集成。
8
+ - 新增 CallKit HarmonyOS 平台支持:含 UI 集成指南与 API 参考文档。
9
+ - 新增 CallKit 小程序 & uni-app 集成文档:含 UI 集成指南、API 参考、uni-app 打包指南。
10
+ - 新增 CallKit uni-app(Android/iOS)独立集成文档与 API 参考。
11
+ - 新增 Chat Vue3/React H5 移动端集成文档。
12
+
13
+ ### 变更
14
+ - 优化 Chat 含 UI 检索标签:vue/react 的 framework 从单标签改为双标签(`['vue','web']` / `['react','web']`),使 `frameworks=['web']` 也能命中 Chat Web 端文档。
15
+
16
+ ## Version 1.7.3 @2026.08.17
17
+
18
+ ### 新增
19
+ - 新增 RoomKit 多端集成、录制、白板、网络代理、AI 降噪与字幕翻译等知识库资源,扩充 Room 产品域知识覆盖。
20
+ - 新增错误码、日志级别、屏幕分享自动停止及微信小程序报错排查等最佳实践文档。
21
+ - 新增通用加性 rerank 模块,实现锚点选择与短语提取,并集成到搜索重排逻辑,提升召回排序准确率。
22
+
23
+ ### 变更
24
+ - 优化 BM25 索引为无原型对象,提升索引结构的隔离性与稳定性。
25
+
26
+ ### 修复
27
+ - 修复 BM25 打分受原型键污染导致的异常,增加原型键守卫,避免打分污染与 NaN 问题。
28
+
3
29
  ## Version 1.7.2 @2026.08.13
4
30
 
5
31
  ### 变更
package/README.md CHANGED
@@ -59,31 +59,39 @@ npx -y @tencentcloud/sdk-mcp
59
59
 
60
60
  > 仅展示最近更新,完整历史请查看 `CHANGELOG.md`。
61
61
 
62
- ## Version 1.7.1 @2026.08.11
62
+ ## Version 1.7.4 @2026.08.31
63
63
 
64
64
  ### 新增
65
- - 新增检索前置归一化:基于 prompt 真值对 `product` / `frameworks` 做归一化,解决 agent 推理错误导致的检索偏差。
65
+ - 新增 CallKit Flutter 最佳实践文档 4 篇:Android 后台通话保活、iOS 后台音频保活、iOS 启动崩溃排查、后台来电无通知排查。
66
+ - 新增 CallKit Android 视频交友场景(VideoChat Demo)最佳实践文档,覆盖 Demo 跑通与组件快速集成。
67
+ - 新增 CallKit HarmonyOS 平台支持:含 UI 集成指南与 API 参考文档。
68
+ - 新增 CallKit 小程序 & uni-app 集成文档:含 UI 集成指南、API 参考、uni-app 打包指南。
69
+ - 新增 CallKit uni-app(Android/iOS)独立集成文档与 API 参考。
70
+ - 新增 Chat Vue3/React H5 移动端集成文档。
66
71
 
67
72
  ### 变更
68
- - 优化 `search_trtc_knowledge` 输出契约:移除 "1-2 sentence per subsection" 等压缩性措辞,改为输出完整合成答案。
73
+ - 优化 Chat 含 UI 检索标签:vue/react 的 framework 从单标签改为双标签(`['vue','web']` / `['react','web']`),使 `frameworks=['web']` 也能命中 Chat Web 端文档。
69
74
 
70
- ### 修复
71
- - 修复 "安卓 Web TRTC" 等 prompt 下 agent 误传双 product / 双 frameworks 时未按 prompt 真值校正的问题。
75
+ ## Version 1.7.3 @2026.08.17
76
+
77
+ ### 新增
78
+ - 新增 RoomKit 多端集成、录制、白板、网络代理、AI 降噪与字幕翻译等知识库资源,扩充 Room 产品域知识覆盖。
79
+ - 新增错误码、日志级别、屏幕分享自动停止及微信小程序报错排查等最佳实践文档。
80
+ - 新增通用加性 rerank 模块,实现锚点选择与短语提取,并集成到搜索重排逻辑,提升召回排序准确率。
72
81
 
73
- ### Version 1.7.0 @2026.08.02
82
+ ### 变更
83
+ - 优化 BM25 索引为无原型对象,提升索引结构的隔离性与稳定性。
74
84
 
75
- #### 新增
76
- - 补充并同步 Chat / Call / Live / Room 等产品域最佳实践文档,增强知识覆盖范围。
85
+ ### 修复
86
+ - 修复 BM25 打分受原型键污染导致的异常,增加原型键守卫,避免打分污染与 NaN 问题。
77
87
 
78
- #### 变更
79
- - 持续重构双语检索链路,优化 query 归一化、意图路由、候选过滤与精确命中策略。
80
- - 优化最佳实践与 URL 类文档的召回与排序,提升问答结果可用性与稳定性。
81
- - 优化 `search_trtc_knowledge` 相关定义与答复约束,提升回答可读性与可执行性。
88
+ ## Version 1.7.1 @2026.08.11
82
89
 
83
- #### 修复
84
- - 修复复杂问法下部分检索结果偏题的问题,降低高分误召回概率。
90
+ ### 新增
91
+ - 新增检索前置归一化:基于 prompt 真值对 `product` / `frameworks` 做归一化,解决 agent 推理错误导致的检索偏差。
85
92
 
86
- ### Version 1.6.6 @2026.07.18
93
+ ### 变更
94
+ - 优化 `search_trtc_knowledge` 输出契约:移除 "1-2 sentence per subsection" 等压缩性措辞,改为输出完整合成答案。
87
95
 
88
- #### 新增
89
- - 支持 `get_native_live_uikit_integration` 工具,支持 LiveKit(Android/iOS) 含 UI 集成。
96
+ ### 修复
97
+ - 修复 "安卓 Web TRTC" 等 prompt 下 agent 误传双 product / 双 frameworks 时未按 prompt 真值校正的问题。
package/knowledge/bm25.js CHANGED
@@ -61,28 +61,29 @@ export function tokenize(text) {
61
61
  return tokens;
62
62
  }
63
63
  export function buildBM25Index(documents) {
64
- const postings = {};
65
- const docLengths = {};
66
- const docFreq = {};
64
+ // 用无原型对象,杜绝 term/id 为 'constructor'/'__proto__' 等原型键时的污染。
65
+ const postings = Object.create(null);
66
+ const docLengths = Object.create(null);
67
+ const docFreq = Object.create(null);
67
68
  let totalLength = 0;
68
69
  for (const doc of documents) {
69
70
  const tokens = tokenize(doc.text);
70
71
  docLengths[doc.id] = tokens.length;
71
72
  totalLength += tokens.length;
72
- const termFreq = {};
73
+ const termFreq = Object.create(null);
73
74
  for (const token of tokens) {
74
75
  termFreq[token] = (termFreq[token] ?? 0) + 1;
75
76
  }
76
77
  for (const [term, freq] of Object.entries(termFreq)) {
77
78
  if (!postings[term])
78
- postings[term] = {};
79
+ postings[term] = Object.create(null);
79
80
  postings[term][doc.id] = freq;
80
81
  docFreq[term] = (docFreq[term] ?? 0) + 1;
81
82
  }
82
83
  }
83
84
  const n = documents.length;
84
85
  const avgDocLength = n > 0 ? totalLength / n : 0;
85
- const idf = {};
86
+ const idf = Object.create(null);
86
87
  for (const [term, df] of Object.entries(docFreq)) {
87
88
  idf[term] = Math.log(1 + (n - df + 0.5) / (df + 0.5));
88
89
  }
@@ -96,15 +97,23 @@ export function buildBM25Index(documents) {
96
97
  }
97
98
  export function scoreBM25(query, chunkId, index) {
98
99
  const tokens = tokenize(query);
99
- const docLength = index.docLengths[chunkId] ?? 0;
100
- if (docLength === 0)
100
+ // Object.prototype 污染防护:postings/idf/docLengths 来自 JSON.parse 的普通对象,
101
+ // term 可能是 'constructor'/'toString'/'__proto__' 等原型键,直接 [] 取值会命中
102
+ // 原型链上的函数(如 Object.prototype.constructor),污染打分为 NaN。用 hasOwn 守卫。
103
+ const docLength = Object.hasOwn(index.docLengths, chunkId) ? index.docLengths[chunkId] : 0;
104
+ if (!docLength || Number.isNaN(docLength))
101
105
  return 0;
102
106
  let score = 0;
103
107
  for (const term of tokens) {
104
- const tf = index.postings[term]?.[chunkId] ?? 0;
105
- if (tf === 0)
108
+ if (!Object.hasOwn(index.postings, term) || !Object.hasOwn(index.idf, term))
109
+ continue;
110
+ const posting = index.postings[term];
111
+ const tf = Object.hasOwn(posting, chunkId) ? posting[chunkId] : 0;
112
+ if (!tf || Number.isNaN(tf))
113
+ continue;
114
+ const idf = index.idf[term];
115
+ if (Number.isNaN(idf))
106
116
  continue;
107
- const idf = index.idf[term] ?? 0;
108
117
  const numerator = tf * (K1 + 1);
109
118
  const denominator = tf + K1 * (1 - B + B * (docLength / (index.avgDocLength || 1)));
110
119
  score += idf * (numerator / denominator);
@@ -8,6 +8,9 @@ function inferTypesFromFilename(fileName, baseTypes) {
8
8
  types.push('error_code');
9
9
  if (lower === 'client-api.md' || lower === 'api.md' || lower === 'index.md')
10
10
  types.push('api');
11
+ // api-<变体>.md(如 api-uniapp.md:微信小程序 uni-app 打包 API)同样是 API 文档
12
+ if (/^api-[\w-]+\.mdx?$/.test(lower))
13
+ types.push('api');
11
14
  if (lower === 'faq.md')
12
15
  types.push('faq');
13
16
  // 文件名 = integration.md 不再默认 push integration(由上游 framework 分支显式声明 type)
@@ -75,7 +78,14 @@ export function inferPathMeta(relativeSource) {
75
78
  else if (normalized.startsWith('knowledge/chat/') || normalized.startsWith('integration/chat/')) {
76
79
  product = 'chat';
77
80
  if (parts.includes('preset') && parts.length >= 4) {
78
- framework = [normalizeFrameworkDir(parts[parts.indexOf('preset') + 1])];
81
+ const fw = normalizeFrameworkDir(parts[parts.indexOf('preset') + 1]);
82
+ // vue/react 运行在 Web/H5 端,追加 web 标签,使 frameworks=['web'] 也能命中
83
+ framework = (fw === 'vue' || fw === 'react') ? [fw, 'web'] : [fw];
84
+ variant = 'preset';
85
+ // preset 下的 integration.md 显式标记 integration type
86
+ if (fileName.toLowerCase() === 'integration.md') {
87
+ types.push('integration');
88
+ }
79
89
  }
80
90
  if (parts.includes('features')) {
81
91
  types.push('feature');
@@ -137,6 +147,13 @@ export function inferPathMeta(relativeSource) {
137
147
  framework = [normalizeFrameworkDir(parts[coreIdx + 1])];
138
148
  variant = 'core-sdk';
139
149
  }
150
+ // 微信小程序 uni-app 打包版:目录归入 miniprogram(运行平台=微信小程序),
151
+ // 但技术栈是 uni-app,通过文件名 *-uniapp.md / uniapp-*.md 触发双标签,
152
+ // 使「微信小程序」与「uni-app」两种 framework 检索都能召回同一篇文档。
153
+ // 原生小程序(api.md/integration.md 等无 uniapp 标记)保持单 miniprogram 标签。
154
+ if (framework[0] === 'miniprogram' && /(^uniapp[-.]|-uniapp\.mdx?$)/.test(fileName.toLowerCase())) {
155
+ framework = ['miniprogram', 'uni-app'];
156
+ }
140
157
  // callkit 最佳实践目录:knowledge/callkit/best-practice/{platform}/{topic}.md
141
158
  // 统一按 FAQ/经验类知识处理,支持 types=faq + frameworks={platform} 的精确检索。
142
159
  // 与 chat best-practice 对齐:common 目录表示多平台通用,按最全集覆盖。
@@ -147,6 +164,11 @@ export function inferPathMeta(relativeSource) {
147
164
  : [fwSlug];
148
165
  types.push('faq');
149
166
  }
167
+ // preset 下的 integration.md(纯文件名,无连字符前缀)需显式标记 integration type,
168
+ // 否则 inferTypesFromFilename 只匹配 *-integration.md,导致兜底为 faq。
169
+ if (variant === 'preset' && fileName.toLowerCase() === 'integration.md') {
170
+ types.push('integration');
171
+ }
150
172
  if (parts.includes('faq'))
151
173
  types.push('faq', 'error_code');
152
174
  if (fileName === 'api.md')
@@ -0,0 +1,123 @@
1
+ /**
2
+ * 通用加性 rerank:数据驱动的高 IDF 锚点命中 + 连续短语命中。
3
+ *
4
+ * 设计约束(零衰减 + 通用):
5
+ * - 纯加性:只往 boosts 加正数,无 penalty;无信号(无锚点且无短语命中)时返回空 map,
6
+ * 排序数学上完全等于现状 → 已有功能零衰减。
7
+ * - 量纲受控:单 chunk 上限 = W_ANCHOR + W_PHRASE,远低于 exact-lookup 的 +200~+300,
8
+ * 只在 BM25 平局区间起微调,不翻转既有精确命中。
9
+ * - 零硬编码:锚点门槛来自运行时 index.idf 分位、短语来自 query 结构,
10
+ * 不含任何具体词 / product / 文件名 → 对任意产品成立。
11
+ *
12
+ * 治两个诊断确认的真病根:
13
+ * - A(锚点命中):对抗「CJK unigram 被拆多份 × 高 tf 堆分」——稀有锚点命中给加权,
14
+ * 把靠通用词堆分的长文档区分开。
15
+ * - B(连续短语):用原始字符串连续匹配抓「组合稀有」(如 WebSocket is not a constructor),
16
+ * 同时天然排除 tokenize 产生的跨词垃圾 bigram(如「错怎」——它在原 query 里虽连续,
17
+ * 但作为连续串在无关文档正文中不命中,不会被误加分)。
18
+ */
19
+ // ── 超参(唯一可调项,均可回归验证)──────────────────────────────
20
+ /** 锚点门槛:取当前检索子库 IDF 分布的分位阈值,IDF ≥ 此值的 query term 视为锚点 */
21
+ const IDF_PERCENTILE = 0.75;
22
+ /** 锚点数上限,防止长 query 稀释权重 */
23
+ const MAX_ANCHORS = 6;
24
+ /** 锚点命中权重(与 BM25 top 分 20~50 同量级,低于 exact-lookup boost 量级) */
25
+ const W_ANCHOR = 40;
26
+ /** 连续短语命中权重 */
27
+ const W_PHRASE = 30;
28
+ /**
29
+ * 从 query term 中选出锚点:IDF ≥ 子库分位阈值的 term,按 IDF 降序取 top-K。
30
+ * 门槛完全由 index.idf 的运行时分布决定(数据驱动),不写死任何词。
31
+ */
32
+ function selectAnchors(queryTerms, index) {
33
+ const allIdf = Object.values(index.idf);
34
+ if (allIdf.length === 0)
35
+ return [];
36
+ const sorted = [...allIdf].sort((a, b) => a - b);
37
+ const threshold = sorted[Math.floor(sorted.length * IDF_PERCENTILE)] ?? 0;
38
+ const seen = new Set();
39
+ const anchors = [];
40
+ for (const term of queryTerms) {
41
+ if (seen.has(term))
42
+ continue;
43
+ seen.add(term);
44
+ // Object.prototype 污染防护:term 可能是 'constructor' 等原型键。
45
+ if (!Object.hasOwn(index.idf, term))
46
+ continue;
47
+ const idf = index.idf[term];
48
+ if (typeof idf !== 'number' || Number.isNaN(idf) || idf < threshold)
49
+ continue;
50
+ anchors.push({ term, idf });
51
+ }
52
+ anchors.sort((a, b) => b.idf - a.idf);
53
+ return anchors.slice(0, MAX_ANCHORS);
54
+ }
55
+ /**
56
+ * 从原始 query 抽取连续短语(不经 tokenize,避免分词假象):
57
+ * - 英文:相邻词对(连续两个 ≥2 长度的英文/数字 token)
58
+ * - 中文:连续 ≥2 字的中文片段(整段,不切分)
59
+ */
60
+ function extractPhrases(prompt) {
61
+ const phrases = [];
62
+ const enWords = prompt.toLowerCase().match(/[a-z0-9_]{2,}/g) ?? [];
63
+ for (let i = 0; i < enWords.length - 1; i += 1) {
64
+ phrases.push(`${enWords[i]} ${enWords[i + 1]}`);
65
+ }
66
+ for (const seg of prompt.match(/[\u4e00-\u9fff]{2,}/g) ?? []) {
67
+ phrases.push(seg);
68
+ }
69
+ return [...new Set(phrases)].filter((p) => p.replace(/\s/g, '').length >= 2);
70
+ }
71
+ /**
72
+ * 计算通用加性 boost。返回 chunkId -> 正分。
73
+ * 无锚点且无短语时返回空 map(排序退化为原始,零衰减)。
74
+ */
75
+ export function computeGenericAnchorBoosts(prompt, pool, index, tokenizeFn) {
76
+ const result = {};
77
+ const anchors = selectAnchors(tokenizeFn(prompt), index);
78
+ const phrases = extractPhrases(prompt);
79
+ // 门槛:既无锚点也无短语 → 直接返回空,排序完全等于原来。
80
+ if (anchors.length === 0 && phrases.length === 0)
81
+ return result;
82
+ const maxIdf = Math.max(1, ...anchors.map((a) => a.idf));
83
+ for (const chunk of pool) {
84
+ // ── 信号 A:命中锚点,按 IDF 归一化累加命中强度 ──
85
+ let anchorStrength = 0;
86
+ let anchorHits = 0;
87
+ for (const { term, idf } of anchors) {
88
+ // Object.prototype 污染防护:term 可能是 'constructor' 等原型键。
89
+ if (!Object.hasOwn(index.postings, term))
90
+ continue;
91
+ const posting = index.postings[term];
92
+ if ((Object.hasOwn(posting, chunk.id) ? posting[chunk.id] : 0) > 0) {
93
+ anchorStrength += idf / maxIdf;
94
+ anchorHits += 1;
95
+ }
96
+ }
97
+ // ── 信号 B:连续短语在 title / key_phrases / 正文原始串命中 ──
98
+ const haystack = [
99
+ chunk.title,
100
+ ...(chunk.key_phrases ?? []),
101
+ chunk.content,
102
+ ].filter(Boolean).join(' ').toLowerCase();
103
+ let phraseHits = 0;
104
+ for (const phrase of phrases) {
105
+ if (haystack.includes(phrase.toLowerCase())) {
106
+ phraseHits += 1;
107
+ }
108
+ }
109
+ // 该 chunk 无任何信号 → 不加分(保持原分)。
110
+ if (anchorHits === 0 && phraseHits === 0)
111
+ continue;
112
+ const boostA = anchors.length > 0
113
+ ? W_ANCHOR * (anchorStrength / anchors.length) // 归一化到 [0, W_ANCHOR]
114
+ : 0;
115
+ const boostB = phrases.length > 0
116
+ ? W_PHRASE * Math.min(1, phraseHits / phrases.length) // [0, W_PHRASE]
117
+ : 0;
118
+ const total = boostA + boostB;
119
+ if (total > 0)
120
+ result[chunk.id] = total;
121
+ }
122
+ return result;
123
+ }
@@ -1,9 +1,10 @@
1
1
  import { attachPoolContent } from '../content-loader.js';
2
2
  import { buildReferences } from '../doc-url-resolver.js';
3
- import { rankSubsetWithIndex } from '../bm25.js';
3
+ import { rankSubsetWithIndex, tokenize } from '../bm25.js';
4
4
  import { getProductsBM25Index } from '../bm25-cache.js';
5
5
  import { filterPool } from './filter-pool.js';
6
6
  import { runExactLookup } from './exact-lookup.js';
7
+ import { computeGenericAnchorBoosts } from './generic-rerank.js';
7
8
  import { applyRankMultipliers, computeApiNameCoverage, computeMissingApiTokens, isUrlMappingSource, postProcess, } from './search-core.js';
8
9
  function isBestPracticeSource(source) {
9
10
  return /\/best-practice\//i.test(source);
@@ -379,6 +380,12 @@ export function runSearchPass(params) {
379
380
  const productIndex = getProductsBM25Index(allChunks, passNorm.product);
380
381
  const poolWithContent = attachPoolContent(pool);
381
382
  const chunksById = new Map(poolWithContent.map((chunk) => [chunk.id, chunk]));
383
+ // 通用加性 rerank:数据驱动的高 IDF 锚点命中 + 连续短语命中。
384
+ // 纯加性、只加不减、无信号时返回空 map → 排序退化为原始,已有功能零衰减。
385
+ const genericBoosts = computeGenericAnchorBoosts(effectivePassNorm.prompt, poolWithContent, productIndex, tokenize);
386
+ for (const [id, amount] of Object.entries(genericBoosts)) {
387
+ boosts[id] = (boosts[id] ?? 0) + amount;
388
+ }
382
389
  const ranked = rankSubsetWithIndex(effectivePassNorm.prompt, pool.map((chunk) => chunk.id), productIndex, boosts);
383
390
  const rankedWithMultipliers = applyRankMultipliers(ranked, chunksById, {
384
391
  product: passNorm.product,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencentcloud/sdk-mcp",
3
- "version": "1.7.2",
3
+ "version": "1.7.4",
4
4
  "description": "Tencent Cloud MCP Server for SDK",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -7,3 +7,9 @@ word:
7
7
  meeting: ["会议", "roomkit", "conference"]
8
8
  room: ["会议", "roomkit", "conference"]
9
9
  roomkit: ["会议", "roomkit", "conference"]
10
+ # 症状词 → 规范词:桌面版微信小程序运行 IM SDK 报 WebSocket is not a constructor / tencent_cloud_im_csig_flutter_for_web_25F_cy undefined。
11
+ # 用户常贴"AppService 逻辑层没有原生 WebSocket 构造函数"这类现象描述,与目标文档
12
+ # "桌面版微信 + 包名版本升级"词汇体系字面不重合,靠此映射补齐规范词,拉高召回重合度。
13
+ "WebSocket is not a constructor": ["桌面版微信", "小程序", "SDK 版本", "升级"]
14
+ AppService: ["桌面版微信", "小程序"]
15
+ "Cannot read properties of undefined (reading 'tencent_cloud_im_csig_flutter_for_web_25F_cy')": ["桌面版微信", "小程序", "SDK 版本"]