From e9ceee15fae8ef6bf0f25a51272ff3baa807794e Mon Sep 17 00:00:00 2001 From: Storme-bit Date: Tue, 18 Aug 2026 01:31:11 -0700 Subject: [PATCH] entity isolation and estimateTokenFix --- packages/orchestration-service/src/chat/index.js | 7 +++++-- packages/orchestration-service/src/services/qdrant.js | 8 ++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/orchestration-service/src/chat/index.js b/packages/orchestration-service/src/chat/index.js index fc8736a..fddb56b 100644 --- a/packages/orchestration-service/src/chat/index.js +++ b/packages/orchestration-service/src/chat/index.js @@ -177,8 +177,11 @@ function fuseEpisodeResults(semanticEps, keywordEps, { semanticWeight, keywordWe } function estimateTokens(episode) { - return episode.token_count - ?? Math.ceil((episode.user_message.length + episode.ai_response.length) / 4); + //NOTE: episode.token_count is not used here. It stores the + //full inference cost of that turn(prompt + injected memory + response), + //this inflate the episodes apparent size and starving the budget. + //Therefore, char/4 on the actual stored text is an honest selectedl + return Math.ceil((episode.user_message.length + episode.ai_response.length) / 4); } function buildScoredPool(fusedWithScores, recentEpisodes, entityBoostedIds, { entityWeight }) { diff --git a/packages/orchestration-service/src/services/qdrant.js b/packages/orchestration-service/src/services/qdrant.js index 7370dd6..33baa83 100644 --- a/packages/orchestration-service/src/services/qdrant.js +++ b/packages/orchestration-service/src/services/qdrant.js @@ -32,10 +32,18 @@ async function searchEpisodes( vector, {limit = ORCHESTRATION.RECENT_EPISODE_LIM async function searchEntities(vector, { limit = ORCHESTRATION.ENTITIES_LIMIT, scoreThreshold = ORCHESTRATION.ENTITIES_THRESHOLD, projectId = undefined } = {}) { const body = { vector, limit, score_threshold: scoreThreshold, with_payload: true }; + // non-project chats must also be filters to the "no project" pool if (projectId !== null && projectId !== undefined) { body.filter = { must: [{ key: 'projectId', match: { value: projectId } }] }; + } else { + //entities from project sessions carry a projectId; + //without this branch, a non-project chat searches ALL entities and project knowledge leaks into the common pool. + //is_empty matches null AND missing payload keys, so pre-isolation-era entities are covered too + body.filter = { + must: [{ is_empty: {key: 'projectId'} }] + } } const res = await fetch( `${BASE_URL}/collections/${COLLECTIONS.ENTITIES}/points/search`,