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,14 @@
1
+ // Python language plugin.
2
+ //
3
+ // tree-sitter-python's default export is an object exposing the Language via both the object
4
+ // itself and a .language property (both are accepted by Parser.setLanguage and new Query).
5
+ // We pass the object directly — both setLanguage and Query accept it (verified at build time).
6
+ import Python from 'tree-sitter-python';
7
+ import { loadQuery } from './query-loader.js';
8
+ export const pythonPlugin = {
9
+ id: 'python',
10
+ extensions: ['.py', '.pyi'],
11
+ language: Python,
12
+ query: loadQuery('python'),
13
+ };
14
+ //# sourceMappingURL=python.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python.js","sourceRoot":"","sources":["../../../src/parser/languages/python.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,EAAE;AACF,6FAA6F;AAC7F,2FAA2F;AAC3F,+FAA+F;AAC/F,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,MAAM,CAAC,MAAM,YAAY,GAAmB;IAC1C,EAAE,EAAE,QAAQ;IACZ,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM;IAChB,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC;CAC3B,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Load a tags.scm query file from the grammars/ directory.
3
+ *
4
+ * Resolves relative to the compiled module location so it works both during development
5
+ * (src/ → grammars/) and after publish (dist/ → grammars/, since grammars/ is in package.json
6
+ * "files"). We walk up from the current file to find the package root (the dir containing
7
+ * grammars/).
8
+ */
9
+ export declare function loadQuery(languageId: string): string;
10
+ //# sourceMappingURL=query-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-loader.d.ts","sourceRoot":"","sources":["../../../src/parser/languages/query-loader.ts"],"names":[],"mappings":"AAMA;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAmBpD"}
@@ -0,0 +1,33 @@
1
+ // Standalone tags.scm loader. Kept separate from registry.ts to avoid a circular import:
2
+ // registry.ts imports the plugin modules, which import loadQuery from here (not from registry).
3
+ import { readFileSync } from 'node:fs';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { dirname, resolve } from 'node:path';
6
+ /**
7
+ * Load a tags.scm query file from the grammars/ directory.
8
+ *
9
+ * Resolves relative to the compiled module location so it works both during development
10
+ * (src/ → grammars/) and after publish (dist/ → grammars/, since grammars/ is in package.json
11
+ * "files"). We walk up from the current file to find the package root (the dir containing
12
+ * grammars/).
13
+ */
14
+ export function loadQuery(languageId) {
15
+ const here = dirname(fileURLToPath(import.meta.url));
16
+ // dev: src/parser/languages/query-loader.ts → ../../../grammars
17
+ // ship: dist/parser/languages/query-loader.js → ../../../grammars
18
+ const candidates = [
19
+ resolve(here, '..', '..', '..', 'grammars', languageId, 'tags.scm'),
20
+ resolve(here, '..', '..', 'grammars', languageId, 'tags.scm'),
21
+ resolve(process.cwd(), 'grammars', languageId, 'tags.scm'),
22
+ ];
23
+ for (const candidate of candidates) {
24
+ try {
25
+ return readFileSync(candidate, 'utf-8');
26
+ }
27
+ catch {
28
+ // try next
29
+ }
30
+ }
31
+ throw new Error(`Could not find grammars/${languageId}/tags.scm (looked in ${candidates.join(', ')})`);
32
+ }
33
+ //# sourceMappingURL=query-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-loader.js","sourceRoot":"","sources":["../../../src/parser/languages/query-loader.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,gGAAgG;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,UAAkB;IAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,iEAAiE;IACjE,kEAAkE;IAClE,MAAM,UAAU,GAAG;QACjB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC;QACnE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC;QAC7D,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC;KAC3D,CAAC;IACF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,OAAO,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,WAAW;QACb,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CACb,2BAA2B,UAAU,wBAAwB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACtF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { LanguageId } from '../types.js';
2
+ export { loadQuery } from './query-loader.js';
3
+ /** What a language plugin provides. `language` is the tree-sitter Language object (typed loosely). */
4
+ export interface LanguagePlugin {
5
+ /** short id stored in files.language, e.g. 'typescript' */
6
+ id: LanguageId;
7
+ /** file extensions (with leading dot) handled by this plugin */
8
+ extensions: string[];
9
+ /** tree-sitter Language object (we accept the native binding shape) */
10
+ language: any;
11
+ /** the tags.scm query source */
12
+ query: string;
13
+ }
14
+ /** All registered plugins, in priority order. */
15
+ export declare const PLUGINS: LanguagePlugin[];
16
+ /**
17
+ * Resolve a plugin for a file path by its extension, or null if unsupported.
18
+ * (e.g. 'src/auth/Auth.ts' → typescriptPlugin)
19
+ */
20
+ export declare function pluginForFile(filePath: string): LanguagePlugin | null;
21
+ /** Get a plugin by its language id. */
22
+ export declare function pluginById(id: LanguageId): LanguagePlugin | undefined;
23
+ /** All supported extensions (for the file watcher / indexer). */
24
+ export declare function supportedExtensions(): string[];
25
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/parser/languages/registry.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK9C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,sGAAsG;AACtG,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,EAAE,EAAE,UAAU,CAAC;IACf,gEAAgE;IAChE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,uEAAuE;IAEvE,QAAQ,EAAE,GAAG,CAAC;IACd,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,iDAAiD;AACjD,eAAO,MAAM,OAAO,EAAE,cAAc,EAAqC,CAAC;AAU1E;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAKrE;AAED,uCAAuC;AACvC,wBAAgB,UAAU,CAAC,EAAE,EAAE,UAAU,GAAG,cAAc,GAAG,SAAS,CAErE;AAED,iEAAiE;AACjE,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C"}
@@ -0,0 +1,33 @@
1
+ import { typescriptPlugin } from './typescript.js';
2
+ import { pythonPlugin } from './python.js';
3
+ // Re-export so existing `import { loadQuery } from './registry.js'` keeps working.
4
+ export { loadQuery } from './query-loader.js';
5
+ /** All registered plugins, in priority order. */
6
+ export const PLUGINS = [typescriptPlugin, pythonPlugin];
7
+ /** Map of file extension → plugin, for O(1) lookup by extension. */
8
+ const EXTENSION_MAP = new Map();
9
+ for (const plugin of PLUGINS) {
10
+ for (const ext of plugin.extensions) {
11
+ EXTENSION_MAP.set(ext.toLowerCase(), plugin);
12
+ }
13
+ }
14
+ /**
15
+ * Resolve a plugin for a file path by its extension, or null if unsupported.
16
+ * (e.g. 'src/auth/Auth.ts' → typescriptPlugin)
17
+ */
18
+ export function pluginForFile(filePath) {
19
+ const dot = filePath.lastIndexOf('.');
20
+ if (dot < 0)
21
+ return null;
22
+ const ext = filePath.slice(dot).toLowerCase();
23
+ return EXTENSION_MAP.get(ext) ?? null;
24
+ }
25
+ /** Get a plugin by its language id. */
26
+ export function pluginById(id) {
27
+ return PLUGINS.find((p) => p.id === id);
28
+ }
29
+ /** All supported extensions (for the file watcher / indexer). */
30
+ export function supportedExtensions() {
31
+ return Array.from(EXTENSION_MAP.keys());
32
+ }
33
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/parser/languages/registry.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,mFAAmF;AACnF,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAe9C,iDAAiD;AACjD,MAAM,CAAC,MAAM,OAAO,GAAqB,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;AAE1E,oEAAoE;AACpE,MAAM,aAAa,GAAgC,IAAI,GAAG,EAAE,CAAC;AAC7D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;IAC7B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACpC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC9C,OAAO,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,UAAU,CAAC,EAAc;IACvC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,mBAAmB;IACjC,OAAO,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { LanguagePlugin } from './registry.js';
2
+ declare const tsxGrammar: unknown;
3
+ /**
4
+ * Single plugin object covering .ts/.tsx/.js/.jsx/.mjs/.cjs. The query is shared; the grammar
5
+ * differs for tsx vs the rest (set per-file in the extractor via parse()).
6
+ */
7
+ export declare const typescriptPlugin: LanguagePlugin;
8
+ /** Choose the right grammar object for a specific TS-family file (tsx vs non-tsx). */
9
+ export declare function typescriptGrammarForFile(filePath: string): unknown;
10
+ export { tsxGrammar };
11
+ //# sourceMappingURL=typescript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../../src/parser/languages/typescript.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,QAAA,MAAM,UAAU,SAA+B,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,cAK9B,CAAC;AAEF,sFAAsF;AACtF,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAElE;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,26 @@
1
+ // TypeScript / JavaScript / TSX language plugin.
2
+ //
3
+ // tree-sitter-typescript exports two grammars: { typescript, tsx }. JavaScript uses the
4
+ // typescript grammar's JS subset, but for accurate JS parsing we'd want tree-sitter-javascript.
5
+ // For v0.1 we parse .js with the typescript grammar (superset — works fine for symbol extraction).
6
+ import TS from 'tree-sitter-typescript';
7
+ import { loadQuery } from './query-loader.js';
8
+ // The package exports { typescript, tsx }. Use tsx for .tsx so JSX parses.
9
+ const tsGrammar = TS.typescript;
10
+ const tsxGrammar = TS.tsx;
11
+ /**
12
+ * Single plugin object covering .ts/.tsx/.js/.jsx/.mjs/.cjs. The query is shared; the grammar
13
+ * differs for tsx vs the rest (set per-file in the extractor via parse()).
14
+ */
15
+ export const typescriptPlugin = {
16
+ id: 'typescript',
17
+ extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'],
18
+ language: tsGrammar,
19
+ query: loadQuery('typescript'),
20
+ };
21
+ /** Choose the right grammar object for a specific TS-family file (tsx vs non-tsx). */
22
+ export function typescriptGrammarForFile(filePath) {
23
+ return filePath.toLowerCase().endsWith('.tsx') ? tsxGrammar : tsGrammar;
24
+ }
25
+ export { tsxGrammar };
26
+ //# sourceMappingURL=typescript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript.js","sourceRoot":"","sources":["../../../src/parser/languages/typescript.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,wFAAwF;AACxF,gGAAgG;AAChG,mGAAmG;AACnG,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAExC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,2EAA2E;AAC3E,MAAM,SAAS,GAAI,EAA8B,CAAC,UAAU,CAAC;AAC7D,MAAM,UAAU,GAAI,EAAuB,CAAC,GAAG,CAAC;AAEhD;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAmB;IAC9C,EAAE,EAAE,YAAY;IAChB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAC1D,QAAQ,EAAE,SAAS;IACnB,KAAK,EAAE,SAAS,CAAC,YAAY,CAAC;CAC/B,CAAC;AAEF,sFAAsF;AACtF,MAAM,UAAU,wBAAwB,CAAC,QAAgB;IACvD,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1E,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { SymbolKind, EdgeKind } from '../graph/types.js';
2
+ /** A symbol extracted from source (not yet persisted). */
3
+ export interface ExtractedSymbol {
4
+ name: string;
5
+ kind: SymbolKind;
6
+ line_start: number;
7
+ line_end: number;
8
+ /** condensed definition: e.g. "function login(user: string): Token" — NOT the body */
9
+ signature: string | null;
10
+ /** base/inherited names referenced by a class (for extends/implements edges) */
11
+ extends?: string[];
12
+ implements?: string[];
13
+ }
14
+ /** A reference from this file to something outside it (an import). */
15
+ export interface ExtractedImport {
16
+ /** the raw specifier as written: './AuthService', '../utils', 'react', '@myorg/ui' */
17
+ specifier: string;
18
+ /** names brought in: ['AuthService', 'TokenService'] (best-effort; may be empty for namespace imports) */
19
+ names: string[];
20
+ }
21
+ /** Full extraction output for one file. */
22
+ export interface ParseResult {
23
+ symbols: ExtractedSymbol[];
24
+ imports: ExtractedImport[];
25
+ }
26
+ /** Edge between two symbols, as the indexer builds it. */
27
+ export interface PendingEdge {
28
+ /** symbol-local name of the source (the importer/caller) */
29
+ fromName: string;
30
+ /** name the edge points to (an imported or referenced name) */
31
+ toName: string;
32
+ kind: EdgeKind;
33
+ }
34
+ /** Supported language identifiers (stored in files.language). */
35
+ export type LanguageId = 'typescript' | 'javascript' | 'python';
36
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/parser/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE9D,0DAA0D;AAC1D,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,sFAAsF;IACtF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;IAClB,0GAA0G;IAC1G,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,2CAA2C;AAC3C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,0DAA0D;AAC1D,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,QAAQ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/parser/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { SymbolRow } from '../graph/types.js';
3
+ import type { DeltaResult } from './types.js';
4
+ /** Sessions older than this are eligible for cleanup. */
5
+ export declare const SESSION_TTL_MS: number;
6
+ export declare class SessionManager {
7
+ private db;
8
+ constructor(db: Database.Database);
9
+ /** Create a new session row. Returns its UUID. */
10
+ createSession(projectRoot: string): string;
11
+ /** True if the session id exists. */
12
+ sessionExists(sessionId: string): boolean;
13
+ /**
14
+ * Split a list of symbols into those NOT yet sent this session vs. those already sent.
15
+ * This is the core delta computation.
16
+ */
17
+ filterAlreadySent(sessionId: string, symbols: SymbolRow[]): DeltaResult<SymbolRow>;
18
+ /** Set of symbol ids already sent to a session. */
19
+ private getSentSymbolIds;
20
+ /**
21
+ * Record that these symbols were sent to a session. Call after every successful tool
22
+ * response that included symbol context. Idempotent (UNIQUE(session_id, symbol_id)).
23
+ */
24
+ markAsSent(sessionId: string, symbols: SymbolRow[]): void;
25
+ /** Delete sessions older than SESSION_TTL_MS (and cascade their ledger entries). */
26
+ cleanOldSessions(): number;
27
+ }
28
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/session/manager.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,yDAAyD;AACzD,eAAO,MAAM,cAAc,QAAsB,CAAC;AAElD,qBAAa,cAAc;IACb,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAEzC,kDAAkD;IAClD,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAU1C,qCAAqC;IACrC,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAKzC;;;OAGG;IACH,iBAAiB,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,SAAS,EAAE,GACnB,WAAW,CAAC,SAAS,CAAC;IAiBzB,mDAAmD;IACnD,OAAO,CAAC,gBAAgB;IAOxB;;;OAGG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,IAAI;IAezD,oFAAoF;IACpF,gBAAgB,IAAI,MAAM;CAK3B"}
@@ -0,0 +1,82 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ /** Sessions older than this are eligible for cleanup. */
3
+ export const SESSION_TTL_MS = 24 * 60 * 60 * 1000; // 24h
4
+ export class SessionManager {
5
+ db;
6
+ constructor(db) {
7
+ this.db = db;
8
+ }
9
+ /** Create a new session row. Returns its UUID. */
10
+ createSession(projectRoot) {
11
+ const id = randomUUID();
12
+ this.db
13
+ .prepare('INSERT INTO sessions (id, created_at, project_root) VALUES (?, ?, ?)')
14
+ .run(id, Date.now(), projectRoot);
15
+ return id;
16
+ }
17
+ /** True if the session id exists. */
18
+ sessionExists(sessionId) {
19
+ const row = this.db.prepare('SELECT 1 AS one FROM sessions WHERE id = ?').get(sessionId);
20
+ return row !== undefined;
21
+ }
22
+ /**
23
+ * Split a list of symbols into those NOT yet sent this session vs. those already sent.
24
+ * This is the core delta computation.
25
+ */
26
+ filterAlreadySent(sessionId, symbols) {
27
+ if (symbols.length === 0)
28
+ return { fresh: [], alreadySent: [] };
29
+ const sentIds = this.getSentSymbolIds(sessionId);
30
+ const fresh = [];
31
+ const alreadySent = [];
32
+ for (const sym of symbols) {
33
+ if (sentIds.has(sym.id)) {
34
+ alreadySent.push(sym);
35
+ }
36
+ else {
37
+ fresh.push(sym);
38
+ }
39
+ }
40
+ return { fresh, alreadySent };
41
+ }
42
+ /** Set of symbol ids already sent to a session. */
43
+ getSentSymbolIds(sessionId) {
44
+ const rows = this.db
45
+ .prepare('SELECT symbol_id FROM ledger_entries WHERE session_id = ?')
46
+ .all(sessionId);
47
+ return new Set(rows.map((r) => r.symbol_id));
48
+ }
49
+ /**
50
+ * Record that these symbols were sent to a session. Call after every successful tool
51
+ * response that included symbol context. Idempotent (UNIQUE(session_id, symbol_id)).
52
+ */
53
+ markAsSent(sessionId, symbols) {
54
+ if (symbols.length === 0)
55
+ return;
56
+ const insert = this.db.prepare(`INSERT OR REPLACE INTO ledger_entries (session_id, symbol_id, content_hash, sent_at)
57
+ VALUES (?, ?, ?, ?)`);
58
+ const insertMany = this.db.transaction((syms) => {
59
+ const now = Date.now();
60
+ for (const sym of syms) {
61
+ insert.run(sessionId, sym.id, contentHashForSymbol(sym), now);
62
+ }
63
+ });
64
+ insertMany(symbols);
65
+ }
66
+ /** Delete sessions older than SESSION_TTL_MS (and cascade their ledger entries). */
67
+ cleanOldSessions() {
68
+ const cutoff = Date.now() - SESSION_TTL_MS;
69
+ const result = this.db.prepare('DELETE FROM sessions WHERE created_at < ?').run(cutoff);
70
+ return result.changes;
71
+ }
72
+ }
73
+ /**
74
+ * A stable hash representing "what was sent" for a symbol. We use the name + location so that
75
+ * a symbol moved to a new line (but otherwise unchanged) re-sends, while an unchanged symbol
76
+ * at the same location is correctly deduped. (A true content hash would require re-reading the
77
+ * file; this is a good-enough proxy and keeps the ledger cheap.)
78
+ */
79
+ function contentHashForSymbol(sym) {
80
+ return `${sym.name}:${sym.file_path}:${sym.line_start}`;
81
+ }
82
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/session/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { SymbolRow } from '../graph/types.js';
2
+ import type { SessionManager } from './manager.js';
3
+ export interface PrunedContext {
4
+ /** callers not yet sent this session */
5
+ callers: SymbolRow[];
6
+ /** dependencies not yet sent this session */
7
+ dependencies: SymbolRow[];
8
+ /** focal symbol (always included, even if re-sent, so the agent knows what was queried) */
9
+ symbol: SymbolRow;
10
+ /** names of symbols skipped because already in context */
11
+ skipped: string[];
12
+ }
13
+ /**
14
+ * Apply session dedup to a traversal result. Does NOT mark anything as sent — the caller does
15
+ * that via sessionManager.markAsSent after building the final response (so a failed/errored
16
+ * tool call doesn't pollute the ledger).
17
+ */
18
+ export declare function pruneBySession(sessionManager: SessionManager, sessionId: string, traversal: {
19
+ symbol: SymbolRow;
20
+ callers: SymbolRow[];
21
+ dependencies: SymbolRow[];
22
+ }): PrunedContext;
23
+ /**
24
+ * Collect every symbol id that would be "sent" in a pruned context, for markAsSent.
25
+ * Includes the focal symbol (always part of the response).
26
+ */
27
+ export declare function symbolsToMark(pruned: PrunedContext): SymbolRow[];
28
+ //# sourceMappingURL=pruner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pruner.d.ts","sourceRoot":"","sources":["../../src/session/pruner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,6CAA6C;IAC7C,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,2FAA2F;IAC3F,MAAM,EAAE,SAAS,CAAC;IAClB,0DAA0D;IAC1D,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE;IACT,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,YAAY,EAAE,SAAS,EAAE,CAAC;CAC3B,GACA,aAAa,CAkBf;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,EAAE,CAEhE"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Apply session dedup to a traversal result. Does NOT mark anything as sent — the caller does
3
+ * that via sessionManager.markAsSent after building the final response (so a failed/errored
4
+ * tool call doesn't pollute the ledger).
5
+ */
6
+ export function pruneBySession(sessionManager, sessionId, traversal) {
7
+ const { fresh: freshCallers, alreadySent: sentCallers } = sessionManager.filterAlreadySent(sessionId, traversal.callers);
8
+ const { fresh: freshDeps, alreadySent: sentDeps } = sessionManager.filterAlreadySent(sessionId, traversal.dependencies);
9
+ const skipped = [...sentCallers, ...sentDeps].map((s) => s.name);
10
+ return {
11
+ symbol: traversal.symbol,
12
+ callers: freshCallers,
13
+ dependencies: freshDeps,
14
+ skipped,
15
+ };
16
+ }
17
+ /**
18
+ * Collect every symbol id that would be "sent" in a pruned context, for markAsSent.
19
+ * Includes the focal symbol (always part of the response).
20
+ */
21
+ export function symbolsToMark(pruned) {
22
+ return [pruned.symbol, ...pruned.callers, ...pruned.dependencies];
23
+ }
24
+ //# sourceMappingURL=pruner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pruner.js","sourceRoot":"","sources":["../../src/session/pruner.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,cAA8B,EAC9B,SAAiB,EACjB,SAIC;IAED,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,cAAc,CAAC,iBAAiB,CACxF,SAAS,EACT,SAAS,CAAC,OAAO,CAClB,CAAC;IACF,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAC,iBAAiB,CAClF,SAAS,EACT,SAAS,CAAC,YAAY,CACvB,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,GAAG,WAAW,EAAE,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAEjE,OAAO;QACL,MAAM,EAAE,SAAS,CAAC,MAAM;QACxB,OAAO,EAAE,YAAY;QACrB,YAAY,EAAE,SAAS;QACvB,OAAO;KACR,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAqB;IACjD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,21 @@
1
+ export interface Session {
2
+ id: string;
3
+ created_at: number;
4
+ project_root: string;
5
+ }
6
+ /** A row in `ledger_entries` — proof that a symbol was sent to a session. */
7
+ export interface LedgerEntry {
8
+ id: number;
9
+ session_id: string;
10
+ symbol_id: number;
11
+ content_hash: string;
12
+ sent_at: number;
13
+ }
14
+ /** Outcome of delta computation: which symbols are new vs. already sent. */
15
+ export interface DeltaResult<T> {
16
+ /** symbols NOT yet sent this session — these go into the response */
17
+ fresh: T[];
18
+ /** symbols already sent — skipped to save tokens */
19
+ alreadySent: T[];
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/session/types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,4EAA4E;AAC5E,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,qEAAqE;IACrE,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,oDAAoD;IACpD,WAAW,EAAE,CAAC,EAAE,CAAC;CAClB"}
@@ -0,0 +1,4 @@
1
+ // Session ledger types. A "session" = one agent conversation. The ledger records which
2
+ // symbols' context was already sent to that agent, so subsequent tool calls can skip them.
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/session/types.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,2FAA2F"}
@@ -0,0 +1,13 @@
1
+ export type LogLevel = 'info' | 'warn' | 'error' | 'debug';
2
+ /**
3
+ * Write a log line to stderr. Never touches stdout.
4
+ *
5
+ * @param message - human-readable message
6
+ * @param level - severity; 'debug' is suppressed unless SLIVER_DEBUG=1
7
+ */
8
+ export declare function log(message: string, level?: LogLevel): void;
9
+ /**
10
+ * Log an error with its stack trace (if available). Used in catch blocks.
11
+ */
12
+ export declare function logError(err: unknown): void;
13
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAY3D;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,QAAiB,GAAG,IAAI,CAGnE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAO3C"}
@@ -0,0 +1,36 @@
1
+ // CRITICAL: All logging MUST go to stderr.
2
+ // stdout is the MCP protocol channel (JSON-RPC). Any console.log() there corrupts the
3
+ // protocol stream and silently disconnects the client — the agent stops working with no error.
4
+ // The `no-console` eslint rule (allowing only console.error) enforces this in src/.
5
+ // Tests: test/integration/stdout-purity.test.ts asserts stdout stays clean.
6
+ const LEVEL_PREFIX = {
7
+ info: 'INFO',
8
+ warn: 'WARN',
9
+ error: 'ERROR',
10
+ debug: 'DEBUG',
11
+ };
12
+ // SLIVER_DEBUG=1 enables debug logs. Off by default to keep stderr quiet for clients.
13
+ const DEBUG_ON = process.env.SLIVER_DEBUG === '1' || process.env.SLIVER_DEBUG === 'true';
14
+ /**
15
+ * Write a log line to stderr. Never touches stdout.
16
+ *
17
+ * @param message - human-readable message
18
+ * @param level - severity; 'debug' is suppressed unless SLIVER_DEBUG=1
19
+ */
20
+ export function log(message, level = 'info') {
21
+ if (level === 'debug' && !DEBUG_ON)
22
+ return;
23
+ process.stderr.write(`[contextsliver:${LEVEL_PREFIX[level]}] ${message}\n`);
24
+ }
25
+ /**
26
+ * Log an error with its stack trace (if available). Used in catch blocks.
27
+ */
28
+ export function logError(err) {
29
+ const message = err instanceof Error ? err.message : String(err);
30
+ log(message, 'error');
31
+ if (err instanceof Error && err.stack) {
32
+ // stack already includes the message; write it raw for debugging
33
+ process.stderr.write(`[contextsliver:ERROR] ${err.stack}\n`);
34
+ }
35
+ }
36
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,sFAAsF;AACtF,+FAA+F;AAC/F,oFAAoF;AACpF,4EAA4E;AAI5E,MAAM,YAAY,GAA6B;IAC7C,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;CACf,CAAC;AAEF,sFAAsF;AACtF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,MAAM,CAAC;AAEzF;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,QAAkB,MAAM;IAC3D,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,QAAQ;QAAE,OAAO;IAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,YAAY,CAAC,KAAK,CAAC,KAAK,OAAO,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAY;IACnC,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACtB,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QACtC,iEAAiE;QACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Convert an absolute or project-relative path to a canonical, posix-style, project-relative path.
3
+ * This is the form stored in `files.path` and used in all graph queries.
4
+ *
5
+ * @example toRelativePath('/proj/src/auth/Auth.ts', '/proj') → 'src/auth/Auth.ts'
6
+ */
7
+ export declare function toRelativePath(absoluteOrRelative: string, projectRoot: string): string;
8
+ /** Normalize a path to posix separators (forward slashes) and strip leading ./ */
9
+ export declare function toPosix(p: string): string;
10
+ /**
11
+ * Resolve a relative import specifier (e.g. './AuthService', '../utils') against the importing
12
+ * file's directory, trying the common extensions. Returns a posix project-relative path, or
13
+ * null if no candidate file exists on disk.
14
+ *
15
+ * Bare specifiers (e.g. 'react', '@myorg/ui') are NOT resolved here — monorepo/workspace
16
+ * resolution handles those separately. Node built-ins ('node:fs', 'fs') never resolve to a file.
17
+ *
18
+ * @param specifier - the import path as written in source
19
+ * @param importerRel - posix project-relative path of the file doing the import
20
+ * @param projectRoot - absolute project root, for existence checks
21
+ * @param extensions - candidate extensions to try (with and without /index)
22
+ */
23
+ export declare function resolveRelativeImport(specifier: string, importerRel: string, projectRoot: string, extensions?: string[]): string | null;
24
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,kBAAkB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAItF;AAED,kFAAkF;AAClF,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAGzC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,GAAE,MAAM,EAAmD,GACpE,MAAM,GAAG,IAAI,CAiBf"}
@@ -0,0 +1,55 @@
1
+ // Path normalization + import-path resolution utilities.
2
+ //
3
+ // All stored file paths are relative to the project root, posix-style (forward slashes),
4
+ // so the index is portable across OSes and the graph query results are stable.
5
+ import { resolve, relative, normalize, sep, posix, isAbsolute } from 'node:path';
6
+ import { existsSync } from 'node:fs';
7
+ /**
8
+ * Convert an absolute or project-relative path to a canonical, posix-style, project-relative path.
9
+ * This is the form stored in `files.path` and used in all graph queries.
10
+ *
11
+ * @example toRelativePath('/proj/src/auth/Auth.ts', '/proj') → 'src/auth/Auth.ts'
12
+ */
13
+ export function toRelativePath(absoluteOrRelative, projectRoot) {
14
+ const abs = isAbsolute(absoluteOrRelative) ? absoluteOrRelative : resolve(projectRoot, absoluteOrRelative);
15
+ const rel = relative(resolve(projectRoot), abs);
16
+ return toPosix(rel);
17
+ }
18
+ /** Normalize a path to posix separators (forward slashes) and strip leading ./ */
19
+ export function toPosix(p) {
20
+ const normalized = sep === '\\' ? p.split(sep).join(posix.sep) : p;
21
+ return normalized.replace(/^\.\//, '').replace(/\\/g, '/');
22
+ }
23
+ /**
24
+ * Resolve a relative import specifier (e.g. './AuthService', '../utils') against the importing
25
+ * file's directory, trying the common extensions. Returns a posix project-relative path, or
26
+ * null if no candidate file exists on disk.
27
+ *
28
+ * Bare specifiers (e.g. 'react', '@myorg/ui') are NOT resolved here — monorepo/workspace
29
+ * resolution handles those separately. Node built-ins ('node:fs', 'fs') never resolve to a file.
30
+ *
31
+ * @param specifier - the import path as written in source
32
+ * @param importerRel - posix project-relative path of the file doing the import
33
+ * @param projectRoot - absolute project root, for existence checks
34
+ * @param extensions - candidate extensions to try (with and without /index)
35
+ */
36
+ export function resolveRelativeImport(specifier, importerRel, projectRoot, extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']) {
37
+ if (!specifier.startsWith('.'))
38
+ return null; // bare or builtin
39
+ const importerDir = posix.dirname(importerRel);
40
+ const base = toPosix(normalize(posix.join(importerDir, specifier)));
41
+ // Try the specifier as-is with each extension, then /index.<ext>
42
+ const candidates = [base, ...extensions.map((ext) => base + ext)];
43
+ for (const ext of extensions) {
44
+ candidates.push(posix.join(base, 'index' + ext));
45
+ }
46
+ for (const candidate of candidates) {
47
+ if (candidate.startsWith('..'))
48
+ continue; // escaped project root
49
+ const abs = resolve(projectRoot, candidate);
50
+ if (existsSync(abs))
51
+ return candidate;
52
+ }
53
+ return null;
54
+ }
55
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,EAAE;AACF,yFAAyF;AACzF,+EAA+E;AAC/E,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,kBAA0B,EAAE,WAAmB;IAC5E,MAAM,GAAG,GAAG,UAAU,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;IAC3G,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,GAAG,CAAC,CAAC;IAChD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,MAAM,UAAU,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,OAAO,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CACnC,SAAiB,EACjB,WAAmB,EACnB,WAAmB,EACnB,aAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAErE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,kBAAkB;IAC/D,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAEpE,iEAAiE;IACjE,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC;IAClE,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS,CAAC,uBAAuB;QACjE,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAC5C,IAAI,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Count tokens in a string using cl100k_base, with a chars/4 fallback on any error.
3
+ * Returns a non-negative integer. Never throws.
4
+ */
5
+ export declare function countTokens(text: string): number;
6
+ /**
7
+ * Sum tokens across multiple strings (e.g. a response with several content parts).
8
+ */
9
+ export declare function countTokensMany(texts: string[]): number;
10
+ //# sourceMappingURL=tokens.d.ts.map