@tencent-rtc/mcp 1.6.7 → 1.7.0
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.
- package/CHANGELOG.md +25 -0
- package/README.md +53 -39
- package/knowledge/build-index.js +31 -4
- package/knowledge/chunker.js +82 -14
- package/knowledge/chunking-policy.js +100 -0
- package/knowledge/content-loader.js +3 -1
- package/knowledge/frontmatter-meta.js +167 -0
- package/knowledge/path-meta.js +28 -6
- package/knowledge/search/exact-lookup.js +9 -227
- package/knowledge/search/filter-pool.js +17 -26
- package/knowledge/search/framework-fallback.js +22 -0
- package/knowledge/search/intent-router.js +13 -0
- package/knowledge/search/query-normalizer.js +129 -0
- package/knowledge/search/search-core.js +391 -0
- package/knowledge/search/search-knowledge.js +351 -323
- package/knowledge/search/search-message.js +87 -0
- package/knowledge/search/search-pass.js +428 -0
- package/knowledge/search/search-types.js +1 -0
- package/knowledge/search/url-row-scorer.js +258 -0
- package/package.json +1 -1
- package/resource/_schema/feature-aliases.yaml +1 -0
- package/resource/_schema/query-normalization.yaml +9 -0
- package/resource/index/manifest.json +1 -1
- package/resource/integration/callkit/preset/android/integration.md +3 -14
- package/resource/integration/callkit/preset/flutter/integration.md +1 -12
- package/resource/integration/callkit/preset/ios/integration.md +2 -12
- package/resource/integration/callkit/preset/react/integration.md +1 -14
- package/resource/integration/callkit/preset/vue/integration.md +1 -14
- package/resource/integration/chat/preset/android/integration.md +6 -13
- package/resource/integration/chat/preset/flutter/integration.md +1 -8
- package/resource/integration/chat/preset/ios/integration.md +4 -12
- package/resource/integration/chat/preset/react/integration.md +6 -16
- package/resource/integration/chat/preset/vue/integration.md +0 -9
- package/resource/integration/livekit/preset/live/android/live-audience-integration.md +2 -6
- package/resource/integration/livekit/preset/live/android/live-host-integration.md +1 -11
- package/resource/integration/livekit/preset/live/android/live-list-integration.md +2 -6
- package/resource/integration/livekit/preset/live/android/prepare-integration.md +2 -7
- package/resource/integration/livekit/preset/live/ios/live-audience-integration.md +2 -7
- package/resource/integration/livekit/preset/live/ios/live-host-integration.md +1 -13
- package/resource/integration/livekit/preset/live/ios/live-list-integration.md +2 -10
- package/resource/integration/livekit/preset/live/ios/prepare-integration.md +3 -8
- package/resource/integration/livekit/preset/live/vue/live-list-integration.md +0 -4
- package/resource/integration/livekit/preset/live/vue/live-player-desk-integration.md +1 -5
- package/resource/integration/livekit/preset/live/vue/live-player-h5-integration.md +2 -7
- package/resource/integration/livekit/preset/live/vue/live-pusher-integration.md +2 -8
- package/resource/integration/roomkit/preset/vue/integration.md +0 -11
- package/resource/knowledge/callkit/best-practice/callkit-miniprogram/uniapp-shrink.md +60 -0
- package/resource/knowledge/callkit/best-practice/common/call-autoplay-blocked.md +77 -0
- package/resource/knowledge/callkit/best-practice/common/call-message-in-chat.md +78 -0
- package/resource/knowledge/callkit/best-practice/common/call-vs-calls.md +110 -0
- package/resource/knowledge/callkit/best-practice/common/callengine-call-flow.md +123 -0
- package/resource/knowledge/callkit/best-practice/common/callengine-log-level.md +67 -0
- package/resource/knowledge/callkit/best-practice/common/callkit-get-engine-instance.md +81 -0
- package/resource/knowledge/callkit/best-practice/common/callkit-get-roomid.md +78 -0
- package/resource/knowledge/callkit/best-practice/common/callkit-limitations.md +37 -0
- package/resource/knowledge/callkit/best-practice/common/callkit-user-register-and-kicked.md +98 -0
- package/resource/knowledge/callkit/core-sdk/android/answer-call.md +0 -7
- package/resource/knowledge/callkit/core-sdk/android/make-call.md +0 -8
- package/resource/knowledge/callkit/core-sdk/android/offline-push.md +1 -9
- package/resource/knowledge/callkit/core-sdk/flutter/answer-call.md +2 -8
- package/resource/knowledge/callkit/core-sdk/flutter/make-call.md +2 -8
- package/resource/knowledge/callkit/core-sdk/flutter/offline-push.md +1 -16
- package/resource/knowledge/callkit/core-sdk/ios/answer-call.md +0 -8
- package/resource/knowledge/callkit/core-sdk/ios/make-call.md +0 -8
- package/resource/knowledge/callkit/core-sdk/ios/offline-push.md +0 -11
- package/resource/knowledge/callkit/core-sdk/uni-app/answer-call.md +178 -200
- package/resource/knowledge/callkit/core-sdk/uni-app/make-call.md +195 -217
- package/resource/knowledge/callkit/faq/android.md +4 -14
- package/resource/knowledge/callkit/faq/common.md +0 -2
- package/resource/knowledge/callkit/faq/error-code.md +2 -4
- package/resource/knowledge/callkit/faq/ios.md +1 -4
- package/resource/knowledge/callkit/preset/android/api.md +0 -6
- package/resource/knowledge/callkit/preset/ios/api.md +0 -4
- package/resource/knowledge/callkit/preset/react/api.md +3 -4
- package/resource/knowledge/callkit/preset/vue/api.md +3 -4
- package/resource/knowledge/chat/best-practice/common/avchatroom-message-loss-diagnosis.md +65 -0
- package/resource/knowledge/chat/best-practice/common/group-conversation-cleanup-on-system-notice.md +62 -0
- package/resource/knowledge/chat/best-practice/common/image-message-url-lifecycle.md +59 -0
- package/resource/knowledge/chat/best-practice/common/login-repeat-2025-diagnosis.md +61 -0
- package/resource/knowledge/chat/best-practice/common/message-read-report-and-receipt.md +64 -0
- package/resource/knowledge/chat/best-practice/common/message-receive-event.md +65 -0
- package/resource/knowledge/chat/best-practice/common/message-risk-error-and-render.md +65 -0
- package/resource/knowledge/chat/best-practice/common/message-unread-count.md +71 -0
- package/resource/knowledge/chat/best-practice/miniprogram/audio-message-send.md +113 -0
- package/resource/knowledge/chat/best-practice/miniprogram/login-timeout-2801-diagnosis.md +63 -0
- package/resource/knowledge/chat/best-practice/miniprogram/media-upload-fail-diagnosis.md +64 -0
- package/resource/knowledge/chat/best-practice/web/audio-message-send.md +118 -0
- package/resource/knowledge/chat/preset/android/features/chat-setting.md +0 -5
- package/resource/knowledge/chat/preset/android/features/contact-list.md +0 -7
- package/resource/knowledge/chat/preset/android/features/conversation-list.md +0 -6
- package/resource/knowledge/chat/preset/android/features/language.md +0 -8
- package/resource/knowledge/chat/preset/android/features/message-input.md +0 -6
- package/resource/knowledge/chat/preset/android/features/message-list.md +0 -8
- package/resource/knowledge/chat/preset/android/features/search.md +0 -7
- package/resource/knowledge/chat/preset/android/features/theme.md +0 -4
- package/resource/knowledge/chat/preset/android-view/integration.md +0 -6
- package/resource/knowledge/chat/preset/flutter/features/chat-setting.md +0 -4
- package/resource/knowledge/chat/preset/flutter/features/contact-list.md +0 -9
- package/resource/knowledge/chat/preset/flutter/features/conversation-list.md +0 -7
- package/resource/knowledge/chat/preset/flutter/features/language.md +0 -5
- package/resource/knowledge/chat/preset/flutter/features/message-input.md +0 -6
- package/resource/knowledge/chat/preset/flutter/features/message-list.md +0 -8
- package/resource/knowledge/chat/preset/flutter/features/search.md +0 -5
- package/resource/knowledge/chat/preset/flutter/features/theme.md +0 -4
- package/resource/knowledge/chat/preset/ios/features/chat-setting.md +0 -5
- package/resource/knowledge/chat/preset/ios/features/contact-list.md +0 -5
- package/resource/knowledge/chat/preset/ios/features/conversation-list.md +0 -7
- package/resource/knowledge/chat/preset/ios/features/language.md +1 -8
- package/resource/knowledge/chat/preset/ios/features/message-input.md +0 -6
- package/resource/knowledge/chat/preset/ios/features/message-list.md +0 -8
- package/resource/knowledge/chat/preset/ios/features/search.md +0 -5
- package/resource/knowledge/chat/preset/ios/features/theme.md +0 -4
- package/resource/knowledge/chat/preset/ios-uikit/integration.md +0 -6
- package/resource/knowledge/chat/preset/react/features/contact-list.md +0 -23
- package/resource/knowledge/chat/preset/react/features/conversation-actions.md +2 -11
- package/resource/knowledge/chat/preset/react/features/conversation-list.md +4 -26
- package/resource/knowledge/chat/preset/react/features/conversation-preview.md +0 -6
- package/resource/knowledge/chat/preset/react/features/search.md +0 -1
- package/resource/knowledge/chat/preset/react/features/theme.md +0 -1
- package/resource/knowledge/chat/preset/vue/features/contact-list.md +3 -9
- package/resource/knowledge/chat/preset/vue/features/conversation-actions.md +0 -3
- package/resource/knowledge/chat/preset/vue/features/conversation-list.md +2 -13
- package/resource/knowledge/chat/preset/vue/features/conversation-preview.md +2 -3
- package/resource/knowledge/chat/preset/vue/features/conversation-search.md +1 -0
- package/resource/knowledge/chat/preset/vue/features/search.md +4 -3
- package/resource/knowledge/chat/urls/sdk/web.md +1 -1
- package/resource/knowledge/livekit/best-practice/android/voice-room-anchor-start.md +120 -0
- package/resource/knowledge/livekit/best-practice/common/admin-take-seat.md +73 -0
- package/resource/knowledge/livekit/best-practice/common/audience-leave-live.md +81 -0
- package/resource/knowledge/livekit/best-practice/common/voice-room-no-audio-troubleshoot.md +100 -0
- package/resource/knowledge/livekit/best-practice/common/voice-room-seat-list-change.md +65 -0
- package/resource/knowledge/livekit/best-practice/flutter/voice-room-anchor-start.md +122 -0
- package/resource/knowledge/livekit/best-practice/ios/voice-room-anchor-start.md +126 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/AudioEffectStore.md +0 -7
- package/resource/knowledge/livekit/core-sdk/api-reference/android/BarrageStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/android/BattleStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/android/CameraView.md +0 -1
- package/resource/knowledge/livekit/core-sdk/api-reference/android/CoGuestStore.md +0 -5
- package/resource/knowledge/livekit/core-sdk/api-reference/android/CoHostStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/android/DeviceStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/android/GiftStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LikeStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LiveAudienceStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LiveCoreView.md +0 -1
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LiveSeatStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LoginStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/AudioEffectStore.md +0 -7
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/BarrageStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/BaseBeautyStore.md +0 -1
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/BattleStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/CoGuestStore.md +0 -5
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/CoHostStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/DeviceStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/GiftStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LikeStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LiveAudienceStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LiveCoreView.md +0 -1
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LiveSeatStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LoginStore.md +1 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/AudioEffectStore.md +0 -7
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/BarrageStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/BaseBeautyStore.md +0 -1
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/BattleStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/CoGuestStore.md +0 -5
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/CoHostStore.md +0 -3
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/DeviceStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/GiftStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LikeStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LiveAudienceStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LiveCoreView.md +0 -1
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LiveSeatStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LoginStore.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/android/audience-list.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/android/audio-effect.md +2 -3
- package/resource/knowledge/livekit/core-sdk/features/android/barrage.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/android/base-beauty.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/android/gift.md +2 -7
- package/resource/knowledge/livekit/core-sdk/features/android/live-list.md +3 -4
- package/resource/knowledge/livekit/core-sdk/features/flutter/audience-list.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/flutter/audio-effect.md +2 -4
- package/resource/knowledge/livekit/core-sdk/features/flutter/barrage.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/flutter/base-beauty.md +0 -2
- package/resource/knowledge/livekit/core-sdk/features/flutter/gift.md +2 -7
- package/resource/knowledge/livekit/core-sdk/features/flutter/live-list.md +3 -2
- package/resource/knowledge/livekit/core-sdk/features/ios/audience-list.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/ios/audio-effect.md +2 -4
- package/resource/knowledge/livekit/core-sdk/features/ios/barrage.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/ios/base-beauty.md +2 -2
- package/resource/knowledge/livekit/core-sdk/features/ios/gift.md +2 -7
- package/resource/knowledge/livekit/core-sdk/features/ios/live-list.md +3 -4
- package/resource/knowledge/livekit/core-sdk/live/android/co-guest-interaction.md +0 -3
- package/resource/knowledge/livekit/core-sdk/live/android/host-interaction.md +0 -4
- package/resource/knowledge/livekit/core-sdk/live/android/integration.md +1 -4
- package/resource/knowledge/livekit/core-sdk/live/flutter/co-guest-interaction.md +1 -3
- package/resource/knowledge/livekit/core-sdk/live/flutter/host-interaction.md +0 -1
- package/resource/knowledge/livekit/core-sdk/live/flutter/integration.md +1 -4
- package/resource/knowledge/livekit/core-sdk/live/ios/co-guest-interaction.md +0 -3
- package/resource/knowledge/livekit/core-sdk/live/ios/host-interaction.md +0 -3
- package/resource/knowledge/livekit/core-sdk/live/ios/integration.md +1 -4
- package/resource/knowledge/livekit/core-sdk/voice/android/co-guest-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/voice/android/host-interaction.md +0 -5
- package/resource/knowledge/livekit/core-sdk/voice/android/integration.md +1 -4
- package/resource/knowledge/livekit/core-sdk/voice/flutter/co-guest-interaction.md +1 -4
- package/resource/knowledge/livekit/core-sdk/voice/flutter/integration.md +3 -6
- package/resource/knowledge/livekit/core-sdk/voice/ios/co-guest-interaction.md +0 -2
- package/resource/knowledge/livekit/core-sdk/voice/ios/host-interaction.md +0 -4
- package/resource/knowledge/livekit/core-sdk/voice/ios/integration.md +1 -4
- package/resource/knowledge/livekit/faq/error-code.md +0 -1
- package/resource/knowledge/livekit/preset/live/vue/features/barrage.md +2 -3
- package/resource/knowledge/livekit/preset/live/vue/features/live-audience-list.md +3 -3
- package/resource/knowledge/livekit/preset/live/vue/features/live-view.md +3 -3
- package/resource/knowledge/push/api-reference/android.md +0 -1
- package/resource/knowledge/push/api-reference/harmonyos.md +0 -2
- package/resource/knowledge/push/api-reference/react-native.md +3 -5
- package/resource/knowledge/push/api-reference/uni-app.md +3 -5
- package/resource/knowledge/push/api-reference/unity.md +0 -1
- package/resource/knowledge/push/api-reference/unreal-engine.md +0 -1
- package/resource/knowledge/push/config/android.md +0 -24
- package/resource/knowledge/push/config/harmonyos.md +0 -1
- package/resource/knowledge/push/config/ios.md +0 -3
- package/resource/knowledge/push/config/react-native.md +0 -29
- package/resource/knowledge/push/config/unity.md +1 -24
- package/resource/knowledge/push/config/unreal-engine.md +1 -24
- package/resource/knowledge/push/integration/android.md +0 -14
- package/resource/knowledge/push/integration/flutter.md +0 -19
- package/resource/knowledge/push/integration/harmonyos.md +0 -2
- package/resource/knowledge/push/integration/ios.md +0 -3
- package/resource/knowledge/push/integration/react-native.md +0 -24
- package/resource/knowledge/push/integration/uni-app.md +1 -11
- package/resource/knowledge/push/integration/unity.md +0 -9
- package/resource/knowledge/push/integration/unreal-engine.md +1 -17
- package/resource/knowledge/roomkit/best-practice/common/room-ghost-member.md +70 -0
- package/resource/knowledge/roomkit/best-practice/common/room-limit-and-multi.md +83 -0
- package/resource/knowledge/roomkit/best-practice/common/room-screen-share-preview.md +83 -0
- package/resource/knowledge/roomkit/best-practice/common/room-status-after-all-leave.md +69 -0
- package/resource/knowledge/roomkit/best-practice/vue/room-uikit-vs-atomicx.md +111 -0
- package/resource/knowledge/roomkit/core-sdk/android/call-user-to-room.md +0 -4
- package/resource/knowledge/roomkit/core-sdk/android/room-participant-state.md +0 -4
- package/resource/knowledge/roomkit/core-sdk/android/room-state.md +0 -4
- package/resource/knowledge/roomkit/core-sdk/android/schedule-room.md +1 -5
- package/resource/knowledge/roomkit/core-sdk/ios/call-user-to-room.md +0 -4
- package/resource/knowledge/roomkit/core-sdk/ios/room-participant-state.md +0 -4
- package/resource/knowledge/roomkit/core-sdk/ios/room-state.md +0 -4
- package/resource/knowledge/roomkit/core-sdk/ios/schedule-room.md +1 -5
- package/resource/knowledge/roomkit/core-sdk/vue/call-user-to-room.md +1 -1
- package/resource/knowledge/roomkit/core-sdk/vue/device-state.md +0 -6
- package/resource/knowledge/roomkit/core-sdk/vue/free-beauty-panel.md +0 -9
- package/resource/knowledge/roomkit/core-sdk/vue/room-chat.md +0 -11
- package/resource/knowledge/roomkit/core-sdk/vue/room-participant-state.md +1 -5
- package/resource/knowledge/roomkit/core-sdk/vue/room-state.md +1 -8
- package/resource/knowledge/roomkit/core-sdk/vue/room-view.md +0 -3
- package/resource/knowledge/roomkit/core-sdk/vue/screen-share.md +0 -3
- package/resource/knowledge/roomkit/core-sdk/vue/virtual-background.md +0 -5
- package/resource/knowledge/roomkit/preset/android/integration.md +0 -4
- package/resource/knowledge/roomkit/preset/flutter/integration.md +1 -13
- package/resource/knowledge/roomkit/preset/ios/integration.md +0 -6
- package/resource/knowledge/roomkit/preset/react/integration.md +0 -16
- package/resource/knowledge/rtcengine/web/api.md +1 -8
- package/resource/knowledge/rtcengine/web/faq.md +3 -5
- package/resource/knowledge/rtcengine/web/how_to_integrated_web_sdk.md +0 -6
- package/resource/knowledge/rtcengine/web/plugin/20-advanced-customized-capture-rendering.md +1 -1
- package/resource/knowledge/rtcengine/web/plugin/21-advanced-auto-play-policy.md +1 -1
- package/resource/knowledge/rtcengine/web/plugin/26-advanced-publish-cdn-stream.md +1 -1
- package/resource/knowledge/rtcengine/web/plugin/27-advanced-small-stream.md +1 -1
- package/resource/knowledge/rtcengine/web/plugin/30-advanced-cross-room-link.md +2 -0
- package/resource/knowledge/rtcengine/web/plugin/31-advanced-plugins-overview.md +1 -3
- package/resource/knowledge/rtcengine/web/plugin/34-advanced-proxy.md +2 -4
- package/resource/knowledge/rtcengine/web/plugin/36-advanced-virtual-background.md +0 -4
- package/resource/knowledge/rtcengine/web/plugin/39-advanced-video-decoder.md +1 -1
- package/resource/knowledge/trtc/android/TRTCCloud.md +8 -56
- package/resource/knowledge/trtc/android/TRTCCloudDef.md +6 -7
- package/resource/knowledge/trtc/android/TRTCCloudListener.md +1 -18
- package/resource/knowledge/trtc/android/TXAudioEffectManager.md +0 -14
- package/resource/knowledge/trtc/android/TXDeviceManager.md +0 -1
- package/resource/knowledge/trtc/android/TXLiteAVCode.md +1 -1
- package/resource/knowledge/trtc/c++/ITRTCCloud.md +7 -59
- package/resource/knowledge/trtc/c++/ITXAudioEffectManager.md +0 -14
- package/resource/knowledge/trtc/c++/ITXDeviceManager.md +0 -4
- package/resource/knowledge/trtc/c++/TRTCCloudCallback.md +1 -19
- package/resource/knowledge/trtc/c++/TRTCTypeDef.md +6 -7
- package/resource/knowledge/trtc/c++/TXLiteAVCode.md +1 -1
- package/resource/knowledge/trtc/ios/TRTCCloud.md +9 -60
- package/resource/knowledge/trtc/ios/TRTCCloudDef.md +6 -7
- package/resource/knowledge/trtc/ios/TRTCCloudDelegate.md +1 -19
- package/resource/knowledge/trtc/ios/TXAudioEffectManager.md +0 -13
- package/resource/knowledge/trtc/ios/TXDeviceManager.md +0 -4
- package/resource/knowledge/trtc/ios/TXLiteAVCode.md +1 -1
- package/server.js +27 -22
- package/tools/common/finalize_answer.js +9 -1
- package/tools/common/search_trtc_knowledge.js +3 -1
- package/tools/definitions/finalize_answer_def.js +2 -2
- package/tools/definitions/integration-boundary.js +2 -1
- package/tools/definitions/search_trtc_knowledge_def.js +2 -1
- package/utils/report-cls-client.js +3 -3
- package/utils/report-es-client.js +1 -1
- package/cursor-setting.png +0 -0
- package/mcp-server-prompt.png +0 -0
- package/resource/knowledge/callkit/best-practice/web/callengine-invitation.md +0 -80
- package/resource/knowledge/callkit/best-practice/web/callengine-log-control.md +0 -24
- package/resource/knowledge/callkit/best-practice/web/callkit-call-vs-calls.md +0 -116
- package/resource/knowledge/callkit/preset/react/uikit-api-reference.md +0 -445
- package/resource/knowledge/callkit/preset/vue/uikit-api-reference.md +0 -465
- package/resource/knowledge/chat/best-practice/web/image-message-url-handling.md +0 -16
- package/resource/knowledge/roomkit/core-sdk/flutter/call-user-to-room.md +0 -230
- package/resource/knowledge/roomkit/core-sdk/flutter/room-participant-state.md +0 -797
- package/resource/knowledge/roomkit/core-sdk/flutter/room-state.md +0 -325
- package/resource/knowledge/roomkit/core-sdk/flutter/schedule-room.md +0 -325
package/knowledge/path-meta.js
CHANGED
|
@@ -110,7 +110,9 @@ export function inferPathMeta(relativeSource) {
|
|
|
110
110
|
// 两者都统一标记为 types=['faq'],便于通过 types=faq 命中“经验类问答”。
|
|
111
111
|
if (parts[1] === 'chat' && parts[2] === 'best-practice' && parts.length >= 5) {
|
|
112
112
|
const fwSlug = normalizeFrameworkDir(parts[3]);
|
|
113
|
-
|
|
113
|
+
// chat best-practice 的 common 目录表示平台通用(Web + 小程序),
|
|
114
|
+
// 不能按 framework=common 打标,否则会被 framework 硬过滤误排除。
|
|
115
|
+
framework = fwSlug === 'common' ? ['web', 'miniprogram'] : [fwSlug];
|
|
114
116
|
types.push('faq');
|
|
115
117
|
}
|
|
116
118
|
if (parts[1] === 'chat' && parts[2] === 'faq' && parts.length >= 4) {
|
|
@@ -137,13 +139,13 @@ export function inferPathMeta(relativeSource) {
|
|
|
137
139
|
}
|
|
138
140
|
// callkit 最佳实践目录:knowledge/callkit/best-practice/{platform}/{topic}.md
|
|
139
141
|
// 统一按 FAQ/经验类知识处理,支持 types=faq + frameworks={platform} 的精确检索。
|
|
142
|
+
// 与 chat best-practice 对齐:common 目录表示多平台通用,按最全集覆盖。
|
|
140
143
|
if (parts[1] === 'callkit' && parts[2] === 'best-practice' && parts.length >= 5) {
|
|
141
|
-
|
|
144
|
+
const fwSlug = normalizeFrameworkDir(parts[3]);
|
|
145
|
+
framework = fwSlug === 'common'
|
|
146
|
+
? ['react', 'vue', 'miniprogram', 'web', 'android', 'ios', 'flutter', 'uni-app']
|
|
147
|
+
: [fwSlug];
|
|
142
148
|
types.push('faq');
|
|
143
|
-
// calls 相关最佳实践既是 FAQ 也是 API 语义,避免 types=api 时被误过滤。
|
|
144
|
-
if (/(callengine-invitation|callkit-call-vs-calls)\.md$/i.test(fileName)) {
|
|
145
|
-
types.push('api');
|
|
146
|
-
}
|
|
147
149
|
}
|
|
148
150
|
if (parts.includes('faq'))
|
|
149
151
|
types.push('faq', 'error_code');
|
|
@@ -226,6 +228,15 @@ export function inferPathMeta(relativeSource) {
|
|
|
226
228
|
types.push('component');
|
|
227
229
|
if (fileName === 'faq.md')
|
|
228
230
|
types.push('faq');
|
|
231
|
+
// livekit 最佳实践目录:knowledge/livekit/best-practice/{platform}/{topic}.md
|
|
232
|
+
// 与 chat/callkit 对齐:common 目录表示多平台通用,按最全集覆盖。
|
|
233
|
+
if (parts[1] === 'livekit' && parts[2] === 'best-practice' && parts.length >= 5) {
|
|
234
|
+
const fwSlug = normalizeFrameworkDir(parts[3]);
|
|
235
|
+
framework = fwSlug === 'common'
|
|
236
|
+
? ['react', 'vue', 'web', 'android', 'ios', 'flutter']
|
|
237
|
+
: [fwSlug];
|
|
238
|
+
types.push('faq');
|
|
239
|
+
}
|
|
229
240
|
// 与 roomkit 对齐:core-sdk 下 capability-matrix.md / unsupported-features.md
|
|
230
241
|
// 视为能力边界文档(doc_kind + capability_status),方便检索层按 doc_kind 过滤
|
|
231
242
|
const docMeta = inferDocMeta(fileName);
|
|
@@ -255,6 +266,15 @@ export function inferPathMeta(relativeSource) {
|
|
|
255
266
|
types.push('feature');
|
|
256
267
|
if (parts.includes('faq'))
|
|
257
268
|
types.push('faq', 'error_code');
|
|
269
|
+
// roomkit 最佳实践目录:knowledge/roomkit/best-practice/{platform}/{topic}.md
|
|
270
|
+
// 与 chat/callkit 对齐:common 目录表示多平台通用,按最全集覆盖。
|
|
271
|
+
if (parts[1] === 'roomkit' && parts[2] === 'best-practice' && parts.length >= 5) {
|
|
272
|
+
const fwSlug = normalizeFrameworkDir(parts[3]);
|
|
273
|
+
framework = fwSlug === 'common'
|
|
274
|
+
? ['react', 'vue', 'web', 'android', 'ios', 'flutter']
|
|
275
|
+
: [fwSlug];
|
|
276
|
+
types.push('faq');
|
|
277
|
+
}
|
|
258
278
|
const docMeta = inferDocMeta(fileName);
|
|
259
279
|
doc_kind = docMeta.doc_kind;
|
|
260
280
|
capability_status = docMeta.capability_status ?? capability_status;
|
|
@@ -333,5 +353,7 @@ export function inferPathMeta(relativeSource) {
|
|
|
333
353
|
doc_kind,
|
|
334
354
|
capability_status,
|
|
335
355
|
retrievable_scope,
|
|
356
|
+
meta_source: 'path',
|
|
357
|
+
meta_override_fields: [],
|
|
336
358
|
};
|
|
337
359
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
+
import { normalizeUrlRowQuery, scoreUrlRow } from './url-row-scorer.js';
|
|
4
5
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
5
6
|
const SCHEMA_ROOT = path.resolve(__dirname, '../../resource/_schema');
|
|
6
7
|
export const DOC_PATH_MAP = {
|
|
@@ -69,184 +70,6 @@ function loadJson(fileName, fallback) {
|
|
|
69
70
|
return fallback;
|
|
70
71
|
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
71
72
|
}
|
|
72
|
-
const E7_EN_STOPWORDS = new Set([
|
|
73
|
-
'the', 'and', 'for', 'with', 'from', 'into', 'about', 'using', 'via',
|
|
74
|
-
'how', 'what', 'where', 'when', 'which', 'please', 'docs', 'documentation',
|
|
75
|
-
'tencent', 'im', 'rest', 'server', 'webhook', 'webhooks',
|
|
76
|
-
]);
|
|
77
|
-
/** Generic terms — excluded from API-token hits to avoid false positives */
|
|
78
|
-
const E7_GENERIC_TERMS = new Set([
|
|
79
|
-
'message', 'messages', 'group', 'groups', 'user', 'users', 'account', 'accounts',
|
|
80
|
-
'send', 'get', 'set', 'delete', 'create', 'update', 'query', 'before', 'after',
|
|
81
|
-
'webhook', 'friend', 'single', 'multiple', 'history', 'chat', 'sdk', 'api',
|
|
82
|
-
'profile', 'conversation', 'import', 'recall', 'modify', 'pull', 'mark', 'data',
|
|
83
|
-
'list', 'online', 'status', 'custom', 'attributes', 'counter', 'member', 'members',
|
|
84
|
-
'management', 'overview', 'integration', 'initialization', 'billing', 'topic',
|
|
85
|
-
'topics', 'community', 'robot', 'chatbot', 'streaming', 'broadcast', 'official',
|
|
86
|
-
'extension', 'receipt', 'receipts', 'global', 'mute', 'ban', 'unban', 'forbid',
|
|
87
|
-
'ordinary', 'specified', 'historical', 'unread', 'read', 'configure', 'configuration', 'invalidate',
|
|
88
|
-
'invalidating', 'disband', 'change', 'search', 'cloud', 'local', 'robot', 'bots',
|
|
89
|
-
]);
|
|
90
|
-
const E7_QUERY_NOISE = /\b(rest\s*ful?\s*api|rest\s*api|server\s*api|webhook|webhooks|how\s+to|how\s+do\s+i|what\s+is|where\s+is|please|documentation|docs?)\b/gi;
|
|
91
|
-
const E7_QUERY_NOISE_CN = /怎么|如何|什么|用哪个|查询|服务端/g;
|
|
92
|
-
const E7_PHRASES = [
|
|
93
|
-
'before send one-to-one message',
|
|
94
|
-
'after send one-to-one message',
|
|
95
|
-
'one-to-one message',
|
|
96
|
-
'group message',
|
|
97
|
-
'recall group message',
|
|
98
|
-
'recall one-to-one message',
|
|
99
|
-
'send one-to-one message',
|
|
100
|
-
'send single chat message',
|
|
101
|
-
'getmessagelist',
|
|
102
|
-
'message history',
|
|
103
|
-
'add friend',
|
|
104
|
-
'import single account',
|
|
105
|
-
'import a single account',
|
|
106
|
-
'multi-device login',
|
|
107
|
-
'multi device login',
|
|
108
|
-
'login policy',
|
|
109
|
-
'login strategy',
|
|
110
|
-
'message storage duration',
|
|
111
|
-
'roaming message storage',
|
|
112
|
-
];
|
|
113
|
-
function extractRestEndpoints(text) {
|
|
114
|
-
return [...text.matchAll(/v4\/[\w/]+/gi)].map((m) => m[0].toLowerCase());
|
|
115
|
-
}
|
|
116
|
-
function extractE7ApiTokens(text) {
|
|
117
|
-
const tokens = new Set();
|
|
118
|
-
for (const match of text.matchAll(/\b([a-z][a-z0-9_]{2,})\b/gi)) {
|
|
119
|
-
const token = match[1].toLowerCase();
|
|
120
|
-
if (!E7_GENERIC_TERMS.has(token) && !E7_EN_STOPWORDS.has(token))
|
|
121
|
-
tokens.add(token);
|
|
122
|
-
}
|
|
123
|
-
for (const match of text.matchAll(/\b([A-Z][A-Za-z0-9]*(?:\.[A-Za-z]\w*)?)\b/g)) {
|
|
124
|
-
const token = match[1].toLowerCase();
|
|
125
|
-
if (!E7_GENERIC_TERMS.has(token))
|
|
126
|
-
tokens.add(token);
|
|
127
|
-
}
|
|
128
|
-
for (const match of text.matchAll(/([a-z]+[A-Z][A-Za-z0-9]*)/g)) {
|
|
129
|
-
tokens.add(match[1].toLowerCase());
|
|
130
|
-
}
|
|
131
|
-
return [...tokens];
|
|
132
|
-
}
|
|
133
|
-
function normalizeE7Text(text) {
|
|
134
|
-
return text
|
|
135
|
-
.toLowerCase()
|
|
136
|
-
.replace(E7_QUERY_NOISE, ' ')
|
|
137
|
-
.replace(E7_QUERY_NOISE_CN, '')
|
|
138
|
-
.replace(/[^\w\u4e00-\u9fff/]+/g, ' ')
|
|
139
|
-
.replace(/\s+/g, ' ')
|
|
140
|
-
.trim();
|
|
141
|
-
}
|
|
142
|
-
function phraseBonus(query, title) {
|
|
143
|
-
const q = query.toLowerCase().replace(/\s+/g, ' ');
|
|
144
|
-
const t = title.toLowerCase();
|
|
145
|
-
let bonus = 0;
|
|
146
|
-
for (const phrase of E7_PHRASES) {
|
|
147
|
-
if (q.includes(phrase) && t.includes(phrase))
|
|
148
|
-
bonus += 180;
|
|
149
|
-
}
|
|
150
|
-
if (/send single chat message/.test(q) && /send one-to-one message/.test(t))
|
|
151
|
-
bonus += 200;
|
|
152
|
-
if (/recall group message/.test(q) && /recall group message/.test(t))
|
|
153
|
-
bonus += 200;
|
|
154
|
-
if (/before send one-to-one message/.test(q) && /before send one-to-one message/.test(t))
|
|
155
|
-
bonus += 220;
|
|
156
|
-
if (/\bbefore\b/.test(q) && t.startsWith('before '))
|
|
157
|
-
bonus += 120;
|
|
158
|
-
if (/\bafter\b/.test(q) && t.startsWith('after '))
|
|
159
|
-
bonus += 120;
|
|
160
|
-
if (/多端登录/.test(query) && /多端登录|multi[\s-]?device/i.test(title))
|
|
161
|
-
bonus += 220;
|
|
162
|
-
if (/登录策略|login\s*(policy|strategy)/i.test(query) && /登录策略|login\s*(policy|strategy)/i.test(title))
|
|
163
|
-
bonus += 200;
|
|
164
|
-
return bonus;
|
|
165
|
-
}
|
|
166
|
-
function scoreE7UrlRow(query, title) {
|
|
167
|
-
const queryEndpoints = extractRestEndpoints(query);
|
|
168
|
-
const titleEndpoints = extractRestEndpoints(title);
|
|
169
|
-
for (const qe of queryEndpoints) {
|
|
170
|
-
if (titleEndpoints.some((te) => te === qe || te.endsWith(qe) || qe.endsWith(te))) {
|
|
171
|
-
return 1000;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
let score = phraseBonus(query, title);
|
|
175
|
-
const titleLower = title.toLowerCase();
|
|
176
|
-
const queryApis = extractE7ApiTokens(query);
|
|
177
|
-
let apiHits = 0;
|
|
178
|
-
let longApiHit = false;
|
|
179
|
-
for (const api of queryApis) {
|
|
180
|
-
if (!titleLower.includes(api))
|
|
181
|
-
continue;
|
|
182
|
-
apiHits += 1;
|
|
183
|
-
if (api.length >= 8)
|
|
184
|
-
longApiHit = true;
|
|
185
|
-
}
|
|
186
|
-
if (longApiHit)
|
|
187
|
-
score = Math.max(score, 940);
|
|
188
|
-
else if (apiHits >= 2)
|
|
189
|
-
score = Math.max(score, 900);
|
|
190
|
-
else if (apiHits === 1)
|
|
191
|
-
score = Math.max(score, 860);
|
|
192
|
-
const qNorm = normalizeE7Text(query);
|
|
193
|
-
const tNorm = normalizeE7Text(title);
|
|
194
|
-
const qTokens = qNorm.split(' ').filter((t) => t.length >= 3 && !E7_GENERIC_TERMS.has(t));
|
|
195
|
-
const tTokens = tNorm.split(' ').filter((t) => t.length >= 3 && !E7_GENERIC_TERMS.has(t));
|
|
196
|
-
let overlap = 0;
|
|
197
|
-
for (const qt of qTokens) {
|
|
198
|
-
if (tTokens.some((tt) => tt.includes(qt) || qt.includes(tt)))
|
|
199
|
-
overlap += 1;
|
|
200
|
-
}
|
|
201
|
-
if (overlap >= 3)
|
|
202
|
-
score = Math.max(score, 720 + overlap * 15);
|
|
203
|
-
else if (overlap >= 2)
|
|
204
|
-
score = Math.max(score, 650);
|
|
205
|
-
else if (overlap >= 1)
|
|
206
|
-
score = Math.max(score, 520);
|
|
207
|
-
const qCompact = qNorm.replace(/\s+/g, '');
|
|
208
|
-
const tCompact = tNorm.replace(/\s+/g, '');
|
|
209
|
-
if (qCompact.length >= 5 && tCompact.includes(qCompact)) {
|
|
210
|
-
score = Math.max(score, 560 - Math.min(tCompact.length - qCompact.length, 80));
|
|
211
|
-
}
|
|
212
|
-
else if (tCompact.length >= 5 && qCompact.includes(tCompact)) {
|
|
213
|
-
score = Math.max(score, 500 + Math.min(tCompact.length, 30));
|
|
214
|
-
}
|
|
215
|
-
const qCjk = query.replace(/[^\u4e00-\u9fff]/g, '');
|
|
216
|
-
const tCjk = title.replace(/[^\u4e00-\u9fff]/g, '');
|
|
217
|
-
if (qCjk.length >= 2 && tCjk.includes(qCjk)) {
|
|
218
|
-
let cjkScore = 500;
|
|
219
|
-
if (/批量|群组|群流|广播|导入|公众号|已读|回执/.test(tCjk) && !/批量|群组|群|已读|回执/.test(qCjk)) {
|
|
220
|
-
cjkScore -= 250;
|
|
221
|
-
}
|
|
222
|
-
if (/^单发/.test(tCjk) && /发送|单聊/.test(qCjk))
|
|
223
|
-
cjkScore += 120;
|
|
224
|
-
score = Math.max(score, cjkScore);
|
|
225
|
-
}
|
|
226
|
-
if (score <= 0)
|
|
227
|
-
return 0;
|
|
228
|
-
const queryL = query.toLowerCase();
|
|
229
|
-
const titleL = title.toLowerCase();
|
|
230
|
-
if (/group/.test(queryL) && /one-to-one|c2c/.test(titleL) && !/group/.test(titleL))
|
|
231
|
-
score -= 400;
|
|
232
|
-
if (/one-to-one|c2c|single chat/.test(queryL) && /import.*account|add friend/.test(titleL))
|
|
233
|
-
score -= 400;
|
|
234
|
-
if (/send.*message|one-to-one message/.test(queryL) && /add friend|import.*account/.test(titleL))
|
|
235
|
-
score -= 400;
|
|
236
|
-
if (/getmessagelist|message history/.test(qCompact) && /integration|initialization/.test(titleL) && !/getmessagelist|history/.test(tCompact))
|
|
237
|
-
score -= 400;
|
|
238
|
-
if (/extension/.test(titleL) && !/extension/.test(queryL))
|
|
239
|
-
score -= 350;
|
|
240
|
-
if (/\bbefore\b/.test(queryL) && !/^before\b/.test(titleL.trim()))
|
|
241
|
-
score -= 250;
|
|
242
|
-
if (/\bafter\b/.test(queryL) && !/^after\b/.test(titleL.trim()))
|
|
243
|
-
score -= 250;
|
|
244
|
-
if (/batch|multiple/.test(titleL) && !/batch|multiple/.test(queryL))
|
|
245
|
-
score -= 200;
|
|
246
|
-
if (/group/.test(titleL) && !/group|channel/.test(queryL) && /one-to-one|c2c|single chat/.test(queryL))
|
|
247
|
-
score -= 200;
|
|
248
|
-
return Math.max(score, 0);
|
|
249
|
-
}
|
|
250
73
|
function loadFeatureAliases() {
|
|
251
74
|
const filePath = path.join(SCHEMA_ROOT, 'feature-aliases.yaml');
|
|
252
75
|
if (!fs.existsSync(filePath))
|
|
@@ -314,8 +137,6 @@ const ROOM_FEATURE_SPECS = [
|
|
|
314
137
|
function detectRoomFeatureHits(prompt) {
|
|
315
138
|
return ROOM_FEATURE_SPECS.filter((spec) => spec.promptPattern.test(prompt));
|
|
316
139
|
}
|
|
317
|
-
const LIVE_LIFECYCLE_PROMPT = /create\s*live|end\s*live|join\s*live|leave\s*live|start\s*live|stop\s*live|watch\s*live|host_streaming|audience_streaming|开播|创建直播|结束直播|停播|观看直播|退出直播|进房|离房|createLive|endLive|joinLive|leaveLive/i;
|
|
318
|
-
const LIVE_LIFECYCLE_APIS = ['createLive', 'endLive', 'joinLive', 'leaveLive'];
|
|
319
140
|
export function runExactLookup(prompt, pool, norm) {
|
|
320
141
|
const boosts = {};
|
|
321
142
|
const exactHits = [];
|
|
@@ -486,52 +307,35 @@ export function runExactLookup(prompt, pool, norm) {
|
|
|
486
307
|
}
|
|
487
308
|
}
|
|
488
309
|
// E7: URL map row match (chunk.title = Query column); boost multiple strong hits with pinned relaxation
|
|
489
|
-
if (
|
|
310
|
+
if (normalizeUrlRowQuery(prompt).replace(/\s+/g, '').length >= 2) {
|
|
490
311
|
const candidates = [];
|
|
491
312
|
for (const chunk of pool) {
|
|
492
313
|
if (!chunk.source.includes('knowledge/chat/urls/'))
|
|
493
314
|
continue;
|
|
494
315
|
if (!chunk.title.trim())
|
|
495
316
|
continue;
|
|
496
|
-
const
|
|
497
|
-
if (score > 0) {
|
|
498
|
-
candidates.push({ chunk, score });
|
|
317
|
+
const scoreResult = scoreUrlRow(prompt, chunk.title);
|
|
318
|
+
if (scoreResult.score > 0) {
|
|
319
|
+
candidates.push({ chunk, score: scoreResult.score });
|
|
499
320
|
}
|
|
500
321
|
}
|
|
501
322
|
candidates.sort((a, b) => b.score - a.score);
|
|
502
323
|
const strongCandidates = candidates
|
|
503
|
-
.filter(({ score }) => score >=
|
|
324
|
+
.filter(({ score }) => score >= 500)
|
|
504
325
|
.slice(0, 12);
|
|
505
326
|
strongCandidates.forEach(({ chunk, score }, idx) => {
|
|
327
|
+
// 递减 boost:前两条更高,其余保持可召回但不过度压制 BM25
|
|
328
|
+
// token 匹配(600 分)至少给 150,确保子句拆分的行不被 BM25 原始分压掉
|
|
506
329
|
const amount = idx === 0
|
|
507
330
|
? 200 + Math.min(score, 100)
|
|
508
331
|
: idx === 1
|
|
509
332
|
? 170 + Math.min(score, 90)
|
|
510
|
-
: Math.max(score >=
|
|
333
|
+
: Math.max(score >= 600 ? 150 : 90, 140 - idx * 8);
|
|
511
334
|
addBoost(chunk, amount, `E7:url-row:${chunk.title}`);
|
|
512
335
|
urlRowHitChunkIds.add(chunk.id);
|
|
513
336
|
});
|
|
514
337
|
}
|
|
515
338
|
}
|
|
516
|
-
// E8: 集成查阅意图 boost——prompt 含集成/接入/快速开始/接入文档等意图词时,
|
|
517
|
-
// 把 {integration|knowledge}/{product}/preset/{fw}/integration.md 系列文件顶到前列。
|
|
518
|
-
// 解决问题:集成文档内容长、词密度低,BM25 原始分常被短小的 features/ 文档压过。
|
|
519
|
-
// 注:android-view / ios-uikit 已迁到 knowledge corpus,但同样是集成指引,需要一并 boost。
|
|
520
|
-
const isIntegrationIntent = /集成|接入|快速开始|快速接入|集成文档|接入文档|集成指南|接入指南|接入流程|集成步骤|如何接入|如何集成|怎么接入|怎么集成/i.test(prompt)
|
|
521
|
-
|| /\b(integrat(e|ion|ing)|getting\s+started|quick\s+start|setup\s+guide|how\s+to\s+(integrate|set\s+up)|install(?:ation)?\s+guide)\b/i.test(prompt);
|
|
522
|
-
if (isIntegrationIntent && norm.product?.length && norm.frameworks?.length) {
|
|
523
|
-
for (const chunk of pool) {
|
|
524
|
-
if (!norm.product.includes(chunk.product))
|
|
525
|
-
continue;
|
|
526
|
-
const fwMatch = norm.frameworks.some((fw) => chunk.framework.includes(fw));
|
|
527
|
-
if (!fwMatch)
|
|
528
|
-
continue;
|
|
529
|
-
// 命中 preset/{fw}/integration.md 系列(含 integration/ 和 knowledge/ 两种 corpus)
|
|
530
|
-
if (!chunk.source.includes('/preset/') || (!chunk.source.endsWith('integration.md') && !chunk.source.endsWith('-integration.md')))
|
|
531
|
-
continue;
|
|
532
|
-
addBoost(chunk, 120, `E8:integration-doc:${chunk.source}`);
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
339
|
// E9: chat faq — types=faq 时优先 knowledge/ 语料,避免 integration 文档内 FAQ 章节抢首位
|
|
536
340
|
if (norm.searchIntent?.includes('faq') && norm.product?.includes('chat')) {
|
|
537
341
|
const authPrompt = /auth|login|signature|usersig|鉴权|登录/i.test(prompt);
|
|
@@ -545,28 +349,6 @@ export function runExactLookup(prompt, pool, norm) {
|
|
|
545
349
|
}
|
|
546
350
|
}
|
|
547
351
|
}
|
|
548
|
-
// E11: LiveKit lifecycle strong recall
|
|
549
|
-
if (norm.product?.includes('live') && LIVE_LIFECYCLE_PROMPT.test(prompt)) {
|
|
550
|
-
const queryApiHits = LIVE_LIFECYCLE_APIS.filter((api) => new RegExp(api, 'i').test(prompt));
|
|
551
|
-
for (const chunk of pool) {
|
|
552
|
-
const isLiveCoreIntegration = chunk.source.startsWith('knowledge/livekit/core-sdk/live/')
|
|
553
|
-
&& chunk.source.endsWith('/integration.md');
|
|
554
|
-
const isVoiceCoreIntegration = chunk.source.startsWith('knowledge/livekit/core-sdk/voice/')
|
|
555
|
-
&& chunk.source.endsWith('/integration.md');
|
|
556
|
-
if (!isLiveCoreIntegration && !isVoiceCoreIntegration)
|
|
557
|
-
continue;
|
|
558
|
-
if (norm.scenario === 'live' && !isLiveCoreIntegration)
|
|
559
|
-
continue;
|
|
560
|
-
if (norm.scenario === 'voice' && !isVoiceCoreIntegration)
|
|
561
|
-
continue;
|
|
562
|
-
addBoost(chunk, 140, 'E11:live-lifecycle-core-integration');
|
|
563
|
-
for (const api of queryApiHits) {
|
|
564
|
-
if (chunk.api_names?.some((name) => name.toLowerCase() === api.toLowerCase())) {
|
|
565
|
-
addBoost(chunk, 160, `E11:live-lifecycle-api:${api}`);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
352
|
// E10: RoomKit Core/Preset disambiguation + unsupported feature routing
|
|
571
353
|
if (norm.product?.includes('room') && norm.frameworks?.length) {
|
|
572
354
|
const platform = norm.frameworks.find((fw) => ['android', 'ios', 'flutter', 'vue'].includes(fw));
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { downgradeToProductType } from './product-scope-intent.js';
|
|
2
|
+
import { normalizeQueryPrompt } from './query-normalizer.js';
|
|
3
|
+
import { hasExplicitFrameworkMatch, hasFrameworkFallbackMatch } from './framework-fallback.js';
|
|
2
4
|
/**
|
|
3
5
|
* MCP framework enum → index 中对应的 framework 值列表。
|
|
4
6
|
* path-meta.ts 已通过 normalizeFrameworkDir 把目录名归一到标准 framework,
|
|
@@ -41,14 +43,6 @@ function resolveTypes(products, types, prompt, frameworks) {
|
|
|
41
43
|
return undefined;
|
|
42
44
|
const downgraded = downgradeToProductType(products, types, prompt, frameworks);
|
|
43
45
|
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');
|
|
51
|
-
}
|
|
52
46
|
return expanded;
|
|
53
47
|
}
|
|
54
48
|
/** 单平台产品的隐式 framework 推断:避免对显然唯一的平台再发起询问 */
|
|
@@ -70,15 +64,16 @@ function inferImplicitFramework(products, frameworks, prompt) {
|
|
|
70
64
|
return undefined;
|
|
71
65
|
}
|
|
72
66
|
export function normalizeParams(params) {
|
|
67
|
+
const normalizedPrompt = normalizeQueryPrompt(params.prompt);
|
|
73
68
|
const limit = Math.min(Math.max(params.limit ?? 8, 1), 16);
|
|
74
|
-
const effectiveFramework = inferImplicitFramework(params.product, params.frameworks,
|
|
69
|
+
const effectiveFramework = inferImplicitFramework(params.product, params.frameworks, normalizedPrompt);
|
|
75
70
|
const requestedFrameworks = params.frameworks?.length
|
|
76
71
|
? params.frameworks
|
|
77
72
|
: effectiveFramework ? [effectiveFramework] : undefined;
|
|
78
73
|
const frameworks = expandFrameworks(requestedFrameworks, params.product);
|
|
79
|
-
const types = resolveTypes(params.product, params.types,
|
|
74
|
+
const types = resolveTypes(params.product, params.types, normalizedPrompt, requestedFrameworks);
|
|
80
75
|
return {
|
|
81
|
-
prompt:
|
|
76
|
+
prompt: normalizedPrompt,
|
|
82
77
|
product: params.product,
|
|
83
78
|
framework: effectiveFramework,
|
|
84
79
|
frameworks,
|
|
@@ -131,27 +126,23 @@ export function filterPool(chunks, norm) {
|
|
|
131
126
|
// 收紧:framework=['*'] 仅在该 chunk 明确是跨平台 type(product/server_api/webhook)时放行;
|
|
132
127
|
// 否则要求 chunk.framework 与请求 framework 有交集。
|
|
133
128
|
const wildcardAllowed = isWildcardChunk && chunkIsCrossPlatform(chunk.types);
|
|
134
|
-
const explicitMatch =
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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)
|
|
129
|
+
const explicitMatch = hasExplicitFrameworkMatch(chunk.framework, norm.frameworks);
|
|
130
|
+
const fallbackMatch = hasFrameworkFallbackMatch(chunk, {
|
|
131
|
+
product: norm.product,
|
|
132
|
+
framework: norm.framework,
|
|
133
|
+
frameworks: norm.frameworks,
|
|
134
|
+
});
|
|
135
|
+
if (!explicitMatch && !wildcardAllowed && !fallbackMatch)
|
|
148
136
|
return false;
|
|
149
137
|
}
|
|
150
138
|
if (norm.scenario && chunk.scenario && chunk.scenario !== norm.scenario) {
|
|
151
139
|
return false;
|
|
152
140
|
}
|
|
141
|
+
// best-practice 文档对 types 过滤免疫:内容不依赖 types 分类,应始终进 pool 靠 BM25 自然排名。
|
|
142
|
+
// 典型场景:Agent 传 types=['api'] 时,types=['faq'] 的 best-practice 不应被过滤掉。
|
|
153
143
|
if (norm.types?.length && !norm.types.some((t) => chunk.types.includes(t))) {
|
|
154
|
-
|
|
144
|
+
if (!chunk.source.includes('/best-practice/'))
|
|
145
|
+
return false;
|
|
155
146
|
}
|
|
156
147
|
return true;
|
|
157
148
|
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function hasExplicitFrameworkMatch(chunkFrameworks, requestFrameworks) {
|
|
2
|
+
if (!requestFrameworks?.length)
|
|
3
|
+
return false;
|
|
4
|
+
return requestFrameworks.some((fw) => chunkFrameworks.includes(fw));
|
|
5
|
+
}
|
|
6
|
+
export function hasFrameworkFallbackMatch(chunk, opts) {
|
|
7
|
+
const callCoreWebFallback = Boolean(opts.product?.includes('call')
|
|
8
|
+
&& (opts.framework === 'react' || opts.framework === 'vue')
|
|
9
|
+
&& chunk.variant === 'core-sdk'
|
|
10
|
+
&& chunk.framework.includes('web'));
|
|
11
|
+
const liveWebVueFallback = Boolean(opts.product?.includes('live')
|
|
12
|
+
&& opts.framework === 'web'
|
|
13
|
+
&& chunk.variant === 'core-sdk'
|
|
14
|
+
&& chunk.framework.includes('vue')
|
|
15
|
+
&& chunk.source.includes('/api-reference/'));
|
|
16
|
+
const roomWebVueFallback = Boolean(opts.product?.includes('room')
|
|
17
|
+
&& opts.framework === 'web'
|
|
18
|
+
&& chunk.variant === 'core-sdk'
|
|
19
|
+
&& chunk.framework.includes('vue')
|
|
20
|
+
&& chunk.source.includes('knowledge/roomkit/core-sdk/vue/'));
|
|
21
|
+
return callCoreWebFallback || liveWebVueFallback || roomWebVueFallback;
|
|
22
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** 枚举/目录浏览意图 */
|
|
2
|
+
const DISCOVERY_INTENT_RE = /有哪些|支持哪些|列一下|清单|目录|可用|全部|全量|对比|怎么选|选哪个|which\s+one|compare|comparison|what\s+(is|are)\s+available|what\s+.*\b(components?|features?|apis?)\b|available\s+(components?|features?|apis?)|supported\s+(components?|features?|apis?)|list\s+(all|available)|catalog/i;
|
|
3
|
+
/** 显式完整文档意图(用户明确说"完整/从零/step by step") */
|
|
4
|
+
const NARRATIVE_INTENT_RE = /从头到尾|一步一步|完整指南|完整教程|完整流程|完整接入|完整集成|完整的\s*(接入|集成|教程|指南|流程)|从零|全流程|接入指南|集成指南|step\s*by(?:\s*step)?|end[-\s]?to[-\s]?end|full\s+(guide|tutorial|flow|integration)|complete\s+(guide|tutorial|integration)|quick\s*start|getting\s*started/i;
|
|
5
|
+
/** 强 point 信号:提到具体 API/错误码/参数 → 即使同时命中 narrative 关键词也优先走 point */
|
|
6
|
+
const POINT_STRONG_SIGNAL_RE = /\b\d{5,7}\b|\bERR_[A-Z0-9_]+\b|\buse[A-Z]\w*\b|\b[A-Z][A-Za-z0-9_]*\.[A-Za-z_][A-Za-z0-9_]*\b|\b(TRTC|TX)[A-Za-z0-9_]+\b|\bprops?\b|\b参数\b|\b事件\b|\b回调\b|\berror\s*code\b|错误码|怎么用|如何用|参数是什么/i;
|
|
7
|
+
export function classifyRetrievalMode(prompt) {
|
|
8
|
+
if (NARRATIVE_INTENT_RE.test(prompt) && !POINT_STRONG_SIGNAL_RE.test(prompt))
|
|
9
|
+
return 'narrative';
|
|
10
|
+
if (DISCOVERY_INTENT_RE.test(prompt))
|
|
11
|
+
return 'discovery';
|
|
12
|
+
return 'point';
|
|
13
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
const SCHEMA_ROOT = path.resolve(__dirname, '../../resource/_schema');
|
|
6
|
+
const QUERY_NORMALIZATION_FILE = path.join(SCHEMA_ROOT, 'query-normalization.yaml');
|
|
7
|
+
const MAX_APPEND_TOKENS = 6;
|
|
8
|
+
const BASE_QUERY_NORMALIZATION = {
|
|
9
|
+
literal: {
|
|
10
|
+
登录: ['login', 'signin', 'authentication', 'auth'],
|
|
11
|
+
鉴权: ['authentication', 'auth', 'usersig'],
|
|
12
|
+
错误码: ['error', 'error code', 'code'],
|
|
13
|
+
重复登录: ['repeat login', 'multi-device login', 'login policy'],
|
|
14
|
+
单聊: ['one-to-one', 'c2c', 'single chat'],
|
|
15
|
+
群聊: ['group chat', 'group message'],
|
|
16
|
+
直播群: ['avchatroom'],
|
|
17
|
+
直播间: ['avchatroom', 'live room'],
|
|
18
|
+
丢消息: ['message loss', 'reliability', 'priority'],
|
|
19
|
+
消息丢失: ['message loss', 'reliability', 'priority'],
|
|
20
|
+
重要消息: ['priority', 'high priority', 'critical message'],
|
|
21
|
+
用户: ['user', 'account'],
|
|
22
|
+
消息: ['message', 'messages'],
|
|
23
|
+
userSig: ['usersig', 'auth', 'authentication'],
|
|
24
|
+
AVChatRoom: ['直播群'],
|
|
25
|
+
'error code': ['错误码', '错误', 'code'],
|
|
26
|
+
'repeat login': ['重复登录', '多端登录', 'login policy'],
|
|
27
|
+
'one-to-one': ['单聊', 'c2c', 'single chat'],
|
|
28
|
+
},
|
|
29
|
+
word: {
|
|
30
|
+
login: ['登录', '鉴权', 'authentication', 'auth'],
|
|
31
|
+
auth: ['鉴权', '登录', 'authentication'],
|
|
32
|
+
authentication: ['鉴权', '登录', 'auth'],
|
|
33
|
+
usersig: ['userSig', '鉴权', '登录'],
|
|
34
|
+
error: ['错误', '错误码', 'error code'],
|
|
35
|
+
code: ['错误码', 'error code'],
|
|
36
|
+
message: ['消息', 'chat', 'conversation'],
|
|
37
|
+
messages: ['消息', 'chat', 'conversation'],
|
|
38
|
+
group: ['群组', '群聊', 'group chat'],
|
|
39
|
+
c2c: ['单聊', 'one-to-one', 'single chat'],
|
|
40
|
+
webhook: ['回调', 'webhook', 'callbacks'],
|
|
41
|
+
avchatroom: ['直播群'],
|
|
42
|
+
priority: ['重要消息', '优先级'],
|
|
43
|
+
reliability: ['消息可靠性'],
|
|
44
|
+
'message loss': ['丢消息', '消息丢失'],
|
|
45
|
+
'rate limit': ['限频', '刷屏'],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
let cachedConfig = null;
|
|
49
|
+
function unquote(input) {
|
|
50
|
+
return input.trim().replace(/^['"]|['"]$/g, '');
|
|
51
|
+
}
|
|
52
|
+
function loadQueryNormalizationConfig() {
|
|
53
|
+
if (cachedConfig)
|
|
54
|
+
return cachedConfig;
|
|
55
|
+
const config = {
|
|
56
|
+
literal: { ...BASE_QUERY_NORMALIZATION.literal },
|
|
57
|
+
word: { ...BASE_QUERY_NORMALIZATION.word },
|
|
58
|
+
};
|
|
59
|
+
if (!fs.existsSync(QUERY_NORMALIZATION_FILE)) {
|
|
60
|
+
cachedConfig = config;
|
|
61
|
+
return config;
|
|
62
|
+
}
|
|
63
|
+
const text = fs.readFileSync(QUERY_NORMALIZATION_FILE, 'utf-8');
|
|
64
|
+
let currentSection = '';
|
|
65
|
+
for (const rawLine of text.split('\n')) {
|
|
66
|
+
const line = rawLine.trimEnd();
|
|
67
|
+
if (!line.trim() || line.trimStart().startsWith('#'))
|
|
68
|
+
continue;
|
|
69
|
+
const sectionMatch = line.match(/^(literal|word):\s*$/);
|
|
70
|
+
if (sectionMatch) {
|
|
71
|
+
currentSection = sectionMatch[1];
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const entryMatch = line.match(/^\s{2}([^:#]+):\s*\[(.*)\]\s*$/);
|
|
75
|
+
if (!entryMatch || !currentSection)
|
|
76
|
+
continue;
|
|
77
|
+
const key = unquote(entryMatch[1]);
|
|
78
|
+
const values = entryMatch[2]
|
|
79
|
+
.split(',')
|
|
80
|
+
.map((token) => unquote(token))
|
|
81
|
+
.filter(Boolean);
|
|
82
|
+
if (!key || !values.length)
|
|
83
|
+
continue;
|
|
84
|
+
config[currentSection][key] = values;
|
|
85
|
+
}
|
|
86
|
+
cachedConfig = config;
|
|
87
|
+
return config;
|
|
88
|
+
}
|
|
89
|
+
function escapeRegExp(value) {
|
|
90
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
91
|
+
}
|
|
92
|
+
function hasCjk(text) {
|
|
93
|
+
return /[\u4e00-\u9fff]/.test(text);
|
|
94
|
+
}
|
|
95
|
+
function hasWordMatch(prompt, promptLower, needle) {
|
|
96
|
+
const normalizedNeedle = needle.toLowerCase();
|
|
97
|
+
if (hasCjk(normalizedNeedle)) {
|
|
98
|
+
return prompt.includes(needle);
|
|
99
|
+
}
|
|
100
|
+
const pattern = new RegExp(`\\b${escapeRegExp(normalizedNeedle)}\\b`, 'i');
|
|
101
|
+
return pattern.test(promptLower);
|
|
102
|
+
}
|
|
103
|
+
export function normalizeQueryPrompt(prompt) {
|
|
104
|
+
const config = loadQueryNormalizationConfig();
|
|
105
|
+
const terms = new Set(prompt.split(/\s+/).filter(Boolean));
|
|
106
|
+
const promptLower = prompt.toLowerCase();
|
|
107
|
+
let appendedCount = 0;
|
|
108
|
+
const tryAppend = (tokens) => {
|
|
109
|
+
for (const token of tokens) {
|
|
110
|
+
if (appendedCount >= MAX_APPEND_TOKENS)
|
|
111
|
+
return;
|
|
112
|
+
if (!terms.has(token)) {
|
|
113
|
+
terms.add(token);
|
|
114
|
+
appendedCount += 1;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
for (const [needle, expansion] of Object.entries(config.literal)) {
|
|
119
|
+
if (!prompt.includes(needle))
|
|
120
|
+
continue;
|
|
121
|
+
tryAppend(expansion);
|
|
122
|
+
}
|
|
123
|
+
for (const [needle, expansion] of Object.entries(config.word)) {
|
|
124
|
+
if (!hasWordMatch(prompt, promptLower, needle))
|
|
125
|
+
continue;
|
|
126
|
+
tryAppend(expansion);
|
|
127
|
+
}
|
|
128
|
+
return [...terms].join(' ');
|
|
129
|
+
}
|