@bodhi-ventures/aiocs 0.6.0 → 0.6.1
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.
|
@@ -4367,7 +4367,7 @@ async function startDaemon(input) {
|
|
|
4367
4367
|
// package.json
|
|
4368
4368
|
var package_default = {
|
|
4369
4369
|
name: "@bodhi-ventures/aiocs",
|
|
4370
|
-
version: "0.6.
|
|
4370
|
+
version: "0.6.1",
|
|
4371
4371
|
license: "MIT",
|
|
4372
4372
|
type: "module",
|
|
4373
4373
|
description: "Local-only documentation store, fetcher, and search CLI for AI agents.",
|
|
@@ -5439,6 +5439,63 @@ function overlapScore(queryTokens, candidate) {
|
|
|
5439
5439
|
}
|
|
5440
5440
|
return matches;
|
|
5441
5441
|
}
|
|
5442
|
+
function uniqueTokens(tokens) {
|
|
5443
|
+
return [...new Set(tokens)];
|
|
5444
|
+
}
|
|
5445
|
+
function hasTokenCoverage(requiredTokens, candidate) {
|
|
5446
|
+
if (requiredTokens.length === 0) {
|
|
5447
|
+
return false;
|
|
5448
|
+
}
|
|
5449
|
+
const candidateTokens = new Set(tokenize(candidate));
|
|
5450
|
+
return requiredTokens.every((token) => candidateTokens.has(token));
|
|
5451
|
+
}
|
|
5452
|
+
var NAVIGATIONAL_TERMS = /* @__PURE__ */ new Set([
|
|
5453
|
+
"api",
|
|
5454
|
+
"apis",
|
|
5455
|
+
"auth",
|
|
5456
|
+
"authentication",
|
|
5457
|
+
"docs",
|
|
5458
|
+
"documentation",
|
|
5459
|
+
"endpoint",
|
|
5460
|
+
"endpoints",
|
|
5461
|
+
"overview",
|
|
5462
|
+
"reference",
|
|
5463
|
+
"references",
|
|
5464
|
+
"rest",
|
|
5465
|
+
"sdk",
|
|
5466
|
+
"transport",
|
|
5467
|
+
"websocket",
|
|
5468
|
+
"ws"
|
|
5469
|
+
]);
|
|
5470
|
+
function classifyRetrievalQuery(query) {
|
|
5471
|
+
const queryTokens = uniqueTokens(tokenize(query));
|
|
5472
|
+
const matchedNavigationalTerms = uniqueTokens(queryTokens.filter((token) => NAVIGATIONAL_TERMS.has(token)));
|
|
5473
|
+
return {
|
|
5474
|
+
isNavigational: matchedNavigationalTerms.length > 0,
|
|
5475
|
+
queryTokens,
|
|
5476
|
+
routingTokens: queryTokens,
|
|
5477
|
+
matchedNavigationalTerms
|
|
5478
|
+
};
|
|
5479
|
+
}
|
|
5480
|
+
function scorePageCandidate(query, input) {
|
|
5481
|
+
const intent = classifyRetrievalQuery(query);
|
|
5482
|
+
const routingTokens = intent.routingTokens;
|
|
5483
|
+
const titleOverlap = overlapScore(routingTokens, input.pageTitle);
|
|
5484
|
+
const referenceOverlap = overlapScore(routingTokens, input.pageReference);
|
|
5485
|
+
const sectionOverlap = Math.max(0, ...input.sectionTitles.map((sectionTitle) => overlapScore(routingTokens, sectionTitle)));
|
|
5486
|
+
const exactTitleCoverage = hasTokenCoverage(routingTokens, input.pageTitle);
|
|
5487
|
+
const exactReferenceCoverage = hasTokenCoverage(routingTokens, input.pageReference);
|
|
5488
|
+
const lexicalWeight = intent.isNavigational ? 6 : 4;
|
|
5489
|
+
const vectorWeight = intent.isNavigational ? 1 : 3;
|
|
5490
|
+
const titleWeight = intent.isNavigational ? 8 : 4;
|
|
5491
|
+
const referenceWeight = intent.isNavigational ? 6 : 3;
|
|
5492
|
+
const sectionWeight = intent.isNavigational ? 4 : 2;
|
|
5493
|
+
const sourceHintWeight = intent.isNavigational ? 3 : 2;
|
|
5494
|
+
const commonLocationWeight = intent.isNavigational ? 7 : 4;
|
|
5495
|
+
const learningWeight = intent.isNavigational ? 5 : 4;
|
|
5496
|
+
const pureVectorPenalty = intent.isNavigational && input.bestLexicalScore === 0 && titleOverlap === 0 && referenceOverlap === 0 && input.commonLocationScore === 0 ? 8 : 0;
|
|
5497
|
+
return input.bestLexicalScore * lexicalWeight + input.bestVectorScore * vectorWeight + titleOverlap * titleWeight + referenceOverlap * referenceWeight + sectionOverlap * sectionWeight + input.sourceHintScore * sourceHintWeight + input.commonLocationScore * commonLocationWeight + input.learningScore * learningWeight + (exactTitleCoverage ? 12 : 0) + (exactReferenceCoverage ? 10 : 0) - pureVectorPenalty;
|
|
5498
|
+
}
|
|
5442
5499
|
function scoreLearning(query, learning) {
|
|
5443
5500
|
const queryTokens = tokenize(query);
|
|
5444
5501
|
const candidates = [learning.intent, ...learning.searchTerms];
|
|
@@ -5537,6 +5594,9 @@ function dedupePagesByIdentity(rows) {
|
|
|
5537
5594
|
}
|
|
5538
5595
|
return deduped;
|
|
5539
5596
|
}
|
|
5597
|
+
function pageIdentityKey(input) {
|
|
5598
|
+
return `${input.sourceId}::${input.snapshotId}::${input.filePath ?? input.pageUrl}`;
|
|
5599
|
+
}
|
|
5540
5600
|
function createCatalog() {
|
|
5541
5601
|
const dataDir = getAiocsDataDir();
|
|
5542
5602
|
getAiocsConfigDir();
|
|
@@ -5796,6 +5856,8 @@ async function retrieveContext(query, options) {
|
|
|
5796
5856
|
const avoidedPageKeys = new Set(
|
|
5797
5857
|
avoidedLearnings.map((learning) => `${learning.sourceId}::${learning.filePath ?? learning.pageUrl ?? ""}`)
|
|
5798
5858
|
);
|
|
5859
|
+
const sourceHintScores = /* @__PURE__ */ new Map();
|
|
5860
|
+
const commonLocationBoosts = /* @__PURE__ */ new Map();
|
|
5799
5861
|
const sourceHints = sourceScope.map((sourceId) => {
|
|
5800
5862
|
const contextRecord = catalog.getSourceContext(sourceId);
|
|
5801
5863
|
const score = scoreSourceContext(query, contextRecord.context);
|
|
@@ -5819,6 +5881,28 @@ async function retrieveContext(query, options) {
|
|
|
5819
5881
|
matchedCommonLocations
|
|
5820
5882
|
};
|
|
5821
5883
|
}).filter((entry) => Boolean(entry)).sort((left, right) => right.score - left.score || left.sourceId.localeCompare(right.sourceId));
|
|
5884
|
+
for (const sourceHint of sourceHints) {
|
|
5885
|
+
sourceHintScores.set(
|
|
5886
|
+
sourceHint.sourceId,
|
|
5887
|
+
Math.max(sourceHint.score, sourceHintScores.get(sourceHint.sourceId) ?? 0)
|
|
5888
|
+
);
|
|
5889
|
+
const latestSnapshotId = options.snapshot ?? catalog.getSourceById(sourceHint.sourceId)?.lastSuccessfulSnapshotId ?? null;
|
|
5890
|
+
if (!latestSnapshotId) {
|
|
5891
|
+
continue;
|
|
5892
|
+
}
|
|
5893
|
+
for (const location of sourceHint.matchedCommonLocations) {
|
|
5894
|
+
const key = pageIdentityKey({
|
|
5895
|
+
sourceId: sourceHint.sourceId,
|
|
5896
|
+
snapshotId: latestSnapshotId,
|
|
5897
|
+
pageUrl: location.url ?? "",
|
|
5898
|
+
filePath: location.filePath ?? null
|
|
5899
|
+
});
|
|
5900
|
+
commonLocationBoosts.set(
|
|
5901
|
+
key,
|
|
5902
|
+
Math.max(sourceHint.score, commonLocationBoosts.get(key) ?? 0)
|
|
5903
|
+
);
|
|
5904
|
+
}
|
|
5905
|
+
}
|
|
5822
5906
|
const search = await searchHybridCatalog({
|
|
5823
5907
|
catalog,
|
|
5824
5908
|
config: hybridConfig,
|
|
@@ -5847,21 +5931,100 @@ async function retrieveContext(query, options) {
|
|
|
5847
5931
|
pageUrl: result.pageUrl,
|
|
5848
5932
|
filePath: result.filePath
|
|
5849
5933
|
}));
|
|
5850
|
-
const
|
|
5934
|
+
const commonLocationPages = sourceHints.flatMap((sourceHint) => {
|
|
5935
|
+
const snapshotId = options.snapshot ?? catalog.getSourceById(sourceHint.sourceId)?.lastSuccessfulSnapshotId ?? "";
|
|
5936
|
+
if (!snapshotId) {
|
|
5937
|
+
return [];
|
|
5938
|
+
}
|
|
5939
|
+
return sourceHint.matchedCommonLocations.map((location) => ({
|
|
5940
|
+
sourceId: sourceHint.sourceId,
|
|
5941
|
+
snapshotId,
|
|
5942
|
+
pageUrl: location.url ?? "",
|
|
5943
|
+
filePath: location.filePath ?? null
|
|
5944
|
+
}));
|
|
5945
|
+
});
|
|
5946
|
+
const pageCandidates = dedupePagesByIdentity([
|
|
5947
|
+
...commonLocationPages,
|
|
5851
5948
|
...learnedPages,
|
|
5852
5949
|
...searchedPages
|
|
5853
|
-
]).
|
|
5854
|
-
const
|
|
5950
|
+
]).filter((entry) => !avoidedPageKeys.has(`${entry.sourceId}::${entry.filePath ?? entry.pageUrl}`));
|
|
5951
|
+
const searchPageSignals = /* @__PURE__ */ new Map();
|
|
5952
|
+
for (const result of search.results) {
|
|
5953
|
+
if (avoidedPageKeys.has(`${result.sourceId}::${result.filePath ?? result.pageUrl}`)) {
|
|
5954
|
+
continue;
|
|
5955
|
+
}
|
|
5956
|
+
const key = pageIdentityKey({
|
|
5957
|
+
sourceId: result.sourceId,
|
|
5958
|
+
snapshotId: result.snapshotId,
|
|
5959
|
+
pageUrl: result.pageUrl,
|
|
5960
|
+
filePath: result.filePath
|
|
5961
|
+
});
|
|
5962
|
+
const record = searchPageSignals.get(key) ?? {
|
|
5963
|
+
bestLexicalScore: 0,
|
|
5964
|
+
bestVectorScore: 0,
|
|
5965
|
+
sectionTitles: /* @__PURE__ */ new Set()
|
|
5966
|
+
};
|
|
5967
|
+
const signalCount = Math.max(1, result.signals.length);
|
|
5968
|
+
const perSignalScore = result.score / signalCount;
|
|
5969
|
+
if (result.signals.includes("lexical")) {
|
|
5970
|
+
record.bestLexicalScore = Math.max(record.bestLexicalScore, perSignalScore);
|
|
5971
|
+
}
|
|
5972
|
+
if (result.signals.includes("vector")) {
|
|
5973
|
+
record.bestVectorScore = Math.max(record.bestVectorScore, perSignalScore);
|
|
5974
|
+
}
|
|
5975
|
+
record.sectionTitles.add(result.sectionTitle);
|
|
5976
|
+
searchPageSignals.set(key, record);
|
|
5977
|
+
}
|
|
5978
|
+
const learningBoosts = /* @__PURE__ */ new Map();
|
|
5979
|
+
for (const learning of matchedLearnings) {
|
|
5980
|
+
if (!learning.pageUrl && !learning.filePath) {
|
|
5981
|
+
continue;
|
|
5982
|
+
}
|
|
5983
|
+
const snapshotId = learning.snapshotId ?? catalog.getSourceById(learning.sourceId)?.lastSuccessfulSnapshotId ?? "";
|
|
5984
|
+
if (!snapshotId) {
|
|
5985
|
+
continue;
|
|
5986
|
+
}
|
|
5987
|
+
const key = pageIdentityKey({
|
|
5988
|
+
sourceId: learning.sourceId,
|
|
5989
|
+
snapshotId,
|
|
5990
|
+
pageUrl: learning.pageUrl ?? "",
|
|
5991
|
+
filePath: learning.filePath ?? null
|
|
5992
|
+
});
|
|
5993
|
+
learningBoosts.set(key, Math.max(learning.score, learningBoosts.get(key) ?? 0));
|
|
5994
|
+
}
|
|
5995
|
+
const rankedPages = pageCandidates.flatMap((entry) => {
|
|
5855
5996
|
try {
|
|
5856
5997
|
const page = catalog.getPage({
|
|
5857
5998
|
sourceId: entry.sourceId,
|
|
5858
5999
|
snapshotId: entry.snapshotId,
|
|
5859
6000
|
...entry.filePath ? { filePath: entry.filePath } : { url: entry.pageUrl }
|
|
5860
6001
|
});
|
|
6002
|
+
const key = pageIdentityKey({
|
|
6003
|
+
sourceId: page.sourceId,
|
|
6004
|
+
snapshotId: page.snapshotId,
|
|
6005
|
+
pageUrl: page.page.url,
|
|
6006
|
+
filePath: page.page.filePath
|
|
6007
|
+
});
|
|
6008
|
+
const searchSignals = searchPageSignals.get(key) ?? {
|
|
6009
|
+
bestLexicalScore: 0,
|
|
6010
|
+
bestVectorScore: 0,
|
|
6011
|
+
sectionTitles: /* @__PURE__ */ new Set()
|
|
6012
|
+
};
|
|
6013
|
+
const score = scorePageCandidate(query, {
|
|
6014
|
+
pageTitle: page.page.title,
|
|
6015
|
+
pageReference: page.page.filePath ?? page.page.url,
|
|
6016
|
+
sectionTitles: [...searchSignals.sectionTitles],
|
|
6017
|
+
bestLexicalScore: searchSignals.bestLexicalScore,
|
|
6018
|
+
bestVectorScore: searchSignals.bestVectorScore,
|
|
6019
|
+
learningScore: learningBoosts.get(key) ?? 0,
|
|
6020
|
+
sourceHintScore: sourceHintScores.get(page.sourceId) ?? 0,
|
|
6021
|
+
commonLocationScore: commonLocationBoosts.get(key) ?? 0
|
|
6022
|
+
});
|
|
5861
6023
|
return [{
|
|
5862
6024
|
sourceId: page.sourceId,
|
|
5863
6025
|
snapshotId: page.snapshotId,
|
|
5864
|
-
|
|
6026
|
+
score,
|
|
6027
|
+
page: page.page
|
|
5865
6028
|
}];
|
|
5866
6029
|
} catch (error) {
|
|
5867
6030
|
if (error instanceof AiocsError && (error.code === AIOCS_ERROR_CODES.pageNotFound || error.code === AIOCS_ERROR_CODES.snapshotNotFound)) {
|
|
@@ -5869,7 +6032,12 @@ async function retrieveContext(query, options) {
|
|
|
5869
6032
|
}
|
|
5870
6033
|
throw error;
|
|
5871
6034
|
}
|
|
5872
|
-
});
|
|
6035
|
+
}).sort((left, right) => right.score - left.score || left.page.title.localeCompare(right.page.title) || left.page.url.localeCompare(right.page.url)).slice(0, Math.max(1, pageLimit));
|
|
6036
|
+
const pages = rankedPages.map((entry) => ({
|
|
6037
|
+
sourceId: entry.sourceId,
|
|
6038
|
+
snapshotId: entry.snapshotId,
|
|
6039
|
+
...entry.page
|
|
6040
|
+
}));
|
|
5873
6041
|
return {
|
|
5874
6042
|
query,
|
|
5875
6043
|
modeRequested: search.modeRequested,
|
package/dist/cli.js
CHANGED
package/dist/mcp-server.js
CHANGED