acp-kernel 0.0.13 → 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/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +284 -31
- package/dist/index.js.map +1 -1
- package/dist/protected.d.ts +4 -1
- package/dist/protected.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/package.json +1 -1
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,7 +706,7 @@ var renderRefsNode = {
|
|
|
706
706
|
|
|
707
707
|
// src/protected.ts
|
|
708
708
|
var ALWAYS_PROTECTED_TOOLS = ["compress"];
|
|
709
|
-
var NEVER_PRESERVE_RECENT_TOOLS = ["decompress"];
|
|
709
|
+
var NEVER_PRESERVE_RECENT_TOOLS = ["decompress", "search_context"];
|
|
710
710
|
function isNeverPreserveRecent(msg) {
|
|
711
711
|
if (msg.contentType !== "tool-call" && msg.contentType !== "tool-result") {
|
|
712
712
|
return false;
|
|
@@ -2394,44 +2394,291 @@ function extractRanges(input, callId) {
|
|
|
2394
2394
|
return ranges;
|
|
2395
2395
|
}
|
|
2396
2396
|
|
|
2397
|
-
// src/search.ts
|
|
2398
|
-
|
|
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) {
|
|
2399
2612
|
const limit = options.limit ?? 10;
|
|
2400
2613
|
const previewLength = options.previewLength ?? 200;
|
|
2401
|
-
const minScore = options.minScore ??
|
|
2402
|
-
const
|
|
2403
|
-
|
|
2404
|
-
const
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
const
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
blockId:
|
|
2417
|
-
tier:
|
|
2418
|
-
score,
|
|
2419
|
-
|
|
2420
|
-
preview: (
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
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)));
|
|
2424
2641
|
}
|
|
2425
|
-
|
|
2426
|
-
return scored.slice(0, limit);
|
|
2642
|
+
return buildResults(applyRoleWeight(scoredOrPromise, docs, rw));
|
|
2427
2643
|
}
|
|
2428
|
-
function
|
|
2429
|
-
|
|
2430
|
-
|
|
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;
|
|
2431
2676
|
}
|
|
2432
2677
|
export {
|
|
2433
2678
|
BLOCKED_REF,
|
|
2434
2679
|
COMPRESS_PHILOSOPHY,
|
|
2680
|
+
DEFAULT_ALGORITHM,
|
|
2681
|
+
DEFAULT_ROLE_WEIGHTS,
|
|
2435
2682
|
HOW_TO_COMPRESS_RULES,
|
|
2436
2683
|
SUMMARY_HEADER,
|
|
2437
2684
|
TIER2_DISTILL_RULES,
|
|
@@ -2443,6 +2690,7 @@ export {
|
|
|
2443
2690
|
applyMessageFilters,
|
|
2444
2691
|
assignRefs,
|
|
2445
2692
|
blockById,
|
|
2693
|
+
blockDocs,
|
|
2446
2694
|
buildRecap,
|
|
2447
2695
|
buildRestoredContentPreview,
|
|
2448
2696
|
buildStatusReport,
|
|
@@ -2461,14 +2709,17 @@ export {
|
|
|
2461
2709
|
findBlocksOverlappingMessages,
|
|
2462
2710
|
formatRanges,
|
|
2463
2711
|
getMessageFilter,
|
|
2712
|
+
getSearchAlgorithm,
|
|
2464
2713
|
hideConsumedCompressCalls,
|
|
2465
2714
|
highestActiveTier,
|
|
2466
2715
|
highestUsedIndex,
|
|
2467
2716
|
indexToRef,
|
|
2468
2717
|
isMessageProtected,
|
|
2469
2718
|
listMessageFilters,
|
|
2719
|
+
listSearchAlgorithms,
|
|
2470
2720
|
makeIO,
|
|
2471
2721
|
matchToolPattern,
|
|
2722
|
+
messageDocs,
|
|
2472
2723
|
parseBlockIdArg,
|
|
2473
2724
|
parseBoundary,
|
|
2474
2725
|
prune,
|
|
@@ -2477,6 +2728,7 @@ export {
|
|
|
2477
2728
|
refForRaw,
|
|
2478
2729
|
refToIndex,
|
|
2479
2730
|
registerMessageFilter,
|
|
2731
|
+
registerSearchAlgorithm,
|
|
2480
2732
|
renderNudgeText,
|
|
2481
2733
|
renderRefsNode,
|
|
2482
2734
|
renderVisibleRefs,
|
|
@@ -2484,6 +2736,7 @@ export {
|
|
|
2484
2736
|
resolveKeepMarkers,
|
|
2485
2737
|
runPipeline,
|
|
2486
2738
|
searchBlocks,
|
|
2739
|
+
searchBlocksAsync,
|
|
2487
2740
|
syncBlocks,
|
|
2488
2741
|
truncateLargeToolOutputs,
|
|
2489
2742
|
validateConfig
|