acp-kernel 0.0.12 → 0.0.14
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/dist/compress.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +319 -42
- package/dist/index.js.map +1 -1
- package/dist/protected.d.ts +21 -0
- package/dist/protected.d.ts.map +1 -1
- package/dist/recommend.d.ts.map +1 -1
- package/dist/search/algorithms/bm25.d.ts +15 -0
- package/dist/search/algorithms/bm25.d.ts.map +1 -0
- package/dist/search/algorithms/fuzzy.d.ts +14 -0
- package/dist/search/algorithms/fuzzy.d.ts.map +1 -0
- package/dist/search/algorithms/hybrid.d.ts +3 -0
- package/dist/search/algorithms/hybrid.d.ts.map +1 -0
- package/dist/search/algorithms/semantic.d.ts +37 -0
- package/dist/search/algorithms/semantic.d.ts.map +1 -0
- package/dist/search/algorithms/substring.d.ts +9 -0
- package/dist/search/algorithms/substring.d.ts.map +1 -0
- package/dist/search/index.d.ts +31 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/registry.d.ts +10 -0
- package/dist/search/registry.d.ts.map +1 -0
- package/dist/search/stemmer.d.ts +11 -0
- package/dist/search/stemmer.d.ts.map +1 -0
- package/dist/search/tokenizer.d.ts +17 -0
- package/dist/search/tokenizer.d.ts.map +1 -0
- package/dist/search/types.d.ts +92 -0
- package/dist/search/types.d.ts.map +1 -0
- package/dist/search.d.ts +5 -24
- package/dist/search.d.ts.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/compress.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../src/compress.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAcpB,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAEhB,MAAM,EAEN,WAAW,EAGX,iBAAiB,EAEjB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,KAAK;IACpB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CAAC;IACxD,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,sBAAsB,CAAC;IACvE,YAAY,IAAI,YAAY,EAAE,CAAC;IAC/B,UAAU,CACR,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,gBAAgB,GACtB,gBAAgB,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;IACnE,MAAM,CACJ,KAAK,EAAE,gBAAgB,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,YAAY,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,EAAE,CAAC;IACJ,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACnC;AAED,wBAAgB,UAAU,CAAC,KAAK,GAAE,KAAU,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../src/compress.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAcpB,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAEhB,MAAM,EAEN,WAAW,EAGX,iBAAiB,EAEjB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,KAAK;IACpB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CAAC;IACxD,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,sBAAsB,CAAC;IACvE,YAAY,IAAI,YAAY,EAAE,CAAC;IAC/B,UAAU,CACR,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,gBAAgB,GACtB,gBAAgB,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;IACnE,MAAM,CACJ,KAAK,EAAE,gBAAgB,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,YAAY,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,EAAE,CAAC;IACJ,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACnC;AAED,wBAAgB,UAAU,CAAC,KAAK,GAAE,KAAU,GAAG,eAAe,CAwN7D;AAwqBD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -25,8 +25,9 @@ export type { HideConsumedResult } from "./hide-consumed.js";
|
|
|
25
25
|
export { rebuildCompressionState } from "./rebuild.js";
|
|
26
26
|
export type { RebuildResult, RebuildPorts } from "./rebuild.js";
|
|
27
27
|
export { renderVisibleRefs, renderRefsNode } from "./render-refs.js";
|
|
28
|
-
export { searchBlocks } from "./search.js";
|
|
29
|
-
export type { SearchResult, SearchOptions } from "./search.js";
|
|
28
|
+
export { searchBlocks, searchBlocksAsync, blockDocs, messageDocs } from "./search.js";
|
|
29
|
+
export type { SearchResult, SearchOptions, SearchAlgorithm, AsyncSearchAlgorithm, AnySearchAlgorithm, SearchDoc, SearchDocKind, ScoredBlock, MessageRole, RoleWeights, MessageInput } from "./search.js";
|
|
30
|
+
export { DEFAULT_ALGORITHM, DEFAULT_ROLE_WEIGHTS, registerSearchAlgorithm, getSearchAlgorithm, listSearchAlgorithms } from "./search.js";
|
|
30
31
|
export { isMessageProtected, matchToolPattern } from "./protected.js";
|
|
31
32
|
export { runPipeline, makeIO, type PipelineNode, type PipelineContext, type NodeIO, type NodeEffects, } from "./pipeline.js";
|
|
32
33
|
export * from "./filter/index.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EACV,KAAK,EACL,eAAe,EACf,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,SAAS,EACT,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,EACT,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC3F,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAChE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC/H,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EACH,eAAe,EACf,6BAA6B,EAC7B,kBAAkB,EAClB,eAAe,EACf,2BAA2B,EAC3B,mBAAmB,GACtB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxG,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC5D,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -706,6 +706,14 @@ var renderRefsNode = {
|
|
|
706
706
|
|
|
707
707
|
// src/protected.ts
|
|
708
708
|
var ALWAYS_PROTECTED_TOOLS = ["compress"];
|
|
709
|
+
var NEVER_PRESERVE_RECENT_TOOLS = ["decompress", "search_context"];
|
|
710
|
+
function isNeverPreserveRecent(msg) {
|
|
711
|
+
if (msg.contentType !== "tool-call" && msg.contentType !== "tool-result") {
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
if (!msg.toolName) return false;
|
|
715
|
+
return NEVER_PRESERVE_RECENT_TOOLS.includes(msg.toolName);
|
|
716
|
+
}
|
|
709
717
|
function matchToolPattern(toolName, pattern) {
|
|
710
718
|
if (pattern.endsWith("*")) {
|
|
711
719
|
return toolName.startsWith(pattern.slice(0, -1));
|
|
@@ -802,6 +810,7 @@ function computeProtectedRefs(messages, state, config) {
|
|
|
802
810
|
const visible = [];
|
|
803
811
|
for (const msg of messages) {
|
|
804
812
|
if (isSyntheticOrPruned(msg, state)) continue;
|
|
813
|
+
if (isNeverPreserveRecent(msg)) continue;
|
|
805
814
|
const ref = state.messageRefs.byRaw[msg.id];
|
|
806
815
|
if (!ref || ref === "BLOCKED") continue;
|
|
807
816
|
visible.push({ ref, tokens: estimateMessageTokens(msg) });
|
|
@@ -946,6 +955,7 @@ function createCore(ports = {}) {
|
|
|
946
955
|
let blocksCreated = 0;
|
|
947
956
|
let tokensCompressed = 0;
|
|
948
957
|
const errors = [];
|
|
958
|
+
const warnings = [];
|
|
949
959
|
const protectedMessageIds = input.protectedMessageIds ?? computeProtectedRefs(input.messages, input.state, input.config);
|
|
950
960
|
const preExistingCoverage = collectCoverage(state);
|
|
951
961
|
const rangeIndexSets = [];
|
|
@@ -984,7 +994,8 @@ function createCore(ports = {}) {
|
|
|
984
994
|
tokensCompressed: 0,
|
|
985
995
|
errors: [
|
|
986
996
|
`content: range (${prev.spec.startRef}..${prev.spec.endRef}) overlaps (${curr.spec.startRef}..${curr.spec.endRef}). Overlapping ranges cannot be compressed in the same batch.`
|
|
987
|
-
]
|
|
997
|
+
],
|
|
998
|
+
warnings: []
|
|
988
999
|
}
|
|
989
1000
|
};
|
|
990
1001
|
}
|
|
@@ -1021,14 +1032,15 @@ function createCore(ports = {}) {
|
|
|
1021
1032
|
tokensCompressed: 0,
|
|
1022
1033
|
errors: [
|
|
1023
1034
|
`Total compressible content too small (${totalRangeChars} chars across ${input.ranges.length} range(s), min ${input.config.compress.minCompressRange}). Combine more messages into your range(s) to meet the threshold.`
|
|
1024
|
-
]
|
|
1035
|
+
],
|
|
1036
|
+
warnings: []
|
|
1025
1037
|
}
|
|
1026
1038
|
};
|
|
1027
1039
|
}
|
|
1028
1040
|
}
|
|
1029
1041
|
for (const spec of input.ranges) {
|
|
1030
1042
|
try {
|
|
1031
|
-
const
|
|
1043
|
+
const outcome = applySingleRange({
|
|
1032
1044
|
spec,
|
|
1033
1045
|
messages: input.messages,
|
|
1034
1046
|
state,
|
|
@@ -1039,7 +1051,8 @@ function createCore(ports = {}) {
|
|
|
1039
1051
|
preExistingCoverage
|
|
1040
1052
|
});
|
|
1041
1053
|
blocksCreated++;
|
|
1042
|
-
tokensCompressed +=
|
|
1054
|
+
tokensCompressed += outcome.tokens;
|
|
1055
|
+
warnings.push(...outcome.warnings);
|
|
1043
1056
|
} catch (error) {
|
|
1044
1057
|
errors.push(error instanceof Error ? error.message : String(error));
|
|
1045
1058
|
}
|
|
@@ -1051,7 +1064,7 @@ function createCore(ports = {}) {
|
|
|
1051
1064
|
state.nudge.lastNudgeShownTokens = 0;
|
|
1052
1065
|
state.nudge.lastShownByTier = {};
|
|
1053
1066
|
}
|
|
1054
|
-
return { state, result: { blocksCreated, tokensCompressed, errors } };
|
|
1067
|
+
return { state, result: { blocksCreated, tokensCompressed, errors, warnings } };
|
|
1055
1068
|
}
|
|
1056
1069
|
function processTurn(input) {
|
|
1057
1070
|
const configErrors = validateConfig(input.config);
|
|
@@ -1234,6 +1247,7 @@ var emergencyTruncateNode = {
|
|
|
1234
1247
|
}
|
|
1235
1248
|
};
|
|
1236
1249
|
function applySingleRange(input) {
|
|
1250
|
+
const warnings = [];
|
|
1237
1251
|
const resolved = resolveBoundaries({
|
|
1238
1252
|
startRef: input.spec.startRef,
|
|
1239
1253
|
endRef: input.spec.endRef,
|
|
@@ -1281,7 +1295,7 @@ function applySingleRange(input) {
|
|
|
1281
1295
|
const directMessageIds = [...effectiveMessageIds].filter(
|
|
1282
1296
|
(id) => !input.preExistingCoverage.has(id)
|
|
1283
1297
|
);
|
|
1284
|
-
|
|
1298
|
+
let filteredIds = filterProtectedToolMessages(
|
|
1285
1299
|
directMessageIds,
|
|
1286
1300
|
input.messages,
|
|
1287
1301
|
input.config
|
|
@@ -1292,12 +1306,22 @@ function applySingleRange(input) {
|
|
|
1292
1306
|
return ref !== void 0 && protectedRefs.has(ref);
|
|
1293
1307
|
}) : [];
|
|
1294
1308
|
if (hitProtectedRaw.length > 0) {
|
|
1295
|
-
const
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1309
|
+
const protectedSet = new Set(hitProtectedRaw);
|
|
1310
|
+
filteredIds = filteredIds.filter((id) => !protectedSet.has(id));
|
|
1311
|
+
for (const id of hitProtectedRaw) effectiveMessageIds.delete(id);
|
|
1312
|
+
const hitRefs = hitProtectedRaw.map((id) => input.state.messageRefs.byRaw[id]).filter((v) => typeof v === "string");
|
|
1313
|
+
if (filteredIds.length === 0 && consumedBlockIds.length === 0) {
|
|
1314
|
+
const recentN = input.config.preserveRecentMessages;
|
|
1315
|
+
throw new Error(
|
|
1316
|
+
`Range is entirely within the protected zone (the last ${recentN} messages and/or the most recent user message): ${hitRefs.join(
|
|
1317
|
+
", "
|
|
1318
|
+
)}. Adjust startId/endId to older messages.`
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
warnings.push(
|
|
1322
|
+
`Excluded ${hitProtectedRaw.length} protected message(s) ${hitRefs.join(
|
|
1299
1323
|
", "
|
|
1300
|
-
)}
|
|
1324
|
+
)} from compression range (recent/last-user zone).`
|
|
1301
1325
|
);
|
|
1302
1326
|
}
|
|
1303
1327
|
validateCompressionRange(input, filteredIds, consumedBlockIds.length);
|
|
@@ -1334,7 +1358,7 @@ function applySingleRange(input) {
|
|
|
1334
1358
|
const consumed = blockById(input.state, consumedId);
|
|
1335
1359
|
if (consumed) consumed.active = false;
|
|
1336
1360
|
}
|
|
1337
|
-
return compressedTokens;
|
|
1361
|
+
return { tokens: compressedTokens, warnings };
|
|
1338
1362
|
}
|
|
1339
1363
|
function applyToolPairAdjustment(resolved, messages) {
|
|
1340
1364
|
if (resolved.boundaryKind === "block") {
|
|
@@ -2370,44 +2394,291 @@ function extractRanges(input, callId) {
|
|
|
2370
2394
|
return ranges;
|
|
2371
2395
|
}
|
|
2372
2396
|
|
|
2373
|
-
// src/search.ts
|
|
2374
|
-
|
|
2397
|
+
// src/search/algorithms/substring.ts
|
|
2398
|
+
var substringAlgorithm = {
|
|
2399
|
+
name: "substring",
|
|
2400
|
+
description: "Exact substring counting (original baseline). Predictable, no normalization.",
|
|
2401
|
+
score(docs, query) {
|
|
2402
|
+
const terms = query.toLowerCase().trim().split(/\s+/).filter((t) => t.length > 0);
|
|
2403
|
+
if (terms.length === 0) return docs.map((d) => ({ ref: d.ref, score: 0 }));
|
|
2404
|
+
return docs.map((d) => {
|
|
2405
|
+
const haystack = d.text.toLowerCase();
|
|
2406
|
+
let score = 0;
|
|
2407
|
+
for (const term of terms) score += countOccurrences2(haystack, term);
|
|
2408
|
+
return { ref: d.ref, score };
|
|
2409
|
+
});
|
|
2410
|
+
}
|
|
2411
|
+
};
|
|
2412
|
+
function countOccurrences2(haystack, needle) {
|
|
2413
|
+
if (!needle) return 0;
|
|
2414
|
+
return haystack.split(needle).length - 1;
|
|
2415
|
+
}
|
|
2416
|
+
|
|
2417
|
+
// src/search/stemmer.ts
|
|
2418
|
+
function stem(word) {
|
|
2419
|
+
let w = word;
|
|
2420
|
+
if (w.length <= 3) return w;
|
|
2421
|
+
if (w.endsWith("ies")) w = w.slice(0, -3) + "y";
|
|
2422
|
+
else if (w.endsWith("ses") || w.endsWith("xes") || w.endsWith("zes")) w = w.slice(0, -2);
|
|
2423
|
+
else if (w.endsWith("ches") || w.endsWith("shes")) w = w.slice(0, -2);
|
|
2424
|
+
else if (w.endsWith("s") && !w.endsWith("ss")) w = w.slice(0, -1);
|
|
2425
|
+
if (w.endsWith("ing") && w.length > 5) w = w.slice(0, -3);
|
|
2426
|
+
if (w.endsWith("ed") && w.length > 4) w = w.slice(0, -2);
|
|
2427
|
+
if (w.endsWith("ation") && w.length > 6) w = w.slice(0, -3);
|
|
2428
|
+
else if (w.endsWith("tion") && w.length > 5) w = w.slice(0, -4) + "t";
|
|
2429
|
+
else if (w.endsWith("ion") && w.length > 4) w = w.slice(0, -3);
|
|
2430
|
+
if (w.endsWith("ment") && w.length > 6) w = w.slice(0, -4);
|
|
2431
|
+
if (w.endsWith("ness") && w.length > 6) w = w.slice(0, -4);
|
|
2432
|
+
if (w.endsWith("ly") && w.length > 4) w = w.slice(0, -2);
|
|
2433
|
+
return w;
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2436
|
+
// src/search/tokenizer.ts
|
|
2437
|
+
var CJK = /[\u3400-\u9fff\uf900-\ufaff\u3040-\u30ff\uac00-\ud7af]/;
|
|
2438
|
+
var CJK_RUN = new RegExp(`${CJK.source}+`, "g");
|
|
2439
|
+
var LATIN_WORD = /[a-z][a-z0-9_]*[a-z0-9]|[a-z0-9]/g;
|
|
2440
|
+
function tokenize(text, opts = {}) {
|
|
2441
|
+
const lower = text.toLowerCase();
|
|
2442
|
+
const tokens = [];
|
|
2443
|
+
const latin = lower.match(LATIN_WORD) ?? [];
|
|
2444
|
+
for (let w of latin) {
|
|
2445
|
+
if (w.length >= 2) {
|
|
2446
|
+
if (opts.stem) w = stem(w);
|
|
2447
|
+
tokens.push(w);
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
const cjkRuns = lower.match(CJK_RUN) ?? [];
|
|
2451
|
+
for (const run of cjkRuns) {
|
|
2452
|
+
if (run.length === 1) {
|
|
2453
|
+
tokens.push(run);
|
|
2454
|
+
} else {
|
|
2455
|
+
for (let i = 0; i < run.length - 1; i++) tokens.push(run.slice(i, i + 2));
|
|
2456
|
+
for (const ch of run) tokens.push(ch);
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
return tokens;
|
|
2460
|
+
}
|
|
2461
|
+
function charBigrams(text) {
|
|
2462
|
+
const grams = [];
|
|
2463
|
+
for (let i = 0; i < text.length - 1; i++) {
|
|
2464
|
+
const pair = text.slice(i, i + 2);
|
|
2465
|
+
if (pair.trim().length === pair.length) grams.push(pair);
|
|
2466
|
+
}
|
|
2467
|
+
return grams;
|
|
2468
|
+
}
|
|
2469
|
+
function tfMap(text, stem2) {
|
|
2470
|
+
const m = /* @__PURE__ */ new Map();
|
|
2471
|
+
for (const t of tokenize(text, { stem: stem2 })) m.set(t, (m.get(t) ?? 0) + 1);
|
|
2472
|
+
return m;
|
|
2473
|
+
}
|
|
2474
|
+
|
|
2475
|
+
// src/search/algorithms/bm25.ts
|
|
2476
|
+
var bm25Algorithm = {
|
|
2477
|
+
name: "bm25",
|
|
2478
|
+
description: "BM25 with stemming + CJK bigram tokenization. IR-standard relevance ranking.",
|
|
2479
|
+
score(docs, query) {
|
|
2480
|
+
const N = docs.length;
|
|
2481
|
+
const k1 = 1.2;
|
|
2482
|
+
const b = 0.75;
|
|
2483
|
+
const parsed = docs.map((d) => {
|
|
2484
|
+
const text = d.text;
|
|
2485
|
+
const tf = tfMap(text, true);
|
|
2486
|
+
let len = 0;
|
|
2487
|
+
for (const v of tf.values()) len += v;
|
|
2488
|
+
return { id: d.ref, tf, len };
|
|
2489
|
+
});
|
|
2490
|
+
const avgdl = parsed.reduce((s, d) => s + d.len, 0) / (N || 1);
|
|
2491
|
+
const qTerms = tokenize(query, { stem: true });
|
|
2492
|
+
if (qTerms.length === 0) return docs.map((d) => ({ ref: d.ref, score: 0 }));
|
|
2493
|
+
const idf = /* @__PURE__ */ new Map();
|
|
2494
|
+
for (const t of new Set(qTerms)) {
|
|
2495
|
+
let df = 0;
|
|
2496
|
+
for (const d of parsed) if (d.tf.has(t)) df++;
|
|
2497
|
+
idf.set(t, Math.log(1 + (N - df + 0.5) / (df + 0.5)));
|
|
2498
|
+
}
|
|
2499
|
+
return parsed.map((d) => {
|
|
2500
|
+
let score = 0;
|
|
2501
|
+
for (const t of qTerms) {
|
|
2502
|
+
const f = d.tf.get(t) ?? 0;
|
|
2503
|
+
if (f === 0) continue;
|
|
2504
|
+
const idfT = idf.get(t) ?? 0;
|
|
2505
|
+
score += idfT * (f * (k1 + 1)) / (f + k1 * (1 - b + b * d.len / (avgdl || 1)));
|
|
2506
|
+
}
|
|
2507
|
+
return { ref: d.id, score };
|
|
2508
|
+
});
|
|
2509
|
+
}
|
|
2510
|
+
};
|
|
2511
|
+
|
|
2512
|
+
// src/search/algorithms/fuzzy.ts
|
|
2513
|
+
var fuzzyAlgorithm = {
|
|
2514
|
+
name: "fuzzy",
|
|
2515
|
+
description: "Character bigram overlap. Typo-tolerant, script-agnostic, high recall.",
|
|
2516
|
+
score(docs, query) {
|
|
2517
|
+
const qTokens = query.toLowerCase().split(/[\s,]+/).filter((t) => t.length >= 4);
|
|
2518
|
+
if (qTokens.length === 0) return docs.map((d) => ({ ref: d.ref, score: 0 }));
|
|
2519
|
+
const qGrams = /* @__PURE__ */ new Set();
|
|
2520
|
+
for (const t of qTokens) for (const g of charBigrams(t)) qGrams.add(g);
|
|
2521
|
+
if (qGrams.size === 0) return docs.map((d) => ({ ref: d.ref, score: 0 }));
|
|
2522
|
+
return docs.map((d) => {
|
|
2523
|
+
const haystack = d.text.toLowerCase();
|
|
2524
|
+
const docGrams = new Set(charBigrams(haystack));
|
|
2525
|
+
let hits = 0;
|
|
2526
|
+
for (const g of qGrams) if (docGrams.has(g)) hits++;
|
|
2527
|
+
return { ref: d.ref, score: hits / qGrams.size };
|
|
2528
|
+
});
|
|
2529
|
+
}
|
|
2530
|
+
};
|
|
2531
|
+
|
|
2532
|
+
// src/search/algorithms/hybrid.ts
|
|
2533
|
+
var W_BM25 = 0.7;
|
|
2534
|
+
var W_FUZZY = 0.3;
|
|
2535
|
+
var hybridAlgorithm = {
|
|
2536
|
+
name: "hybrid",
|
|
2537
|
+
description: "Weighted BM25(stem) + fuzzy n-gram. Default \u2014 best precision + recall.",
|
|
2538
|
+
score(docs, query) {
|
|
2539
|
+
const bm = bm25Algorithm.score(docs, query);
|
|
2540
|
+
const fz = fuzzyAlgorithm.score(docs, query);
|
|
2541
|
+
const maxBm = Math.max(...bm.map((r) => r.score), 1e-9);
|
|
2542
|
+
const maxFz = Math.max(...fz.map((r) => r.score), 1e-9);
|
|
2543
|
+
const bmMap = new Map(bm.map((r) => [r.ref, r.score / maxBm]));
|
|
2544
|
+
const fzMap = new Map(fz.map((r) => [r.ref, r.score / maxFz]));
|
|
2545
|
+
return docs.map((d) => ({
|
|
2546
|
+
ref: d.ref,
|
|
2547
|
+
score: W_BM25 * (bmMap.get(d.ref) ?? 0) + W_FUZZY * (fzMap.get(d.ref) ?? 0)
|
|
2548
|
+
}));
|
|
2549
|
+
}
|
|
2550
|
+
};
|
|
2551
|
+
|
|
2552
|
+
// src/search/registry.ts
|
|
2553
|
+
var registry2 = /* @__PURE__ */ new Map();
|
|
2554
|
+
function registerSearchAlgorithm(algo) {
|
|
2555
|
+
registry2.set(algo.name, algo);
|
|
2556
|
+
}
|
|
2557
|
+
function getSearchAlgorithm(name) {
|
|
2558
|
+
return registry2.get(name);
|
|
2559
|
+
}
|
|
2560
|
+
function listSearchAlgorithms() {
|
|
2561
|
+
return [...registry2.values()];
|
|
2562
|
+
}
|
|
2563
|
+
registerSearchAlgorithm(substringAlgorithm);
|
|
2564
|
+
registerSearchAlgorithm(bm25Algorithm);
|
|
2565
|
+
registerSearchAlgorithm(fuzzyAlgorithm);
|
|
2566
|
+
registerSearchAlgorithm(hybridAlgorithm);
|
|
2567
|
+
|
|
2568
|
+
// src/search/types.ts
|
|
2569
|
+
var DEFAULT_ROLE_WEIGHTS = {
|
|
2570
|
+
user: 1.5,
|
|
2571
|
+
assistant: 1,
|
|
2572
|
+
tool: 0.6,
|
|
2573
|
+
block: 1
|
|
2574
|
+
};
|
|
2575
|
+
var DEFAULT_ALGORITHM = "hybrid";
|
|
2576
|
+
|
|
2577
|
+
// src/search/index.ts
|
|
2578
|
+
function blockDocs(state) {
|
|
2579
|
+
return state.blocks.map((b) => ({
|
|
2580
|
+
kind: "block",
|
|
2581
|
+
ref: b.blockId,
|
|
2582
|
+
text: `${b.topic ?? ""} ${b.summary ?? ""}`,
|
|
2583
|
+
title: b.topic ?? b.blockId,
|
|
2584
|
+
blockId: b.blockId,
|
|
2585
|
+
tier: b.tier ?? 1,
|
|
2586
|
+
tokens: b.compressedTokens
|
|
2587
|
+
}));
|
|
2588
|
+
}
|
|
2589
|
+
function messageDocs(msgs) {
|
|
2590
|
+
return msgs.map((m) => ({
|
|
2591
|
+
kind: "message",
|
|
2592
|
+
ref: m.ref,
|
|
2593
|
+
text: m.text,
|
|
2594
|
+
title: `${m.role}: ${m.text.slice(0, 60)}`,
|
|
2595
|
+
role: m.role,
|
|
2596
|
+
blockId: m.blockId,
|
|
2597
|
+
tier: m.tier,
|
|
2598
|
+
tokens: m.tokens
|
|
2599
|
+
}));
|
|
2600
|
+
}
|
|
2601
|
+
function applyRoleWeight(scored, docs, rw) {
|
|
2602
|
+
if (docs.length === 0) return scored;
|
|
2603
|
+
const docByRef = new Map(docs.map((d) => [d.ref, d]));
|
|
2604
|
+
return scored.map((s) => {
|
|
2605
|
+
const doc = docByRef.get(s.ref);
|
|
2606
|
+
if (!doc) return s;
|
|
2607
|
+
const w = doc.kind === "message" ? doc.role === "user" ? rw.user : doc.role === "assistant" ? rw.assistant : rw.tool : rw.block;
|
|
2608
|
+
return { ref: s.ref, score: s.score * w };
|
|
2609
|
+
});
|
|
2610
|
+
}
|
|
2611
|
+
function runSearch(docs, query, options) {
|
|
2375
2612
|
const limit = options.limit ?? 10;
|
|
2376
2613
|
const previewLength = options.previewLength ?? 200;
|
|
2377
|
-
const minScore = options.minScore ??
|
|
2378
|
-
const
|
|
2379
|
-
|
|
2380
|
-
const
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
const
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
blockId:
|
|
2393
|
-
tier:
|
|
2394
|
-
score,
|
|
2395
|
-
|
|
2396
|
-
preview: (
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2614
|
+
const minScore = options.minScore ?? 0.01;
|
|
2615
|
+
const algoName = options.algorithm ?? DEFAULT_ALGORITHM;
|
|
2616
|
+
const rw = { ...DEFAULT_ROLE_WEIGHTS, ...options.roleWeights };
|
|
2617
|
+
const algo = getSearchAlgorithm(algoName);
|
|
2618
|
+
if (!algo) return [];
|
|
2619
|
+
if (docs.length === 0) return [];
|
|
2620
|
+
const scoredOrPromise = algo.score(docs, query);
|
|
2621
|
+
const buildResults = (weighted) => {
|
|
2622
|
+
const byRef = new Map(docs.map((d) => [d.ref, d]));
|
|
2623
|
+
return weighted.map((s) => {
|
|
2624
|
+
const doc = byRef.get(s.ref);
|
|
2625
|
+
if (!doc) return null;
|
|
2626
|
+
return {
|
|
2627
|
+
kind: doc.kind,
|
|
2628
|
+
ref: doc.ref,
|
|
2629
|
+
blockId: doc.blockId,
|
|
2630
|
+
tier: doc.tier ?? 1,
|
|
2631
|
+
score: s.score,
|
|
2632
|
+
title: doc.title,
|
|
2633
|
+
preview: makePreview(doc.text, query, previewLength),
|
|
2634
|
+
role: doc.role,
|
|
2635
|
+
tokens: doc.tokens
|
|
2636
|
+
};
|
|
2637
|
+
}).filter((r) => r !== null && r.score >= minScore).sort((a, b) => b.score - a.score).slice(0, limit);
|
|
2638
|
+
};
|
|
2639
|
+
if (scoredOrPromise instanceof Promise) {
|
|
2640
|
+
return scoredOrPromise.then((raw) => buildResults(applyRoleWeight(raw, docs, rw)));
|
|
2400
2641
|
}
|
|
2401
|
-
|
|
2402
|
-
return scored.slice(0, limit);
|
|
2642
|
+
return buildResults(applyRoleWeight(scoredOrPromise, docs, rw));
|
|
2403
2643
|
}
|
|
2404
|
-
function
|
|
2405
|
-
|
|
2406
|
-
|
|
2644
|
+
function searchBlocks(docs, query, options = {}) {
|
|
2645
|
+
const result = runSearch(docs, query, options);
|
|
2646
|
+
if (result instanceof Promise) {
|
|
2647
|
+
throw new Error(
|
|
2648
|
+
`searchBlocks: algorithm "${options.algorithm ?? DEFAULT_ALGORITHM}" is async (e.g. semantic). Use searchBlocksAsync() instead.`
|
|
2649
|
+
);
|
|
2650
|
+
}
|
|
2651
|
+
return result;
|
|
2652
|
+
}
|
|
2653
|
+
async function searchBlocksAsync(docs, query, options = {}) {
|
|
2654
|
+
return await runSearch(docs, query, options);
|
|
2655
|
+
}
|
|
2656
|
+
function makePreview(text, query, len) {
|
|
2657
|
+
if (!text) return "";
|
|
2658
|
+
const terms = query.toLowerCase().trim().split(/\s+/).filter((t) => t.length > 1);
|
|
2659
|
+
if (terms.length === 0) return text.slice(0, len);
|
|
2660
|
+
const lower = text.toLowerCase();
|
|
2661
|
+
let hitIdx = -1;
|
|
2662
|
+
for (const term of terms) {
|
|
2663
|
+
const idx = lower.indexOf(term);
|
|
2664
|
+
if (idx >= 0) {
|
|
2665
|
+
hitIdx = idx;
|
|
2666
|
+
break;
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
if (hitIdx < 0) return text.slice(0, len);
|
|
2670
|
+
const half = Math.max(0, Math.floor(len / 2) - 10);
|
|
2671
|
+
const start = Math.max(0, hitIdx - half);
|
|
2672
|
+
const end = Math.min(text.length, start + len);
|
|
2673
|
+
const prefix = start > 0 ? "\u2026" : "";
|
|
2674
|
+
const suffix = end < text.length ? "\u2026" : "";
|
|
2675
|
+
return prefix + text.slice(start, end).trim() + suffix;
|
|
2407
2676
|
}
|
|
2408
2677
|
export {
|
|
2409
2678
|
BLOCKED_REF,
|
|
2410
2679
|
COMPRESS_PHILOSOPHY,
|
|
2680
|
+
DEFAULT_ALGORITHM,
|
|
2681
|
+
DEFAULT_ROLE_WEIGHTS,
|
|
2411
2682
|
HOW_TO_COMPRESS_RULES,
|
|
2412
2683
|
SUMMARY_HEADER,
|
|
2413
2684
|
TIER2_DISTILL_RULES,
|
|
@@ -2419,6 +2690,7 @@ export {
|
|
|
2419
2690
|
applyMessageFilters,
|
|
2420
2691
|
assignRefs,
|
|
2421
2692
|
blockById,
|
|
2693
|
+
blockDocs,
|
|
2422
2694
|
buildRecap,
|
|
2423
2695
|
buildRestoredContentPreview,
|
|
2424
2696
|
buildStatusReport,
|
|
@@ -2437,14 +2709,17 @@ export {
|
|
|
2437
2709
|
findBlocksOverlappingMessages,
|
|
2438
2710
|
formatRanges,
|
|
2439
2711
|
getMessageFilter,
|
|
2712
|
+
getSearchAlgorithm,
|
|
2440
2713
|
hideConsumedCompressCalls,
|
|
2441
2714
|
highestActiveTier,
|
|
2442
2715
|
highestUsedIndex,
|
|
2443
2716
|
indexToRef,
|
|
2444
2717
|
isMessageProtected,
|
|
2445
2718
|
listMessageFilters,
|
|
2719
|
+
listSearchAlgorithms,
|
|
2446
2720
|
makeIO,
|
|
2447
2721
|
matchToolPattern,
|
|
2722
|
+
messageDocs,
|
|
2448
2723
|
parseBlockIdArg,
|
|
2449
2724
|
parseBoundary,
|
|
2450
2725
|
prune,
|
|
@@ -2453,6 +2728,7 @@ export {
|
|
|
2453
2728
|
refForRaw,
|
|
2454
2729
|
refToIndex,
|
|
2455
2730
|
registerMessageFilter,
|
|
2731
|
+
registerSearchAlgorithm,
|
|
2456
2732
|
renderNudgeText,
|
|
2457
2733
|
renderRefsNode,
|
|
2458
2734
|
renderVisibleRefs,
|
|
@@ -2460,6 +2736,7 @@ export {
|
|
|
2460
2736
|
resolveKeepMarkers,
|
|
2461
2737
|
runPipeline,
|
|
2462
2738
|
searchBlocks,
|
|
2739
|
+
searchBlocksAsync,
|
|
2463
2740
|
syncBlocks,
|
|
2464
2741
|
truncateLargeToolOutputs,
|
|
2465
2742
|
validateConfig
|