@maxgfr/codeindex 2.12.0 → 2.14.0
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/README.md +35 -11
- package/docs/MIGRATION.md +155 -36
- package/docs/SEMANTIC.md +12 -5
- package/package.json +1 -1
- package/scripts/engine.d.mts +49 -7
- package/scripts/engine.mjs +1233 -749
- package/src/ast/extract.ts +7 -5
- package/src/ast/grammars-pull.ts +178 -0
- package/src/ast/loader.ts +77 -15
- package/src/bm25.ts +16 -6
- package/src/callers.ts +0 -0
- package/src/complexity.ts +7 -1
- package/src/deadcode.ts +5 -4
- package/src/derived.ts +128 -0
- package/src/embed/model.ts +23 -14
- package/src/engine-cli.ts +307 -51
- package/src/engine.ts +21 -4
- package/src/extract/code.ts +9 -5
- package/src/hash.ts +5 -2
- package/src/lang/js-ts.ts +1 -1
- package/src/mcp.ts +220 -26
- package/src/pipeline.ts +16 -5
- package/src/query.ts +8 -5
- package/src/scan.ts +74 -8
- package/src/types.ts +6 -3
- package/src/walk.ts +41 -11
package/README.md
CHANGED
|
@@ -8,9 +8,8 @@ import resolution, a typed cross-file link-graph, and graph analytics — shippe
|
|
|
8
8
|
as a single zero-dependency `engine.mjs` that consumer tools **vendor** (copy
|
|
9
9
|
into their repo) instead of installing.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
ultraeval, reconstruct, construct, ultra11y).
|
|
11
|
+
Designed for downstream tools — agent skills, CLIs, CI gates — that vendor the
|
|
12
|
+
engine as a single file instead of taking an npm dependency.
|
|
14
13
|
|
|
15
14
|
## What it does
|
|
16
15
|
|
|
@@ -44,7 +43,28 @@ const { scan, graph, symbols } = buildIndexArtifacts("/path/to/repo");
|
|
|
44
43
|
|
|
45
44
|
The AST tier is optional: without a `grammars/` directory next to the bundle
|
|
46
45
|
the engine silently uses its regex tier. Only tools that want AST precision
|
|
47
|
-
|
|
46
|
+
also vendor `scripts/grammars/` (~17 MiB of wasm).
|
|
47
|
+
|
|
48
|
+
### Slim grammars (pull instead of vendor)
|
|
49
|
+
|
|
50
|
+
Consumers that want AST precision but not the ~17 MiB of vendored wasm can
|
|
51
|
+
`codeindex grammars pull` the grammars once into a shared, per-machine cache
|
|
52
|
+
(`<XDG_CACHE_HOME|~/.cache>/codeindex/grammars/<ENGINE_VERSION>`) instead:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
codeindex grammars status # active tier (adjacent/env/cache/none) + whether a pull is needed
|
|
56
|
+
codeindex grammars pull # fetch the per-release grammars asset, sha256-verified, into the cache
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Resolution is **adjacent > env > cache > regex**: a bundle-adjacent `grammars/`
|
|
60
|
+
still wins if present (offline setups are untouched), then
|
|
61
|
+
`CODEINDEX_GRAMMARS_DIR`, then the pulled cache. `pull` fetches the official
|
|
62
|
+
`grammars-<version>.tar.gz` release asset (its `.sha256` sidecar is verified
|
|
63
|
+
before anything is written) and extracts it atomically; the same wasm bytes
|
|
64
|
+
produce **byte-identical** AST extraction from the cache as from a vendored dir.
|
|
65
|
+
It is fully **offline-safe**: with no grammars resolvable anywhere — and after a
|
|
66
|
+
failed or absent pull — the engine silently falls back to the regex tier exactly
|
|
67
|
+
as it does today; a pull never throws into indexing.
|
|
48
68
|
|
|
49
69
|
## Use from npm
|
|
50
70
|
|
|
@@ -62,8 +82,8 @@ const scan = scanRepo("/path/to/repo");
|
|
|
62
82
|
```
|
|
63
83
|
|
|
64
84
|
The CLI ships in the same package — see **Use as a CLI** below for the global
|
|
65
|
-
install command.
|
|
66
|
-
bundle single-file and pinned to an exact commit without an npm dependency.
|
|
85
|
+
install command. Consumer tools should still prefer vendoring: it keeps their
|
|
86
|
+
own bundle single-file and pinned to an exact commit without an npm dependency.
|
|
67
87
|
|
|
68
88
|
## Use as a CLI
|
|
69
89
|
|
|
@@ -129,9 +149,13 @@ and the `embeddings.bin` artifact are byte-identical across builds and platforms
|
|
|
129
149
|
It is **opt-in by asset**: with no model on disk the engine silently stays
|
|
130
150
|
lexical, and `--semantic` without a model returns lexical results on **exit 0**
|
|
131
151
|
(a stderr note only). Models are **never** shipped in the package; a model is
|
|
132
|
-
resolved from `CODEINDEX_EMBED_DIR` or `<repo>/.codeindex/models/`.
|
|
152
|
+
resolved from `CODEINDEX_EMBED_DIR` or `<repo>/.codeindex/models/`. Getting one
|
|
153
|
+
is zero-config: `codeindex embed pull` fetches the official `embed-model-v1`
|
|
154
|
+
release asset, sha256-verified before anything is written.
|
|
133
155
|
|
|
134
156
|
```sh
|
|
157
|
+
codeindex embed pull --repo . # fetch the official model asset into
|
|
158
|
+
# CODEINDEX_EMBED_DIR (or <repo>/.codeindex/models/); sha256-verified
|
|
135
159
|
codeindex embed status --repo . # effective mode + reachability (JSON)
|
|
136
160
|
codeindex embed build --repo . --out .codeindex # write embeddings.bin
|
|
137
161
|
codeindex search "http client retry" --repo . --semantic
|
|
@@ -182,8 +206,8 @@ into their own CLIs); `cli.mjs` is the thin standalone CLI/MCP wrapper.
|
|
|
182
206
|
## Versioning
|
|
183
207
|
|
|
184
208
|
- `ENGINE_VERSION` — the release tag, embedded greppably in the bundle.
|
|
185
|
-
- `SCHEMA_VERSION` — the `graph.json`/`symbols.json` shape (
|
|
186
|
-
|
|
209
|
+
- `SCHEMA_VERSION` — the `graph.json`/`symbols.json` shape (currently 4).
|
|
210
|
+
Consumers reject mismatched artifacts.
|
|
187
211
|
- `EXTRACTOR_VERSION` — the extraction output shape; incremental caches keyed
|
|
188
212
|
on it are discarded wholesale when it bumps.
|
|
189
213
|
|
|
@@ -214,8 +238,8 @@ pnpm check:build # proves the committed bundle is byte-reproducible
|
|
|
214
238
|
pnpm test:e2e # opt-in: pinned real-repo builds with ratchets
|
|
215
239
|
```
|
|
216
240
|
|
|
217
|
-
The compat suite pins
|
|
218
|
-
|
|
241
|
+
The compat suite pins golden bytes for the `mini-repo` fixture — the proof
|
|
242
|
+
that extraction stays lossless across releases.
|
|
219
243
|
|
|
220
244
|
## License
|
|
221
245
|
|
package/docs/MIGRATION.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Migrating a
|
|
1
|
+
# Migrating a consumer tool onto the codeindex engine
|
|
2
2
|
|
|
3
3
|
The engine ships as two files, released together at every tag:
|
|
4
4
|
|
|
@@ -6,12 +6,12 @@ The engine ships as two files, released together at every tag:
|
|
|
6
6
|
- `scripts/engine.d.mts` — TypeScript declarations for the bundle
|
|
7
7
|
|
|
8
8
|
Consumers **vendor** them (commit a copy) — never an npm dependency — so every
|
|
9
|
-
|
|
9
|
+
consumer stays standalone-installable.
|
|
10
10
|
|
|
11
11
|
## Vendoring steps
|
|
12
12
|
|
|
13
|
-
1.
|
|
14
|
-
|
|
13
|
+
1. Add a small `scripts/sync-engine.mjs` to your repo (a ~50-line fetch script
|
|
14
|
+
with the behavior described below) and run:
|
|
15
15
|
|
|
16
16
|
```sh
|
|
17
17
|
node scripts/sync-engine.mjs --ref v1.0.0
|
|
@@ -40,8 +40,7 @@ skill stays standalone-installable.
|
|
|
40
40
|
|
|
41
41
|
The AST tier is optional: without a `grammars/` directory next to the vendored
|
|
42
42
|
bundle the engine uses its regex tier (15 languages). Only vendor
|
|
43
|
-
`scripts/grammars/` (~17 MiB wasm) if you need AST-exact symbols
|
|
44
|
-
does; nobody else should).
|
|
43
|
+
`scripts/grammars/` (~17 MiB wasm) if you need AST-exact symbols.
|
|
45
44
|
|
|
46
45
|
## Version constants
|
|
47
46
|
|
|
@@ -53,7 +52,7 @@ does; nobody else should).
|
|
|
53
52
|
|
|
54
53
|
`buildGraph(...)` / `buildIndexArtifacts(...)` accept
|
|
55
54
|
`meta: { version, schemaVersion }` so a consumer stamps its own identity into
|
|
56
|
-
artifacts it persists
|
|
55
|
+
artifacts it persists and keeps its own `graph.json` lineage.
|
|
57
56
|
|
|
58
57
|
## v2.9.0 — `search` trigram fuzzy fallback
|
|
59
58
|
|
|
@@ -93,39 +92,159 @@ embeddings live in a separate `embeddings.bin` sidecar keyed by a dedicated
|
|
|
93
92
|
`--semantic` without a model degrades to lexical results on **exit 0** (a stderr
|
|
94
93
|
note only) — so wiring it on is safe before an asset exists.
|
|
95
94
|
|
|
96
|
-
##
|
|
95
|
+
## v2.12.0 — two return-shape changes (check your call sites)
|
|
97
96
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
97
|
+
Not additive: two public return shapes changed in this release without a
|
|
98
|
+
compat flag, so a consumer re-pinning across v2.12.0 must check both call
|
|
99
|
+
sites. Artifact schemas are untouched (`SCHEMA_VERSION` / `EMBED_VERSION`
|
|
100
|
+
unchanged) — this is API shape only.
|
|
101
|
+
|
|
102
|
+
- `resolveEmbedPullUrl()` now returns an `EmbedPullTarget`
|
|
103
|
+
(`{ url: string; sha256?: string }`) — it previously returned
|
|
104
|
+
`string | undefined`. It always resolves: `CODEINDEX_EMBED_URL` wins
|
|
105
|
+
outright and carries **no** `sha256` (a custom mirror keeps the
|
|
106
|
+
un-verified behavior); with no env it falls back to the built-in official
|
|
107
|
+
asset **with** its pinned `sha256` so `embed pull` verifies the default
|
|
108
|
+
download. Replace `const url = resolveEmbedPullUrl()` with
|
|
109
|
+
`const { url, sha256 } = resolveEmbedPullUrl()`. The `EmbedPullTarget`
|
|
110
|
+
type is exported from the barrel.
|
|
111
|
+
- MCP `search` with `semantic: true` now returns
|
|
112
|
+
`{ results, tier, degradedReason? }` — it previously returned the bare
|
|
113
|
+
ranked array. `tier` is `"endpoint" | "static" | "lexical"` and
|
|
114
|
+
`degradedReason` is present only when the semantic tier degraded to
|
|
115
|
+
lexical, so a caller can tell "fusion happened" apart from "degraded".
|
|
116
|
+
Plain lexical `search` (no `semantic: true`) still returns the bare
|
|
117
|
+
array, byte-compatible with existing consumers.
|
|
118
|
+
|
|
119
|
+
## v2.13.0 — `.codeindex` excluded from the walk
|
|
120
|
+
|
|
121
|
+
`.codeindex/` — the engine's own output directory (index artifacts, pulled
|
|
122
|
+
models, MCP memories) — joined `IGNORE_DIRS`, so `walk`/`scanRepo` no longer
|
|
123
|
+
descend into it and memories stop entering BM25/embedding results (previously
|
|
124
|
+
every `write_memory` also churned the scan fingerprint, busting the MCP
|
|
125
|
+
server's memoized embedding index). Access memories through the MCP memory
|
|
126
|
+
tools (`read_memory` / `list_memories` / `delete_memory`), never `search`.
|
|
127
|
+
This is a file-set change only — extraction shape and `SCHEMA_VERSION` are
|
|
128
|
+
untouched, so **no re-pin is required**; a consumer that deliberately wants
|
|
129
|
+
`.codeindex` walked can pass `ignoreDirs` (replace semantics, also new in
|
|
130
|
+
this release) with its own set.
|
|
131
|
+
|
|
132
|
+
## v2.14.0 — incremental fastpaths (all additive, no re-pin required)
|
|
133
|
+
|
|
134
|
+
Pure fastpaths: every entry point still produces byte-identical artifacts for
|
|
135
|
+
unchanged inputs, so **no re-pin is required** and no consumer needs to act.
|
|
136
|
+
`SCHEMA_VERSION` / `EMBED_VERSION` / `EXTRACTOR_VERSION` are untouched; the new
|
|
137
|
+
surface is additive (semver-minor).
|
|
138
|
+
|
|
139
|
+
- **`RepoScan.contentUnchanged` / `RepoScan.cacheDirty` + `ScanOptions.precomputedWalk`.**
|
|
140
|
+
Two derived read-only flags: `contentUnchanged` is true when a `cache` was
|
|
141
|
+
supplied and every kept file reused its cached record (stat fastpath or exact
|
|
142
|
+
content-hash) with an unchanged file set; `cacheDirty` is true when persisting
|
|
143
|
+
the cache would change any byte (a hash/size/mtime drift, a file-set
|
|
144
|
+
difference, or no cache at all). `precomputedWalk` lets a caller that already
|
|
145
|
+
walked hand its `WalkResult` to `scanRepo` instead of re-walking — it must
|
|
146
|
+
come from `walk(root, <the same options>)`.
|
|
147
|
+
- **`buildArtifactsFromScan(scan, opts)` export.** The downstream half of
|
|
148
|
+
`buildIndexArtifacts` (resolve → graph → communities → centrality → symbol
|
|
149
|
+
index) split out as its own export; `buildIndexArtifacts` is now `scanRepo` +
|
|
150
|
+
this call. A consumer already holding a `RepoScan` builds artifacts without
|
|
151
|
+
re-walking; the extracted body is verbatim, so output is byte-identical.
|
|
152
|
+
- **`cache.json` additive meta keys.** Writes gain a fixed-order `meta` block —
|
|
153
|
+
`engineVersion`, `commit`, `graphSha1`, `symbolsSha1`, and `embed`
|
|
154
|
+
(`{ embedVersion, modelId, sha1 }`) only when `embeddings.bin` was written.
|
|
155
|
+
Old engines ignore these keys (they only check schema/extractor); an old cache
|
|
156
|
+
lacking them never fastpaths but still reuses records. `cache.json` embeds
|
|
157
|
+
mtimes so it never was cross-machine byte-reproducible — no determinism
|
|
158
|
+
surface changes.
|
|
159
|
+
- **CLI `index` fastpath.** `index` skips `buildArtifactsFromScan`, both renders
|
|
160
|
+
and every artifact write when a guard proves the run would reproduce the
|
|
161
|
+
on-disk bytes: `scan.contentUnchanged`, `meta.engineVersion` matches,
|
|
162
|
+
`meta.commit` matches the scan's commit (graph.json embeds the commit — an
|
|
163
|
+
identical tree under a new HEAD rebuilds), the sha1 of the on-disk
|
|
164
|
+
graph/symbols equals the recorded shas, and the embed leg holds (no model, or
|
|
165
|
+
the model's embedVersion+modelId and `embeddings.bin` sha match — a model swap
|
|
166
|
+
rebuilds the sidecar). Any failure — deleted, truncated or tampered artifacts
|
|
167
|
+
included — falls through to the full rebuild that rewrites everything, so the
|
|
168
|
+
fastpath self-heals on corruption; `cache.json` is rewritten on the fastpath
|
|
169
|
+
only when `scan.cacheDirty`.
|
|
170
|
+
- **MCP session scan + artifacts cache.** The long-lived server memoizes a
|
|
171
|
+
single scan and its artifacts across tool calls: `getScan` re-runs `scanRepo`
|
|
172
|
+
with the prior scan re-expressed as its `cache`, so scan.ts's stat/hash oracle
|
|
173
|
+
decides freshness and an unchanged repo returns the SAME `RepoScan` object,
|
|
174
|
+
while `getArtifacts` lazily runs `buildArtifactsFromScan` memoized on scan
|
|
175
|
+
object identity (rendered strings are never cached). Any successful edit tool
|
|
176
|
+
(`replace_symbol_body`, `insert_after_/insert_before_symbol`) drops the entry
|
|
177
|
+
— a controlled write landing in the same mtime tick at the same byte count
|
|
178
|
+
would fool the (size, mtime) fastpath; `write_memory` needs no invalidation
|
|
179
|
+
(`.codeindex/` is off the walk since v2.13.0).
|
|
180
|
+
- **`runMcpServer` serverInfo override.** `runMcpServer(opts?)` accepts
|
|
181
|
+
`{ serverInfo?: { name?, version? } }` so a consumer embedding the server
|
|
182
|
+
announces its own identity in the `initialize` response; omitted fields keep
|
|
183
|
+
the `{ name: "codeindex", version: ENGINE_VERSION }` defaults, the zero-arg
|
|
184
|
+
call is unchanged, and `McpServerOptions` is exported from the barrel.
|
|
185
|
+
- **Lazy grammar warm — covering-set guarantee.** The CLI and MCP server warm
|
|
186
|
+
only the grammars for languages actually present (`grammarKeysForExts` over
|
|
187
|
+
the walked extensions) rather than every grammar at startup. The walk's
|
|
188
|
+
extension set is a superset of what `scanRepo` keeps (scope/include/exclude
|
|
189
|
+
only filter further), so every extracted file has its grammar loaded before
|
|
190
|
+
extraction and AST output stays byte-identical — including a language whose
|
|
191
|
+
first file appears mid-session (the MCP warm re-derives per call). The
|
|
192
|
+
**pre-existing cache-tier caveat is unchanged**: a record reused by hash may
|
|
193
|
+
have been extracted under a different grammar tier.
|
|
194
|
+
- **Slim grammars-pull tier (`grammars pull` / `grammars status`).** The AST
|
|
195
|
+
wasm sidecar (`scripts/grammars/`, ~17 MiB) stays optional and opt-in by
|
|
196
|
+
presence, but a consumer that vendors only `engine.mjs` no longer has to
|
|
197
|
+
vendor the wasm to get AST-exact symbols. `resolveGrammarsTier` /
|
|
198
|
+
`resolveGrammarsDir` now resolve in order **adjacent > env > cache > regex**:
|
|
199
|
+
the bundle-adjacent `grammars/` dir wins if present (the offline, no-network
|
|
200
|
+
story is untouched), then `CODEINDEX_GRAMMARS_DIR`, then the shared
|
|
201
|
+
version-scoped cache `sharedGrammarsCacheDir()`
|
|
202
|
+
(`<XDG_CACHE_HOME|~/.cache>/codeindex/grammars/<ENGINE_VERSION>`), else nothing
|
|
203
|
+
resolvable → the regex tier exactly as today. `codeindex grammars pull`
|
|
204
|
+
fetches the per-release `grammars-<ENGINE_VERSION>.tar.gz` asset (built and
|
|
205
|
+
uploaded to the `v<ENGINE_VERSION>` tag by the release workflow) plus its
|
|
206
|
+
`.sha256` sidecar, verifies the digest, and extracts atomically into that
|
|
207
|
+
cache with a zero-dep inline ustar reader (path-traversal-guarded, no spawned
|
|
208
|
+
`tar`); it is idempotent (a matching marker skips the ~22 MB download) and
|
|
209
|
+
`CODEINDEX_GRAMMARS_URL` overrides the source (private mirror, unverified,
|
|
210
|
+
like the embed-pull precedent). `codeindex grammars status` reports the active
|
|
211
|
+
tier, resolved dir, pinned `ENGINE_VERSION`, and whether a pull is needed
|
|
212
|
+
(JSON). The **guarantee**: the same committed wasm bytes loaded from the cache
|
|
213
|
+
produce byte-identical AST extraction as from a bundle-adjacent dir (same wasm
|
|
214
|
+
→ same AST → same symbols), so `SCHEMA_VERSION` / `EXTRACTOR_VERSION` are
|
|
215
|
+
untouched and **no re-pin is required**. **Offline-safe**: `grammars pull`
|
|
216
|
+
never runs during indexing, and a failed/absent pull only ever leaves the
|
|
217
|
+
cache empty — it never throws into the scan, which silently uses the regex
|
|
218
|
+
tier. New exports: `resolveGrammarsTier`, `resolveGrammarsDir`,
|
|
219
|
+
`sharedGrammarsCacheDir`, `GrammarsTier` / `GrammarsTierName`,
|
|
220
|
+
`resolveGrammarsPullTarget`, `fetchGrammarsTarball`, `fetchExpectedSha256`,
|
|
221
|
+
`extractGrammarsTarball`, `GrammarsPullTarget`.
|
|
222
|
+
|
|
223
|
+
## Typical mapping (what to replace with what)
|
|
224
|
+
|
|
225
|
+
What a consumer usually deletes from its own codebase, and the engine export
|
|
226
|
+
that replaces it:
|
|
227
|
+
|
|
228
|
+
| Hand-rolled piece | Engine replacement |
|
|
229
|
+
|---|---|
|
|
230
|
+
| file walker + skip lists + gitignore parser | `walk` / `scanRepo` (gitignore on by default; `include`/`exclude`/`scope`) |
|
|
231
|
+
| extension→language map | `extToLang` / `languageOf` |
|
|
232
|
+
| per-language symbol/import/call regexes | `extractCode` / `extractSymbols` (`symbols`/`refs`/`calls`), `buildSymbolIndex` |
|
|
233
|
+
| import resolution (tsconfig paths, package `exports`, go.mod, Cargo…) | `buildResolveContext` + `resolveImport` |
|
|
234
|
+
| workspace/monorepo probing | `detectWorkspaces` (packages/dependsOn/cycle/topoOrder) |
|
|
235
|
+
| dependency/link graph construction | `buildGraph` + `resolveCallEdges` |
|
|
236
|
+
| grep with ripgrep + JS fallback | `grepRepo` |
|
|
237
|
+
| git churn / changed-files helpers | `gitChurn`, `changedSince` |
|
|
238
|
+
| language histogram, test detection | `scanRepo` (`.languages`) + `isTestPath` |
|
|
239
|
+
| caller lookup, precision-gated | `buildCallerIndex` (def-resolved and gated: language-family filter, JS/TS import gate, same-file self-declaration skip) |
|
|
240
|
+
| caller lookup, raw recall (e.g. taint-BFS input) | `buildRawCallerIndex` (issue #8) — every name-matched call site keyed by the raw callee name, no def resolution or gating, `enclosingSymbol` computed per site. `buildCallerIndex` is **NOT** a substitute here: its gates silently drop sites a recall consumer needs. Both are bounded by `FileRecord.calls`'s per-file 512-call cap (dedup by name+line) — a file with more raw call sites than that loses sites upstream of either function. |
|
|
241
|
+
|
|
242
|
+
What a consumer keeps is everything above the index: its own scoring,
|
|
243
|
+
rendering, retrieval and domain logic.
|
|
125
244
|
|
|
126
245
|
## Golden-diff adjudication (every migration)
|
|
127
246
|
|
|
128
|
-
Capture the
|
|
247
|
+
Capture the consumer's load-bearing artifact **before** touching code (a committed
|
|
129
248
|
snapshot test), migrate, then adjudicate every diff:
|
|
130
249
|
|
|
131
250
|
- **Accept + document**: file-set changes from better ignore rules (gitignore
|
package/docs/SEMANTIC.md
CHANGED
|
@@ -78,7 +78,7 @@ rows at one global scale. The download is **sha256-verified** against
|
|
|
78
78
|
`EMBED_ASSET_SHA256` (`src/embed/model.ts`) before it is written; a mismatch
|
|
79
79
|
fails the pull and writes nothing. The asset is **never** committed to git or
|
|
80
80
|
shipped in the npm tarball — it lives only in the release. Reproduce it
|
|
81
|
-
byte-for-byte with the pinned toolchain in [`scripts/embed-asset/`](
|
|
81
|
+
byte-for-byte with the pinned toolchain in [`scripts/embed-asset/`](https://github.com/maxgfr/codeindex/tree/main/scripts/embed-asset).
|
|
82
82
|
|
|
83
83
|
## CLI
|
|
84
84
|
|
|
@@ -110,13 +110,20 @@ codeindex search "http client retry" --repo <dir> --semantic
|
|
|
110
110
|
|
|
111
111
|
## Artifact: `embeddings.bin`
|
|
112
112
|
|
|
113
|
+
### Layout (the `deserializeEmbeddings` contract)
|
|
114
|
+
|
|
113
115
|
```
|
|
114
|
-
"CIE1"
|
|
115
|
-
uint32 LE
|
|
116
|
-
UTF-8 JSON header
|
|
117
|
-
int8 body
|
|
116
|
+
offset 0 "CIE1" 4-byte ASCII magic
|
|
117
|
+
offset 4 uint32 LE header length (headerLen)
|
|
118
|
+
offset 8 UTF-8 JSON header { embedVersion, modelId, dim, count, records:[{file,symbol,line}] }
|
|
119
|
+
offset 8+headerLen int8 body count × dim signed bytes (row-major)
|
|
118
120
|
```
|
|
119
121
|
|
|
122
|
+
This is exactly what `deserializeEmbeddings` (`src/embed/index.ts`) reads back:
|
|
123
|
+
it throws on a bad magic (a corrupt or foreign file fails loudly instead of
|
|
124
|
+
being misread), parses the JSON header, and slices the packed body at
|
|
125
|
+
`8 + headerLen`.
|
|
126
|
+
|
|
120
127
|
The header carries **no absolute path and no timestamp**; records follow scan
|
|
121
128
|
order (files sorted by `rel`, symbols in declaration order). Two builds of an
|
|
122
129
|
unchanged repo produce byte-identical `embeddings.bin`. A dedicated
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maxgfr/codeindex",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.14.0",
|
|
4
4
|
"description": "Self-contained, deterministic repo-indexing engine: walk + language detection + symbol/import extraction (tree-sitter AST with regex fallback) + import resolution + typed cross-file link-graph + analytics. Ships as a single zero-dependency engine.mjs that consumer tools vendor.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@10.33.0",
|
package/scripts/engine.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
declare const ENGINE_VERSION = "2.
|
|
1
|
+
declare const ENGINE_VERSION = "2.14.0";
|
|
2
2
|
declare const SCHEMA_VERSION = 4;
|
|
3
|
-
declare const EXTRACTOR_VERSION =
|
|
3
|
+
declare const EXTRACTOR_VERSION = 10;
|
|
4
4
|
type FileKind = "code" | "doc" | "config" | "asset" | "other";
|
|
5
5
|
type EdgeKind = "contains" | "doc-link" | "import" | "call" | "use" | "mention";
|
|
6
6
|
type Tier = 0 | 1 | 2;
|
|
@@ -121,6 +121,7 @@ interface WalkOptions {
|
|
|
121
121
|
maxFileBytes?: number;
|
|
122
122
|
maxFiles?: number;
|
|
123
123
|
gitignore?: boolean;
|
|
124
|
+
ignoreDirs?: string[];
|
|
124
125
|
}
|
|
125
126
|
interface WalkedFile {
|
|
126
127
|
rel: string;
|
|
@@ -147,14 +148,18 @@ interface RepoScan {
|
|
|
147
148
|
mtimes: Map<string, number>;
|
|
148
149
|
capped: boolean;
|
|
149
150
|
excluded: number;
|
|
151
|
+
contentUnchanged: boolean;
|
|
152
|
+
cacheDirty: boolean;
|
|
150
153
|
}
|
|
151
154
|
interface ScanOptions {
|
|
152
155
|
include?: string[];
|
|
153
156
|
exclude?: string[];
|
|
154
157
|
scope?: string;
|
|
155
158
|
gitignore?: boolean;
|
|
159
|
+
ignoreDirs?: string[];
|
|
156
160
|
maxBytes?: number;
|
|
157
161
|
maxFiles?: number;
|
|
162
|
+
maxCallsPerFile?: number;
|
|
158
163
|
out?: string;
|
|
159
164
|
cache?: Map<string, {
|
|
160
165
|
hash: string;
|
|
@@ -163,6 +168,7 @@ interface ScanOptions {
|
|
|
163
168
|
mtimeMs?: number;
|
|
164
169
|
}>;
|
|
165
170
|
fullHash?: boolean;
|
|
171
|
+
precomputedWalk?: WalkResult;
|
|
166
172
|
}
|
|
167
173
|
declare function scanRepo(root: string, opts?: ScanOptions): RepoScan;
|
|
168
174
|
|
|
@@ -202,7 +208,9 @@ interface CodeInfo {
|
|
|
202
208
|
}[];
|
|
203
209
|
importedNames?: string[];
|
|
204
210
|
}
|
|
205
|
-
declare function extractCode(rel: string, ext: string, content: string
|
|
211
|
+
declare function extractCode(rel: string, ext: string, content: string, opts?: {
|
|
212
|
+
maxCallsPerFile?: number;
|
|
213
|
+
}): CodeInfo;
|
|
206
214
|
|
|
207
215
|
interface MarkdownInfo {
|
|
208
216
|
title?: string;
|
|
@@ -213,8 +221,22 @@ interface MarkdownInfo {
|
|
|
213
221
|
declare function extractMarkdown(content: string): MarkdownInfo;
|
|
214
222
|
|
|
215
223
|
declare function grammarKeyForExt(ext: string): string | undefined;
|
|
224
|
+
type GrammarsTierName = "adjacent" | "env" | "cache" | "none";
|
|
225
|
+
interface GrammarsTier {
|
|
226
|
+
tier: GrammarsTierName;
|
|
227
|
+
dir?: string;
|
|
228
|
+
cacheDir: string;
|
|
229
|
+
}
|
|
230
|
+
declare function sharedGrammarsCacheDir(): string;
|
|
231
|
+
declare function resolveGrammarsTier(opts?: {
|
|
232
|
+
moduleDir?: string;
|
|
233
|
+
}): GrammarsTier;
|
|
234
|
+
declare function resolveGrammarsDir(opts?: {
|
|
235
|
+
moduleDir?: string;
|
|
236
|
+
}): string | undefined;
|
|
216
237
|
declare function ensureGrammars(keys: Iterable<string>): Promise<void>;
|
|
217
238
|
declare function allGrammarKeys(): string[];
|
|
239
|
+
declare function grammarKeysForExts(exts: Iterable<string>): string[];
|
|
218
240
|
declare function grammarReady(key: string): boolean;
|
|
219
241
|
|
|
220
242
|
interface AstResult {
|
|
@@ -229,7 +251,20 @@ interface AstResult {
|
|
|
229
251
|
}[];
|
|
230
252
|
importedNames: string[];
|
|
231
253
|
}
|
|
232
|
-
declare function extractAst(rel: string, ext: string, content: string
|
|
254
|
+
declare function extractAst(rel: string, ext: string, content: string, opts?: {
|
|
255
|
+
maxCalls?: number;
|
|
256
|
+
}): AstResult | undefined;
|
|
257
|
+
|
|
258
|
+
declare const DEFAULT_GRAMMARS_URL = "https://github.com/maxgfr/codeindex/releases/download/v2.14.0/grammars-2.14.0.tar.gz";
|
|
259
|
+
interface GrammarsPullTarget {
|
|
260
|
+
url: string;
|
|
261
|
+
sha256Url?: string;
|
|
262
|
+
}
|
|
263
|
+
declare function resolveGrammarsPullTarget(): GrammarsPullTarget;
|
|
264
|
+
declare function fetchGrammarsTarball(url: string, expectedSha256?: string): Promise<Uint8Array>;
|
|
265
|
+
declare function fetchExpectedSha256(url: string): Promise<string>;
|
|
266
|
+
declare function extractTarInto(rawTar: Uint8Array, destDir: string): string[];
|
|
267
|
+
declare function extractGrammarsTarball(bytes: Uint8Array, destDir: string): string[];
|
|
233
268
|
|
|
234
269
|
type Resolution = {
|
|
235
270
|
kind: "resolved";
|
|
@@ -442,6 +477,7 @@ interface IndexArtifacts {
|
|
|
442
477
|
symbols: SymbolIndex;
|
|
443
478
|
}
|
|
444
479
|
declare function buildIndexArtifacts(repo: string, opts?: BuildIndexOptions): IndexArtifacts;
|
|
480
|
+
declare function buildArtifactsFromScan(scan: RepoScan, opts?: BuildIndexOptions): IndexArtifacts;
|
|
445
481
|
|
|
446
482
|
declare function headCommit(dir: string): string | undefined;
|
|
447
483
|
interface DiffFile {
|
|
@@ -672,9 +708,15 @@ interface MermaidOptions {
|
|
|
672
708
|
}
|
|
673
709
|
declare function renderMermaid(graph: Graph, opts?: MermaidOptions): string;
|
|
674
710
|
|
|
675
|
-
|
|
711
|
+
interface McpServerOptions {
|
|
712
|
+
serverInfo?: {
|
|
713
|
+
name?: string;
|
|
714
|
+
version?: string;
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
declare function runMcpServer(opts?: McpServerOptions): Promise<void>;
|
|
676
718
|
|
|
677
|
-
declare function sha1(s: string): string;
|
|
719
|
+
declare function sha1(s: string | Uint8Array): string;
|
|
678
720
|
declare function shortHash(s: string, n?: number): string;
|
|
679
721
|
|
|
680
722
|
declare function byStr(a: string, b: string): number;
|
|
@@ -705,4 +747,4 @@ declare function rrf<T>(lists: T[][], keyOf: (item: T) => string, k?: number): M
|
|
|
705
747
|
|
|
706
748
|
declare function runCli(argv: string[]): Promise<void>;
|
|
707
749
|
|
|
708
|
-
export { type ArchRule, type BuildIndexOptions, type BuiltinRule, type CallerEntry, type CallerIndex, type CallerIndexOptions, type CallerSite, type ChangeCoupling, type CodeInfo, type CodeSymbol, type CouplingOptions, DEFAULT_MAX_FILES, type DeadSymbol, type DiffFile, type DiffSpec, EMBED_VERSION, ENGINE_VERSION, EXTRACTOR_VERSION, type Edge, type EdgeKind, type EditResult, type EmbedEndpointOptions, type EmbeddingIndex, type EmbeddingRecord, type EmbeddingUnit, type FileCategory, type FileKind, type FileNode, type FileRecord, type FindSymbolOptions, type ForbiddenEdgeRule, type Graph, type GrepOptions, type Hotspot, type Hunk, type IgnoreRule, type IndexArtifacts, MARKDOWN_EXT, type MarkdownInfo, type MermaidOptions, type ModuleInfo, type ModuleNode, type RawCallerIndex, type RawCallerSite, type RawRef, type RenderScipOptions, type RepoMapOptions, type RepoScan, type Resolution, type ResolveContext, type RiskHotspot, type RuleSeverity, type RuleViolation, SCHEMA_VERSION, type ScanOptions, type SearchHit, type SearchOptions, type SearchResult, type SemanticSearchOptions, type SemanticSearchResult, type ShResult, type StaticEmbedModel, type SurpriseEdge, type SymbolComplexity, type SymbolIndex, type SymbolMatch, type SymbolReferences, type TestMap, type Tier, type WalkOptions, type WalkResult, type WalkedFile, type WorkspaceInfo, type WorkspaceKind, type WorkspacePackage, allGrammarKeys, applyCentrality, basicTokenize, betweennessOf, buildCallerIndex, buildEmbeddingIndex, buildEndpointIndex, buildGraph, buildIndexArtifacts, buildModules, buildRawCallerIndex, buildResolveContext, buildSymbolIndex, byKey, byStr, categorize, changeCoupling, changedSince, checkRules, classify, clip, clipInline, communityOf, compileGlobs, complexityOfSource, computeImportPairs, computeSurprises, computeSymbolRefs, computeTestMap, deleteMemory, deserializeEmbeddings, detectCommunities, detectWorkspaces, diffFiles, diffHunks, embedEndpointUrl, embedViaEndpoint, embeddingUnits, enclosingSymbol, encode, encodeQueryViaEndpoint, ensureGrammars, escapeRegExp, extToLang, extractAst, extractCode, extractMarkdown, extractSymbols, findDeadCode, findReferences, findSymbol, foldText, gitChurn, grammarKeyForExt, grammarReady, grepRepo, hasEmbedModel, have, headCommit, healthzUrl, insertAfterSymbol, insertBeforeSymbol, intDot, isCode, isDoc, isGitWorktree, isIgnored, isSurprising, isTestFile, isTestPath, keywords, languageOf, listMemories, loadEmbedModel, pagerankOf, parseGitignore, parseRules, probeEndpoint, quantize, rankHotspots, rankedKeywords, readMemory, readText, renderGraphJson, renderMermaid, renderRepoMap, renderScip, renderSymbolsJson, replaceSymbolBody, resolveBaseRef, resolveCallEdges, resolveDocLink, resolveEmbedEndpoint, resolveEmbedModelDir, resolveEmbedPullUrl, resolveImport, resolveUniqueSymbol, riskHotspots, roundHalfToEven, rrf, runCli, runMcpServer, scanRepo, searchIndex, searchSemantic, serializeEmbeddings, sh, sha1, shortHash, slugify, subtokens, symbolComplexity, symbolsOverview, testsForModule, tierForPath, tokenize, uniqueSymbolDefs, untestedModules, untrackedFiles, walk, wordpiece, writeMemory };
|
|
750
|
+
export { type ArchRule, type BuildIndexOptions, type BuiltinRule, type CallerEntry, type CallerIndex, type CallerIndexOptions, type CallerSite, type ChangeCoupling, type CodeInfo, type CodeSymbol, type CouplingOptions, DEFAULT_GRAMMARS_URL, DEFAULT_MAX_FILES, type DeadSymbol, type DiffFile, type DiffSpec, EMBED_VERSION, ENGINE_VERSION, EXTRACTOR_VERSION, type Edge, type EdgeKind, type EditResult, type EmbedEndpointOptions, type EmbedPullTarget, type EmbeddingIndex, type EmbeddingRecord, type EmbeddingUnit, type FileCategory, type FileKind, type FileNode, type FileRecord, type FindSymbolOptions, type ForbiddenEdgeRule, type GrammarsPullTarget, type GrammarsTier, type GrammarsTierName, type Graph, type GrepOptions, type Hotspot, type Hunk, type IgnoreRule, type IndexArtifacts, MARKDOWN_EXT, type MarkdownInfo, type McpServerOptions, type MermaidOptions, type ModuleInfo, type ModuleNode, type RawCallerIndex, type RawCallerSite, type RawRef, type RenderScipOptions, type RepoMapOptions, type RepoScan, type Resolution, type ResolveContext, type RiskHotspot, type RuleSeverity, type RuleViolation, SCHEMA_VERSION, type ScanOptions, type SearchHit, type SearchOptions, type SearchResult, type SemanticSearchOptions, type SemanticSearchResult, type ShResult, type StaticEmbedModel, type SurpriseEdge, type SymbolComplexity, type SymbolIndex, type SymbolMatch, type SymbolReferences, type TestMap, type Tier, type WalkOptions, type WalkResult, type WalkedFile, type WorkspaceInfo, type WorkspaceKind, type WorkspacePackage, allGrammarKeys, applyCentrality, basicTokenize, betweennessOf, buildArtifactsFromScan, buildCallerIndex, buildEmbeddingIndex, buildEndpointIndex, buildGraph, buildIndexArtifacts, buildModules, buildRawCallerIndex, buildResolveContext, buildSymbolIndex, byKey, byStr, categorize, changeCoupling, changedSince, checkRules, classify, clip, clipInline, communityOf, compileGlobs, complexityOfSource, computeImportPairs, computeSurprises, computeSymbolRefs, computeTestMap, deleteMemory, deserializeEmbeddings, detectCommunities, detectWorkspaces, diffFiles, diffHunks, embedEndpointUrl, embedViaEndpoint, embeddingUnits, enclosingSymbol, encode, encodeQueryViaEndpoint, ensureGrammars, escapeRegExp, extToLang, extractAst, extractCode, extractGrammarsTarball, extractMarkdown, extractSymbols, extractTarInto, fetchExpectedSha256, fetchGrammarsTarball, findDeadCode, findReferences, findSymbol, foldText, gitChurn, grammarKeyForExt, grammarKeysForExts, grammarReady, grepRepo, hasEmbedModel, have, headCommit, healthzUrl, insertAfterSymbol, insertBeforeSymbol, intDot, isCode, isDoc, isGitWorktree, isIgnored, isSurprising, isTestFile, isTestPath, keywords, languageOf, listMemories, loadEmbedModel, pagerankOf, parseGitignore, parseRules, probeEndpoint, quantize, rankHotspots, rankedKeywords, readMemory, readText, renderGraphJson, renderMermaid, renderRepoMap, renderScip, renderSymbolsJson, replaceSymbolBody, resolveBaseRef, resolveCallEdges, resolveDocLink, resolveEmbedEndpoint, resolveEmbedModelDir, resolveEmbedPullUrl, resolveGrammarsDir, resolveGrammarsPullTarget, resolveGrammarsTier, resolveImport, resolveUniqueSymbol, riskHotspots, roundHalfToEven, rrf, runCli, runMcpServer, scanRepo, searchIndex, searchSemantic, serializeEmbeddings, sh, sha1, sharedGrammarsCacheDir, shortHash, slugify, subtokens, symbolComplexity, symbolsOverview, testsForModule, tierForPath, tokenize, uniqueSymbolDefs, untestedModules, untrackedFiles, walk, wordpiece, writeMemory };
|