@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
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
-
import { attachPoolContent, getSourceFileContent } from '../content-loader.js';
|
|
5
|
-
import { buildReferences, resolveFragmentDocUrls } from '../doc-url-resolver.js';
|
|
6
|
-
import { rankSubsetWithIndex } from '../bm25.js';
|
|
7
|
-
import { getProductsBM25Index } from '../bm25-cache.js';
|
|
8
4
|
import { filterPool, normalizeParams } from './filter-pool.js';
|
|
9
|
-
import { runExactLookup } from './exact-lookup.js';
|
|
10
5
|
import { requiresFramework } from './requires-framework.js';
|
|
6
|
+
import { classifyRetrievalMode } from './intent-router.js';
|
|
7
|
+
import { rankSubsetWithIndex } from '../bm25.js';
|
|
8
|
+
import { getProductsBM25Index } from '../bm25-cache.js';
|
|
9
|
+
import { hasExplicitFrameworkMatch } from './framework-fallback.js';
|
|
10
|
+
import { assessConfidence, assessNarrativeCompleteness, buildDiscoveryCatalog, buildNarrativeDocument, hasNativeClientFramework, hasNativeTrtcApiSignal, hasProductScopeIntent, inferQueryApiTokens, pickNarrativeSource, } from './search-core.js';
|
|
11
|
+
import { buildAnswerContract, buildAgentMessage } from './search-message.js';
|
|
12
|
+
import { runSearchPass } from './search-pass.js';
|
|
11
13
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
14
|
let cachedManifest = null;
|
|
13
15
|
function resolveResourcePath(...segments) {
|
|
@@ -18,284 +20,80 @@ function loadManifest() {
|
|
|
18
20
|
return cachedManifest;
|
|
19
21
|
const manifestPath = resolveResourcePath('index', 'manifest.json');
|
|
20
22
|
if (!fs.existsSync(manifestPath)) {
|
|
21
|
-
throw new Error('manifest.json not found. Run `npm run build`
|
|
23
|
+
throw new Error('manifest.json not found. Run `npm run build` first.');
|
|
22
24
|
}
|
|
23
25
|
cachedManifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
24
26
|
return cachedManifest;
|
|
25
27
|
}
|
|
26
|
-
function
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const chunk = chunksById.get(item.id);
|
|
34
|
-
if (!chunk)
|
|
35
|
-
continue;
|
|
36
|
-
const isUrlMapping = Boolean(isUrlMappingSource(chunk.source));
|
|
37
|
-
const isPinnedUrlRow = isUrlMapping && (opts?.pinnedUrlRowChunkIds?.has(chunk.id) ?? false);
|
|
38
|
-
if (isUrlMapping) {
|
|
39
|
-
const urlCount = urlMappingSourceCount[chunk.source] ?? 0;
|
|
40
|
-
if (!isPinnedUrlRow && urlCount >= 1)
|
|
41
|
-
continue;
|
|
42
|
-
urlMappingSourceCount[chunk.source] = urlCount + 1;
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
const count = sourceCount[chunk.source] ?? 0;
|
|
46
|
-
if (count >= 3)
|
|
47
|
-
continue;
|
|
48
|
-
sourceCount[chunk.source] = count + 1;
|
|
49
|
-
}
|
|
50
|
-
// 当用户明确问某厂商时,抑制同目录下其他厂商文档的噪声
|
|
51
|
-
// 规则:如果已有 config/android/{vendor}.md 入选,
|
|
52
|
-
// 后续其他 config/android/{other}.md 跳过
|
|
53
|
-
const isVendorDoc = chunk.source.match(/^knowledge\/push\/config\/android\/[a-z]+\.md$/);
|
|
54
|
-
if (isVendorDoc) {
|
|
55
|
-
if (!selectedVendorFile) {
|
|
56
|
-
selectedVendorFile = chunk.source;
|
|
57
|
-
}
|
|
58
|
-
else if (chunk.source !== selectedVendorFile) {
|
|
59
|
-
continue; // 跳过其他厂商
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
// 当已明确命中了厂商配置页后,后续的 push 通用文件(integration/、其他 config/)不再有意义
|
|
63
|
-
// 只保留同厂商文件(已由 vendor dedup 处理)和 overview 综述,其他 push 通用文档视为噪声
|
|
64
|
-
if (selectedVendorFile && chunk.source.startsWith('knowledge/push/') && !chunk.source.includes('/overview/')) {
|
|
65
|
-
if (chunk.source !== selectedVendorFile)
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
const firstPush = fragments.length === 0;
|
|
69
|
-
if (firstPush) {
|
|
70
|
-
// 首条不设分数截止,至少保证 1 条返回
|
|
71
|
-
}
|
|
72
|
-
else if (!isPinnedUrlRow) {
|
|
73
|
-
// 分数衰减到 top 的 5% 以下时停止,不硬填到 limit
|
|
74
|
-
// chat/urls 的行级精确命中(E7)不受该规则截断,保证多子主题可并行返回
|
|
75
|
-
const topScore = fragments[0].score;
|
|
76
|
-
if (topScore > 0 && item.score < topScore * 0.05)
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
const contentWithHint = chunk.contains_code
|
|
80
|
-
? `【代码示例,须与目标端一致】\n${chunk.content}`
|
|
81
|
-
: chunk.content;
|
|
82
|
-
fragments.push({
|
|
83
|
-
rank: fragments.length + 1,
|
|
84
|
-
score: item.score,
|
|
85
|
-
title: chunk.title,
|
|
86
|
-
content: contentWithHint,
|
|
87
|
-
source: chunk.source,
|
|
88
|
-
doc_urls: resolveFragmentDocUrls(chunk.source, chunk.content, getSourceFileContent(chunk.source)),
|
|
89
|
-
product: chunk.product,
|
|
90
|
-
framework: chunk.framework,
|
|
91
|
-
types: chunk.types,
|
|
92
|
-
variant: chunk.variant,
|
|
93
|
-
scope: chunk.scope,
|
|
94
|
-
doc_kind: chunk.doc_kind,
|
|
95
|
-
capability_status: chunk.capability_status,
|
|
96
|
-
api_names: chunk.api_names,
|
|
97
|
-
contains_code: chunk.contains_code,
|
|
98
|
-
citation: `[来源: ${chunk.id}]`,
|
|
99
|
-
chunk_id: chunk.id,
|
|
100
|
-
});
|
|
101
|
-
if (fragments.length >= limit)
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
return fragments;
|
|
105
|
-
}
|
|
106
|
-
function isUrlMappingSource(source) {
|
|
107
|
-
const normalized = source.replace(/\\/g, '/');
|
|
108
|
-
const match = normalized.match(/knowledge\/chat\/urls\/(.+\.md)$/);
|
|
109
|
-
if (!match)
|
|
110
|
-
return null;
|
|
111
|
-
return match[1].replace(/\.md$/, '').replace(/\/index$/, '');
|
|
112
|
-
}
|
|
113
|
-
function partitionFragments(fragments) {
|
|
114
|
-
const urlMapping = [];
|
|
115
|
-
const localDoc = [];
|
|
116
|
-
for (const fragment of fragments) {
|
|
117
|
-
if (isUrlMappingSource(fragment.source)) {
|
|
118
|
-
urlMapping.push(fragment);
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
localDoc.push(fragment);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
const urlMappingKinds = [...new Set(urlMapping.map((f) => isUrlMappingSource(f.source)).filter(Boolean))];
|
|
125
|
-
return { urlMapping, localDoc, urlMappingKinds };
|
|
126
|
-
}
|
|
127
|
-
function hasBestPracticeFragment(fragments) {
|
|
128
|
-
return fragments.some((f) => /\/best-practice\//i.test(f.source));
|
|
129
|
-
}
|
|
130
|
-
function inferQueryApiTokens(prompt) {
|
|
131
|
-
const tokens = new Set();
|
|
132
|
-
const upperNoise = new Set(['SDK', 'API', 'HTTP', 'HTTPS', 'JSON', 'CALL', 'NAME', 'STATUS']);
|
|
133
|
-
for (const match of prompt.matchAll(/\b([a-z]+[A-Z][A-Za-z0-9_]*)\b/g)) {
|
|
134
|
-
tokens.add(match[1]);
|
|
135
|
-
}
|
|
136
|
-
for (const match of prompt.matchAll(/\b([A-Z][A-Za-z0-9_]*\.[A-Za-z_][A-Za-z0-9_]*)\b/g)) {
|
|
137
|
-
tokens.add(match[1]);
|
|
138
|
-
}
|
|
139
|
-
for (const match of prompt.matchAll(/\b(use[A-Z]\w*)\b/g)) {
|
|
140
|
-
tokens.add(match[1]);
|
|
141
|
-
}
|
|
142
|
-
for (const match of prompt.matchAll(/\b(I[A-Z][A-Za-z0-9_]*)\b/g)) {
|
|
143
|
-
tokens.add(match[1]);
|
|
144
|
-
}
|
|
145
|
-
for (const match of prompt.matchAll(/\b([A-Z][A-Za-z0-9_]*\.[A-Z_][A-Z0-9_]*)\b/g)) {
|
|
146
|
-
tokens.add(match[1]);
|
|
147
|
-
}
|
|
148
|
-
for (const match of prompt.matchAll(/\b([A-Z_]{3,})\b/g)) {
|
|
149
|
-
const token = match[1];
|
|
150
|
-
if (!upperNoise.has(token))
|
|
151
|
-
tokens.add(token);
|
|
28
|
+
function buildCoverageReport(allChunks, fragments, preferredSource) {
|
|
29
|
+
if (!fragments.length) {
|
|
30
|
+
return {
|
|
31
|
+
files: [],
|
|
32
|
+
allow_pending_confirm: true,
|
|
33
|
+
retry_suggested: false,
|
|
34
|
+
};
|
|
152
35
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (!tokens.length)
|
|
171
|
-
return [];
|
|
172
|
-
return tokens.filter((token) => !candidates.some((chunk) => tokenInChunk(token, chunk)));
|
|
173
|
-
}
|
|
174
|
-
function applyRankMultipliers(ranked, chunksById, opts) {
|
|
175
|
-
const adjusted = ranked.map((item) => {
|
|
176
|
-
const chunk = chunksById.get(item.id);
|
|
177
|
-
if (!chunk)
|
|
178
|
-
return item;
|
|
179
|
-
let multiplier = 1;
|
|
180
|
-
// A2: 传了 product 时,命中 scope 的通配语料允许召回但降权
|
|
181
|
-
if (opts.product?.length && chunk.product === '*') {
|
|
182
|
-
multiplier *= 0.2;
|
|
183
|
-
}
|
|
184
|
-
// F2: framework 软降权(保留硬过滤,处理 fallback/边界残留)
|
|
185
|
-
if (opts.framework && opts.frameworks?.length && !chunk.framework.includes('*')) {
|
|
186
|
-
const explicitMatch = opts.frameworks.some((fw) => chunk.framework.includes(fw));
|
|
187
|
-
const callCoreWebFallback = Boolean(opts.product?.includes('call')
|
|
188
|
-
&& (opts.framework === 'react' || opts.framework === 'vue')
|
|
189
|
-
&& chunk.variant === 'core-sdk'
|
|
190
|
-
&& chunk.framework.includes('web'));
|
|
191
|
-
const liveWebVueFallback = Boolean(opts.product?.includes('live')
|
|
192
|
-
&& opts.framework === 'web'
|
|
193
|
-
&& chunk.variant === 'core-sdk'
|
|
194
|
-
&& chunk.framework.includes('vue')
|
|
195
|
-
&& chunk.source.includes('/api-reference/'));
|
|
196
|
-
if (!explicitMatch && !callCoreWebFallback && !liveWebVueFallback) {
|
|
197
|
-
multiplier *= 0.2;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
return { ...item, score: item.score * multiplier };
|
|
36
|
+
const hitChunkIds = new Set(fragments.map((f) => f.chunk_id));
|
|
37
|
+
const sources = [...new Set(fragments.map((f) => f.source))];
|
|
38
|
+
const files = sources.map((source) => {
|
|
39
|
+
const sourceChunks = allChunks.filter((chunk) => chunk.source === source);
|
|
40
|
+
const fileToken = sourceChunks.reduce((sum, chunk) => sum + Math.max(0, chunk.char_end - chunk.char_start), 0);
|
|
41
|
+
const hitToken = sourceChunks
|
|
42
|
+
.filter((chunk) => hitChunkIds.has(chunk.id))
|
|
43
|
+
.reduce((sum, chunk) => sum + Math.max(0, chunk.char_end - chunk.char_start), 0);
|
|
44
|
+
const completeness = fileToken > 0 ? Number((hitToken / fileToken).toFixed(2)) : 0;
|
|
45
|
+
const missingChunkIds = sourceChunks.filter((chunk) => !hitChunkIds.has(chunk.id)).map((chunk) => chunk.id).slice(0, 12);
|
|
46
|
+
return {
|
|
47
|
+
source,
|
|
48
|
+
hit_token: hitToken,
|
|
49
|
+
file_token: fileToken,
|
|
50
|
+
completeness,
|
|
51
|
+
missing_chunk_ids: missingChunkIds,
|
|
52
|
+
};
|
|
201
53
|
});
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const ratio = second > 0 ? top / second : Infinity;
|
|
214
|
-
let confidence;
|
|
215
|
-
if (exactHits.length > 0 || top >= 50)
|
|
216
|
-
confidence = 'high';
|
|
217
|
-
else if (top >= 12 && ratio >= 1.25)
|
|
218
|
-
confidence = 'medium';
|
|
219
|
-
else if (top >= 6 && ratio >= 1.12)
|
|
220
|
-
confidence = 'medium';
|
|
221
|
-
else
|
|
222
|
-
confidence = 'low';
|
|
223
|
-
// D2: API 覆盖过低时,confidence 上限降为 low
|
|
224
|
-
if (queryApiTokens.length > 0 && apiNameCoverage < 0.3) {
|
|
225
|
-
confidence = 'low';
|
|
226
|
-
}
|
|
227
|
-
const status = confidence === 'low' ? 'low_confidence' : 'success';
|
|
228
|
-
return { confidence, status };
|
|
229
|
-
}
|
|
230
|
-
function buildAnswerContract(status, confidence, opts) {
|
|
231
|
-
const uncertaintyRule = status === 'low_confidence' || confidence === 'low'
|
|
232
|
-
? '当信息不足时必须显式写“待确认:”,只允许陈述缺口,不允许猜测补全。'
|
|
233
|
-
: '除“待确认:”段落外,不得出现“可能/大概/应该/推测”等猜测措辞。';
|
|
234
|
-
const riskRule = opts?.fabricationRisk
|
|
235
|
-
? 'fabrication_risk=true 时,若片段未覆盖该细节,必须输出“待确认:知识片段未覆盖此项”。'
|
|
236
|
-
: '';
|
|
237
|
-
return [
|
|
238
|
-
'【输出模板(必须遵守)】',
|
|
239
|
-
'使用“问题导向”标题组织答案,优先复用用户提问原句:一、<问题1> 二、<问题2> 三、<问题3> …',
|
|
240
|
-
'每个小节先给直接结论,再补 1-2 句必要说明;避免模板化术语(如“依据/操作”字样)。',
|
|
241
|
-
'信息缺口统一放在对应小节末尾,使用“待确认:xxx”;若全都确认则可省略“待确认”小节。',
|
|
242
|
-
'末尾保留“参考文档”小节,仅列文档标题或 URL;正文不展示检索过程、证据链、打分细节。',
|
|
243
|
-
'用户可见正文禁止出现系统检索话术(如“命中片段/检索结果/置信度/分数/召回/重排”)。',
|
|
244
|
-
'硬约束:不得引入 fragments 未出现的 API 名、字段值、枚举项、事件名。',
|
|
245
|
-
uncertaintyRule,
|
|
246
|
-
riskRule,
|
|
247
|
-
].filter(Boolean).join(' ');
|
|
54
|
+
const primarySource = preferredSource ?? fragments[0]?.source;
|
|
55
|
+
const primaryCompleteness = primarySource
|
|
56
|
+
? files.find((file) => file.source === primarySource)?.completeness ?? 0
|
|
57
|
+
: 0;
|
|
58
|
+
return {
|
|
59
|
+
files,
|
|
60
|
+
allow_pending_confirm: primaryCompleteness < 0.9,
|
|
61
|
+
primary_source: primarySource,
|
|
62
|
+
primary_completeness: primaryCompleteness,
|
|
63
|
+
retry_suggested: primaryCompleteness < 0.6,
|
|
64
|
+
};
|
|
248
65
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
const
|
|
254
|
-
if (
|
|
255
|
-
return
|
|
256
|
-
|
|
257
|
-
const
|
|
258
|
-
const
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
return `当前问题在该平台 / 形态下 **不支持**${scopeLabel}。回答 MUST:① 第一段先明确写“**不支持**”;② 说明这是当前平台 Core 的能力边界,而不是缺少示例代码;③ 仅提供当前平台已支持的替代方案(如对应平台 preset 预制 UI);若当前知识库未给出明确替代形态,应直接说明暂无可执行替代路径;④ **禁止**输出当前平台 Core 的 API 调用步骤或集成步骤。${tail}`;
|
|
267
|
-
}
|
|
268
|
-
if (hasUrlMapping && !hasLocalDoc) {
|
|
269
|
-
return `当前可用信息主要是文档入口链接(${urlKindLabel})。请先匹配用户问题对应的目标 URL,抓取官网文档后再合成答案;禁止仅复述映射表或臆造 API/错误码细节。${tail}`;
|
|
270
|
-
}
|
|
271
|
-
if (hasUrlMapping && hasLocalDoc) {
|
|
272
|
-
if (hasBestPractice) {
|
|
273
|
-
return `优先基于已命中的 best-practice 与本地片段直接作答;URL 映射仅作补充参考,不要再抓官网做二次求证。${tail}`;
|
|
274
|
-
}
|
|
275
|
-
return `本地文档片段可直接用于作答;若本地片段未覆盖关键细节,再从 URL 映射中提取目标 URL 抓取官网文档补齐。${tail}`;
|
|
276
|
-
}
|
|
277
|
-
return `请仅基于已返回 fragments 合成答案;不要并行 web_search 或额外抓取官网文档。${tail}`;
|
|
278
|
-
}
|
|
279
|
-
if (status === 'low_confidence') {
|
|
280
|
-
if (hasUrlMapping) {
|
|
281
|
-
if (hasBestPractice) {
|
|
282
|
-
return `优先基于 best-practice 与本地片段给出可执行结论;未覆盖的内容统一写入“待确认”,不要默认抓官网二次求证。${tail}`;
|
|
283
|
-
}
|
|
284
|
-
return `请先从 URL 映射里提取目标 URL 并抓取官网文档补齐关键信息,再给出答案;仍无法确认的内容明确写“待确认”。${tail}`;
|
|
285
|
-
}
|
|
286
|
-
return `请基于已有 fragments 给出最可执行答案,并将未覆盖细节明确写为“待确认”;可引导用户补充组件名/API 名/错误码后重新检索。不要默认并行 web_search。${tail}`;
|
|
287
|
-
}
|
|
288
|
-
return `知识库未命中有效片段。请向用户说明并确认 product/framework 是否准确;若仍无 platform 信息且问题依赖具体客户端,应先 \`present_framework_choice\`。${tail}`;
|
|
66
|
+
/** 轻量覆盖度:仅算主文件完整度,用于非收敛场景的 allow_pending_confirm 判定,不产出逐文件明细 */
|
|
67
|
+
function computePrimaryCompleteness(allChunks, fragments, preferredSource) {
|
|
68
|
+
if (!fragments.length)
|
|
69
|
+
return { primary_completeness: 0 };
|
|
70
|
+
const primarySource = preferredSource ?? fragments[0]?.source;
|
|
71
|
+
if (!primarySource)
|
|
72
|
+
return { primary_completeness: 0 };
|
|
73
|
+
const hitChunkIds = new Set(fragments.map((f) => f.chunk_id));
|
|
74
|
+
const sourceChunks = allChunks.filter((chunk) => chunk.source === primarySource);
|
|
75
|
+
const fileToken = sourceChunks.reduce((sum, chunk) => sum + Math.max(0, chunk.char_end - chunk.char_start), 0);
|
|
76
|
+
const hitToken = sourceChunks
|
|
77
|
+
.filter((chunk) => hitChunkIds.has(chunk.id))
|
|
78
|
+
.reduce((sum, chunk) => sum + Math.max(0, chunk.char_end - chunk.char_start), 0);
|
|
79
|
+
return {
|
|
80
|
+
primary_source: primarySource,
|
|
81
|
+
primary_completeness: fileToken > 0 ? Number((hitToken / fileToken).toFixed(2)) : 0,
|
|
82
|
+
};
|
|
289
83
|
}
|
|
290
84
|
export function searchKnowledge(params) {
|
|
291
85
|
const norm = normalizeParams(params);
|
|
86
|
+
const retrievalMode = classifyRetrievalMode(norm.prompt);
|
|
292
87
|
if (requiresFramework(norm)) {
|
|
293
88
|
const manifest = loadManifest();
|
|
294
89
|
return {
|
|
295
90
|
status: 'needs_framework',
|
|
296
91
|
confidence: 'none',
|
|
297
|
-
message: buildAgentMessage('needs_framework', [], 'none', undefined),
|
|
92
|
+
message: buildAgentMessage('needs_framework', retrievalMode, [], 'none', undefined),
|
|
298
93
|
query: params,
|
|
94
|
+
retrieval_mode: retrievalMode,
|
|
95
|
+
documents: [],
|
|
96
|
+
catalog: [],
|
|
299
97
|
meta: {
|
|
300
98
|
pool_size: manifest.chunks.length,
|
|
301
99
|
filtered_size: 0,
|
|
@@ -307,90 +105,303 @@ export function searchKnowledge(params) {
|
|
|
307
105
|
const manifest = loadManifest();
|
|
308
106
|
const allChunks = manifest.chunks;
|
|
309
107
|
const queryApiTokens = inferQueryApiTokens(norm.prompt);
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
108
|
+
let pass = runSearchPass({
|
|
109
|
+
allChunks,
|
|
110
|
+
passNorm: norm,
|
|
111
|
+
retrievalMode,
|
|
112
|
+
queryApiTokens,
|
|
113
|
+
});
|
|
114
|
+
// best-practice 懒补充:仅在主 pass 无本地片段(仅 URL 映射行或完全为空)时触发。
|
|
115
|
+
// 典型场景:Agent 传 types=['sdk'],filterPool 把 best-practice(type=faq)硬过滤掉,
|
|
116
|
+
// 只剩 URL 映射行(有 E7 boost 但内容只是一个 URL 链接)。
|
|
117
|
+
// 不侵入 runSearchPass 层,避免每次调用都执行重复检索。
|
|
118
|
+
const passRetryReasons = [];
|
|
119
|
+
const hasLocalContent = pass.fragments.some((f) => !f.source.includes('/urls/'));
|
|
120
|
+
if (!hasLocalContent && norm.product?.length && !norm.types?.includes('faq')) {
|
|
121
|
+
const primaryProduct = norm.product[0];
|
|
122
|
+
const bpCandidates = allChunks.filter((chunk) => {
|
|
123
|
+
if (!/\/best-practice\//i.test(chunk.source))
|
|
124
|
+
return false;
|
|
125
|
+
if (chunk.product !== primaryProduct && chunk.product !== '*')
|
|
126
|
+
return false;
|
|
127
|
+
if (norm.frameworks?.length) {
|
|
128
|
+
const explicitMatch = hasExplicitFrameworkMatch(chunk.framework, norm.frameworks);
|
|
129
|
+
const wildcardAllowed = chunk.framework.includes('*');
|
|
130
|
+
if (!explicitMatch && !wildcardAllowed)
|
|
131
|
+
return false;
|
|
323
132
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if (
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
133
|
+
return true;
|
|
134
|
+
});
|
|
135
|
+
if (bpCandidates.length > 0) {
|
|
136
|
+
const bpIndex = getProductsBM25Index(allChunks, [norm.product[0]]);
|
|
137
|
+
const bpRanked = rankSubsetWithIndex(norm.prompt, bpCandidates.map((c) => c.id), bpIndex, {});
|
|
138
|
+
if ((bpRanked[0]?.score ?? 0) >= 6) {
|
|
139
|
+
const bpPass = runSearchPass({
|
|
140
|
+
allChunks,
|
|
141
|
+
passNorm: { ...norm, types: undefined },
|
|
142
|
+
retrievalMode,
|
|
143
|
+
queryApiTokens,
|
|
144
|
+
});
|
|
145
|
+
if (bpPass.fragments.length > 0) {
|
|
146
|
+
pass = bpPass;
|
|
147
|
+
passRetryReasons.push('best_practice_supplement');
|
|
330
148
|
}
|
|
331
149
|
}
|
|
332
150
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
const chunksById = new Map(poolWithContent.map((chunk) => [chunk.id, chunk]));
|
|
336
|
-
const ranked = rankSubsetWithIndex(passNorm.prompt, pool.map((chunk) => chunk.id), productIndex, boosts);
|
|
337
|
-
const rankedWithMultipliers = applyRankMultipliers(ranked, chunksById, {
|
|
338
|
-
product: passNorm.product,
|
|
339
|
-
framework: passNorm.framework,
|
|
340
|
-
frameworks: passNorm.frameworks,
|
|
341
|
-
});
|
|
342
|
-
const pinnedUrlRowChunkIds = new Set(urlRowHitChunkIds);
|
|
343
|
-
const fragments = postProcess(rankedWithMultipliers, chunksById, passNorm.limit, {
|
|
344
|
-
pinnedUrlRowChunkIds,
|
|
345
|
-
});
|
|
346
|
-
const urlMappingSources = [...new Set(fragments.map((f) => f.source).filter((source) => isUrlMappingSource(source)))];
|
|
347
|
-
const references = buildReferences(fragments);
|
|
348
|
-
const apiNameCoverage = computeApiNameCoverage(queryApiTokens, poolWithContent);
|
|
349
|
-
const missingApiTokens = computeMissingApiTokens(queryApiTokens, poolWithContent);
|
|
350
|
-
return {
|
|
351
|
-
pool,
|
|
352
|
-
fragments,
|
|
353
|
-
exactHits,
|
|
354
|
-
urlMappingSources,
|
|
355
|
-
references,
|
|
356
|
-
apiNameCoverage,
|
|
357
|
-
missingApiTokens,
|
|
358
|
-
urlMapRelaxed: pinnedUrlRowChunkIds.size > 0,
|
|
359
|
-
urlMapExactHitCount: pinnedUrlRowChunkIds.size,
|
|
360
|
-
};
|
|
361
|
-
};
|
|
362
|
-
let pass = runSearchPass(norm);
|
|
363
|
-
let retryReason;
|
|
151
|
+
}
|
|
152
|
+
const retryReasons = [...passRetryReasons];
|
|
364
153
|
// B2: API token 覆盖不足时触发一次扩检(去掉 types 约束 + api/integration 轻提权)
|
|
365
154
|
const missingRatio = queryApiTokens.length > 0
|
|
366
155
|
? Number((pass.missingApiTokens.length / queryApiTokens.length).toFixed(2))
|
|
367
156
|
: 0;
|
|
368
157
|
if (queryApiTokens.length > 0 && (pass.apiNameCoverage === 0 || missingRatio >= 0.3)) {
|
|
369
|
-
const retryPass = runSearchPass({
|
|
158
|
+
const retryPass = runSearchPass({
|
|
159
|
+
allChunks,
|
|
160
|
+
passNorm: { ...norm, types: undefined },
|
|
161
|
+
retrievalMode,
|
|
162
|
+
queryApiTokens,
|
|
163
|
+
opts: { apiRetry: true },
|
|
164
|
+
});
|
|
165
|
+
const retryMissingRatio = queryApiTokens.length > 0
|
|
166
|
+
? Number((retryPass.missingApiTokens.length / queryApiTokens.length).toFixed(2))
|
|
167
|
+
: 0;
|
|
168
|
+
if (retryPass.apiNameCoverage > pass.apiNameCoverage
|
|
169
|
+
|| retryMissingRatio < missingRatio
|
|
170
|
+
|| (pass.fragments.length === 0 && retryPass.fragments.length > 0)) {
|
|
171
|
+
pass = retryPass;
|
|
172
|
+
retryReasons.push(`api_gap_retry:coverage=${pass.apiNameCoverage},missing_ratio=${retryMissingRatio}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// B3: 混合“集成 + 产品开通/计费/控制台”问法时,补充 product type,避免仅搜 integration/feature。
|
|
176
|
+
if (norm.types?.length && !norm.types.includes('product') && hasProductScopeIntent(norm.prompt)) {
|
|
177
|
+
const widenedTypes = [...new Set([...norm.types, 'product'])];
|
|
178
|
+
const retryPass = runSearchPass({
|
|
179
|
+
allChunks,
|
|
180
|
+
passNorm: { ...norm, types: widenedTypes },
|
|
181
|
+
retrievalMode,
|
|
182
|
+
queryApiTokens,
|
|
183
|
+
});
|
|
184
|
+
const baseHasProduct = pass.fragments.some((f) => f.types.includes('product'));
|
|
185
|
+
const retryHasProduct = retryPass.fragments.some((f) => f.types.includes('product'));
|
|
186
|
+
if ((retryHasProduct && !baseHasProduct)
|
|
187
|
+
|| (pass.fragments.length === 0 && retryPass.fragments.length > 0)
|
|
188
|
+
|| (retryPass.fragments[0]?.score ?? 0) > (pass.fragments[0]?.score ?? 0) * 1.08) {
|
|
189
|
+
pass = retryPass;
|
|
190
|
+
retryReasons.push('product_scope_retry:types+=product');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// B4: 若疑似 Native TRTC API 问法却路由到 live/room/call,自动补扩 native_trtc_sdk 产品重检。
|
|
194
|
+
const shouldRetryNativeProduct = hasNativeClientFramework(norm.frameworks)
|
|
195
|
+
&& hasNativeTrtcApiSignal(norm.prompt, queryApiTokens)
|
|
196
|
+
&& norm.product?.some((p) => ['live', 'room', 'call'].includes(p))
|
|
197
|
+
&& !norm.product?.includes('native_trtc_sdk')
|
|
198
|
+
&& queryApiTokens.length > 0
|
|
199
|
+
&& pass.apiNameCoverage < 0.5;
|
|
200
|
+
if (shouldRetryNativeProduct) {
|
|
201
|
+
const expandedProducts = [...new Set([...(norm.product ?? []), 'native_trtc_sdk'])];
|
|
202
|
+
const retryPass = runSearchPass({
|
|
203
|
+
allChunks,
|
|
204
|
+
passNorm: { ...norm, product: expandedProducts, types: undefined },
|
|
205
|
+
retrievalMode,
|
|
206
|
+
queryApiTokens,
|
|
207
|
+
opts: { apiRetry: true },
|
|
208
|
+
});
|
|
370
209
|
const retryMissingRatio = queryApiTokens.length > 0
|
|
371
210
|
? Number((retryPass.missingApiTokens.length / queryApiTokens.length).toFixed(2))
|
|
372
211
|
: 0;
|
|
373
212
|
if (retryPass.apiNameCoverage > pass.apiNameCoverage
|
|
213
|
+
|| retryPass.exactHits.length > pass.exactHits.length
|
|
374
214
|
|| retryMissingRatio < missingRatio
|
|
375
215
|
|| (pass.fragments.length === 0 && retryPass.fragments.length > 0)) {
|
|
376
216
|
pass = retryPass;
|
|
377
|
-
|
|
217
|
+
retryReasons.push(`native_product_retry:products=${expandedProducts.join('+')},coverage=${retryPass.apiNameCoverage}`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const resolveNarrativeState = (passSnapshot) => {
|
|
221
|
+
const source = retrievalMode === 'narrative'
|
|
222
|
+
? pickNarrativeSource(passSnapshot.exactHits, passSnapshot.rankedWithMultipliers, passSnapshot.poolWithContent)
|
|
223
|
+
: null;
|
|
224
|
+
const document = source ? buildNarrativeDocument(source, allChunks) : null;
|
|
225
|
+
const quality = assessNarrativeCompleteness(document, norm.prompt);
|
|
226
|
+
return { source, document, quality };
|
|
227
|
+
};
|
|
228
|
+
let narrativeState = resolveNarrativeState(pass);
|
|
229
|
+
// P0: narrative 自动扩检(一次)——当“完整流程”候选文档缺失或完整度不足时,放宽 types 并提高 limit。
|
|
230
|
+
const shouldRetryNarrative = retrievalMode === 'narrative'
|
|
231
|
+
&& (narrativeState.document === null || !narrativeState.quality.isComplete);
|
|
232
|
+
if (shouldRetryNarrative) {
|
|
233
|
+
const narrativeRetryNorm = {
|
|
234
|
+
...norm,
|
|
235
|
+
types: undefined,
|
|
236
|
+
limit: Math.max(norm.limit ?? 8, 12),
|
|
237
|
+
};
|
|
238
|
+
const retryPass = runSearchPass({
|
|
239
|
+
allChunks,
|
|
240
|
+
passNorm: narrativeRetryNorm,
|
|
241
|
+
retrievalMode,
|
|
242
|
+
queryApiTokens,
|
|
243
|
+
opts: { apiRetry: true },
|
|
244
|
+
});
|
|
245
|
+
const retryNarrativeState = resolveNarrativeState(retryPass);
|
|
246
|
+
if (retryNarrativeState.quality.score > narrativeState.quality.score
|
|
247
|
+
|| (narrativeState.document === null && retryNarrativeState.document !== null)
|
|
248
|
+
|| (retryPass.exactHits.length > pass.exactHits.length && retryNarrativeState.document !== null)) {
|
|
249
|
+
pass = retryPass;
|
|
250
|
+
narrativeState = retryNarrativeState;
|
|
251
|
+
retryReasons.push(`narrative_retry:score=${retryNarrativeState.quality.score}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// 覆盖度深检(全量 files 明细 + 自动扩检)仅在收敛到单一 best-practice 时启用,
|
|
255
|
+
// 避免对普通点查场景做无差别二次检索与全量 coverage_report 外发。
|
|
256
|
+
const shouldDeepCoverageCheck = Boolean(pass.preferredSource || pass.fullDocumentMode) && pass.fragments.length > 0;
|
|
257
|
+
let coverageReport;
|
|
258
|
+
if (shouldDeepCoverageCheck) {
|
|
259
|
+
coverageReport = buildCoverageReport(allChunks, pass.fragments, pass.preferredSource);
|
|
260
|
+
if (coverageReport.retry_suggested) {
|
|
261
|
+
const coverageRetryPass = runSearchPass({
|
|
262
|
+
allChunks,
|
|
263
|
+
passNorm: { ...norm, types: undefined, limit: Math.max(norm.limit ?? 8, 12) },
|
|
264
|
+
retrievalMode,
|
|
265
|
+
queryApiTokens,
|
|
266
|
+
opts: { apiRetry: true },
|
|
267
|
+
});
|
|
268
|
+
const retriedCoverageReport = buildCoverageReport(allChunks, coverageRetryPass.fragments, coverageRetryPass.preferredSource);
|
|
269
|
+
const currentCoverage = coverageReport.primary_completeness ?? 0;
|
|
270
|
+
const retriedCoverage = retriedCoverageReport.primary_completeness ?? 0;
|
|
271
|
+
if (retriedCoverage > currentCoverage || coverageRetryPass.fragments.length > pass.fragments.length) {
|
|
272
|
+
pass = coverageRetryPass;
|
|
273
|
+
coverageReport = retriedCoverageReport;
|
|
274
|
+
retryReasons.push(`coverage_check_retry:primary=${retriedCoverage}`);
|
|
275
|
+
}
|
|
378
276
|
}
|
|
277
|
+
// 单 chunk 文档 completeness 恒为 1,不代表问题被完整覆盖;
|
|
278
|
+
// 仅在 fullDocumentMode 聚合多 chunk(>1)且覆盖度足够时才禁止“待确认”。
|
|
279
|
+
const primaryChunkCount = coverageReport.primary_source
|
|
280
|
+
? allChunks.filter((chunk) => chunk.source === coverageReport.primary_source).length
|
|
281
|
+
: 0;
|
|
282
|
+
coverageReport = {
|
|
283
|
+
...coverageReport,
|
|
284
|
+
allow_pending_confirm: !(pass.fullDocumentMode
|
|
285
|
+
&& primaryChunkCount > 1
|
|
286
|
+
&& (coverageReport.primary_completeness ?? 0) >= 0.9),
|
|
287
|
+
};
|
|
379
288
|
}
|
|
289
|
+
else {
|
|
290
|
+
const primary = computePrimaryCompleteness(allChunks, pass.fragments, pass.preferredSource);
|
|
291
|
+
coverageReport = {
|
|
292
|
+
allow_pending_confirm: true,
|
|
293
|
+
...(primary.primary_source ? { primary_source: primary.primary_source } : {}),
|
|
294
|
+
primary_completeness: primary.primary_completeness,
|
|
295
|
+
retry_suggested: false,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
narrativeState = resolveNarrativeState(pass);
|
|
299
|
+
const retryReason = retryReasons.length ? retryReasons.join(';') : undefined;
|
|
380
300
|
const routeInconsistencyWarning = pass.fragments.length > 0
|
|
381
301
|
? pass.fragments.filter((f) => f.product === '*').length / pass.fragments.length > 0.3
|
|
382
302
|
: false;
|
|
383
303
|
const { confidence, status } = assessConfidence(pass.fragments, pass.exactHits, pass.apiNameCoverage, queryApiTokens);
|
|
384
304
|
const fabricationRisk = (queryApiTokens.length > 0 && pass.apiNameCoverage < 0.3)
|
|
385
305
|
|| (confidence === 'low' && pass.fragments.length < 2);
|
|
306
|
+
// point 模式不再返回 documents:fullDocumentMode 下 fragments 已按 char_start 顺序返回完整章节,
|
|
307
|
+
// 再回 documents 会造成同一篇内容重复外发。
|
|
308
|
+
const documents = retrievalMode === 'narrative'
|
|
309
|
+
? (narrativeState.document ? [narrativeState.document] : [])
|
|
310
|
+
: [];
|
|
311
|
+
const catalog = retrievalMode === 'discovery'
|
|
312
|
+
? buildDiscoveryCatalog(pass.rankedWithMultipliers, pass.poolWithContent, norm.limit)
|
|
313
|
+
: [];
|
|
314
|
+
let finalStatus = status;
|
|
315
|
+
let finalConfidence = confidence;
|
|
316
|
+
if (retrievalMode === 'narrative' && documents.length > 0) {
|
|
317
|
+
if (narrativeState.quality.isComplete) {
|
|
318
|
+
finalStatus = 'success';
|
|
319
|
+
finalConfidence = 'high';
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
finalStatus = 'low_confidence';
|
|
323
|
+
finalConfidence = 'low';
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (retrievalMode === 'discovery' && catalog.length > 0) {
|
|
327
|
+
finalStatus = 'success';
|
|
328
|
+
finalConfidence = finalConfidence === 'none' ? 'medium' : finalConfidence;
|
|
329
|
+
}
|
|
386
330
|
const topScore = pass.fragments[0]?.score;
|
|
387
331
|
const secondScore = pass.fragments[1]?.score;
|
|
388
|
-
const
|
|
332
|
+
const aggregatedFragments = pass.fragments
|
|
333
|
+
.filter((fragment) => fragment.aggregated || fragment.citation?.includes('[aggregated]'))
|
|
334
|
+
.map((fragment) => ({
|
|
335
|
+
chunk_id: fragment.chunk_id,
|
|
336
|
+
source: fragment.source,
|
|
337
|
+
citation: fragment.citation ?? `[来源: ${fragment.chunk_id}][aggregated]`,
|
|
338
|
+
}));
|
|
339
|
+
const fullDocumentRequired = retrievalMode === 'narrative'
|
|
340
|
+
&& /完整的?\s*(接入|集成|教程|指南|流程)|完整\s*md|全文|原文|不要总结|含\s*(示例)?代码|全部步骤|完整步骤/i.test(norm.prompt);
|
|
341
|
+
const answerContract = buildAnswerContract(finalStatus, finalConfidence, retrievalMode, {
|
|
342
|
+
fabricationRisk,
|
|
343
|
+
fullDocumentRequired,
|
|
344
|
+
hasAggregatedFragments: aggregatedFragments.length > 0,
|
|
345
|
+
});
|
|
346
|
+
const hasProductScope = hasProductScopeIntent(norm.prompt);
|
|
347
|
+
const hasNativeSignal = hasNativeTrtcApiSignal(norm.prompt, queryApiTokens);
|
|
348
|
+
const hasProductContent = pass.fragments.some((f) => f.types.includes('product') || /\/product\.md$/i.test(f.source) || /\/best-practice\//i.test(f.source));
|
|
349
|
+
const hasIntegrationContent = pass.fragments.some((f) => f.types.includes('integration') || /\/integration\.md$/i.test(f.source) || /\/preset\//i.test(f.source));
|
|
350
|
+
const hasApiQueryTokens = queryApiTokens.length > 0;
|
|
351
|
+
const finalMissingRatio = hasApiQueryTokens
|
|
352
|
+
? Number((pass.missingApiTokens.length / queryApiTokens.length).toFixed(2))
|
|
353
|
+
: 0;
|
|
354
|
+
const apiGapDetected = hasApiQueryTokens && (pass.apiNameCoverage === 0 || finalMissingRatio >= 0.3);
|
|
355
|
+
const retryApiGapApplied = retryReasons.some((r) => r.startsWith('api_gap_retry:'));
|
|
356
|
+
const retryProductScopeApplied = retryReasons.includes('product_scope_retry:types+=product');
|
|
357
|
+
const retryNativeProductApplied = retryReasons.some((r) => r.startsWith('native_product_retry:'));
|
|
358
|
+
const narrativeConverged = retrievalMode !== 'narrative'
|
|
359
|
+
|| (documents.length > 0 && narrativeState.quality.isComplete);
|
|
360
|
+
const convergenceReached = (retrievalMode === 'narrative' && narrativeConverged)
|
|
361
|
+
|| (retrievalMode === 'discovery' && catalog.length > 0)
|
|
362
|
+
|| (finalStatus === 'success'
|
|
363
|
+
&& (finalConfidence === 'high' || finalConfidence === 'medium')
|
|
364
|
+
&& (!hasApiQueryTokens || pass.apiNameCoverage >= 0.5)
|
|
365
|
+
&& (!hasProductScope || hasProductContent || hasIntegrationContent));
|
|
366
|
+
const retryAdvice = (() => {
|
|
367
|
+
if (finalStatus === 'needs_framework') {
|
|
368
|
+
return { stop_retry: true, next_action: 'ask_framework', reason: 'missing_framework' };
|
|
369
|
+
}
|
|
370
|
+
if (retrievalMode === 'narrative' && !narrativeConverged) {
|
|
371
|
+
return { stop_retry: false, next_action: 'retry_or_clarify', reason: 'narrative_incomplete' };
|
|
372
|
+
}
|
|
373
|
+
if (convergenceReached) {
|
|
374
|
+
return { stop_retry: true, next_action: 'answer', reason: 'converged' };
|
|
375
|
+
}
|
|
376
|
+
if (hasApiQueryTokens && apiGapDetected && !retryApiGapApplied) {
|
|
377
|
+
return { stop_retry: false, next_action: 'retry_widen_types', reason: 'api_coverage_gap' };
|
|
378
|
+
}
|
|
379
|
+
if (hasProductScope && !hasProductContent && !retryProductScopeApplied) {
|
|
380
|
+
return { stop_retry: false, next_action: 'retry_add_product_scope', reason: 'missing_product_scope_content' };
|
|
381
|
+
}
|
|
382
|
+
if (hasNativeSignal && hasNativeClientFramework(norm.frameworks) && !retryNativeProductApplied) {
|
|
383
|
+
return { stop_retry: false, next_action: 'retry_add_native_trtc_sdk', reason: 'possible_native_product_misroute' };
|
|
384
|
+
}
|
|
385
|
+
if (finalStatus === 'empty' || finalConfidence === 'low') {
|
|
386
|
+
return { stop_retry: false, next_action: 'retry_or_clarify', reason: 'insufficient_retrieval_signal' };
|
|
387
|
+
}
|
|
388
|
+
return { stop_retry: true, next_action: 'answer', reason: 'default_stop' };
|
|
389
|
+
})();
|
|
389
390
|
return {
|
|
390
|
-
status,
|
|
391
|
-
confidence,
|
|
392
|
-
message: buildAgentMessage(
|
|
391
|
+
status: finalStatus,
|
|
392
|
+
confidence: finalConfidence,
|
|
393
|
+
message: buildAgentMessage(finalStatus, retrievalMode, pass.fragments, finalConfidence, pass.references, {
|
|
394
|
+
fabricationRisk,
|
|
395
|
+
hasDocuments: documents.length > 0,
|
|
396
|
+
hasCatalog: catalog.length > 0,
|
|
397
|
+
fullDocumentRequired,
|
|
398
|
+
preferDocuments: pass.fullDocumentMode,
|
|
399
|
+
hasAggregatedFragments: aggregatedFragments.length > 0,
|
|
400
|
+
}),
|
|
393
401
|
query: params,
|
|
402
|
+
retrieval_mode: retrievalMode,
|
|
403
|
+
documents,
|
|
404
|
+
catalog,
|
|
394
405
|
meta: {
|
|
395
406
|
pool_size: allChunks.length,
|
|
396
407
|
filtered_size: pass.pool.length,
|
|
@@ -404,10 +415,27 @@ export function searchKnowledge(params) {
|
|
|
404
415
|
...(queryApiTokens.length ? { query_api_tokens: queryApiTokens } : {}),
|
|
405
416
|
...(pass.missingApiTokens.length ? { missing_api_tokens: pass.missingApiTokens } : {}),
|
|
406
417
|
...(retryReason ? { retry_reason: retryReason } : {}),
|
|
418
|
+
...(retrievalMode === 'narrative' && narrativeState.source ? { narrative_source: narrativeState.source } : {}),
|
|
419
|
+
...(pass.preferredSource ? { preferred_source: pass.preferredSource } : {}),
|
|
420
|
+
...(pass.fullDocumentMode ? { full_document_mode: pass.fullDocumentMode } : {}),
|
|
421
|
+
coverage_report: coverageReport,
|
|
422
|
+
...(aggregatedFragments.length ? { aggregated_fragments: aggregatedFragments } : {}),
|
|
423
|
+
...(retrievalMode === 'narrative'
|
|
424
|
+
? {
|
|
425
|
+
narrative_completeness: {
|
|
426
|
+
is_complete: narrativeState.quality.isComplete,
|
|
427
|
+
score: narrativeState.quality.score,
|
|
428
|
+
section_count: narrativeState.quality.sectionCount,
|
|
429
|
+
total_chars: narrativeState.quality.totalChars,
|
|
430
|
+
reason: narrativeState.quality.reason,
|
|
431
|
+
},
|
|
432
|
+
}
|
|
433
|
+
: {}),
|
|
407
434
|
answer_contract: answerContract,
|
|
408
435
|
api_name_coverage: pass.apiNameCoverage,
|
|
409
436
|
fabrication_risk: fabricationRisk,
|
|
410
437
|
route_inconsistency_warning: routeInconsistencyWarning,
|
|
438
|
+
retry_advice: retryAdvice,
|
|
411
439
|
},
|
|
412
440
|
fragments: pass.fragments,
|
|
413
441
|
};
|