sweet-search 2.5.2 → 2.5.3
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/core/cli.js +24 -3
- package/core/graph/graph-expansion.js +215 -36
- package/core/graph/graph-extractor.js +196 -11
- package/core/graph/graph-search.js +395 -92
- package/core/graph/hcgs-generator.js +2 -1
- package/core/graph/index.js +2 -0
- package/core/graph/repo-map.js +28 -6
- package/core/graph/structural-answer-cues.js +168 -0
- package/core/graph/structural-callsite-hints.js +40 -0
- package/core/graph/structural-context-format.js +40 -0
- package/core/graph/structural-context.js +450 -0
- package/core/graph/structural-forward-push.js +156 -0
- package/core/graph/structural-header-context.js +19 -0
- package/core/graph/structural-importance.js +148 -0
- package/core/graph/structural-pagerank.js +197 -0
- package/core/graph/summary-manager.js +13 -9
- package/core/incremental-indexing/application/dirty-scan.mjs +236 -0
- package/core/incremental-indexing/application/file-watcher.mjs +197 -0
- package/core/incremental-indexing/application/maintenance-handlers.mjs +519 -0
- package/core/incremental-indexing/application/maintenance-worker.mjs +380 -0
- package/core/incremental-indexing/application/operator-cli.mjs +554 -0
- package/core/incremental-indexing/application/production-li-delta.mjs +192 -0
- package/core/incremental-indexing/application/production-reconciler-helpers.mjs +107 -0
- package/core/incremental-indexing/application/production-reconciler.mjs +583 -0
- package/core/incremental-indexing/application/reconciler.mjs +477 -0
- package/core/incremental-indexing/application/tombstone-injector.mjs +148 -0
- package/core/incremental-indexing/domain/chunk-identity.mjs +260 -0
- package/core/incremental-indexing/domain/encoder-deps.mjs +193 -0
- package/core/incremental-indexing/domain/encoder-input.mjs +225 -0
- package/core/incremental-indexing/domain/interval-autotune.mjs +255 -0
- package/core/incremental-indexing/domain/reconcile-counters.mjs +149 -0
- package/core/incremental-indexing/domain/watermark-scheduler.mjs +239 -0
- package/core/incremental-indexing/infrastructure/artifact-temp-sweep.mjs +163 -0
- package/core/incremental-indexing/infrastructure/baseline-readiness.mjs +121 -0
- package/core/incremental-indexing/infrastructure/dirty-set.mjs +233 -0
- package/core/incremental-indexing/infrastructure/graph-gc.mjs +314 -0
- package/core/incremental-indexing/infrastructure/hashing.mjs +298 -0
- package/core/incremental-indexing/infrastructure/hcgs-invalidation.mjs +182 -0
- package/core/incremental-indexing/infrastructure/li-segment-merge.mjs +278 -0
- package/core/incremental-indexing/infrastructure/li-segment-state.mjs +173 -0
- package/core/incremental-indexing/infrastructure/lockfile.mjs +119 -0
- package/core/incremental-indexing/infrastructure/maintenance-state-reader.mjs +283 -0
- package/core/incremental-indexing/infrastructure/manifest.mjs +194 -0
- package/core/incremental-indexing/infrastructure/path-filter.mjs +190 -0
- package/core/incremental-indexing/infrastructure/reader-heartbeat.mjs +201 -0
- package/core/incremental-indexing/infrastructure/schema-migrations.mjs +257 -0
- package/core/incremental-indexing/infrastructure/sparse-gram-delta.mjs +335 -0
- package/core/incremental-indexing/infrastructure/sqlite-fts5.mjs +176 -0
- package/core/incremental-indexing/infrastructure/staleness-display.mjs +105 -0
- package/core/incremental-indexing/infrastructure/tombstone-bitmap.mjs +234 -0
- package/core/incremental-indexing/infrastructure/vector-delta-writer.mjs +359 -0
- package/core/incremental-indexing/infrastructure/vector-gc.mjs +133 -0
- package/core/incremental-indexing/infrastructure/worktree-stamp.mjs +155 -0
- package/core/incremental-indexing/infrastructure/wsl2-detect.mjs +115 -0
- package/core/indexing/admission-policy.js +139 -0
- package/core/indexing/artifact-builder.js +29 -12
- package/core/indexing/ast-chunker.js +107 -30
- package/core/indexing/dedup/exemplar-selector.js +19 -1
- package/core/indexing/gitignore-filter.js +223 -0
- package/core/indexing/incremental-tracker.js +99 -30
- package/core/indexing/index-codebase-v21.js +6 -5
- package/core/indexing/index-maintainer.mjs +698 -6
- package/core/indexing/indexer-ann.js +99 -15
- package/core/indexing/indexer-build.js +158 -45
- package/core/indexing/indexer-empty-baseline.js +80 -0
- package/core/indexing/indexer-manifest.js +66 -0
- package/core/indexing/indexer-phases.js +56 -23
- package/core/indexing/indexer-sparse-gram.js +54 -13
- package/core/indexing/indexer-utils.js +26 -208
- package/core/indexing/indexing-file-policy.js +32 -7
- package/core/indexing/maintainer-launcher.mjs +137 -0
- package/core/indexing/merkle-tracker.js +251 -244
- package/core/indexing/model-pool.js +46 -5
- package/core/infrastructure/code-graph-repository.js +758 -6
- package/core/infrastructure/code-graph-visibility.js +157 -0
- package/core/infrastructure/codebase-repository.js +100 -13
- package/core/infrastructure/config/search.js +1 -1
- package/core/infrastructure/db-utils.js +118 -0
- package/core/infrastructure/dedup-hashing.js +10 -13
- package/core/infrastructure/hardware-capability.js +17 -7
- package/core/infrastructure/index.js +8 -2
- package/core/infrastructure/language-patterns/maps.js +4 -1
- package/core/infrastructure/language-patterns/registry-core.js +56 -17
- package/core/infrastructure/language-patterns/registry-object-oriented.js +12 -5
- package/core/infrastructure/language-patterns.js +69 -0
- package/core/infrastructure/model-registry.js +20 -0
- package/core/infrastructure/native-inference.js +7 -12
- package/core/infrastructure/native-resolver.js +52 -37
- package/core/infrastructure/native-sparse-gram.js +261 -20
- package/core/infrastructure/native-tokenizer.js +6 -15
- package/core/infrastructure/simd-distance.js +10 -16
- package/core/infrastructure/sparse-gram-delta-reader.js +76 -0
- package/core/infrastructure/structural-alias-resolver.js +122 -0
- package/core/infrastructure/structural-candidate-ranker.js +34 -0
- package/core/infrastructure/structural-context-repository.js +472 -0
- package/core/infrastructure/structural-context-utils.js +51 -0
- package/core/infrastructure/structural-graph-signals.js +121 -0
- package/core/infrastructure/structural-qualified-resolution.js +15 -0
- package/core/infrastructure/structural-source-definitions.js +100 -0
- package/core/infrastructure/tombstone-bitmap-reader.js +139 -0
- package/core/infrastructure/tree-sitter-provider.js +811 -37
- package/core/prompt-optimization/data/p7-final/sweet-search-system-prompt.md +50 -0
- package/core/query/query-router.js +55 -5
- package/core/ranking/file-kind-ranking.js +2192 -15
- package/core/ranking/late-interaction-index.js +87 -12
- package/core/search/cli-decoration.js +290 -0
- package/core/search/context-expander.js +988 -78
- package/core/search/index.js +1 -0
- package/core/search/output-policy.js +275 -0
- package/core/search/search-anchor.js +499 -0
- package/core/search/search-boost.js +93 -1
- package/core/search/search-cli.js +61 -204
- package/core/search/search-hybrid.js +250 -10
- package/core/search/search-pattern-chunks.js +57 -8
- package/core/search/search-pattern-planner.js +68 -9
- package/core/search/search-pattern-prefilter.js +30 -10
- package/core/search/search-pattern-ripgrep.js +40 -4
- package/core/search/search-pattern-sparse-overlay.js +256 -0
- package/core/search/search-pattern.js +117 -29
- package/core/search/search-postprocess.js +479 -5
- package/core/search/search-read-semantic.js +260 -23
- package/core/search/search-read.js +82 -64
- package/core/search/search-reader-pin.js +71 -0
- package/core/search/search-rrf.js +279 -0
- package/core/search/search-semantic.js +110 -5
- package/core/search/search-server.js +130 -57
- package/core/search/search-trace.js +107 -0
- package/core/search/server-identity.js +93 -0
- package/core/search/session-daemon-prewarm.mjs +33 -10
- package/core/search/sweet-search.js +399 -7
- package/core/skills/sweet-index/SKILL.md +8 -6
- package/core/vector-store/binary-hnsw-index.js +194 -30
- package/core/vector-store/float-vector-store.js +96 -6
- package/core/vector-store/hnsw-index.js +220 -49
- package/eval/agent-read-workflows/bin/_ss-helpers.mjs +471 -0
- package/eval/agent-read-workflows/bin/ss-find +15 -0
- package/eval/agent-read-workflows/bin/ss-grep +12 -0
- package/eval/agent-read-workflows/bin/ss-read +14 -0
- package/eval/agent-read-workflows/bin/ss-search +18 -0
- package/eval/agent-read-workflows/bin/ss-semantic +12 -0
- package/eval/agent-read-workflows/bin/ss-trace +11 -0
- package/mcp/read-tool.js +109 -0
- package/mcp/server.js +55 -15
- package/mcp/tool-handlers.js +14 -124
- package/mcp/trace-tool.js +81 -0
- package/package.json +25 -10
- package/scripts/hooks/intercept-read.mjs +55 -0
- package/scripts/hooks/remind-tools.mjs +40 -0
- package/scripts/init.js +698 -54
- package/scripts/inject-agent-instructions.js +431 -0
- package/scripts/install-prompt-reminders.js +188 -0
- package/scripts/install-tool-enforcement.js +220 -0
- package/scripts/smoke-test.js +12 -9
- package/scripts/uninstall.js +276 -18
- package/scripts/write-claude-rules.js +110 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
function escapeRegExp(text) {
|
|
2
|
+
return String(text).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function definitionPattern(name) {
|
|
6
|
+
const n = escapeRegExp(name);
|
|
7
|
+
return new RegExp([
|
|
8
|
+
`^\\s*(?:export\\s+)?(?:const|let|var)\\s+${n}\\b`,
|
|
9
|
+
`^\\s*(?:export\\s+)?(?:async\\s+)?function\\s+${n}\\s*\\(`,
|
|
10
|
+
`^\\s*(?:export\\s+)?(?:class|interface|enum|type)\\s+${n}\\b`,
|
|
11
|
+
`^\\s*(?:pub(?:\\([^)]*\\))?\\s+)?(?:const|static|fn|struct|enum|trait|type)\\s+${n}\\b`,
|
|
12
|
+
`^\\s*(?:const|var|type)\\s+${n}\\b`,
|
|
13
|
+
`^\\s*func\\s+(?:\\([^)]*\\)\\s+)?${n}\\s*\\(`,
|
|
14
|
+
`^\\s*(?:def|class)\\s+${n}\\s*[(:]`,
|
|
15
|
+
].join('|'));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function definitionType(line) {
|
|
19
|
+
if (/\b(const|static)\b/.test(line)) return 'const';
|
|
20
|
+
if (/\b(var|let)\b/.test(line)) return 'variable';
|
|
21
|
+
if (/\b(class|struct)\b/.test(line)) return 'class';
|
|
22
|
+
if (/\b(interface|trait)\b/.test(line)) return 'interface';
|
|
23
|
+
if (/\benum\b/.test(line)) return 'enum';
|
|
24
|
+
if (/\b(type)\b/.test(line)) return 'type';
|
|
25
|
+
return 'function';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function memberAssignmentPattern(name) {
|
|
29
|
+
const n = escapeRegExp(name);
|
|
30
|
+
return new RegExp([
|
|
31
|
+
`^\\s*(?:exports|module\\.exports|[A-Za-z_$][\\w$]*)(?:\\.prototype)?(?:\\.${n}|\\[['"]${n}['"]\\])\\s*=\\s*(?:async\\s+)?function(?:\\s+${n})?\\s*\\(`,
|
|
32
|
+
`^\\s*defineGetter\\([^,]+,\\s*['"]${n}['"]\\s*,\\s*function(?:\\s+${n})?\\s*\\(`,
|
|
33
|
+
].join('|'));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function findBlockEnd(lines, start) {
|
|
37
|
+
let depth = 0, seenBrace = false;
|
|
38
|
+
for (let i = start; i < lines.length; i++) {
|
|
39
|
+
for (const ch of lines[i]) {
|
|
40
|
+
if (ch === '{') { depth++; seenBrace = true; }
|
|
41
|
+
else if (ch === '}') depth--;
|
|
42
|
+
}
|
|
43
|
+
if (seenBrace && depth <= 0) return i + 1;
|
|
44
|
+
}
|
|
45
|
+
return start + 1;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function compactSnippet(lines, start, end) {
|
|
49
|
+
return lines.slice(start, Math.min(end, start + 4)).map(line => line.trim()).filter(Boolean).join(' ');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function findSameFileDefinition({ name, filePath, readFileRange }) {
|
|
53
|
+
if (!name || !filePath || !readFileRange) return null;
|
|
54
|
+
const text = readFileRange(filePath, 1, 20000);
|
|
55
|
+
if (!text) return null;
|
|
56
|
+
const re = definitionPattern(name);
|
|
57
|
+
const lines = text.split('\n');
|
|
58
|
+
const idx = lines.findIndex(line => re.test(line));
|
|
59
|
+
if (idx < 0) return null;
|
|
60
|
+
const end = findBlockEnd(lines, idx);
|
|
61
|
+
return {
|
|
62
|
+
id: `synthetic:def:${filePath}:${idx + 1}:${name}`,
|
|
63
|
+
name,
|
|
64
|
+
type: definitionType(lines[idx]),
|
|
65
|
+
filePath,
|
|
66
|
+
startLine: idx + 1,
|
|
67
|
+
endLine: end,
|
|
68
|
+
signature: lines[idx].trim(),
|
|
69
|
+
summary: compactSnippet(lines, idx, end),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function findAssignedMemberDefinitions({ name, files, readFileRange, limit = 12 }) {
|
|
74
|
+
if (!name || !files?.length || !readFileRange) return [];
|
|
75
|
+
const re = memberAssignmentPattern(name);
|
|
76
|
+
const out = [];
|
|
77
|
+
for (const filePath of files) {
|
|
78
|
+
const text = readFileRange(filePath, 1, 20000);
|
|
79
|
+
if (!text) continue;
|
|
80
|
+
const lines = text.split('\n');
|
|
81
|
+
const idx = lines.findIndex(line => re.test(line));
|
|
82
|
+
if (idx < 0) continue;
|
|
83
|
+
out.push({
|
|
84
|
+
id: `synthetic:member:${filePath}:${idx + 1}:${name}`,
|
|
85
|
+
name,
|
|
86
|
+
type: 'method',
|
|
87
|
+
filePath,
|
|
88
|
+
startLine: idx + 1,
|
|
89
|
+
endLine: findBlockEnd(lines, idx),
|
|
90
|
+
signature: lines[idx].trim(),
|
|
91
|
+
summary: 'Member assignment definition found from source text',
|
|
92
|
+
});
|
|
93
|
+
if (out.length >= limit) break;
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function findAssignedMemberDefinition(opts) {
|
|
99
|
+
return findAssignedMemberDefinitions(opts)[0] || null;
|
|
100
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tombstone bitmap helpers for query-time artifact filtering and soft-delete
|
|
3
|
+
* writers that live outside the incremental-indexing bounded context.
|
|
4
|
+
*
|
|
5
|
+
* The writer lives in the incremental-indexing bounded context. Runtime
|
|
6
|
+
* readers in ranking/vector-store cannot import that context without
|
|
7
|
+
* violating dependency direction, so this infrastructure module owns the
|
|
8
|
+
* stable on-disk bitmap layout used by those readers.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import fs from 'node:fs';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
|
|
14
|
+
const HEADER_MAGIC = Buffer.from('SSTB', 'ascii');
|
|
15
|
+
const HEADER_VERSION = 1;
|
|
16
|
+
const HEADER_RESERVED = 64;
|
|
17
|
+
const BITS_PER_BYTE = 8;
|
|
18
|
+
|
|
19
|
+
function payloadByteLength(capacityBits) {
|
|
20
|
+
const minBytes = Math.ceil(capacityBits / BITS_PER_BYTE);
|
|
21
|
+
return Math.ceil(minBytes / 64) * 64;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function createBitmap(capacityBits) {
|
|
25
|
+
if (!Number.isInteger(capacityBits) || capacityBits <= 0) {
|
|
26
|
+
throw new Error(`createBitmap: capacityBits must be a positive integer, got ${capacityBits}`);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
capacity: capacityBits,
|
|
30
|
+
payload: Buffer.alloc(payloadByteLength(capacityBits)),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function loadBitmap(filePath) {
|
|
35
|
+
if (!fs.existsSync(filePath)) return null;
|
|
36
|
+
const raw = fs.readFileSync(filePath);
|
|
37
|
+
if (raw.length < HEADER_RESERVED) {
|
|
38
|
+
throw new Error(`loadBitmap: ${filePath} too short (${raw.length} bytes)`);
|
|
39
|
+
}
|
|
40
|
+
if (!raw.subarray(0, 4).equals(HEADER_MAGIC)) {
|
|
41
|
+
throw new Error(`loadBitmap: ${filePath} magic mismatch`);
|
|
42
|
+
}
|
|
43
|
+
const version = raw.readUInt32LE(4);
|
|
44
|
+
if (version !== HEADER_VERSION) {
|
|
45
|
+
throw new Error(`loadBitmap: unsupported version ${version}`);
|
|
46
|
+
}
|
|
47
|
+
const capacity = Number(raw.readBigUInt64LE(8));
|
|
48
|
+
const expectedLength = HEADER_RESERVED + payloadByteLength(capacity);
|
|
49
|
+
if (raw.length < expectedLength) {
|
|
50
|
+
throw new Error(`loadBitmap: ${filePath} truncated payload (${raw.length} bytes, expected ${expectedLength})`);
|
|
51
|
+
}
|
|
52
|
+
const payload = raw.subarray(HEADER_RESERVED, HEADER_RESERVED + payloadByteLength(capacity));
|
|
53
|
+
return { capacity, payload: Buffer.from(payload) };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function saveBitmap(filePath, bitmap) {
|
|
57
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
58
|
+
const tmp = filePath + '.tmp';
|
|
59
|
+
const header = Buffer.alloc(HEADER_RESERVED);
|
|
60
|
+
HEADER_MAGIC.copy(header, 0);
|
|
61
|
+
header.writeUInt32LE(HEADER_VERSION, 4);
|
|
62
|
+
header.writeBigUInt64LE(BigInt(bitmap.capacity), 8);
|
|
63
|
+
const out = Buffer.concat([header, bitmap.payload]);
|
|
64
|
+
|
|
65
|
+
const fd = fs.openSync(tmp, 'w');
|
|
66
|
+
try {
|
|
67
|
+
fs.writeSync(fd, out);
|
|
68
|
+
fs.fsyncSync(fd);
|
|
69
|
+
} finally {
|
|
70
|
+
fs.closeSync(fd);
|
|
71
|
+
}
|
|
72
|
+
fs.renameSync(tmp, filePath);
|
|
73
|
+
try {
|
|
74
|
+
const dirFd = fs.openSync(path.dirname(filePath), 'r');
|
|
75
|
+
try { fs.fsyncSync(dirFd); } finally { fs.closeSync(dirFd); }
|
|
76
|
+
} catch {
|
|
77
|
+
// Best effort: some container/tmpfs filesystems reject directory fsync.
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function resizeBitmap(bitmap, newCapacityBits) {
|
|
82
|
+
if (newCapacityBits <= bitmap.capacity) return bitmap;
|
|
83
|
+
const fresh = Buffer.alloc(payloadByteLength(newCapacityBits));
|
|
84
|
+
bitmap.payload.copy(fresh, 0, 0, bitmap.payload.length);
|
|
85
|
+
bitmap.capacity = newCapacityBits;
|
|
86
|
+
bitmap.payload = fresh;
|
|
87
|
+
return bitmap;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function byteAndMask(index) {
|
|
91
|
+
const byte = index >>> 3;
|
|
92
|
+
const mask = 1 << (index & 7);
|
|
93
|
+
return { byte, mask };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function isSet(bitmap, index) {
|
|
97
|
+
if (!bitmap || index < 0 || index >= bitmap.capacity) return false;
|
|
98
|
+
const { byte, mask } = byteAndMask(index);
|
|
99
|
+
return (bitmap.payload[byte] & mask) !== 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function setBit(bitmap, index) {
|
|
103
|
+
if (index < 0 || index >= bitmap.capacity) {
|
|
104
|
+
throw new RangeError(`setBit: ${index} outside bitmap capacity ${bitmap.capacity}`);
|
|
105
|
+
}
|
|
106
|
+
const { byte, mask } = byteAndMask(index);
|
|
107
|
+
bitmap.payload[byte] |= mask;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function popcount(bitmap) {
|
|
111
|
+
if (!bitmap) return 0;
|
|
112
|
+
let count = 0;
|
|
113
|
+
const buf = bitmap.payload;
|
|
114
|
+
const fullBytes = Math.floor(bitmap.capacity / BITS_PER_BYTE);
|
|
115
|
+
const wordBytes = fullBytes - (fullBytes % 4);
|
|
116
|
+
for (let i = 0; i < wordBytes; i += 4) {
|
|
117
|
+
let x = buf.readUInt32LE(i);
|
|
118
|
+
while (x !== 0) {
|
|
119
|
+
x &= x - 1;
|
|
120
|
+
count += 1;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
for (let i = wordBytes; i < fullBytes; i++) {
|
|
124
|
+
let b = buf[i];
|
|
125
|
+
while (b !== 0) {
|
|
126
|
+
b &= b - 1;
|
|
127
|
+
count += 1;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const tailBits = bitmap.capacity % BITS_PER_BYTE;
|
|
131
|
+
if (tailBits > 0) {
|
|
132
|
+
let b = buf[fullBytes] & ((1 << tailBits) - 1);
|
|
133
|
+
while (b !== 0) {
|
|
134
|
+
b &= b - 1;
|
|
135
|
+
count += 1;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return count;
|
|
139
|
+
}
|