@colbymchenry/codegraph 1.2.0 → 1.3.1
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 +94 -1
- package/dist/bin/codegraph.d.ts +1 -1
- package/dist/db/index.d.ts +17 -5
- package/dist/db/migrations.d.ts +1 -1
- package/dist/db/queries.d.ts +76 -1
- package/dist/directory.d.ts +9 -5
- package/dist/extraction/cfml-extractor.d.ts +107 -0
- package/dist/extraction/grammars.d.ts +9 -0
- package/dist/extraction/index.d.ts +46 -1
- package/dist/extraction/languages/arkts.d.ts +3 -0
- package/dist/extraction/languages/c-cpp.d.ts +42 -0
- package/dist/extraction/languages/cfquery.d.ts +12 -0
- package/dist/extraction/languages/cfscript.d.ts +3 -0
- package/dist/extraction/languages/cobol.d.ts +33 -0
- package/dist/extraction/languages/erlang.d.ts +3 -0
- package/dist/extraction/languages/nix.d.ts +3 -0
- package/dist/extraction/languages/solidity.d.ts +3 -0
- package/dist/extraction/languages/terraform.d.ts +3 -0
- package/dist/extraction/languages/vbnet.d.ts +11 -0
- package/dist/extraction/mybatis-extractor.d.ts +30 -10
- package/dist/extraction/tree-sitter-types.d.ts +3 -1
- package/dist/extraction/tree-sitter.d.ts +38 -0
- package/dist/index.d.ts +63 -1
- package/dist/mcp/daemon.d.ts +25 -3
- package/dist/mcp/early-ppid.d.ts +26 -0
- package/dist/mcp/query-pool.d.ts +14 -0
- package/dist/mcp/startup-handshake.d.ts +44 -0
- package/dist/mcp/tools.d.ts +22 -0
- package/dist/project-config.d.ts +38 -0
- package/dist/resolution/c-fnptr-synthesizer.d.ts +2 -1
- package/dist/resolution/frameworks/cics.d.ts +20 -0
- package/dist/resolution/frameworks/terraform.d.ts +38 -0
- package/dist/resolution/goframe-synthesizer.d.ts +2 -1
- package/dist/resolution/import-resolver.d.ts +7 -0
- package/dist/resolution/index.d.ts +49 -6
- package/dist/resolution/name-matcher.d.ts +0 -3
- package/dist/resolution/strip-comments.d.ts +1 -1
- package/dist/resolution/types.d.ts +29 -0
- package/dist/resolution/workspace-packages.d.ts +10 -0
- package/dist/search/identifier-segments.d.ts +60 -0
- package/dist/sync/watcher.d.ts +10 -5
- package/dist/types.d.ts +19 -1
- package/npm-shim.js +8 -1
- package/package.json +7 -7
- package/dist/reasoning/config.d.ts +0 -45
- package/dist/reasoning/credentials.d.ts +0 -5
- package/dist/reasoning/login.d.ts +0 -21
- package/dist/reasoning/reasoner.d.ts +0 -43
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COBOL Language Extractor
|
|
3
|
+
*
|
|
4
|
+
* COBOL's AST (vendored, patched build of yutaro-sakamoto/tree-sitter-cobol)
|
|
5
|
+
* is fundamentally different from block-structured languages, so extraction
|
|
6
|
+
* runs almost entirely through the custom visitNode hook (the Pascal pattern):
|
|
7
|
+
*
|
|
8
|
+
* - A program (PROGRAM-ID) becomes a `module` node.
|
|
9
|
+
* - PROCEDURE DIVISION sections and paragraphs become `function` nodes. The
|
|
10
|
+
* grammar emits them FLAT — a section_header/paragraph_header followed by
|
|
11
|
+
* sibling statements — so extents are reconstructed here: a paragraph runs
|
|
12
|
+
* from its header to the next header, a section to the next section header.
|
|
13
|
+
* - PERFORM (including THRU ranges), GO TO, and CALL 'literal' become `calls`
|
|
14
|
+
* references. A dynamic CALL through a data name is skipped — announce,
|
|
15
|
+
* don't guess. EXEC CICS LINK/XCTL PROGRAM('X') with a literal target also
|
|
16
|
+
* becomes a `calls` reference; EXEC SQL INCLUDE X becomes an `imports`
|
|
17
|
+
* reference (DB2's COPY).
|
|
18
|
+
* - COPY statements become `import` nodes + `imports` references.
|
|
19
|
+
* - DATA DIVISION entries become `variable` (01/77 levels), `field` (nested
|
|
20
|
+
* levels, contained in their group item), or `constant` (88-level condition
|
|
21
|
+
* names) nodes, so impact queries on working-storage names work.
|
|
22
|
+
* - Standalone copybooks (.cpy) parse via the grammar's copybook_fragment
|
|
23
|
+
* entry point: data copybooks yield their record structure, procedure
|
|
24
|
+
* copybooks yield paragraphs.
|
|
25
|
+
*
|
|
26
|
+
* The grammar is fixed-format (code area columns 8-72). preParse detects a
|
|
27
|
+
* free-format file (division header or level number starting before column 8)
|
|
28
|
+
* and indents every line by 7 spaces: line numbers are preserved, columns
|
|
29
|
+
* drift by 7 — acceptable for line-oriented consumers.
|
|
30
|
+
*/
|
|
31
|
+
import type { LanguageExtractor } from '../tree-sitter-types';
|
|
32
|
+
export declare const cobolExtractor: LanguageExtractor;
|
|
33
|
+
//# sourceMappingURL=cobol.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LanguageExtractor } from '../tree-sitter-types';
|
|
2
|
+
/**
|
|
3
|
+
* The vendored VB.NET grammar has no true end-of-file token (its `_eof` rule is
|
|
4
|
+
* a literal-`$` placeholder that never matches real input), so a file whose
|
|
5
|
+
* last line lacks a trailing newline ends every parse with a MISSING-newline
|
|
6
|
+
* error on the final statement. Appending a newline is offset-preserving for
|
|
7
|
+
* all existing content.
|
|
8
|
+
*/
|
|
9
|
+
export declare function ensureTrailingNewline(source: string): string;
|
|
10
|
+
export declare const vbnetExtractor: LanguageExtractor;
|
|
11
|
+
//# sourceMappingURL=vbnet.d.ts.map
|
|
@@ -12,15 +12,21 @@ import { ExtractionResult } from '../types';
|
|
|
12
12
|
*
|
|
13
13
|
* This extractor emits one method-shaped node per `<select|insert|update|
|
|
14
14
|
* delete>` and per `<sql>` fragment, qualified as `<namespace>::<id>` so the
|
|
15
|
-
* MyBatis framework synthesizer
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* MyBatis framework synthesizer can link the matching Java method → XML
|
|
16
|
+
* statement by suffix-matching qualified names. `<include refid="...">` inside
|
|
17
|
+
* a statement yields an unresolved reference to the SQL fragment, also keyed
|
|
18
|
+
* by `<namespace>::<refid>`.
|
|
19
|
+
*
|
|
20
|
+
* Both dialects are covered: MyBatis 3 `<mapper namespace="...">` and the
|
|
21
|
+
* legacy iBatis 2 `<sqlMap>` (namespaced, or namespace-less with `Map.stmt`
|
|
22
|
+
* ids, plus its extra `<statement>`/`<procedure>` verbs). Attribute values may
|
|
23
|
+
* use either quote style, and statements commented out with `<!-- ... -->` are
|
|
24
|
+
* ignored (see the constructor's comment-stripping pre-pass).
|
|
19
25
|
*
|
|
20
26
|
* Non-mapper XML (Maven `pom.xml`, Spring beans XML, `web.xml`, log4j config,
|
|
21
|
-
* etc.) is detected by the absence of a `<mapper namespace="...">`
|
|
22
|
-
* returns just a file node — we still need the file row so
|
|
23
|
-
* track it, but we emit no symbols.
|
|
27
|
+
* etc.) is detected by the absence of a `<mapper namespace="...">` /
|
|
28
|
+
* `<sqlMap>` root and returns just a file node — we still need the file row so
|
|
29
|
+
* the watcher can track it, but we emit no symbols.
|
|
24
30
|
*/
|
|
25
31
|
export declare class MyBatisExtractor {
|
|
26
32
|
private filePath;
|
|
@@ -31,16 +37,30 @@ export declare class MyBatisExtractor {
|
|
|
31
37
|
private errors;
|
|
32
38
|
private lineStarts;
|
|
33
39
|
constructor(filePath: string, source: string);
|
|
40
|
+
private static stripXmlComments;
|
|
34
41
|
extract(): ExtractionResult;
|
|
35
42
|
private createFileNode;
|
|
36
43
|
/**
|
|
37
|
-
* Find the
|
|
38
|
-
*
|
|
39
|
-
*
|
|
44
|
+
* Find the mapper root and its dialect. Two shapes are recognized:
|
|
45
|
+
* - MyBatis 3: `<mapper namespace="com.foo.Bar">` — namespace required.
|
|
46
|
+
* - iBatis 2: `<sqlMap namespace="Account">`, or a namespace-less
|
|
47
|
+
* `<sqlMap>` whose statement ids carry the qualifier as `Map.statement`.
|
|
48
|
+
* Returns the namespace, the dialect, and the byte offsets of the body
|
|
49
|
+
* (between the opening and closing tag) so statement extraction is scoped to
|
|
50
|
+
* the root's contents. Either quote style is accepted for the namespace
|
|
51
|
+
* (`namespace='X'` is legal XML and common in older mappers).
|
|
40
52
|
*/
|
|
41
53
|
private findMapperRoot;
|
|
42
54
|
private extractMapper;
|
|
43
55
|
private buildSignature;
|
|
56
|
+
/**
|
|
57
|
+
* Build the `<namespace>::<id>` qualified name the MyBatis synthesizer
|
|
58
|
+
* suffix-matches against a Java `<Class>::<method>`, and the display name.
|
|
59
|
+
* For a namespace-less iBatis `<sqlMap>`, the statement id carries the
|
|
60
|
+
* qualifier as `Map.statement`, so split on the last dot to reach the same
|
|
61
|
+
* shape (`Account.getById` → `Account::getById`, name `getById`).
|
|
62
|
+
*/
|
|
63
|
+
private qualifyStatement;
|
|
44
64
|
private previewSql;
|
|
45
65
|
private computeLineStarts;
|
|
46
66
|
private getLineNumber;
|
|
@@ -76,8 +76,10 @@ export interface LanguageExtractor {
|
|
|
76
76
|
* grammar mis-parses inside enum bodies). MUST preserve byte offsets (replace
|
|
77
77
|
* removed text with spaces, keep newlines) so node positions and getNodeText
|
|
78
78
|
* stay correct; the returned string is used for both parsing and extraction.
|
|
79
|
+
* `filePath` lets a transform key off the concrete file extension when one
|
|
80
|
+
* language id serves several dialects (C++ also parses `.metal` shaders).
|
|
79
81
|
*/
|
|
80
|
-
preParse?: (source: string) => string;
|
|
82
|
+
preParse?: (source: string, filePath?: string) => string;
|
|
81
83
|
/** Node types that represent functions */
|
|
82
84
|
functionTypes: string[];
|
|
83
85
|
/** Node types that represent classes */
|
|
@@ -25,6 +25,8 @@ export declare class TreeSitterExtractor {
|
|
|
25
25
|
private errors;
|
|
26
26
|
private extractor;
|
|
27
27
|
private nodeStack;
|
|
28
|
+
private namespacePrefix;
|
|
29
|
+
private cppLocalFnPtrs;
|
|
28
30
|
private methodIndex;
|
|
29
31
|
private fnRefSpec;
|
|
30
32
|
private fnRefCandidates;
|
|
@@ -427,6 +429,25 @@ export declare class TreeSitterExtractor {
|
|
|
427
429
|
/**
|
|
428
430
|
* Extract a function call
|
|
429
431
|
*/
|
|
432
|
+
/**
|
|
433
|
+
* The module an Erlang gen_server target expression statically names, or
|
|
434
|
+
* null when it's dynamic (pid/var/tuple form). Static shapes:
|
|
435
|
+
* - a bare atom — either this module or another one; OTP's dominant
|
|
436
|
+
* registration convention (`{local, ?MODULE}`) names a server process
|
|
437
|
+
* after its module, so `gen_server:call(other_mod, …)` reaches
|
|
438
|
+
* `other_mod`'s handlers. A registered name that matches no module
|
|
439
|
+
* resolves to nothing downstream (the qualified ref just drops).
|
|
440
|
+
* - `?MODULE`, or a macro the file defines as `?MODULE`
|
|
441
|
+
* (`-define(SERVER, ?MODULE)` — the standard self idiom)
|
|
442
|
+
* - a macro the file defines as a bare atom
|
|
443
|
+
* (`-define(STORE, kv_store)` — the cross-module variant)
|
|
444
|
+
* The macro tables are memoized per file (single entry — extraction is
|
|
445
|
+
* file-sequential).
|
|
446
|
+
*/
|
|
447
|
+
private erlangServerMacroFile;
|
|
448
|
+
private erlangSelfMacros;
|
|
449
|
+
private erlangAtomMacros;
|
|
450
|
+
private resolveErlangGenServerTarget;
|
|
430
451
|
private extractCall;
|
|
431
452
|
/**
|
|
432
453
|
* `new Foo(...)` / `Foo::new(...)` / object_creation_expression —
|
|
@@ -437,6 +458,15 @@ export declare class TreeSitterExtractor {
|
|
|
437
458
|
* Children are still walked so nested calls inside the constructor
|
|
438
459
|
* arguments (`new Foo(bar())`) get their own `calls` references.
|
|
439
460
|
*/
|
|
461
|
+
/**
|
|
462
|
+
* VB.NET `New Invoice(1)` is syntactically ambiguous between constructing
|
|
463
|
+
* Invoice with an argument and allocating an Invoice array of bound 1; the
|
|
464
|
+
* grammar parses the parenthesized form as array_creation_expression. A
|
|
465
|
+
* user-defined type with no `{...}` array initializer is overwhelmingly a
|
|
466
|
+
* constructor call, so treat it as an instantiation. Predefined element
|
|
467
|
+
* types (`New Byte(1023)`) and brace-initialized forms stay arrays.
|
|
468
|
+
*/
|
|
469
|
+
private isVbnetConstructorShapedArrayCreation;
|
|
440
470
|
private extractInstantiation;
|
|
441
471
|
/**
|
|
442
472
|
* Is this C++ `declaration` a stack/direct-initialization object construction
|
|
@@ -528,6 +558,14 @@ export declare class TreeSitterExtractor {
|
|
|
528
558
|
* heuristic — no false edges (resolution still validates each path).
|
|
529
559
|
*/
|
|
530
560
|
private extractRustRouteMacro;
|
|
561
|
+
/**
|
|
562
|
+
* Record a C++ local function-pointer binding (`local = &fn` / `&fn<…>` /
|
|
563
|
+
* `&ns::fn<…>`) for the CURRENT enclosing symbol, so calls through the local
|
|
564
|
+
* resolve to the real target (see cppLocalFnPtrs). Only the address-of shape
|
|
565
|
+
* is accepted — a bare-identifier RHS (`auto x = y;`) is any value copy, and
|
|
566
|
+
* linking through it would guess.
|
|
567
|
+
*/
|
|
568
|
+
private recordCppFnPtrBinding;
|
|
531
569
|
private visitFunctionBody;
|
|
532
570
|
/**
|
|
533
571
|
* Extract inheritance relationships
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* A local-first code intelligence system that builds a semantic
|
|
5
5
|
* knowledge graph from any codebase.
|
|
6
6
|
*/
|
|
7
|
-
import { Node, Edge, FileRecord, ExtractionResult, Subgraph, TraversalOptions, SearchOptions, SearchResult, Context, GraphStats, TaskInput, TaskContext, BuildContextOptions, FindRelevantContextOptions } from './types';
|
|
7
|
+
import { Node, Edge, FileRecord, ExtractionResult, Subgraph, TraversalOptions, SearchOptions, SearchResult, SegmentMatch, Context, GraphStats, TaskInput, TaskContext, BuildContextOptions, FindRelevantContextOptions } from './types';
|
|
8
8
|
import { IndexProgress, IndexResult, SyncResult } from './extraction';
|
|
9
9
|
import { ResolutionResult } from './resolution';
|
|
10
10
|
import { WatchOptions, PendingFile } from './sync';
|
|
@@ -227,6 +227,16 @@ export declare class CodeGraph {
|
|
|
227
227
|
* freshness without shelling out to `codegraph status --json`. (#329)
|
|
228
228
|
*/
|
|
229
229
|
getLastIndexedAt(): number | null;
|
|
230
|
+
/**
|
|
231
|
+
* Completeness of the last full index run. `'complete'` is the only good
|
|
232
|
+
* state. `'indexing'` after the fact means a run was killed mid-index (OOM,
|
|
233
|
+
* SIGKILL, liveness watchdog) and the on-disk index is truncated;
|
|
234
|
+
* `'partial'` means the run finished but silently dropped files
|
|
235
|
+
* (discovered > indexed+skipped+errored); `'failed'` means it reported
|
|
236
|
+
* failure. `null` = index predates this marker. Surfaced by
|
|
237
|
+
* `codegraph status`.
|
|
238
|
+
*/
|
|
239
|
+
getIndexState(): 'indexing' | 'complete' | 'partial' | 'failed' | null;
|
|
230
240
|
/**
|
|
231
241
|
* Which engine built the current index: the package version + extraction
|
|
232
242
|
* version stamped at the last full `indexAll`. Either field is null for an
|
|
@@ -264,6 +274,13 @@ export declare class CodeGraph {
|
|
|
264
274
|
* Processes chunks of unresolved refs, persisting results after each batch.
|
|
265
275
|
*/
|
|
266
276
|
resolveReferencesBatched(onProgress?: (current: number, total: number) => void): Promise<ResolutionResult>;
|
|
277
|
+
/**
|
|
278
|
+
* References extracted but not yet resolved into edges. Zero on a healthy
|
|
279
|
+
* index — a completed resolution pass consumes every row. Non-zero at rest
|
|
280
|
+
* means a pass was interrupted mid-run (killed indexer, crash — #1187), so
|
|
281
|
+
* some files' call edges are missing; the next `sync` sweeps them.
|
|
282
|
+
*/
|
|
283
|
+
getPendingReferenceCount(): number;
|
|
267
284
|
/**
|
|
268
285
|
* Get detected frameworks in the project
|
|
269
286
|
*/
|
|
@@ -307,10 +324,55 @@ export declare class CodeGraph {
|
|
|
307
324
|
* definition the caller wants is never dropped below a search cut.
|
|
308
325
|
*/
|
|
309
326
|
getNodesByName(name: string): Node[];
|
|
327
|
+
/** Nodes whose name starts with `prefix` (index range scan, capped). */
|
|
328
|
+
getNodesByNamePrefix(prefix: string, limit?: number): Node[];
|
|
310
329
|
/**
|
|
311
330
|
* Search nodes by text
|
|
312
331
|
*/
|
|
313
332
|
searchNodes(query: string, options?: SearchOptions): SearchResult[];
|
|
333
|
+
/**
|
|
334
|
+
* Graph-derived prompt matching for the front-load hook's MEDIUM tier:
|
|
335
|
+
* which indexed symbols do these prose words name? "state machine des
|
|
336
|
+
* commandes" → `OrderStateMachine`, in any human language whose technical
|
|
337
|
+
* nouns are Latin script — no keyword list involved.
|
|
338
|
+
*
|
|
339
|
+
* Precision comes from the repo's own naming statistics, not vocabulary:
|
|
340
|
+
* - CO-OCCURRENCE: ≥2 words that are segments of the SAME name ("state" +
|
|
341
|
+
* "machine" → OrderStateMachine) is strong evidence and always qualifies.
|
|
342
|
+
* - RARITY: a single matched word qualifies only when its segment is
|
|
343
|
+
* discriminative here (≤ {@link SEGMENT_RARITY_CEILING} distinct names) —
|
|
344
|
+
* "checkout" in a shop backend yes, "state" in a react app no.
|
|
345
|
+
* Every candidate is re-verified against `nodes` before being returned
|
|
346
|
+
* (vocab rows are proposals; deletions leave orphans by design), so a
|
|
347
|
+
* returned symbol is guaranteed to exist right now.
|
|
348
|
+
*/
|
|
349
|
+
getSegmentMatches(words: string[], limit?: number): SegmentMatch[];
|
|
350
|
+
/** A single word ("state") can match hundreds of names in a big repo — that
|
|
351
|
+
* is noise, not signal. Ceiling for the single-word tier; co-occurrence is
|
|
352
|
+
* exempt because two words on one name is already discriminative. */
|
|
353
|
+
private static readonly SEGMENT_RARITY_CEILING;
|
|
354
|
+
/** Which of the prompt's original words match `name`'s segments (via
|
|
355
|
+
* variants). Segments are recomputed in JS — a name-keyed vocab lookup
|
|
356
|
+
* would scan the (segment, name) primary key. */
|
|
357
|
+
private wordsMatchingName;
|
|
358
|
+
/**
|
|
359
|
+
* One-shot upgrade heal for callers that open the graph WITHOUT syncing —
|
|
360
|
+
* concretely the prompt hook, whose MEDIUM tier reads the segment
|
|
361
|
+
* vocabulary: a database migrated from before the vocab table existed
|
|
362
|
+
* starts with it empty, and the only other backfill lives inside `sync()`,
|
|
363
|
+
* which such callers never run (#1142). Returns true when the vocab is
|
|
364
|
+
* usable (already populated — the overwhelmingly common one-SELECT case —
|
|
365
|
+
* or healed here); false when it isn't (empty graph, or another process
|
|
366
|
+
* holds the index lock — that process's own sync heals it).
|
|
367
|
+
*/
|
|
368
|
+
healSegmentVocabIfEmpty(): Promise<boolean>;
|
|
369
|
+
/**
|
|
370
|
+
* Rebuild the segment vocabulary from the current graph, batched and
|
|
371
|
+
* yielding — the upgrade-heal path for indexes built before the vocab table
|
|
372
|
+
* existed. Runs inside the index mutex/lock (sync and
|
|
373
|
+
* healSegmentVocabIfEmpty hold them).
|
|
374
|
+
*/
|
|
375
|
+
private rebuildNameSegmentVocab;
|
|
314
376
|
/**
|
|
315
377
|
* Normalized project-name tokens (go.mod / package.json / repo dir) used to
|
|
316
378
|
* down-weight the non-discriminative project name in search ranking (#720).
|
package/dist/mcp/daemon.d.ts
CHANGED
|
@@ -136,9 +136,11 @@ export declare class Daemon {
|
|
|
136
136
|
/**
|
|
137
137
|
* Defense-in-depth against a daemon that outlives its clients (#692), for the
|
|
138
138
|
* cases the refcount + idle timer miss because a socket close never arrives:
|
|
139
|
-
* - **Inactivity backstop:**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
139
|
+
* - **Inactivity backstop:** after `maxIdleMs` with no inbound traffic, reap
|
|
140
|
+
* the daemon — but ONLY if no connected client can be proven alive (see
|
|
141
|
+
* {@link backstopShouldExit}). This is the sole phantom class the sweep
|
|
142
|
+
* below can't catch: a client whose client-hello never arrived, so we have
|
|
143
|
+
* no pid to check.
|
|
142
144
|
* - **Liveness sweep:** drop any client whose peer process has died (per the
|
|
143
145
|
* client-hello pids), which re-arms the idle timer once the last real
|
|
144
146
|
* client is gone. Catches a dead peer within one sweep instead of waiting
|
|
@@ -147,6 +149,26 @@ export declare class Daemon {
|
|
|
147
149
|
* neither should hold it open on its own.
|
|
148
150
|
*/
|
|
149
151
|
private startLivenessTimers;
|
|
152
|
+
/**
|
|
153
|
+
* Decide whether the inactivity backstop should reap the daemon right now.
|
|
154
|
+
* Public + `isAlive`-injected for deterministic tests; the timer calls it each
|
|
155
|
+
* tick with the real liveness probe.
|
|
156
|
+
*
|
|
157
|
+
* The backstop exists ONLY to catch a **phantom** client (#692) — one counted
|
|
158
|
+
* but actually gone, whose socket-close was never delivered. It must never
|
|
159
|
+
* reap a **live-but-quiet** session (connected, alive peer, just not querying):
|
|
160
|
+
* doing so silently severed the shared daemon and degraded that session — and
|
|
161
|
+
* any others sharing it — to an in-process engine. `lastActivityAt` only tracks
|
|
162
|
+
* inbound query bytes, and MCP has no keepalive, so a genuinely-live session
|
|
163
|
+
* trips the raw inactivity window after ~30 min of not being queried.
|
|
164
|
+
*
|
|
165
|
+
* So: once the inactivity window elapses, drop provably-dead peers (the same
|
|
166
|
+
* check the periodic sweep runs), then reap the daemon only when NOT ONE
|
|
167
|
+
* remaining client can be proven alive — i.e. every client left is an
|
|
168
|
+
* unknown-pid connection the sweep can't verify. A single provably-alive
|
|
169
|
+
* client keeps the daemon up. Has the sweep's side effect (drops dead peers).
|
|
170
|
+
*/
|
|
171
|
+
backstopShouldExit(isAlive: (pid: number) => boolean): boolean;
|
|
150
172
|
/**
|
|
151
173
|
* Drop every connected client whose peer process is gone. Returns the count
|
|
152
174
|
* reaped. `isAlive` is injected for testing. Clients with unknown pids (no
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parent-pid baseline captured as early as possible in process life (#1185).
|
|
3
|
+
*
|
|
4
|
+
* The PPID watchdog's POSIX signal is "`process.ppid` CHANGED since startup" —
|
|
5
|
+
* but a launcher killed within the first ~100ms of our boot (an MCP host's
|
|
6
|
+
* config probe, an instant user cancel, an initialize-timeout teardown) can
|
|
7
|
+
* reparent this process to init BEFORE the serve/proxy code captured its
|
|
8
|
+
* baseline. The baseline then reads `1`, never diverges, and the watchdog is
|
|
9
|
+
* permanently blind — the orphaned-server accumulation reported in #1185.
|
|
10
|
+
* Reproduced on macOS: SIGKILL the launcher 50ms after spawn while the host
|
|
11
|
+
* holds the stdio pipes open, and the server survived indefinitely; at 150ms
|
|
12
|
+
* the old capture had already run and the watchdog reaped it.
|
|
13
|
+
*
|
|
14
|
+
* The CLI entry imports this module before anything else, so the capture runs
|
|
15
|
+
* within the first few ms of JS execution — the earliest a Node process can
|
|
16
|
+
* observe its parent. A kill landing in the remaining pre-JS window (process
|
|
17
|
+
* spawn → first require) still captures `1`; that residual case is covered by
|
|
18
|
+
* the startup-handshake timeout (see ./startup-handshake.ts), which reaps a
|
|
19
|
+
* server that never receives any MCP traffic.
|
|
20
|
+
*
|
|
21
|
+
* Library consumers don't load the CLI entry; for them the capture runs at
|
|
22
|
+
* first import of the MCP layer — no worse than the previous per-call-site
|
|
23
|
+
* capture, and identical once the module cache warms.
|
|
24
|
+
*/
|
|
25
|
+
export declare const EARLY_PPID: number;
|
|
26
|
+
//# sourceMappingURL=early-ppid.d.ts.map
|
package/dist/mcp/query-pool.d.ts
CHANGED
|
@@ -81,6 +81,20 @@ export declare class QueryPool {
|
|
|
81
81
|
* degrades to today's behavior instead of failing tool calls.
|
|
82
82
|
*/
|
|
83
83
|
get healthy(): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* True once at least one worker has completed its cold start (posted the
|
|
86
|
+
* 'ready' handshake). Until then the ToolHandler serves calls IN-PROCESS:
|
|
87
|
+
* a worker cold start is a full module load + DB open — seconds normally,
|
|
88
|
+
* tens of seconds on a loaded machine — and a call queued behind it gets
|
|
89
|
+
* nothing until the 45s busy backstop. The daemon's very first tool call
|
|
90
|
+
* hitting that window was the recurring #662 test flake (and a real
|
|
91
|
+
* first-call stall for agents). The pool exists for CONCURRENT load, which
|
|
92
|
+
* by definition arrives after warm-up; the pre-pool in-process path is
|
|
93
|
+
* strictly better while nothing is warm. Stays true for the pool's
|
|
94
|
+
* lifetime — later crash-respawn gaps are covered by retry + backstop.
|
|
95
|
+
*/
|
|
96
|
+
get ready(): boolean;
|
|
97
|
+
private everReady;
|
|
84
98
|
private spawnOne;
|
|
85
99
|
private onMessage;
|
|
86
100
|
private onWorkerGone;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Never-initialized backstop for `serve --mcp` (#1185).
|
|
3
|
+
*
|
|
4
|
+
* Every real MCP host sends `initialize` immediately after spawning a server.
|
|
5
|
+
* A server that has received NO bytes at all for many minutes is not serving
|
|
6
|
+
* anyone — it is the residue of an abandoned launch: the host killed the
|
|
7
|
+
* launcher chain during startup (config probe, instant cancel, initialize
|
|
8
|
+
* timeout) but kept our stdio pipe fds open, so stdin never EOFs. If the kill
|
|
9
|
+
* landed before {@link ../mcp/early-ppid} could observe the real parent, the
|
|
10
|
+
* PPID watchdog is blind too (baseline `1`), and — pre-#1185 — the orphan
|
|
11
|
+
* lived until the HOST process exited, accumulating one ~30MB node process
|
|
12
|
+
* per occurrence.
|
|
13
|
+
*
|
|
14
|
+
* This backstop closes that last hole: arm a one-shot timer at serve start
|
|
15
|
+
* and disarm it on the first byte of client traffic. If the timer fires, the
|
|
16
|
+
* caller shuts the server down. The default is deliberately generous (15
|
|
17
|
+
* minutes) — hosts initialize within milliseconds, so the only processes this
|
|
18
|
+
* ever reaps are ones nobody is talking to. It never affects a session that
|
|
19
|
+
* spoke even once: after the first byte the timer is gone for good (a
|
|
20
|
+
* quiet-but-live session is the PPID watchdog's / stdin teardown's job).
|
|
21
|
+
*
|
|
22
|
+
* IMPORTANT (callers): attaching a `'data'` listener switches the stream into
|
|
23
|
+
* flowing mode. Arm this AFTER the real stdin consumer is attached, in the
|
|
24
|
+
* same synchronous block, so no early bytes are emitted while only our
|
|
25
|
+
* listener exists. The detached daemon must never arm this — its stdin is
|
|
26
|
+
* `'ignore'` and its lifecycle is refcount/idle-based.
|
|
27
|
+
*
|
|
28
|
+
* Tune with `CODEGRAPH_STARTUP_HANDSHAKE_TIMEOUT_MS`; `0` disables.
|
|
29
|
+
*/
|
|
30
|
+
/** Default wait for the first byte of MCP traffic before assuming orphaned. */
|
|
31
|
+
export declare const DEFAULT_STARTUP_HANDSHAKE_TIMEOUT_MS = 900000;
|
|
32
|
+
export declare const STARTUP_HANDSHAKE_TIMEOUT_ENV = "CODEGRAPH_STARTUP_HANDSHAKE_TIMEOUT_MS";
|
|
33
|
+
/**
|
|
34
|
+
* Parse the timeout env override. Missing/invalid → default; `<= 0` → `0`
|
|
35
|
+
* (disabled), the same disable convention as `CODEGRAPH_PPID_POLL_MS`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseStartupHandshakeTimeoutMs(raw: string | undefined): number;
|
|
38
|
+
/**
|
|
39
|
+
* Arm the backstop. `onAbandoned` runs at most once, only if no `'data'` event
|
|
40
|
+
* arrives on `stream` within the timeout. Returns a disarm function (idempotent;
|
|
41
|
+
* also detaches the listener). `stream`/`timeoutMs` are injectable for tests.
|
|
42
|
+
*/
|
|
43
|
+
export declare function armStartupHandshakeTimeout(onAbandoned: () => void, stream?: NodeJS.ReadableStream, timeoutMs?: number): () => void;
|
|
44
|
+
//# sourceMappingURL=startup-handshake.d.ts.map
|
package/dist/mcp/tools.d.ts
CHANGED
|
@@ -25,6 +25,28 @@ export declare class NotIndexedError extends Error {
|
|
|
25
25
|
*/
|
|
26
26
|
export declare class PathRefusalError extends Error {
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Normalize Erlang-native symbol spellings in an explore query into the shapes
|
|
30
|
+
* the rest of the pipeline already understands. Agents working Erlang code
|
|
31
|
+
* name symbols the way the language spells them — `mod:fn/3`, `init/2` — and
|
|
32
|
+
* those tokens previously died in both consumers: the flow-builder's token
|
|
33
|
+
* filter rejects `:` and `/arity` outright, and the search-side field parser
|
|
34
|
+
* eats `mod:fn` as an unknown `field:value`. Measured on cowboy: the agent
|
|
35
|
+
* named `cowboy_stream_h:request_process/3` in two queries, got no body back
|
|
36
|
+
* either time, and fell back to Read.
|
|
37
|
+
*
|
|
38
|
+
* - `fn/3` → `fn` (arity tail after an identifier; a path segment like
|
|
39
|
+
* `src/2fa` doesn't match because the tail must be all digits)
|
|
40
|
+
* - `mod:fn` → `mod.fn` (exactly one colon between identifiers, so it rides
|
|
41
|
+
* the existing Class.method qualified handling; `::`, URLs, drive letters,
|
|
42
|
+
* and times don't match, and the query language's own field prefixes —
|
|
43
|
+
* kind:/lang:/language:/path:/name: — are left alone)
|
|
44
|
+
*
|
|
45
|
+
* Safe cross-language: Lua's `t:m` spelling maps to the same `t.m` its
|
|
46
|
+
* qualified names use, and no other supported spelling contains a bare
|
|
47
|
+
* single-colon identifier pair.
|
|
48
|
+
*/
|
|
49
|
+
export declare function normalizeQuerySpelling(query: string): string;
|
|
28
50
|
/**
|
|
29
51
|
* Calculate the recommended number of codegraph_explore calls based on project size.
|
|
30
52
|
* Larger codebases need more exploration calls to cover their surface area,
|
package/dist/project-config.d.ts
CHANGED
|
@@ -23,6 +23,20 @@ export interface ProjectConfig {
|
|
|
23
23
|
* and your `.gitignore`.
|
|
24
24
|
*/
|
|
25
25
|
exclude?: string[];
|
|
26
|
+
/**
|
|
27
|
+
* Gitignore-style patterns for first-party source to force INTO the index even
|
|
28
|
+
* when `.gitignore` would drop it — the general whitelist `includeIgnored`
|
|
29
|
+
* never was (that one only revives *embedded git repos* inside ignored dirs).
|
|
30
|
+
* The case this exists for: a project under a second VCS (SVN, Perforce, …)
|
|
31
|
+
* deliberately `.gitignore`s its own real source so it never lands in Git, yet
|
|
32
|
+
* that source must still be indexed. Matched against project-root-relative
|
|
33
|
+
* paths, so `"Tools/"`, a recursive `"Tools/**"` glob, or `"Local/typescript"`
|
|
34
|
+
* all work.
|
|
35
|
+
* Built-in default-ignored dirs (`node_modules`, `dist`, …), `.git`, and
|
|
36
|
+
* CodeGraph's own data dir are never resurfaced; an explicit `exclude` still
|
|
37
|
+
* wins. Absent/empty (the default) forces nothing in.
|
|
38
|
+
*/
|
|
39
|
+
include?: string[];
|
|
26
40
|
}
|
|
27
41
|
/**
|
|
28
42
|
* Load the validated extension overrides for a project, mtime-cached.
|
|
@@ -51,6 +65,30 @@ export declare function loadIncludeIgnoredPatterns(rootDir: string): string[];
|
|
|
51
65
|
* the built-in defaults and the project's `.gitignore`.
|
|
52
66
|
*/
|
|
53
67
|
export declare function loadExcludePatterns(rootDir: string): string[];
|
|
68
|
+
/**
|
|
69
|
+
* Load the validated `include` patterns for a project, mtime-cached.
|
|
70
|
+
*
|
|
71
|
+
* These name first-party source to force INTO the index even when `.gitignore`
|
|
72
|
+
* would drop it — the whitelist for SVN/Perforce-only source a project
|
|
73
|
+
* gitignores out of Git. An empty result — the zero-config default — forces
|
|
74
|
+
* nothing in. Built-in default-ignored dirs, `.git`, and CodeGraph's data dir
|
|
75
|
+
* are never resurfaced, and an explicit `exclude` still wins.
|
|
76
|
+
*/
|
|
77
|
+
export declare function loadIncludePatterns(rootDir: string): string[];
|
|
54
78
|
/** Test/maintenance hook: forget cached config (e.g. after rewriting it in a test). */
|
|
55
79
|
export declare function clearProjectConfigCache(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Add gitignore-style patterns to a project's `codegraph.json` `includeIgnored`
|
|
82
|
+
* list, creating the file if absent and preserving every other key. Used by the
|
|
83
|
+
* CLI to opt a "super-repo of gitignored child repos" (#1156) into the index on
|
|
84
|
+
* the user's say-so. Returns the count of patterns actually ADDED (ones already
|
|
85
|
+
* present are skipped, so a re-run is idempotent).
|
|
86
|
+
*
|
|
87
|
+
* A plain-JSON round-trip: a `codegraph.json` carrying comments (not valid JSON)
|
|
88
|
+
* already fails to load with a warning, so rather than silently clobber such a
|
|
89
|
+
* file this throws when an existing config won't parse — the caller falls back
|
|
90
|
+
* to printing the manual snippet. Invalidates the config cache so a subsequent
|
|
91
|
+
* index in the same process sees the new patterns.
|
|
92
|
+
*/
|
|
93
|
+
export declare function addIncludeIgnoredPatterns(rootDir: string, patterns: string[]): number;
|
|
56
94
|
//# sourceMappingURL=project-config.d.ts.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Edge } from '../types';
|
|
2
2
|
import type { QueryBuilder } from '../db/queries';
|
|
3
3
|
import type { ResolutionContext } from './types';
|
|
4
|
-
|
|
4
|
+
import type { MaybeYield } from './cooperative-yield';
|
|
5
|
+
export declare function cFnPointerDispatchEdges(_queries: QueryBuilder, ctx: ResolutionContext, onYield: MaybeYield): Promise<Edge[]>;
|
|
5
6
|
//# sourceMappingURL=c-fnptr-synthesizer.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CICS Framework Resolver (COBOL)
|
|
3
|
+
*
|
|
4
|
+
* Resolves the pseudo-conversational transaction hop: a program ends with
|
|
5
|
+
* `EXEC CICS RETURN TRANSID('CB00')` (or START), and CICS re-invokes the
|
|
6
|
+
* program that OWNS transaction CB00 on the next attention key. The
|
|
7
|
+
* transaction→program mapping lives in the CICS CSD, which is never in the
|
|
8
|
+
* repo — but by near-universal convention each program declares its own
|
|
9
|
+
* transaction id as a working-storage constant:
|
|
10
|
+
*
|
|
11
|
+
* 05 WS-TRANID PIC X(04) VALUE 'CB00'.
|
|
12
|
+
*
|
|
13
|
+
* The COBOL extractor emits `cics-transid:CB00` call references for literal
|
|
14
|
+
* (or same-file-dereferenced) TRANSID options; this resolver maps the id to
|
|
15
|
+
* the program module whose TRAN*-named data item declares that VALUE. No
|
|
16
|
+
* match (an id owned by a program outside the repo) stays unresolved.
|
|
17
|
+
*/
|
|
18
|
+
import { FrameworkResolver } from '../types';
|
|
19
|
+
export declare const cicsResolver: FrameworkResolver;
|
|
20
|
+
//# sourceMappingURL=cics.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terraform Framework Resolver
|
|
3
|
+
*
|
|
4
|
+
* Terraform's scoping rule is narrow and directory-shaped: `var.X`,
|
|
5
|
+
* `local.X`, `module.M`, and resource/data references resolve ONLY inside
|
|
6
|
+
* the same module directory as the reference site. The generic name matcher
|
|
7
|
+
* resolves by qualified-name alone, so a reference to `var.project_id` from
|
|
8
|
+
* `modules/net-vpc/main.tf` could bind to a `variable "project_id"` declared
|
|
9
|
+
* in an unrelated module — a wrong cross-module edge that poisons impact
|
|
10
|
+
* analysis. This resolver enforces the real semantics:
|
|
11
|
+
*
|
|
12
|
+
* 1. Same directory as the reference site → resolve (highest confidence).
|
|
13
|
+
* 2. `.tfvars` files additionally walk UP to the nearest ancestor
|
|
14
|
+
* directory declaring the variable (`terraform apply -var-file=envs/prod.tfvars`
|
|
15
|
+
* sets ROOT module variables from a subdirectory).
|
|
16
|
+
* 3. Otherwise: no edge. Terraform cannot reference across sibling module
|
|
17
|
+
* directories, so a non-local candidate is never a correct target.
|
|
18
|
+
*
|
|
19
|
+
* It also bridges the module boundary through `:`-scoped references that
|
|
20
|
+
* only this resolver understands (see the extractor's emitModuleWiring):
|
|
21
|
+
*
|
|
22
|
+
* - `module.M:file` → the entry file of the module's local source
|
|
23
|
+
* directory (an `imports` edge, so a module call connects to the code
|
|
24
|
+
* it instantiates).
|
|
25
|
+
* - `module.M:var.<in>` → the child module's `variable "<in>"` node —
|
|
26
|
+
* the module block sets that variable, so "what depends on the child's
|
|
27
|
+
* var.cidr" reaches every caller.
|
|
28
|
+
* - `module.M:output.<o>` → the child module's `output "<o>"` node —
|
|
29
|
+
* `module.M.o` uses flow through to the output's definition instead of
|
|
30
|
+
* dead-ending at the module declaration.
|
|
31
|
+
*
|
|
32
|
+
* The module's `source` is re-read from the declaration's file (cached
|
|
33
|
+
* lines); only local `./`/`../` sources bridge. Registry/git sources stay
|
|
34
|
+
* unresolved — an out-of-repo module is a visible boundary, never a guess.
|
|
35
|
+
*/
|
|
36
|
+
import type { FrameworkResolver } from '../types';
|
|
37
|
+
export declare const terraformResolver: FrameworkResolver;
|
|
38
|
+
//# sourceMappingURL=terraform.d.ts.map
|
|
@@ -24,5 +24,6 @@
|
|
|
24
24
|
*/
|
|
25
25
|
import type { Edge } from '../types';
|
|
26
26
|
import type { ResolutionContext } from './types';
|
|
27
|
-
|
|
27
|
+
import type { MaybeYield } from './cooperative-yield';
|
|
28
|
+
export declare function goframeRouteEdges(ctx: ResolutionContext, onYield: MaybeYield): Promise<Edge[]>;
|
|
28
29
|
//# sourceMappingURL=goframe-synthesizer.d.ts.map
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Language } from '../types';
|
|
7
7
|
import { UnresolvedRef, ResolvedRef, ResolutionContext, ImportMapping, ReExport } from './types';
|
|
8
|
+
export declare function isNixPathImportRef(ref: UnresolvedRef): boolean;
|
|
8
9
|
/**
|
|
9
10
|
* Resolve an import path to an actual file
|
|
10
11
|
*/
|
|
@@ -37,6 +38,12 @@ export declare function loadCppIncludeDirs(projectRoot: string): string[];
|
|
|
37
38
|
* to a same-named symbol — so callers must not fall back to the name-matcher.
|
|
38
39
|
*/
|
|
39
40
|
export declare function isPhpIncludePathRef(ref: UnresolvedRef): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Is this a COBOL COPY / EXEC SQL INCLUDE copybook reference? These resolve
|
|
43
|
+
* to files only (or stay unresolved for compiler-supplied members) — never
|
|
44
|
+
* to a same-named symbol via the name-matcher.
|
|
45
|
+
*/
|
|
46
|
+
export declare function isCobolCopybookRef(ref: UnresolvedRef): boolean;
|
|
40
47
|
/**
|
|
41
48
|
* Extract import mappings from a file
|
|
42
49
|
*/
|