@remnic/coding-graph 9.3.759
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 +130 -0
- package/dist/chunk-5I2DBHOQ.js +1042 -0
- package/dist/chunk-5I2DBHOQ.js.map +1 -0
- package/dist/chunk-CPYJACC5.js +1838 -0
- package/dist/chunk-CPYJACC5.js.map +1 -0
- package/dist/chunk-ZVCMIM4T.js +216 -0
- package/dist/chunk-ZVCMIM4T.js.map +1 -0
- package/dist/cypher/query-parser.d.ts +253 -0
- package/dist/cypher/query-parser.js +17 -0
- package/dist/cypher/query-parser.js.map +1 -0
- package/dist/graph-schema.d.ts +84 -0
- package/dist/graph-schema.js +17 -0
- package/dist/graph-schema.js.map +1 -0
- package/dist/graph-store.d.ts +938 -0
- package/dist/graph-store.js +16 -0
- package/dist/graph-store.js.map +1 -0
- package/dist/index.d.ts +1953 -0
- package/dist/index.js +3509 -0
- package/dist/index.js.map +1 -0
- package/grammars/tree-sitter-bash.wasm +0 -0
- package/grammars/tree-sitter-c.wasm +0 -0
- package/grammars/tree-sitter-c_sharp.wasm +0 -0
- package/grammars/tree-sitter-cpp.wasm +0 -0
- package/grammars/tree-sitter-go.wasm +0 -0
- package/grammars/tree-sitter-java.wasm +0 -0
- package/grammars/tree-sitter-javascript.wasm +0 -0
- package/grammars/tree-sitter-kotlin.wasm +0 -0
- package/grammars/tree-sitter-php.wasm +0 -0
- package/grammars/tree-sitter-python.wasm +0 -0
- package/grammars/tree-sitter-ruby.wasm +0 -0
- package/grammars/tree-sitter-rust.wasm +0 -0
- package/grammars/tree-sitter-swift.wasm +0 -0
- package/grammars/tree-sitter-tsx.wasm +0 -0
- package/grammars/tree-sitter-typescript.wasm +0 -0
- package/package.json +79 -0
- package/src/co-change.test.ts +175 -0
- package/src/co-change.ts +167 -0
- package/src/cypher/query-parser.test.ts +1107 -0
- package/src/cypher/query-parser.ts +1692 -0
- package/src/detect-changes.test.ts +533 -0
- package/src/detect-changes.ts +367 -0
- package/src/engine/emit.ts +556 -0
- package/src/engine/engine.test.ts +1417 -0
- package/src/engine/engine.ts +182 -0
- package/src/engine/extractors.ts +486 -0
- package/src/engine/fixtures.ts +364 -0
- package/src/engine/language-sniff.ts +56 -0
- package/src/engine/parser-backend.ts +206 -0
- package/src/engine/utf16-offsets.ts +68 -0
- package/src/git-invoker.test.ts +116 -0
- package/src/git-invoker.ts +426 -0
- package/src/graph-schema.test.ts +541 -0
- package/src/graph-schema.ts +383 -0
- package/src/graph-store-pr2.test.ts +1879 -0
- package/src/graph-store.test.ts +1420 -0
- package/src/graph-store.ts +3489 -0
- package/src/index-status.test.ts +303 -0
- package/src/index-status.ts +135 -0
- package/src/index.ts +384 -0
- package/src/lsp/byte-position.ts +173 -0
- package/src/lsp/characterization.test.ts +174 -0
- package/src/lsp/client.test.ts +275 -0
- package/src/lsp/client.ts +484 -0
- package/src/lsp/config.ts +219 -0
- package/src/lsp/degradation.ts +86 -0
- package/src/lsp/fixtures/fake-server.mjs +198 -0
- package/src/lsp/framing.test.ts +180 -0
- package/src/lsp/framing.ts +177 -0
- package/src/lsp/resolution.test.ts +497 -0
- package/src/lsp/resolution.ts +483 -0
- package/src/lsp/status.ts +140 -0
- package/src/lsp/types.ts +167 -0
- package/src/reindex.test.ts +1038 -0
- package/src/reindex.ts +908 -0
- package/src/row-types.ts +45 -0
- package/src/semantic/canonical-text.test.ts +150 -0
- package/src/semantic/canonical-text.ts +219 -0
- package/src/semantic/config.ts +235 -0
- package/src/semantic/index.ts +78 -0
- package/src/semantic/minhash.test.ts +197 -0
- package/src/semantic/minhash.ts +261 -0
- package/src/semantic/semantic-query.ts +173 -0
- package/src/semantic/semantic.test.ts +1315 -0
- package/src/semantic/similarity.ts +268 -0
- package/src/semantic/types.ts +145 -0
- package/src/semantic/vectors.ts +235 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @remnic/coding-graph — symbol-extraction engine + SQLite knowledge-graph
|
|
3
|
+
* store for codebase memory.
|
|
4
|
+
*
|
|
5
|
+
* À-la-carte optional companion of @remnic/core (CLAUDE.md rule 57).
|
|
6
|
+
*
|
|
7
|
+
* This package unifies two PR1 surfaces:
|
|
8
|
+
* - The web-tree-sitter engine scaffold (#1551 step 1): the package and
|
|
9
|
+
* its build wiring exist; the engine public surface is declared and
|
|
10
|
+
* the placeholder factory throws a tagged
|
|
11
|
+
* `CodingGraphError("not_implemented", …)`. The real backend lands in
|
|
12
|
+
* #1551 PR2.
|
|
13
|
+
* - The SQLite knowledge-graph store (#1552 PR1): versioned schema + the
|
|
14
|
+
* write pipeline (upsert/drop file batches, node-id derivation,
|
|
15
|
+
* dangling-edge accounting). Traversal, search, dead-code, and the
|
|
16
|
+
* openCypher subset land in #1552 PR2/PR3.
|
|
17
|
+
*
|
|
18
|
+
* Type-source direction:
|
|
19
|
+
* The contract types (CodingGraphEngine, FileIR, etc.) and the
|
|
20
|
+
* TIER_1_LANGUAGES / CODING_GRAPH_ENGINE_VERSION constants live in
|
|
21
|
+
* @remnic/core (packages/remnic-core/src/coding/coding-graph-types.ts,
|
|
22
|
+
* re-exported from the main index). This package imports them and
|
|
23
|
+
* implements against them; it does NOT redefine them. That keeps a
|
|
24
|
+
* single source of truth so updating the engine version in one place
|
|
25
|
+
* keeps every consumer in lockstep (Cursor Bugbot low-severity on
|
|
26
|
+
* PR #1588 round 2: "ENGINE_VERSION duplicated not imported").
|
|
27
|
+
*
|
|
28
|
+
* @remnic/coding-graph declares @remnic/core as both `peerDependencies`
|
|
29
|
+
* and `devDependencies: "workspace:*"` in its package.json, so the
|
|
30
|
+
* pnpm workspace link exists and the `import from "@remnic/core"`
|
|
31
|
+
* below resolves in development.
|
|
32
|
+
*
|
|
33
|
+
* The store modules (graph-schema, graph-store, row-types) are local to
|
|
34
|
+
* this package; they import `openBetterSqlite3` from
|
|
35
|
+
* `@remnic/core/runtime/better-sqlite` so the native-binding lifecycle
|
|
36
|
+
* is paid for once there (rule 23/38: do not invent a new pattern).
|
|
37
|
+
*
|
|
38
|
+
* IR-type re-export policy:
|
|
39
|
+
* graph-store.ts imports the core IR contract types (`FileIR`,
|
|
40
|
+
* `SymbolIR`, etc.) from `@remnic/core/coding/coding-graph-types`
|
|
41
|
+
* and re-exports them so existing `import { type FileIR } from
|
|
42
|
+
* "./graph-store.js"` call-sites continue to resolve. The store
|
|
43
|
+
* does NOT redefine these types — it derives from the core contract
|
|
44
|
+
* so PR2 callers can pass `ParseResult.ir` directly
|
|
45
|
+
* (chatgpt-codex-connector P2: 'Derive store FileIR from the core
|
|
46
|
+
* parser contract'). At the package root, `FileIR`/`SymbolIR`
|
|
47
|
+
* resolve to the @remnic/core contract types re-exported below;
|
|
48
|
+
* the store-specific `StoreFileIR` (FileIR + edges extension) and
|
|
49
|
+
* `EdgeIR` are re-exported from the root via graph-store.
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
import {
|
|
53
|
+
CODING_GRAPH_ENGINE_VERSION,
|
|
54
|
+
TIER_1_LANGUAGES,
|
|
55
|
+
type CodingGraphEngine,
|
|
56
|
+
type CodingGraphErrorCode,
|
|
57
|
+
type CodingGraphLanguage,
|
|
58
|
+
type CreateCodingGraphEngineOptions,
|
|
59
|
+
type FileIR,
|
|
60
|
+
type ParseFileInput,
|
|
61
|
+
type ParseResult,
|
|
62
|
+
type SymbolIR,
|
|
63
|
+
} from "@remnic/core";
|
|
64
|
+
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Engine version — single source of truth lives in @remnic/core as
|
|
67
|
+
// `CODING_GRAPH_ENGINE_VERSION`. We re-export it under the conventional
|
|
68
|
+
// `ENGINE_VERSION` name (the dynamic-import loader in @remnic/core
|
|
69
|
+
// validates the shape using this field name) AND keep the core alias
|
|
70
|
+
// available so any consumer that wants the local name or the core
|
|
71
|
+
// name gets the same value. Updating the constant in core propagates
|
|
72
|
+
// here automatically.
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
/** Public engine version. Imported from @remnic/core (single source of truth). */
|
|
76
|
+
export const ENGINE_VERSION = CODING_GRAPH_ENGINE_VERSION;
|
|
77
|
+
|
|
78
|
+
/** Core-alias re-export so callers can use either name. */
|
|
79
|
+
export { CODING_GRAPH_ENGINE_VERSION };
|
|
80
|
+
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Tier-1 language list re-export. The list itself lives in @remnic/core
|
|
83
|
+
// (single source of truth) so consumers that reach the optional package
|
|
84
|
+
// via the loader get the same shape they would get from core directly.
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
export { TIER_1_LANGUAGES };
|
|
87
|
+
export type { CodingGraphLanguage };
|
|
88
|
+
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// Tagged error — `code` is the load-bearing signal for programmatic
|
|
91
|
+
// detection (see PR2 contract).
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
export type { CodingGraphErrorCode } from "@remnic/core";
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Thrown by `createCodingGraphEngine` while the real implementation is
|
|
98
|
+
* being landed. It is *not* a generic Error — the `code` field is the
|
|
99
|
+
* load-bearing signal for programmatic detection (see PR2 contract).
|
|
100
|
+
*/
|
|
101
|
+
export class CodingGraphError extends Error {
|
|
102
|
+
readonly code: CodingGraphErrorCode;
|
|
103
|
+
readonly engineVersion: string;
|
|
104
|
+
|
|
105
|
+
constructor(
|
|
106
|
+
code: CodingGraphErrorCode,
|
|
107
|
+
message: string,
|
|
108
|
+
engineVersion: string = ENGINE_VERSION,
|
|
109
|
+
) {
|
|
110
|
+
super(message);
|
|
111
|
+
this.name = "CodingGraphError";
|
|
112
|
+
this.code = code;
|
|
113
|
+
this.engineVersion = engineVersion;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// Engine implementation (PR2): WASM tree-sitter parser + tier-1 extractors.
|
|
119
|
+
// Delegates to ./engine/engine.js which wires the ParserBackend, per-language
|
|
120
|
+
// .scm queries, and the FileIR emitter.
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
|
|
123
|
+
export { createCodingGraphEngine } from "./engine/engine.js";
|
|
124
|
+
|
|
125
|
+
// Backwards-compat: re-export the engine module's internal types for any
|
|
126
|
+
// consumer that reached into the implementation.
|
|
127
|
+
export type { ParserBackend } from "./engine/parser-backend.js";
|
|
128
|
+
export { WasmTreeSitterBackend } from "./engine/parser-backend.js";
|
|
129
|
+
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
// Re-export the contract types so the public surface is stable whether a
|
|
132
|
+
// consumer reaches into @remnic/coding-graph or @remnic/core. `export type`
|
|
133
|
+
// guarantees these are erased at runtime — no double-emit.
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
export type {
|
|
137
|
+
CodingGraphEngine,
|
|
138
|
+
CreateCodingGraphEngineOptions,
|
|
139
|
+
FileIR,
|
|
140
|
+
ParseFileInput,
|
|
141
|
+
ParseResult,
|
|
142
|
+
SymbolIR,
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
// SQLite knowledge-graph store (#1552 PR1 + PR2): versioned schema, write
|
|
147
|
+
// pipeline, and PR2 read primitives (traverse / searchGraph / schemaStats /
|
|
148
|
+
// deadCode / snippetFor). Re-exported from the package root so consumers
|
|
149
|
+
// can import `import { GraphStore } from "@remnic/coding-graph"` (the
|
|
150
|
+
// subpath exports `./graph-schema` and `./graph-store` remain available
|
|
151
|
+
// for callers that want only one half). Only non-colliding store types
|
|
152
|
+
// are re-exported here — see the file header's IR-type policy note.
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
|
|
155
|
+
export {
|
|
156
|
+
CODING_GRAPH_SCHEMA_VERSION,
|
|
157
|
+
EDGE_PROVENANCE_VALUES,
|
|
158
|
+
applyCodingGraphSchema,
|
|
159
|
+
readSchemaVersion,
|
|
160
|
+
isEdgeProvenance,
|
|
161
|
+
type EdgeProvenance,
|
|
162
|
+
} from "./graph-schema.js";
|
|
163
|
+
|
|
164
|
+
export {
|
|
165
|
+
GraphStore,
|
|
166
|
+
nodeIdFor,
|
|
167
|
+
DEFAULT_TRAVERSE_PATHS_MAX,
|
|
168
|
+
MAX_TRAVERSE_PATHS_HOPS,
|
|
169
|
+
DEAD_CODE_EXCLUSION,
|
|
170
|
+
type ByteSpan,
|
|
171
|
+
type DeadCodeHit,
|
|
172
|
+
type DeadCodeResult,
|
|
173
|
+
type EdgeIR,
|
|
174
|
+
type ExportIR,
|
|
175
|
+
type GraphStoreFailure,
|
|
176
|
+
type GraphStoreFailureCode,
|
|
177
|
+
type GraphStoreOptions,
|
|
178
|
+
type ImportIR,
|
|
179
|
+
type NodeIdInput,
|
|
180
|
+
type SchemaStats,
|
|
181
|
+
type SchemaStatsResult,
|
|
182
|
+
type SearchHit,
|
|
183
|
+
type SearchQuery,
|
|
184
|
+
type SearchResult,
|
|
185
|
+
type SnippetFailureCode,
|
|
186
|
+
type SnippetQuery,
|
|
187
|
+
type SnippetResult,
|
|
188
|
+
type SnippetSuccess,
|
|
189
|
+
type StoreFileIR,
|
|
190
|
+
type SymbolKind,
|
|
191
|
+
type TraverseDirection,
|
|
192
|
+
type TraverseHit,
|
|
193
|
+
type TraverseQuery,
|
|
194
|
+
type TraversePathHit,
|
|
195
|
+
type TraversePathsQuery,
|
|
196
|
+
type TraversePathsResult,
|
|
197
|
+
type TraverseResult,
|
|
198
|
+
type ReadCoChangeEdge,
|
|
199
|
+
type ReadCoChangesResult,
|
|
200
|
+
type ReadFileHashesResult,
|
|
201
|
+
type ReadMetaResult,
|
|
202
|
+
type UpsertBatchResult,
|
|
203
|
+
type UpsertEdgesResult,
|
|
204
|
+
type UpsertEdgesSuccess,
|
|
205
|
+
type UpsertResult,
|
|
206
|
+
type UpsertSuccess,
|
|
207
|
+
} from "./graph-store.js";
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
// PR3 (issue #1553): incremental git-based reindex, detect_changes + blast
|
|
210
|
+
// radius, co-change mining, and index-status reporting. Re-exported from
|
|
211
|
+
// the package root so consumers can import them alongside the store.
|
|
212
|
+
// ---------------------------------------------------------------------------
|
|
213
|
+
|
|
214
|
+
export {
|
|
215
|
+
planReindex,
|
|
216
|
+
executeReindex,
|
|
217
|
+
readLastIndexedHead,
|
|
218
|
+
readFileHashes,
|
|
219
|
+
hashContent,
|
|
220
|
+
META_KEY_LAST_HEAD,
|
|
221
|
+
META_KEY_PENDING_PARSE_FAILURES,
|
|
222
|
+
type ParseFileFn,
|
|
223
|
+
type ReadFileFn,
|
|
224
|
+
type ReindexGitFacts,
|
|
225
|
+
type ReindexPlan,
|
|
226
|
+
type ReindexResult,
|
|
227
|
+
type ReindexState,
|
|
228
|
+
} from "./reindex.js";
|
|
229
|
+
|
|
230
|
+
export {
|
|
231
|
+
classifyRisk,
|
|
232
|
+
computeBlastRadius,
|
|
233
|
+
findDirectlyAffectedSymbols,
|
|
234
|
+
byteSpanToLines,
|
|
235
|
+
rangesOverlap,
|
|
236
|
+
BLAST_RADIUS_EDGE_TYPES,
|
|
237
|
+
FAN_IN_ESCALATION_THRESHOLD,
|
|
238
|
+
DEFAULT_BLAST_RADIUS_DEPTH,
|
|
239
|
+
type AffectedSymbol,
|
|
240
|
+
type BlastRadiusResult,
|
|
241
|
+
type DetectChangesResult,
|
|
242
|
+
type RiskLevel,
|
|
243
|
+
} from "./detect-changes.js";
|
|
244
|
+
|
|
245
|
+
export {
|
|
246
|
+
mineCoChangeEdges,
|
|
247
|
+
mineAndStoreCoChanges,
|
|
248
|
+
DEFAULT_CO_CHANGE_CONFIG,
|
|
249
|
+
type CoChangeConfig,
|
|
250
|
+
type CoChangeEdge,
|
|
251
|
+
type MineCoChangesResult,
|
|
252
|
+
} from "./co-change.js";
|
|
253
|
+
|
|
254
|
+
export {
|
|
255
|
+
getIndexStatus,
|
|
256
|
+
type IndexStatus,
|
|
257
|
+
type IndexStatusMode,
|
|
258
|
+
} from "./index-status.js";
|
|
259
|
+
|
|
260
|
+
export {
|
|
261
|
+
defaultCodingGitInvoker,
|
|
262
|
+
parseNameStatus,
|
|
263
|
+
parseHunks,
|
|
264
|
+
parseLogFiles,
|
|
265
|
+
type CodingGitInvoker,
|
|
266
|
+
type DiffHunk,
|
|
267
|
+
type GitFailure,
|
|
268
|
+
type LogFilesEntry,
|
|
269
|
+
type NameStatusEntry,
|
|
270
|
+
} from "./git-invoker.js";
|
|
271
|
+
|
|
272
|
+
// ---------------------------------------------------------------------------
|
|
273
|
+
// PR3 (issue #1552): openCypher read-subset — parser + executor. Re-exported
|
|
274
|
+
// from the package root so consumers can `import { executeCypher } from
|
|
275
|
+
// "@remnic/coding-graph"` (the subpath export `./cypher` remains for callers
|
|
276
|
+
// that want only this layer).
|
|
277
|
+
// ---------------------------------------------------------------------------
|
|
278
|
+
|
|
279
|
+
export {
|
|
280
|
+
executeCypher,
|
|
281
|
+
executeAst,
|
|
282
|
+
parseCypher,
|
|
283
|
+
VALID_CYPHER_LABELS,
|
|
284
|
+
type CypherAst,
|
|
285
|
+
type CypherFailure,
|
|
286
|
+
type CypherFailureCode,
|
|
287
|
+
type CypherNodeValue,
|
|
288
|
+
type CypherParseResult,
|
|
289
|
+
type CypherResult,
|
|
290
|
+
type CypherRow,
|
|
291
|
+
type CypherScalar,
|
|
292
|
+
type CypherSuccess,
|
|
293
|
+
type CypherValue,
|
|
294
|
+
} from "./cypher/query-parser.js";
|
|
295
|
+
// ---------------------------------------------------------------------------
|
|
296
|
+
// PR (issue #1555): Phase B type resolution — LSP client layer over
|
|
297
|
+
// installed language servers. Minimal JSON-RPC-over-stdio client, server
|
|
298
|
+
// registry, resolution pass, and status surfacing. All behind
|
|
299
|
+
// `codingGraph.lsp.enabled` (default false — rule 30/48).
|
|
300
|
+
// ---------------------------------------------------------------------------
|
|
301
|
+
|
|
302
|
+
export {
|
|
303
|
+
LspClient,
|
|
304
|
+
pathToUri,
|
|
305
|
+
uriToPath,
|
|
306
|
+
type LspClientOptions,
|
|
307
|
+
} from "./lsp/client.js";
|
|
308
|
+
|
|
309
|
+
export {
|
|
310
|
+
LspFrameDecoder,
|
|
311
|
+
encodeLspFrame,
|
|
312
|
+
type FrameDecodeError,
|
|
313
|
+
type FrameDecodeErrorKind,
|
|
314
|
+
type FrameDecodeResult,
|
|
315
|
+
} from "./lsp/framing.js";
|
|
316
|
+
|
|
317
|
+
export {
|
|
318
|
+
DEFAULT_LSP_CONFIG,
|
|
319
|
+
DEFAULT_LSP_MAX_REQUESTS_PER_RUN,
|
|
320
|
+
DEFAULT_LSP_TIMEOUT_MS,
|
|
321
|
+
parseLspConfig,
|
|
322
|
+
readLspEnabledEnv,
|
|
323
|
+
type LspConfig,
|
|
324
|
+
type LspConfigParseResult,
|
|
325
|
+
type LspServerLaunchSpec,
|
|
326
|
+
type LspServerOverrides,
|
|
327
|
+
} from "./lsp/config.js";
|
|
328
|
+
|
|
329
|
+
export {
|
|
330
|
+
lspDegradation,
|
|
331
|
+
type LspBackend,
|
|
332
|
+
type LspDegradation,
|
|
333
|
+
type LspDegradationCode,
|
|
334
|
+
type LspResult,
|
|
335
|
+
} from "./lsp/degradation.js";
|
|
336
|
+
|
|
337
|
+
export {
|
|
338
|
+
executeLspResolution,
|
|
339
|
+
mapLocationToNode,
|
|
340
|
+
planLspUpgrades,
|
|
341
|
+
type EdgeUpgrade,
|
|
342
|
+
type LspBudget,
|
|
343
|
+
type NodeLocator,
|
|
344
|
+
type PlanResult,
|
|
345
|
+
type PlannedLspRequest,
|
|
346
|
+
type ResolutionResult,
|
|
347
|
+
type ResolveOptions,
|
|
348
|
+
type UnresolvedCallSite,
|
|
349
|
+
} from "./lsp/resolution.js";
|
|
350
|
+
|
|
351
|
+
export {
|
|
352
|
+
formatLspStatusLine,
|
|
353
|
+
getLspStatus,
|
|
354
|
+
resolutionResultToStatusMaps,
|
|
355
|
+
type LspStatusEntry,
|
|
356
|
+
type LspStatusInput,
|
|
357
|
+
} from "./lsp/status.js";
|
|
358
|
+
export {
|
|
359
|
+
buildLineOffsetMap,
|
|
360
|
+
byteOffsetToPosition,
|
|
361
|
+
positionToByteOffset,
|
|
362
|
+
type LineOffsetMap,
|
|
363
|
+
} from "./lsp/byte-position.js";
|
|
364
|
+
|
|
365
|
+
export type {
|
|
366
|
+
LspInitializeParams,
|
|
367
|
+
LspInitializeResult,
|
|
368
|
+
LspLocation,
|
|
369
|
+
LspPosition,
|
|
370
|
+
LspRange,
|
|
371
|
+
LspServerCapabilities,
|
|
372
|
+
LspTextDocumentItem,
|
|
373
|
+
LspTextDocumentPositionParams,
|
|
374
|
+
} from "./lsp/types.js";
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
// ---------------------------------------------------------------------------
|
|
378
|
+
// Semantic layer (issue #1556): symbol embeddings, SIMILAR_TO near-clone
|
|
379
|
+
// edges, and semantic_query. OFF by default (SemanticConfig.enabled = false).
|
|
380
|
+
// The layer builds on @remnic/core's host embedding provider + fallback —
|
|
381
|
+
// no new embedding stack. See ./semantic/index.ts for the full surface.
|
|
382
|
+
// ---------------------------------------------------------------------------
|
|
383
|
+
|
|
384
|
+
export * from "./semantic/index.js";
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Byte-offset ↔ LSP position conversion.
|
|
3
|
+
*
|
|
4
|
+
* LSP positions are zero-based {line, character} where `character` is a
|
|
5
|
+
* UTF-16 code-unit offset within the line (LSP 3.17 §3.17). The coding-
|
|
6
|
+
* graph store uses UTF-8 byte spans. This module converts between the two.
|
|
7
|
+
*
|
|
8
|
+
* A {@link LineOffsetMap} pre-computes the UTF-8 BYTE offset of each line
|
|
9
|
+
* start, making both directions O(log n) via binary search for the line,
|
|
10
|
+
* then O(line length) for the character within the line.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Pre-computed line-start byte offsets for a single file. Built once per
|
|
15
|
+
* file from its content; reused for all position conversions in that file.
|
|
16
|
+
*
|
|
17
|
+
* `lineStarts[i]` = UTF-8 byte offset of the first character on line `i`.
|
|
18
|
+
* Line 0 always starts at byte 0.
|
|
19
|
+
*/
|
|
20
|
+
export interface LineOffsetMap {
|
|
21
|
+
readonly lineStarts: readonly number[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Compute the UTF-8 byte length of a single UTF-16 code unit or a
|
|
26
|
+
* surrogate pair. Surrogate pairs encode to 4 bytes (U+10000-U+10FFFF).
|
|
27
|
+
*/
|
|
28
|
+
function utf8ByteLength(code: number, nextCode: number): number {
|
|
29
|
+
if (code >= 0xd800 && code <= 0xdbff && nextCode >= 0xdc00 && nextCode <= 0xdfff) {
|
|
30
|
+
return 4;
|
|
31
|
+
}
|
|
32
|
+
if (code < 0x80) return 1;
|
|
33
|
+
if (code < 0x800) return 2;
|
|
34
|
+
return 3;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** True if this code unit is the high half of a surrogate pair. */
|
|
38
|
+
function isHighSurrogate(code: number, nextCode: number): boolean {
|
|
39
|
+
return code >= 0xd800 && code <= 0xdbff && nextCode >= 0xdc00 && nextCode <= 0xdfff;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Build a line-offset map from file content (as a UTF-8 string or Buffer).
|
|
44
|
+
* Records UTF-8 BYTE offsets — not UTF-16 string indices — because
|
|
45
|
+
* Content-Length and the store's span_start/span_end count bytes.
|
|
46
|
+
* Handles `\n`, `\r\n`, and `\r` line endings.
|
|
47
|
+
*/
|
|
48
|
+
export function buildLineOffsetMap(content: string | Buffer): LineOffsetMap {
|
|
49
|
+
const text = typeof content === "string" ? content : content.toString("utf8");
|
|
50
|
+
const lineStarts = [0];
|
|
51
|
+
let byteOffset = 0;
|
|
52
|
+
|
|
53
|
+
for (let i = 0; i < text.length; i++) {
|
|
54
|
+
const code = text.charCodeAt(i);
|
|
55
|
+
const nextCode = i + 1 < text.length ? text.charCodeAt(i + 1) : 0;
|
|
56
|
+
|
|
57
|
+
if (code === 0x0d && nextCode === 0x0a) {
|
|
58
|
+
// \r\n — 2 bytes, advance past \n.
|
|
59
|
+
byteOffset += 2;
|
|
60
|
+
lineStarts.push(byteOffset);
|
|
61
|
+
i++;
|
|
62
|
+
} else if (code === 0x0a || code === 0x0d) {
|
|
63
|
+
byteOffset += 1;
|
|
64
|
+
lineStarts.push(byteOffset);
|
|
65
|
+
} else {
|
|
66
|
+
byteOffset += utf8ByteLength(code, nextCode);
|
|
67
|
+
if (isHighSurrogate(code, nextCode)) i++;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return { lineStarts };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Convert a UTF-8 byte offset to an LSP position {line, character}.
|
|
75
|
+
* `character` is a UTF-16 code-unit count from the line start (surrogates
|
|
76
|
+
* count as 2, matching LSP §3.17).
|
|
77
|
+
*/
|
|
78
|
+
export function byteOffsetToPosition(
|
|
79
|
+
content: string,
|
|
80
|
+
byteOffset: number,
|
|
81
|
+
map: LineOffsetMap,
|
|
82
|
+
): { line: number; character: number } {
|
|
83
|
+
const lineIdx = binarySearchLine(map.lineStarts, byteOffset);
|
|
84
|
+
const lineByteStart = map.lineStarts[lineIdx];
|
|
85
|
+
|
|
86
|
+
// Find the string index where the line starts (byte offset == lineByteStart).
|
|
87
|
+
let strIdx = 0;
|
|
88
|
+
let byteAccum = 0;
|
|
89
|
+
for (strIdx = 0; strIdx < content.length; strIdx++) {
|
|
90
|
+
if (byteAccum >= lineByteStart) break;
|
|
91
|
+
const code = content.charCodeAt(strIdx);
|
|
92
|
+
const nextCode = strIdx + 1 < content.length ? content.charCodeAt(strIdx + 1) : 0;
|
|
93
|
+
byteAccum += utf8ByteLength(code, nextCode);
|
|
94
|
+
if (isHighSurrogate(code, nextCode)) strIdx++;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Walk from the line start to byteOffset, counting UTF-16 code units.
|
|
98
|
+
let charCount = 0;
|
|
99
|
+
let currentByte = lineByteStart;
|
|
100
|
+
for (let i = strIdx; i < content.length; i++) {
|
|
101
|
+
if (currentByte >= byteOffset) break;
|
|
102
|
+
const code = content.charCodeAt(i);
|
|
103
|
+
const nextCode = i + 1 < content.length ? content.charCodeAt(i + 1) : 0;
|
|
104
|
+
currentByte += utf8ByteLength(code, nextCode);
|
|
105
|
+
if (isHighSurrogate(code, nextCode)) {
|
|
106
|
+
charCount += 2;
|
|
107
|
+
i++;
|
|
108
|
+
} else {
|
|
109
|
+
charCount++;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return { line: lineIdx, character: charCount };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Convert an LSP position {line, character} to a UTF-8 byte offset.
|
|
118
|
+
* `character` is a UTF-16 code-unit count from the line start.
|
|
119
|
+
*/
|
|
120
|
+
export function positionToByteOffset(
|
|
121
|
+
content: string,
|
|
122
|
+
position: { line: number; character: number },
|
|
123
|
+
map: LineOffsetMap,
|
|
124
|
+
): number {
|
|
125
|
+
const lineIdx = Math.min(position.line, map.lineStarts.length - 1);
|
|
126
|
+
const lineByteStart = map.lineStarts[lineIdx];
|
|
127
|
+
|
|
128
|
+
// Find the string index where the line starts (byte offset == lineByteStart).
|
|
129
|
+
let strIdx = 0;
|
|
130
|
+
let byteAccum = 0;
|
|
131
|
+
for (strIdx = 0; strIdx < content.length; strIdx++) {
|
|
132
|
+
if (byteAccum >= lineByteStart) break;
|
|
133
|
+
const code = content.charCodeAt(strIdx);
|
|
134
|
+
const nextCode = strIdx + 1 < content.length ? content.charCodeAt(strIdx + 1) : 0;
|
|
135
|
+
byteAccum += utf8ByteLength(code, nextCode);
|
|
136
|
+
if (isHighSurrogate(code, nextCode)) strIdx++;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Walk from the line start, counting UTF-16 code units until position.character.
|
|
140
|
+
let charCount = 0;
|
|
141
|
+
let byteOffset = lineByteStart;
|
|
142
|
+
for (let i = strIdx; i < content.length && charCount < position.character; i++) {
|
|
143
|
+
const code = content.charCodeAt(i);
|
|
144
|
+
const nextCode = i + 1 < content.length ? content.charCodeAt(i + 1) : 0;
|
|
145
|
+
byteOffset += utf8ByteLength(code, nextCode);
|
|
146
|
+
if (isHighSurrogate(code, nextCode)) {
|
|
147
|
+
charCount += 2;
|
|
148
|
+
i++;
|
|
149
|
+
} else {
|
|
150
|
+
charCount++;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return byteOffset;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Binary search for the last lineStart that is <= byteOffset.
|
|
159
|
+
* Returns the line index (0-based).
|
|
160
|
+
*/
|
|
161
|
+
function binarySearchLine(lineStarts: readonly number[], byteOffset: number): number {
|
|
162
|
+
let lo = 0;
|
|
163
|
+
let hi = lineStarts.length - 1;
|
|
164
|
+
while (lo < hi) {
|
|
165
|
+
const mid = (lo + hi + 1) >> 1;
|
|
166
|
+
if (lineStarts[mid] <= byteOffset) {
|
|
167
|
+
lo = mid;
|
|
168
|
+
} else {
|
|
169
|
+
hi = mid - 1;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return lo;
|
|
173
|
+
}
|