contextsliver 0.1.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.
Files changed (134) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +130 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +156 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/graph/rank.d.ts +9 -0
  8. package/dist/graph/rank.d.ts.map +1 -0
  9. package/dist/graph/rank.js +10 -0
  10. package/dist/graph/rank.js.map +1 -0
  11. package/dist/graph/schema.d.ts +4 -0
  12. package/dist/graph/schema.d.ts.map +1 -0
  13. package/dist/graph/schema.js +74 -0
  14. package/dist/graph/schema.js.map +1 -0
  15. package/dist/graph/store.d.ts +56 -0
  16. package/dist/graph/store.d.ts.map +1 -0
  17. package/dist/graph/store.js +163 -0
  18. package/dist/graph/store.js.map +1 -0
  19. package/dist/graph/traverse.d.ts +20 -0
  20. package/dist/graph/traverse.d.ts.map +1 -0
  21. package/dist/graph/traverse.js +81 -0
  22. package/dist/graph/traverse.js.map +1 -0
  23. package/dist/graph/types.d.ts +48 -0
  24. package/dist/graph/types.d.ts.map +1 -0
  25. package/dist/graph/types.js +4 -0
  26. package/dist/graph/types.js.map +1 -0
  27. package/dist/index.d.ts +13 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +16 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/mcp/responses.d.ts +19 -0
  32. package/dist/mcp/responses.d.ts.map +1 -0
  33. package/dist/mcp/responses.js +25 -0
  34. package/dist/mcp/responses.js.map +1 -0
  35. package/dist/mcp/server.d.ts +16 -0
  36. package/dist/mcp/server.d.ts.map +1 -0
  37. package/dist/mcp/server.js +88 -0
  38. package/dist/mcp/server.js.map +1 -0
  39. package/dist/mcp/tools/cs_blast_radius.d.ts +3 -0
  40. package/dist/mcp/tools/cs_blast_radius.d.ts.map +1 -0
  41. package/dist/mcp/tools/cs_blast_radius.js +96 -0
  42. package/dist/mcp/tools/cs_blast_radius.js.map +1 -0
  43. package/dist/mcp/tools/cs_get_context.d.ts +3 -0
  44. package/dist/mcp/tools/cs_get_context.d.ts.map +1 -0
  45. package/dist/mcp/tools/cs_get_context.js +80 -0
  46. package/dist/mcp/tools/cs_get_context.js.map +1 -0
  47. package/dist/mcp/tools/cs_index_repo.d.ts +3 -0
  48. package/dist/mcp/tools/cs_index_repo.d.ts.map +1 -0
  49. package/dist/mcp/tools/cs_index_repo.js +45 -0
  50. package/dist/mcp/tools/cs_index_repo.js.map +1 -0
  51. package/dist/mcp/tools/cs_index_status.d.ts +3 -0
  52. package/dist/mcp/tools/cs_index_status.d.ts.map +1 -0
  53. package/dist/mcp/tools/cs_index_status.js +31 -0
  54. package/dist/mcp/tools/cs_index_status.js.map +1 -0
  55. package/dist/mcp/tools/cs_search_symbols.d.ts +3 -0
  56. package/dist/mcp/tools/cs_search_symbols.d.ts.map +1 -0
  57. package/dist/mcp/tools/cs_search_symbols.js +51 -0
  58. package/dist/mcp/tools/cs_search_symbols.js.map +1 -0
  59. package/dist/mcp/tools/index.d.ts +4 -0
  60. package/dist/mcp/tools/index.d.ts.map +1 -0
  61. package/dist/mcp/tools/index.js +14 -0
  62. package/dist/mcp/tools/index.js.map +1 -0
  63. package/dist/mcp/types.d.ts +22 -0
  64. package/dist/mcp/types.d.ts.map +1 -0
  65. package/dist/mcp/types.js +2 -0
  66. package/dist/mcp/types.js.map +1 -0
  67. package/dist/parser/extractor.d.ts +16 -0
  68. package/dist/parser/extractor.d.ts.map +1 -0
  69. package/dist/parser/extractor.js +304 -0
  70. package/dist/parser/extractor.js.map +1 -0
  71. package/dist/parser/index.d.ts +30 -0
  72. package/dist/parser/index.d.ts.map +1 -0
  73. package/dist/parser/index.js +270 -0
  74. package/dist/parser/index.js.map +1 -0
  75. package/dist/parser/languages/python.d.ts +3 -0
  76. package/dist/parser/languages/python.d.ts.map +1 -0
  77. package/dist/parser/languages/python.js +14 -0
  78. package/dist/parser/languages/python.js.map +1 -0
  79. package/dist/parser/languages/query-loader.d.ts +10 -0
  80. package/dist/parser/languages/query-loader.d.ts.map +1 -0
  81. package/dist/parser/languages/query-loader.js +33 -0
  82. package/dist/parser/languages/query-loader.js.map +1 -0
  83. package/dist/parser/languages/registry.d.ts +25 -0
  84. package/dist/parser/languages/registry.d.ts.map +1 -0
  85. package/dist/parser/languages/registry.js +33 -0
  86. package/dist/parser/languages/registry.js.map +1 -0
  87. package/dist/parser/languages/typescript.d.ts +11 -0
  88. package/dist/parser/languages/typescript.d.ts.map +1 -0
  89. package/dist/parser/languages/typescript.js +26 -0
  90. package/dist/parser/languages/typescript.js.map +1 -0
  91. package/dist/parser/types.d.ts +36 -0
  92. package/dist/parser/types.d.ts.map +1 -0
  93. package/dist/parser/types.js +2 -0
  94. package/dist/parser/types.js.map +1 -0
  95. package/dist/session/manager.d.ts +28 -0
  96. package/dist/session/manager.d.ts.map +1 -0
  97. package/dist/session/manager.js +82 -0
  98. package/dist/session/manager.js.map +1 -0
  99. package/dist/session/pruner.d.ts +28 -0
  100. package/dist/session/pruner.d.ts.map +1 -0
  101. package/dist/session/pruner.js +24 -0
  102. package/dist/session/pruner.js.map +1 -0
  103. package/dist/session/types.d.ts +21 -0
  104. package/dist/session/types.d.ts.map +1 -0
  105. package/dist/session/types.js +4 -0
  106. package/dist/session/types.js.map +1 -0
  107. package/dist/utils/logger.d.ts +13 -0
  108. package/dist/utils/logger.d.ts.map +1 -0
  109. package/dist/utils/logger.js +36 -0
  110. package/dist/utils/logger.js.map +1 -0
  111. package/dist/utils/paths.d.ts +24 -0
  112. package/dist/utils/paths.d.ts.map +1 -0
  113. package/dist/utils/paths.js +55 -0
  114. package/dist/utils/paths.js.map +1 -0
  115. package/dist/utils/tokens.d.ts +10 -0
  116. package/dist/utils/tokens.d.ts.map +1 -0
  117. package/dist/utils/tokens.js +28 -0
  118. package/dist/utils/tokens.js.map +1 -0
  119. package/dist/watcher/hasher.d.ts +11 -0
  120. package/dist/watcher/hasher.d.ts.map +1 -0
  121. package/dist/watcher/hasher.js +29 -0
  122. package/dist/watcher/hasher.js.map +1 -0
  123. package/dist/watcher/index.d.ts +9 -0
  124. package/dist/watcher/index.d.ts.map +1 -0
  125. package/dist/watcher/index.js +100 -0
  126. package/dist/watcher/index.js.map +1 -0
  127. package/grammars/python/tags.scm +16 -0
  128. package/grammars/typescript/tags.scm +39 -0
  129. package/hooks/pre-tool-use.js +46 -0
  130. package/package.json +89 -0
  131. package/templates/CLAUDE.md +50 -0
  132. package/templates/mcp-config-claude-code.json +9 -0
  133. package/templates/mcp-config-cline.json +15 -0
  134. package/templates/mcp-config-cursor.json +9 -0
@@ -0,0 +1,163 @@
1
+ import { SCHEMA_SQL } from './schema.js';
2
+ export class GraphStore {
3
+ db;
4
+ constructor(db) {
5
+ this.db = db;
6
+ this.db.exec(SCHEMA_SQL);
7
+ }
8
+ // ── files ──────────────────────────────────────────────────────────────────
9
+ /** Insert or replace a file row. Returns the file id. */
10
+ upsertFile(path, contentHash, language) {
11
+ const stmt = this.db.prepare(`
12
+ INSERT INTO files (path, content_hash, indexed_at, language)
13
+ VALUES (?, ?, ?, ?)
14
+ ON CONFLICT(path) DO UPDATE SET
15
+ content_hash = excluded.content_hash,
16
+ indexed_at = excluded.indexed_at,
17
+ language = excluded.language
18
+ RETURNING id
19
+ `);
20
+ const row = stmt.get(path, contentHash, Date.now(), language);
21
+ if (!row) {
22
+ // RETURNING not matched (shouldn't happen) — fall back to SELECT
23
+ return this.getFileId(path);
24
+ }
25
+ return row.id;
26
+ }
27
+ getFileId(path) {
28
+ const row = this.db.prepare('SELECT id FROM files WHERE path = ?').get(path);
29
+ return row?.id;
30
+ }
31
+ getFile(path) {
32
+ return this.db
33
+ .prepare('SELECT id, path, content_hash, indexed_at, language FROM files WHERE path = ?')
34
+ .get(path);
35
+ }
36
+ /** Delete a file and cascade-delete its symbols (and their edges via ON DELETE CASCADE). */
37
+ deleteFile(path) {
38
+ this.db.prepare('DELETE FROM files WHERE path = ?').run(path);
39
+ }
40
+ /** All indexed files. Used for full re-index accounting. */
41
+ countFiles() {
42
+ const row = this.db.prepare('SELECT COUNT(*) AS n FROM files').get();
43
+ return row.n;
44
+ }
45
+ /** Hash of a file's content as stored at last index, or undefined if not indexed. */
46
+ getFileHash(path) {
47
+ const row = this.db.prepare('SELECT content_hash FROM files WHERE path = ?').get(path);
48
+ return row?.content_hash;
49
+ }
50
+ // ── symbols ────────────────────────────────────────────────────────────────
51
+ /** Insert a symbol for a file. Returns the new symbol id. */
52
+ insertSymbol(sym) {
53
+ const stmt = this.db.prepare(`
54
+ INSERT INTO symbols (file_id, name, kind, line_start, line_end, signature, package)
55
+ VALUES (@file_id, @name, @kind, @line_start, @line_end, @signature, @package)
56
+ RETURNING id
57
+ `);
58
+ const row = stmt.get(sym);
59
+ return row.id;
60
+ }
61
+ /** Remove all symbols belonging to a file (edges cascade). Used before re-inserting. */
62
+ deleteFileSymbols(fileId) {
63
+ this.db.prepare('DELETE FROM symbols WHERE file_id = ?').run(fileId);
64
+ }
65
+ /** Find a symbol by exact name (first match). Returns the enriched SymbolRow. */
66
+ findSymbolByName(name) {
67
+ return this.db
68
+ .prepare(`SELECT s.id, s.name, s.kind, s.file_id, s.line_start, s.line_end, s.signature, s.package,
69
+ f.path AS file_path
70
+ FROM symbols s JOIN files f ON f.id = s.file_id
71
+ WHERE s.name = ?
72
+ LIMIT 1`)
73
+ .get(name);
74
+ }
75
+ /** All symbols matching a name (names are not globally unique). */
76
+ findSymbolsByName(name) {
77
+ return this.db
78
+ .prepare(`SELECT s.id, s.name, s.kind, s.file_id, s.line_start, s.line_end, s.signature, s.package,
79
+ f.path AS file_path
80
+ FROM symbols s JOIN files f ON f.id = s.file_id
81
+ WHERE s.name = ?`)
82
+ .all(name);
83
+ }
84
+ /** Full-row symbol by id (joined with file path). */
85
+ getSymbol(id) {
86
+ return this.db
87
+ .prepare(`SELECT s.id, s.name, s.kind, s.file_id, s.line_start, s.line_end, s.signature, s.package,
88
+ f.path AS file_path
89
+ FROM symbols s JOIN files f ON f.id = s.file_id
90
+ WHERE s.id = ?`)
91
+ .get(id);
92
+ }
93
+ /** FTS-lite substring search across symbol name + file path. Used by cs_search_symbols. */
94
+ searchSymbols(query, limit) {
95
+ const like = `%${query.replace(/[%_]/g, (m) => '\\' + m)}%`;
96
+ return this.db
97
+ .prepare(`SELECT s.id, s.name, s.kind, s.file_id, s.line_start, s.line_end, s.signature, s.package,
98
+ f.path AS file_path
99
+ FROM symbols s JOIN files f ON f.id = s.file_id
100
+ WHERE s.name LIKE ? ESCAPE '\\' OR f.path LIKE ? ESCAPE '\\'
101
+ ORDER BY
102
+ CASE WHEN s.name LIKE ? ESCAPE '\\' THEN 0 ELSE 1 END,
103
+ s.name
104
+ LIMIT ?`)
105
+ .all(like, like, like, limit);
106
+ }
107
+ /** Look up a symbol by name within a specific file (for import resolution). */
108
+ findSymbolInFile(fileId, name) {
109
+ return this.db
110
+ .prepare(`SELECT s.id, s.name, s.kind, s.file_id, s.line_start, s.line_end, s.signature, s.package,
111
+ f.path AS file_path
112
+ FROM symbols s JOIN files f ON f.id = s.file_id
113
+ WHERE s.file_id = ? AND s.name = ?
114
+ LIMIT 1`)
115
+ .get(fileId, name);
116
+ }
117
+ // ── edges ───────────────────────────────────────────────────────────────────
118
+ /** Insert an edge (UNIQUE constraint dedupes on from/to/kind). Ignores if exists. */
119
+ insertEdge(fromId, toId, kind) {
120
+ this.db
121
+ .prepare('INSERT OR IGNORE INTO edges (from_id, to_id, kind) VALUES (?, ?, ?)')
122
+ .run(fromId, toId, kind);
123
+ }
124
+ /** Symbols this symbol points to (forward edges), any kind. */
125
+ getDependencies(symbolId) {
126
+ return this.db
127
+ .prepare(`SELECT s.id, s.name, s.kind, s.file_id, s.line_start, s.line_end, s.signature, s.package,
128
+ f.path AS file_path
129
+ FROM edges e JOIN symbols s ON s.id = e.to_id JOIN files f ON f.id = s.file_id
130
+ WHERE e.from_id = ?`)
131
+ .all(symbolId);
132
+ }
133
+ /** Symbols that point to this one (reverse edges), any kind. */
134
+ getCallers(symbolId) {
135
+ return this.db
136
+ .prepare(`SELECT s.id, s.name, s.kind, s.file_id, s.line_start, s.line_end, s.signature, s.package,
137
+ f.path AS file_path
138
+ FROM edges e JOIN symbols s ON s.id = e.from_id JOIN files f ON f.id = s.file_id
139
+ WHERE e.to_id = ?`)
140
+ .all(symbolId);
141
+ }
142
+ // ── misc ────────────────────────────────────────────────────────────────────
143
+ /** Run a function inside a DB transaction (batches writes). */
144
+ transaction(fn) {
145
+ return this.db.transaction(fn)();
146
+ }
147
+ /** Expose the raw db for traversal/manager modules that need their own prepared statements. */
148
+ get raw() {
149
+ return this.db;
150
+ }
151
+ /** Index health stats for cs_index_status. */
152
+ stats() {
153
+ const row = this.db
154
+ .prepare(`SELECT
155
+ (SELECT COUNT(*) FROM files) AS files,
156
+ (SELECT COUNT(*) FROM symbols) AS symbols,
157
+ (SELECT COUNT(*) FROM edges) AS edges,
158
+ (SELECT MAX(indexed_at) FROM files) AS lastIndexedAt`)
159
+ .get();
160
+ return row;
161
+ }
162
+ }
163
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/graph/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { SymbolRow, TraversalResult } from './types.js';
3
+ /**
4
+ * Compute the blast radius around a symbol up to maxDepth hops.
5
+ *
6
+ * @param db - the open SQLite database
7
+ * @param symbolId - focal symbol id
8
+ * @param maxDepth - max hops (default 2). Clamped to [1, 4] by callers.
9
+ * @returns the focal symbol + callers + dependencies, or null if symbol not found.
10
+ */
11
+ export declare function blastRadius(db: Database.Database, symbolId: number, maxDepth?: number): TraversalResult | null;
12
+ /**
13
+ * Convenience: get ONLY direct (1-hop) neighbors. Used by cs_get_context for the lightweight
14
+ * "what does this symbol touch" view.
15
+ */
16
+ export declare function directNeighbors(db: Database.Database, symbolId: number): {
17
+ callers: SymbolRow[];
18
+ dependencies: SymbolRow[];
19
+ };
20
+ //# sourceMappingURL=traverse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverse.d.ts","sourceRoot":"","sources":["../../src/graph/traverse.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7D;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,MAAU,GACnB,eAAe,GAAG,IAAI,CAQxB;AAwED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,EAAE,MAAM,GACf;IAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IAAC,YAAY,EAAE,SAAS,EAAE,CAAA;CAAE,CAKrD"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Compute the blast radius around a symbol up to maxDepth hops.
3
+ *
4
+ * @param db - the open SQLite database
5
+ * @param symbolId - focal symbol id
6
+ * @param maxDepth - max hops (default 2). Clamped to [1, 4] by callers.
7
+ * @returns the focal symbol + callers + dependencies, or null if symbol not found.
8
+ */
9
+ export function blastRadius(db, symbolId, maxDepth = 2) {
10
+ const focal = getSymbolJoined(db, symbolId);
11
+ if (!focal)
12
+ return null;
13
+ const dependencies = bfsForward(db, symbolId, maxDepth);
14
+ const callers = bfsReverse(db, symbolId, maxDepth);
15
+ return { symbol: focal, callers, dependencies, depth: maxDepth };
16
+ }
17
+ /** Get a symbol joined with its file path. */
18
+ function getSymbolJoined(db, symbolId) {
19
+ return db
20
+ .prepare(`SELECT s.id, s.name, s.kind, s.file_id, s.line_start, s.line_end, s.signature, s.package,
21
+ f.path AS file_path
22
+ FROM symbols s JOIN files f ON f.id = s.file_id
23
+ WHERE s.id = ?`)
24
+ .get(symbolId);
25
+ }
26
+ /**
27
+ * BFS forward (dependencies): what does this symbol reference?
28
+ * Follows edges where from_id = current. Returns symbols at depth 1..maxDepth.
29
+ */
30
+ function bfsForward(db, startId, maxDepth) {
31
+ const stmt = db.prepare(`SELECT s.id, s.name, s.kind, s.file_id, s.line_start, s.line_end, s.signature, s.package,
32
+ f.path AS file_path
33
+ FROM edges e JOIN symbols s ON s.id = e.to_id JOIN files f ON f.id = s.file_id
34
+ WHERE e.from_id = ?`);
35
+ return bfs(db, startId, maxDepth, (id) => stmt.all(id));
36
+ }
37
+ /**
38
+ * BFS reverse (callers): who references this symbol?
39
+ * Follows edges where to_id = current. Returns symbols at depth 1..maxDepth.
40
+ */
41
+ function bfsReverse(db, startId, maxDepth) {
42
+ const stmt = db.prepare(`SELECT s.id, s.name, s.kind, s.file_id, s.line_start, s.line_end, s.signature, s.package,
43
+ f.path AS file_path
44
+ FROM edges e JOIN symbols s ON s.id = e.from_id JOIN files f ON f.id = s.file_id
45
+ WHERE e.to_id = ?`);
46
+ return bfs(db, startId, maxDepth, (id) => stmt.all(id));
47
+ }
48
+ /**
49
+ * Generic BFS. The `neighbors` callback returns the adjacent symbols for a given id,
50
+ * already filtered to the desired edge direction. The visited set guarantees termination
51
+ * on cycles.
52
+ */
53
+ function bfs(_db, startId, maxDepth, neighbors) {
54
+ const visited = new Set([startId]);
55
+ const queue = [{ id: startId, depth: 0 }];
56
+ const results = [];
57
+ while (queue.length > 0) {
58
+ const { id, depth } = queue.shift();
59
+ if (depth >= maxDepth)
60
+ continue;
61
+ for (const neighbor of neighbors(id)) {
62
+ if (visited.has(neighbor.id))
63
+ continue; // cycle: already seen, skip
64
+ visited.add(neighbor.id);
65
+ results.push(neighbor);
66
+ queue.push({ id: neighbor.id, depth: depth + 1 });
67
+ }
68
+ }
69
+ return results;
70
+ }
71
+ /**
72
+ * Convenience: get ONLY direct (1-hop) neighbors. Used by cs_get_context for the lightweight
73
+ * "what does this symbol touch" view.
74
+ */
75
+ export function directNeighbors(db, symbolId) {
76
+ return {
77
+ dependencies: bfsForward(db, symbolId, 1),
78
+ callers: bfsReverse(db, symbolId, 1),
79
+ };
80
+ }
81
+ //# sourceMappingURL=traverse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverse.js","sourceRoot":"","sources":["../../src/graph/traverse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /** A row of the `symbols` table joined with its owning file path. */
2
+ export interface SymbolRow {
3
+ id: number;
4
+ name: string;
5
+ kind: SymbolKind;
6
+ /** posix project-relative path of the file containing this symbol */
7
+ file_path: string;
8
+ file_id?: number;
9
+ line_start: number;
10
+ line_end: number;
11
+ signature: string | null;
12
+ package: string | null;
13
+ }
14
+ export type SymbolKind = 'function' | 'class' | 'interface' | 'variable' | 'type';
15
+ /** Edge kinds (see `edges.kind`). */
16
+ export type EdgeKind = 'calls' | 'imports' | 'extends' | 'implements' | 'uses';
17
+ /** A directed edge between two symbols. */
18
+ export interface EdgeRow {
19
+ id: number;
20
+ from_id: number;
21
+ to_id: number;
22
+ kind: EdgeKind;
23
+ }
24
+ /** A row of the `files` table. */
25
+ export interface FileRow {
26
+ id: number;
27
+ path: string;
28
+ content_hash: string;
29
+ indexed_at: number;
30
+ language: string;
31
+ }
32
+ /** Compact representation returned by MCP tools (no internal ids leaked). */
33
+ export interface SymbolRef {
34
+ name: string;
35
+ file: string;
36
+ kind: string;
37
+ signature?: string | null;
38
+ }
39
+ /** Result of a blast-radius traversal — the core query for cs_blast_radius / cs_get_context. */
40
+ export interface TraversalResult {
41
+ symbol: SymbolRow;
42
+ /** who uses this symbol (reverse edges) */
43
+ callers: SymbolRow[];
44
+ /** what this symbol uses (forward edges) */
45
+ dependencies: SymbolRow[];
46
+ depth: number;
47
+ }
48
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/graph/types.ts"],"names":[],"mappings":"AAGA,qEAAqE;AACrE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,CAAC;IACjB,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAElF,qCAAqC;AACrC,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,CAAC;AAE/E,2CAA2C;AAC3C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,kCAAkC;AAClC,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,6EAA6E;AAC7E,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,gGAAgG;AAChG,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,CAAC;IAClB,2CAA2C;IAC3C,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,4CAA4C;IAC5C,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;CACf"}
@@ -0,0 +1,4 @@
1
+ // Shared graph types. These describe the rows that come back from SQLite queries,
2
+ // plus the public traversal result shape returned to the MCP tools.
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/graph/types.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,oEAAoE"}
@@ -0,0 +1,13 @@
1
+ export { GraphStore } from './graph/store.js';
2
+ export { blastRadius, directNeighbors } from './graph/traverse.js';
3
+ export { SCHEMA_SQL } from './graph/schema.js';
4
+ export { SessionManager } from './session/manager.js';
5
+ export { indexFile, indexRepository } from './parser/index.js';
6
+ export { extractSymbols } from './parser/extractor.js';
7
+ export { startMCPServer } from './mcp/server.js';
8
+ export { countTokens } from './utils/tokens.js';
9
+ export type { SymbolRow, TraversalResult, SymbolKind, EdgeKind } from './graph/types.js';
10
+ export type { ParseResult, ExtractedSymbol, ExtractedImport } from './parser/types.js';
11
+ export type { ServerOptions } from './mcp/server.js';
12
+ export type { ToolContext } from './mcp/types.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACzF,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACvF,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ // Package entry point.
2
+ //
3
+ // ContextSliver is primarily a CLI + MCP server (run via `npx contextsliver start`), but this
4
+ // module re-exports the core building blocks so the engine can be embedded programmatically:
5
+ //
6
+ // import { GraphStore, SessionManager, indexRepository } from 'contextsliver';
7
+ //
8
+ export { GraphStore } from './graph/store.js';
9
+ export { blastRadius, directNeighbors } from './graph/traverse.js';
10
+ export { SCHEMA_SQL } from './graph/schema.js';
11
+ export { SessionManager } from './session/manager.js';
12
+ export { indexFile, indexRepository } from './parser/index.js';
13
+ export { extractSymbols } from './parser/extractor.js';
14
+ export { startMCPServer } from './mcp/server.js';
15
+ export { countTokens } from './utils/tokens.js';
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,EAAE;AACF,8FAA8F;AAC9F,6FAA6F;AAC7F,EAAE;AACF,iFAAiF;AACjF,EAAE;AACF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /** A standard MCP tool response: an array of text content blocks. */
2
+ export interface ToolResponse {
3
+ [x: string]: unknown;
4
+ content: Array<{
5
+ type: 'text';
6
+ text: string;
7
+ }>;
8
+ isError?: boolean;
9
+ }
10
+ /**
11
+ * Build a text response from a JSON-serializable payload, annotated with an approximate
12
+ * token count so the agent can reason about its context budget.
13
+ */
14
+ export declare function textResponse(payload: unknown, opts?: {
15
+ annotateTokens?: boolean;
16
+ }): ToolResponse;
17
+ /** Build an error response (isError=true) so the client surfaces it as a tool failure. */
18
+ export declare function errorResponse(message: string, hint?: string): ToolResponse;
19
+ //# sourceMappingURL=responses.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses.d.ts","sourceRoot":"","sources":["../../src/mcp/responses.ts"],"names":[],"mappings":"AAIA,qEAAqE;AACrE,MAAM,WAAW,YAAY;IAG3B,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,YAAY,CAKhG;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,CAQ1E"}
@@ -0,0 +1,25 @@
1
+ // Shared MCP response helpers. Keeps tool handlers thin and the response shape consistent
2
+ // across all five tools.
3
+ import { countTokens } from '../utils/tokens.js';
4
+ /**
5
+ * Build a text response from a JSON-serializable payload, annotated with an approximate
6
+ * token count so the agent can reason about its context budget.
7
+ */
8
+ export function textResponse(payload, opts) {
9
+ const text = JSON.stringify(payload, null, 2);
10
+ const annotate = opts?.annotateTokens ?? true;
11
+ const out = annotate ? `${text}\n\n// ~${countTokens(text)} tokens` : text;
12
+ return { content: [{ type: 'text', text: out }] };
13
+ }
14
+ /** Build an error response (isError=true) so the client surfaces it as a tool failure. */
15
+ export function errorResponse(message, hint) {
16
+ const payload = { error: message };
17
+ if (hint)
18
+ payload.hint = hint;
19
+ const text = JSON.stringify(payload, null, 2);
20
+ return {
21
+ content: [{ type: 'text', text }],
22
+ isError: true,
23
+ };
24
+ }
25
+ //# sourceMappingURL=responses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses.js","sourceRoot":"","sources":["../../src/mcp/responses.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,yBAAyB;AACzB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAWjD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,OAAgB,EAAE,IAAmC;IAChF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,IAAI,EAAE,cAAc,IAAI,IAAI,CAAC;IAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,WAAW,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;AACpD,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,IAAa;IAC1D,MAAM,OAAO,GAA4B,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAC5D,IAAI,IAAI;QAAE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9C,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACjC,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface ServerOptions {
2
+ /** Absolute project root to index/serve. */
3
+ projectRoot: string;
4
+ /** Start the file watcher alongside the server (default true). */
5
+ watch?: boolean;
6
+ }
7
+ /**
8
+ * Start the ContextSliver MCP server (stdio transport). Blocks until the client disconnects.
9
+ *
10
+ * - ensures .sliver/ exists and opens index.db
11
+ * - creates the graph store + session manager
12
+ * - registers all tools
13
+ * - optionally starts the file watcher for incremental re-indexing
14
+ */
15
+ export declare function startMCPServer(opts: ServerOptions): Promise<void>;
16
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkEvE"}
@@ -0,0 +1,88 @@
1
+ // MCP server entry point.
2
+ //
3
+ // Sets up the high-level McpServer (current SDK API: server.registerTool with a Zod raw-shape
4
+ // inputSchema), opens the SQLite index, registers all five tools, and connects over stdio.
5
+ //
6
+ // CRITICAL: stdout is the JSON-RPC protocol channel. Nothing in this server path may write to
7
+ // stdout except the SDK transport itself. All our logging goes through utils/logger.ts → stderr.
8
+ // The stdout-purity integration test (test/integration/stdout-purity.test.ts) guards this.
9
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
10
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
11
+ import Database from 'better-sqlite3';
12
+ import { join } from 'node:path';
13
+ import { mkdirSync } from 'node:fs';
14
+ import { GraphStore } from '../graph/store.js';
15
+ import { SessionManager } from '../session/manager.js';
16
+ import { ALL_TOOLS } from './tools/index.js';
17
+ import { startWatcher } from '../watcher/index.js';
18
+ import { log, logError } from '../utils/logger.js';
19
+ /**
20
+ * Start the ContextSliver MCP server (stdio transport). Blocks until the client disconnects.
21
+ *
22
+ * - ensures .sliver/ exists and opens index.db
23
+ * - creates the graph store + session manager
24
+ * - registers all tools
25
+ * - optionally starts the file watcher for incremental re-indexing
26
+ */
27
+ export async function startMCPServer(opts) {
28
+ const projectRoot = opts.projectRoot;
29
+ const watch = opts.watch ?? true;
30
+ // 1. Ensure .sliver/ + open the database.
31
+ const sliverDir = join(projectRoot, '.sliver');
32
+ mkdirSync(sliverDir, { recursive: true });
33
+ const dbPath = join(sliverDir, 'index.db');
34
+ const db = new Database(dbPath);
35
+ const store = new GraphStore(db);
36
+ const sessionManager = new SessionManager(db);
37
+ // Opportunistic cleanup of stale sessions.
38
+ try {
39
+ const removed = sessionManager.cleanOldSessions();
40
+ if (removed > 0)
41
+ log(`Cleaned up ${removed} old session(s)`);
42
+ }
43
+ catch (err) {
44
+ logError(err);
45
+ }
46
+ // Self-healing: if the index is empty (e.g. server started without prior `init`), index the
47
+ // project now so the tools have something to query. This keeps `start` usable standalone.
48
+ try {
49
+ const stats = store.stats();
50
+ if (stats.files === 0) {
51
+ log('Index is empty; running initial index on startup');
52
+ const { indexRepository } = await import('../parser/index.js');
53
+ const result = indexRepository(store, projectRoot, { force: true });
54
+ log(`Startup index: ${result.filesIndexed} files, ${result.symbols} symbols, ${result.edges} edges`);
55
+ }
56
+ }
57
+ catch (err) {
58
+ // A failed startup index shouldn't kill the server — tools can still trigger cs_index_repo.
59
+ logError(err);
60
+ }
61
+ // 2. Build the tool context (shared by all tool handlers).
62
+ const ctx = { store, sessionManager, projectRoot };
63
+ // 3. Create the server and register tools.
64
+ const server = new McpServer({
65
+ name: 'contextsliver',
66
+ version: '0.1.0',
67
+ });
68
+ for (const tool of ALL_TOOLS) {
69
+ tool.register(server, ctx);
70
+ }
71
+ log(`Registered ${ALL_TOOLS.length} tool(s)`);
72
+ // 4. Optional file watcher for incremental re-indexing.
73
+ if (watch) {
74
+ try {
75
+ startWatcher(store, projectRoot);
76
+ }
77
+ catch (err) {
78
+ // A dead watcher shouldn't kill the server — log and continue (tools still work).
79
+ logError(err);
80
+ log('File watcher disabled; tools still operational', 'warn');
81
+ }
82
+ }
83
+ // 5. Connect over stdio. This blocks until the client closes the transport.
84
+ const transport = new StdioServerTransport();
85
+ await server.connect(transport);
86
+ log('ContextSliver MCP server running on stdio');
87
+ }
88
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ToolModule } from '../types.js';
2
+ export declare const csBlastRadiusTool: ToolModule;
3
+ //# sourceMappingURL=cs_blast_radius.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cs_blast_radius.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/cs_blast_radius.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAe,UAAU,EAAE,MAAM,aAAa,CAAC;AAE3D,eAAO,MAAM,iBAAiB,EAAE,UA2F/B,CAAC"}