modular-studio 1.0.5 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/README.md +122 -122
  2. package/dist/assets/Badge-Bsy2H_p2.js +1 -0
  3. package/dist/assets/GraphPanel-D4X3faxA.js +47 -0
  4. package/dist/assets/{Input-Bgp734xs.js → Input-Dyb88Erk.js} +1 -1
  5. package/dist/assets/KnowledgeTab-BccWz7Np.js +5 -0
  6. package/dist/assets/MemoryTab-Y_66cE01.js +16 -0
  7. package/dist/assets/QualificationTab-Dm9dEIpM.js +1 -0
  8. package/dist/assets/ReviewTab-BrfXSyyf.js +104 -0
  9. package/dist/assets/{Section-DoJrmytO.js → Section-68XDCFTl.js} +1 -1
  10. package/dist/assets/TestTab-CLKRT63X.js +42 -0
  11. package/dist/assets/ToolsTab-xumi9Uds.js +1 -0
  12. package/dist/assets/icons-CS8RUPBi.js +1 -0
  13. package/dist/assets/index-B2bm0161.css +1 -0
  14. package/dist/assets/index-C626nWuA.js +422 -0
  15. package/dist/assets/services-BDk6yY4o.js +369 -0
  16. package/dist/index.html +18 -18
  17. package/dist-server/bin/modular-mcp.js +1 -0
  18. package/dist-server/server/index.d.ts.map +1 -1
  19. package/dist-server/server/index.js +34 -0
  20. package/dist-server/server/mcp/manager.d.ts +3 -0
  21. package/dist-server/server/mcp/manager.d.ts.map +1 -1
  22. package/dist-server/server/mcp/manager.js +80 -5
  23. package/dist-server/server/migrations/index.d.ts +11 -0
  24. package/dist-server/server/migrations/index.d.ts.map +1 -0
  25. package/dist-server/server/migrations/index.js +57 -0
  26. package/dist-server/server/routes/agents.d.ts.map +1 -1
  27. package/dist-server/server/routes/agents.js +27 -0
  28. package/dist-server/server/routes/analytics.d.ts +3 -0
  29. package/dist-server/server/routes/analytics.d.ts.map +1 -0
  30. package/dist-server/server/routes/analytics.js +24 -0
  31. package/dist-server/server/routes/cache.d.ts +3 -0
  32. package/dist-server/server/routes/cache.d.ts.map +1 -0
  33. package/dist-server/server/routes/cache.js +55 -0
  34. package/dist-server/server/routes/connectors/airtable.d.ts +7 -0
  35. package/dist-server/server/routes/connectors/airtable.d.ts.map +1 -0
  36. package/dist-server/server/routes/connectors/airtable.js +119 -0
  37. package/dist-server/server/routes/connectors/confluence.d.ts +7 -0
  38. package/dist-server/server/routes/connectors/confluence.d.ts.map +1 -0
  39. package/dist-server/server/routes/connectors/confluence.js +176 -0
  40. package/dist-server/server/routes/connectors/github.d.ts +7 -0
  41. package/dist-server/server/routes/connectors/github.d.ts.map +1 -0
  42. package/dist-server/server/routes/connectors/github.js +195 -0
  43. package/dist-server/server/routes/connectors/gmail.d.ts +7 -0
  44. package/dist-server/server/routes/connectors/gmail.d.ts.map +1 -0
  45. package/dist-server/server/routes/connectors/gmail.js +115 -0
  46. package/dist-server/server/routes/connectors/google-docs.d.ts +10 -0
  47. package/dist-server/server/routes/connectors/google-docs.d.ts.map +1 -0
  48. package/dist-server/server/routes/connectors/google-docs.js +165 -0
  49. package/dist-server/server/routes/connectors/google-drive.d.ts +7 -0
  50. package/dist-server/server/routes/connectors/google-drive.d.ts.map +1 -0
  51. package/dist-server/server/routes/connectors/google-drive.js +163 -0
  52. package/dist-server/server/routes/connectors/google-sheets.d.ts +7 -0
  53. package/dist-server/server/routes/connectors/google-sheets.d.ts.map +1 -0
  54. package/dist-server/server/routes/connectors/google-sheets.js +90 -0
  55. package/dist-server/server/routes/connectors/hubspot.d.ts +7 -0
  56. package/dist-server/server/routes/connectors/hubspot.d.ts.map +1 -0
  57. package/dist-server/server/routes/connectors/hubspot.js +134 -0
  58. package/dist-server/server/routes/connectors/index.d.ts +6 -0
  59. package/dist-server/server/routes/connectors/index.d.ts.map +1 -0
  60. package/dist-server/server/routes/connectors/index.js +38 -0
  61. package/dist-server/server/routes/connectors/jira.d.ts +7 -0
  62. package/dist-server/server/routes/connectors/jira.d.ts.map +1 -0
  63. package/dist-server/server/routes/connectors/jira.js +151 -0
  64. package/dist-server/server/routes/connectors/linear.d.ts +7 -0
  65. package/dist-server/server/routes/connectors/linear.d.ts.map +1 -0
  66. package/dist-server/server/routes/connectors/linear.js +154 -0
  67. package/dist-server/server/routes/connectors/notion.d.ts +10 -0
  68. package/dist-server/server/routes/connectors/notion.d.ts.map +1 -0
  69. package/dist-server/server/routes/connectors/notion.js +201 -0
  70. package/dist-server/server/routes/connectors/plane.d.ts +10 -0
  71. package/dist-server/server/routes/connectors/plane.d.ts.map +1 -0
  72. package/dist-server/server/routes/connectors/plane.js +189 -0
  73. package/dist-server/server/routes/connectors/shared.d.ts +25 -0
  74. package/dist-server/server/routes/connectors/shared.d.ts.map +1 -0
  75. package/dist-server/server/routes/connectors/shared.js +202 -0
  76. package/dist-server/server/routes/connectors/slack.d.ts +7 -0
  77. package/dist-server/server/routes/connectors/slack.d.ts.map +1 -0
  78. package/dist-server/server/routes/connectors/slack.js +153 -0
  79. package/dist-server/server/routes/connectors.d.ts.map +1 -1
  80. package/dist-server/server/routes/connectors.js +47 -17
  81. package/dist-server/server/routes/cost.d.ts +3 -0
  82. package/dist-server/server/routes/cost.d.ts.map +1 -0
  83. package/dist-server/server/routes/cost.js +113 -0
  84. package/dist-server/server/routes/graph.d.ts +11 -0
  85. package/dist-server/server/routes/graph.d.ts.map +1 -0
  86. package/dist-server/server/routes/graph.js +213 -0
  87. package/dist-server/server/routes/lessons.d.ts +3 -0
  88. package/dist-server/server/routes/lessons.d.ts.map +1 -0
  89. package/dist-server/server/routes/lessons.js +160 -0
  90. package/dist-server/server/routes/llm.d.ts.map +1 -1
  91. package/dist-server/server/routes/llm.js +85 -18
  92. package/dist-server/server/routes/memory.d.ts.map +1 -1
  93. package/dist-server/server/routes/memory.js +31 -0
  94. package/dist-server/server/routes/metaprompt-v2.d.ts +3 -0
  95. package/dist-server/server/routes/metaprompt-v2.d.ts.map +1 -0
  96. package/dist-server/server/routes/metaprompt-v2.js +104 -0
  97. package/dist-server/server/routes/qualification.d.ts.map +1 -1
  98. package/dist-server/server/routes/qualification.js +342 -334
  99. package/dist-server/server/routes/repo-index.d.ts.map +1 -1
  100. package/dist-server/server/routes/repo-index.js +7 -0
  101. package/dist-server/server/routes/skills-search.d.ts.map +1 -1
  102. package/dist-server/server/routes/skills-search.js +192 -26
  103. package/dist-server/server/routes/tool-analytics.d.ts +3 -0
  104. package/dist-server/server/routes/tool-analytics.d.ts.map +1 -0
  105. package/dist-server/server/routes/tool-analytics.js +47 -0
  106. package/dist-server/server/services/adapters/hindsightAdapter.d.ts +28 -0
  107. package/dist-server/server/services/adapters/hindsightAdapter.d.ts.map +1 -0
  108. package/dist-server/server/services/adapters/hindsightAdapter.js +63 -0
  109. package/dist-server/server/services/adapters/postgresAdapter.js +30 -30
  110. package/dist-server/server/services/adapters/sqliteAdapter.d.ts +1 -0
  111. package/dist-server/server/services/adapters/sqliteAdapter.d.ts.map +1 -1
  112. package/dist-server/server/services/adapters/sqliteAdapter.js +66 -36
  113. package/dist-server/server/services/agentStore.d.ts +2 -1
  114. package/dist-server/server/services/agentStore.d.ts.map +1 -1
  115. package/dist-server/server/services/agentStore.js +2 -1
  116. package/dist-server/server/services/correctionDetector.d.ts +22 -0
  117. package/dist-server/server/services/correctionDetector.d.ts.map +1 -0
  118. package/dist-server/server/services/correctionDetector.js +91 -0
  119. package/dist-server/server/services/credentialStore.d.ts +10 -0
  120. package/dist-server/server/services/credentialStore.d.ts.map +1 -0
  121. package/dist-server/server/services/credentialStore.js +123 -0
  122. package/dist-server/server/services/hindsightClient.d.ts +15 -0
  123. package/dist-server/server/services/hindsightClient.d.ts.map +1 -0
  124. package/dist-server/server/services/hindsightClient.js +48 -0
  125. package/dist-server/server/services/lessonExtractor.d.ts +21 -0
  126. package/dist-server/server/services/lessonExtractor.d.ts.map +1 -0
  127. package/dist-server/server/services/lessonExtractor.js +92 -0
  128. package/dist-server/server/services/repoIndexer.d.ts +7 -1
  129. package/dist-server/server/services/repoIndexer.d.ts.map +1 -1
  130. package/dist-server/server/services/repoIndexer.js +295 -94
  131. package/dist-server/server/services/responseCache.d.ts +24 -0
  132. package/dist-server/server/services/responseCache.d.ts.map +1 -0
  133. package/dist-server/server/services/responseCache.js +163 -0
  134. package/dist-server/server/services/sqliteStore.d.ts +72 -0
  135. package/dist-server/server/services/sqliteStore.d.ts.map +1 -1
  136. package/dist-server/server/services/sqliteStore.js +291 -13
  137. package/dist-server/src/config.d.ts +2 -0
  138. package/dist-server/src/config.d.ts.map +1 -0
  139. package/dist-server/src/config.js +3 -0
  140. package/dist-server/src/graph/db.d.ts +46 -0
  141. package/dist-server/src/graph/db.d.ts.map +1 -0
  142. package/dist-server/src/graph/db.js +241 -0
  143. package/dist-server/src/graph/extractors/code.d.ts +12 -0
  144. package/dist-server/src/graph/extractors/code.d.ts.map +1 -0
  145. package/dist-server/src/graph/extractors/code.js +239 -0
  146. package/dist-server/src/graph/extractors/cross-type.d.ts +16 -0
  147. package/dist-server/src/graph/extractors/cross-type.d.ts.map +1 -0
  148. package/dist-server/src/graph/extractors/cross-type.js +67 -0
  149. package/dist-server/src/graph/extractors/markdown.d.ts +29 -0
  150. package/dist-server/src/graph/extractors/markdown.d.ts.map +1 -0
  151. package/dist-server/src/graph/extractors/markdown.js +224 -0
  152. package/dist-server/src/graph/extractors/yaml.d.ts +15 -0
  153. package/dist-server/src/graph/extractors/yaml.d.ts.map +1 -0
  154. package/dist-server/src/graph/extractors/yaml.js +104 -0
  155. package/dist-server/src/graph/index.d.ts +62 -0
  156. package/dist-server/src/graph/index.d.ts.map +1 -0
  157. package/dist-server/src/graph/index.js +67 -0
  158. package/dist-server/src/graph/packer.d.ts +19 -0
  159. package/dist-server/src/graph/packer.d.ts.map +1 -0
  160. package/dist-server/src/graph/packer.js +134 -0
  161. package/dist-server/src/graph/resolver.d.ts +12 -0
  162. package/dist-server/src/graph/resolver.d.ts.map +1 -0
  163. package/dist-server/src/graph/resolver.js +81 -0
  164. package/dist-server/src/graph/scanner.d.ts +34 -0
  165. package/dist-server/src/graph/scanner.d.ts.map +1 -0
  166. package/dist-server/src/graph/scanner.js +252 -0
  167. package/dist-server/src/graph/traverser.d.ts +17 -0
  168. package/dist-server/src/graph/traverser.d.ts.map +1 -0
  169. package/dist-server/src/graph/traverser.js +185 -0
  170. package/dist-server/src/graph/types.d.ts +117 -0
  171. package/dist-server/src/graph/types.d.ts.map +1 -0
  172. package/dist-server/src/graph/types.js +63 -0
  173. package/dist-server/src/metaprompt/v2/assembler.d.ts +3 -0
  174. package/dist-server/src/metaprompt/v2/assembler.d.ts.map +1 -0
  175. package/dist-server/src/metaprompt/v2/assembler.js +261 -0
  176. package/dist-server/src/metaprompt/v2/context-strategist.d.ts +3 -0
  177. package/dist-server/src/metaprompt/v2/context-strategist.d.ts.map +1 -0
  178. package/dist-server/src/metaprompt/v2/context-strategist.js +173 -0
  179. package/dist-server/src/metaprompt/v2/evaluator.d.ts +3 -0
  180. package/dist-server/src/metaprompt/v2/evaluator.d.ts.map +1 -0
  181. package/dist-server/src/metaprompt/v2/evaluator.js +281 -0
  182. package/dist-server/src/metaprompt/v2/index.d.ts +41 -0
  183. package/dist-server/src/metaprompt/v2/index.d.ts.map +1 -0
  184. package/dist-server/src/metaprompt/v2/index.js +90 -0
  185. package/dist-server/src/metaprompt/v2/parser.d.ts +3 -0
  186. package/dist-server/src/metaprompt/v2/parser.d.ts.map +1 -0
  187. package/dist-server/src/metaprompt/v2/parser.js +138 -0
  188. package/dist-server/src/metaprompt/v2/pattern-selector.d.ts +3 -0
  189. package/dist-server/src/metaprompt/v2/pattern-selector.d.ts.map +1 -0
  190. package/dist-server/src/metaprompt/v2/pattern-selector.js +154 -0
  191. package/dist-server/src/metaprompt/v2/researcher.d.ts +3 -0
  192. package/dist-server/src/metaprompt/v2/researcher.d.ts.map +1 -0
  193. package/dist-server/src/metaprompt/v2/researcher.js +194 -0
  194. package/dist-server/src/metaprompt/v2/tool-discovery.d.ts +74 -0
  195. package/dist-server/src/metaprompt/v2/tool-discovery.d.ts.map +1 -0
  196. package/dist-server/src/metaprompt/v2/tool-discovery.js +290 -0
  197. package/dist-server/src/metaprompt/v2/types.d.ts +154 -0
  198. package/dist-server/src/metaprompt/v2/types.d.ts.map +1 -0
  199. package/dist-server/src/metaprompt/v2/types.js +2 -0
  200. package/dist-server/src/services/contradictionDetector.js +1 -1
  201. package/dist-server/src/services/llmService.d.ts +61 -0
  202. package/dist-server/src/services/llmService.d.ts.map +1 -0
  203. package/dist-server/src/services/llmService.js +222 -0
  204. package/dist-server/src/store/knowledgeBase.d.ts +6 -1
  205. package/dist-server/src/store/knowledgeBase.d.ts.map +1 -1
  206. package/dist-server/src/store/knowledgeBase.js +0 -1
  207. package/dist-server/src/store/lessonStore.d.ts +26 -0
  208. package/dist-server/src/store/lessonStore.d.ts.map +1 -0
  209. package/dist-server/src/store/lessonStore.js +64 -0
  210. package/dist-server/src/store/mcp-registry.d.ts +29 -0
  211. package/dist-server/src/store/mcp-registry.d.ts.map +1 -0
  212. package/dist-server/src/store/mcp-registry.js +1303 -0
  213. package/dist-server/src/store/memoryStore.d.ts +12 -1
  214. package/dist-server/src/store/memoryStore.d.ts.map +1 -1
  215. package/dist-server/src/store/memoryStore.js +9 -0
  216. package/dist-server/src/types/registry.types.d.ts +13 -0
  217. package/dist-server/src/types/registry.types.d.ts.map +1 -0
  218. package/dist-server/src/types/registry.types.js +2 -0
  219. package/dist-server/tsconfig.server.tsbuildinfo +1 -1
  220. package/package.json +15 -1
  221. package/scripts/cleanup-worktrees.ps1 +29 -0
  222. package/dist/assets/Badge-22Ai0eyi.js +0 -1
  223. package/dist/assets/KnowledgeTab-DABxirZh.js +0 -4
  224. package/dist/assets/MemoryTab-DZeYElIT.js +0 -16
  225. package/dist/assets/QualificationTab-Dfpy3J30.js +0 -1
  226. package/dist/assets/ReviewTab-SD8lQuCc.js +0 -103
  227. package/dist/assets/TestTab-PDyMF8Fw.js +0 -33
  228. package/dist/assets/ToolsTab-B83qGCmG.js +0 -1
  229. package/dist/assets/icons-C2EV-le6.js +0 -1
  230. package/dist/assets/index-DkpMAxX7.css +0 -1
  231. package/dist/assets/index-q24ug5Qs.js +0 -143
  232. package/dist/assets/services-BaKotDf0.js +0 -343
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Markdown Relation Extractor
3
+ *
4
+ * Extracts: links_to, references, supersedes, continues, defined_in, depends_on
5
+ */
6
+ // ── Link Patterns ─────────────────────────────────────────────────────────────
7
+ const MD_LINK_RE = /\[([^\]]*)\]\(([^)]+)\)/g;
8
+ const WIKI_LINK_RE = /\[\[([^\]]+)\]\]/g;
9
+ // ── Supersedes / Continues Patterns ───────────────────────────────────────────
10
+ const SUPERSEDES_RE = /(?:superseded|replaced|deprecated|updated)\s+(?:by|in)\s*:?\s*\[?([^\]\n]+)\]?/gi;
11
+ const CONTINUES_RE = /(?:continued\s+from|part\s+\d+\s+of|follows\s+from)\s*:?\s*\[?([^\]\n]+)\]?/gi;
12
+ // ── Dependency Patterns ───────────────────────────────────────────────────────
13
+ const DEPENDS_RE = /(?:prerequisites?|depends?\s+on|requires?|see\s+also|before\s+reading)\s*:?\s*\[?([^\]\n]+)\]?/gi;
14
+ // ── Definition Patterns ───────────────────────────────────────────────────────
15
+ const BOLD_DEF_RE = /^\*\*([^*]+)\*\*\s*[:—–-]\s*(.+)$/gm;
16
+ /**
17
+ * Resolve a relative markdown link to a file path.
18
+ */
19
+ function resolveMarkdownLink(href, sourceDir) {
20
+ // Skip external links, anchors-only, mailto, etc.
21
+ if (/^(https?:|mailto:|#|data:)/.test(href))
22
+ return null;
23
+ if (href.startsWith('/'))
24
+ return null; // Absolute paths — skip
25
+ const [pathPart, anchor] = href.split('#');
26
+ if (!pathPart)
27
+ return anchor ? { path: '', anchor } : null;
28
+ const parts = sourceDir.split('/').filter(Boolean);
29
+ for (const segment of pathPart.split('/')) {
30
+ if (segment === '.')
31
+ continue;
32
+ if (segment === '..') {
33
+ parts.pop();
34
+ continue;
35
+ }
36
+ parts.push(segment);
37
+ }
38
+ return { path: parts.join('/'), anchor };
39
+ }
40
+ /**
41
+ * Find a FileNode by path (with fuzzy matching for extensions).
42
+ */
43
+ function findNodeByPath(path, allNodes) {
44
+ // Exact match
45
+ let match = allNodes.find(n => n.path === path);
46
+ if (match)
47
+ return match;
48
+ // Try with .md extension
49
+ if (!path.endsWith('.md')) {
50
+ match = allNodes.find(n => n.path === path + '.md');
51
+ if (match)
52
+ return match;
53
+ }
54
+ // Try filename match (for wiki-links)
55
+ const fileName = path.split('/').pop()?.toLowerCase() ?? '';
56
+ return allNodes.find(n => {
57
+ const nodeName = n.path.split('/').pop()?.toLowerCase() ?? '';
58
+ return nodeName === fileName || nodeName === fileName + '.md';
59
+ });
60
+ }
61
+ /**
62
+ * Collect all defined terms across markdown files.
63
+ * Returns: Map<term (lowercase), { file, originalTerm }>
64
+ */
65
+ export function collectDefinedTerms(mdNodes) {
66
+ const terms = new Map();
67
+ for (const node of mdNodes) {
68
+ if (node.language !== 'markdown')
69
+ continue;
70
+ // Headings become linkable terms
71
+ for (const sym of node.symbols) {
72
+ if (sym.kind === 'heading' && sym.name.length > 3) {
73
+ terms.set(sym.name.toLowerCase(), { file: node, term: sym.name });
74
+ }
75
+ if (sym.kind === 'definition') {
76
+ terms.set(sym.name.toLowerCase(), { file: node, term: sym.name });
77
+ }
78
+ }
79
+ }
80
+ return terms;
81
+ }
82
+ /**
83
+ * Extract all relations from a markdown file.
84
+ */
85
+ export function extractMarkdownRelations(file, allNodes, content) {
86
+ if (file.language !== 'markdown')
87
+ return [];
88
+ const relations = [];
89
+ const sourceDir = file.path.split('/').slice(0, -1).join('/');
90
+ // ── Explicit links: [text](path.md) ─────────────────────────────────────
91
+ MD_LINK_RE.lastIndex = 0;
92
+ let match;
93
+ while ((match = MD_LINK_RE.exec(content)) !== null) {
94
+ const href = match[2];
95
+ const resolved = resolveMarkdownLink(href, sourceDir);
96
+ if (!resolved || !resolved.path)
97
+ continue;
98
+ const target = findNodeByPath(resolved.path, allNodes);
99
+ if (target && target.id !== file.id) {
100
+ relations.push({
101
+ sourceFile: file.id,
102
+ targetFile: target.id,
103
+ targetSymbol: resolved.anchor,
104
+ kind: 'links_to',
105
+ weight: 1.0,
106
+ });
107
+ }
108
+ }
109
+ // ── Wiki links: [[page-name]] ────────────────────────────────────────────
110
+ WIKI_LINK_RE.lastIndex = 0;
111
+ while ((match = WIKI_LINK_RE.exec(content)) !== null) {
112
+ const linkName = match[1].trim();
113
+ const target = findNodeByPath(linkName, allNodes);
114
+ if (target && target.id !== file.id) {
115
+ relations.push({
116
+ sourceFile: file.id,
117
+ targetFile: target.id,
118
+ kind: 'links_to',
119
+ weight: 1.0,
120
+ });
121
+ }
122
+ }
123
+ // ── Supersedes ───────────────────────────────────────────────────────────
124
+ SUPERSEDES_RE.lastIndex = 0;
125
+ while ((match = SUPERSEDES_RE.exec(content)) !== null) {
126
+ const ref = match[1].trim().replace(/\[|\]/g, '');
127
+ const target = findNodeByPath(ref, allNodes);
128
+ if (target && target.id !== file.id) {
129
+ relations.push({
130
+ sourceFile: file.id,
131
+ targetFile: target.id,
132
+ kind: 'supersedes',
133
+ weight: 0.9,
134
+ });
135
+ }
136
+ }
137
+ // ── Continues ────────────────────────────────────────────────────────────
138
+ CONTINUES_RE.lastIndex = 0;
139
+ while ((match = CONTINUES_RE.exec(content)) !== null) {
140
+ const ref = match[1].trim().replace(/\[|\]/g, '');
141
+ const target = findNodeByPath(ref, allNodes);
142
+ if (target && target.id !== file.id) {
143
+ relations.push({
144
+ sourceFile: file.id,
145
+ targetFile: target.id,
146
+ kind: 'continues',
147
+ weight: 0.8,
148
+ });
149
+ }
150
+ }
151
+ // ── Depends on / Prerequisites ───────────────────────────────────────────
152
+ DEPENDS_RE.lastIndex = 0;
153
+ while ((match = DEPENDS_RE.exec(content)) !== null) {
154
+ const ref = match[1].trim().replace(/\[|\]/g, '');
155
+ const target = findNodeByPath(ref, allNodes);
156
+ if (target && target.id !== file.id) {
157
+ relations.push({
158
+ sourceFile: file.id,
159
+ targetFile: target.id,
160
+ kind: 'depends_on',
161
+ weight: 0.8,
162
+ });
163
+ }
164
+ }
165
+ // ── Cross-document term references ───────────────────────────────────────
166
+ const definedTerms = collectDefinedTerms(allNodes.filter(n => n.id !== file.id));
167
+ for (const [termLower, { file: defFile, term }] of definedTerms) {
168
+ // Only match multi-word terms (> 2 words) or long single words (> 8 chars)
169
+ const wordCount = term.split(/\s+/).length;
170
+ if (wordCount < 2 && term.length <= 8)
171
+ continue;
172
+ // Word-boundary match, case-insensitive
173
+ const escaped = termLower.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
174
+ const re = new RegExp(`\\b${escaped}\\b`, 'i');
175
+ if (re.test(content)) {
176
+ // Don't duplicate if we already have a links_to for this file
177
+ const alreadyLinked = relations.some(r => r.targetFile === defFile.id && (r.kind === 'links_to' || r.kind === 'references'));
178
+ if (!alreadyLinked) {
179
+ relations.push({
180
+ sourceFile: file.id,
181
+ targetFile: defFile.id,
182
+ targetSymbol: term,
183
+ kind: 'references',
184
+ weight: 0.6,
185
+ });
186
+ }
187
+ }
188
+ }
189
+ return relations;
190
+ }
191
+ /**
192
+ * Extract markdown symbols (headings + defined terms) for FileNode.symbols.
193
+ */
194
+ export function extractMarkdownSymbols(content) {
195
+ const symbols = [];
196
+ const lines = content.split('\n');
197
+ // Headings
198
+ for (let i = 0; i < lines.length; i++) {
199
+ const hMatch = /^(#{1,6})\s+(.+)$/.exec(lines[i]);
200
+ if (hMatch) {
201
+ symbols.push({
202
+ name: hMatch[2].trim(),
203
+ kind: 'heading',
204
+ lineStart: i + 1,
205
+ lineEnd: i + 1,
206
+ isExported: true,
207
+ });
208
+ }
209
+ }
210
+ // Bold definitions: **Term**: definition
211
+ BOLD_DEF_RE.lastIndex = 0;
212
+ let defMatch;
213
+ while ((defMatch = BOLD_DEF_RE.exec(content)) !== null) {
214
+ const lineNum = content.substring(0, defMatch.index).split('\n').length;
215
+ symbols.push({
216
+ name: defMatch[1].trim(),
217
+ kind: 'definition',
218
+ lineStart: lineNum,
219
+ lineEnd: lineNum,
220
+ isExported: true,
221
+ });
222
+ }
223
+ return symbols;
224
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * YAML / JSON Relation Extractor
3
+ *
4
+ * Extracts: configured_by
5
+ * Scans config files for path-like string values that reference known source files.
6
+ */
7
+ import type { FileNode, Relation } from '../types.js';
8
+ /**
9
+ * Extract relations from a YAML or JSON config file.
10
+ *
11
+ * Creates 'configured_by' relations from the referenced code file TO the config.
12
+ * Weight: 0.8 for explicit path references, 0.6 for inferred ($schema).
13
+ */
14
+ export declare function extractYamlRelations(node: FileNode, allNodes: FileNode[], content: string): Relation[];
15
+ //# sourceMappingURL=yaml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml.d.ts","sourceRoot":"","sources":["../../../../src/graph/extractors/yaml.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA0CtD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,QAAQ,EAAE,EACpB,OAAO,EAAE,MAAM,GACd,QAAQ,EAAE,CAyDZ"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * YAML / JSON Relation Extractor
3
+ *
4
+ * Extracts: configured_by
5
+ * Scans config files for path-like string values that reference known source files.
6
+ */
7
+ // ── Path Detection Patterns ───────────────────────────────────────────────────
8
+ // Quoted string values ending in code/doc extensions
9
+ const QUOTED_PATH_RE = /["']([^"'\n\r]+\.(?:ts|tsx|js|jsx|py|md))["']/g;
10
+ // Unquoted YAML values: `key: ./src/foo.ts`
11
+ const YAML_UNQUOTED_PATH_RE = /:\s+([^\s'"{\[,\n\r]+\.(?:ts|tsx|js|jsx|py|md))(?:\s*$|\s*#)/gm;
12
+ // JSON Schema self-reference: "$schema": "./path/to/schema.json"
13
+ const JSON_SCHEMA_KEY_RE = /['"]\$schema['"]\s*:\s*["']([^"']+\.json)["']/g;
14
+ // ── Path Normalization ────────────────────────────────────────────────────────
15
+ /**
16
+ * Normalize a raw path reference from config content to a repo-relative path.
17
+ * Resolves relative segments (./ and ../) against the config file's directory.
18
+ */
19
+ function normalizePath(raw, configDir) {
20
+ let ref = raw.trim();
21
+ if (ref.startsWith('./'))
22
+ ref = ref.slice(2);
23
+ if (ref.startsWith('../')) {
24
+ const parts = configDir.split('/').filter(Boolean);
25
+ for (const seg of ref.split('/')) {
26
+ if (seg === '.')
27
+ continue;
28
+ if (seg === '..') {
29
+ parts.pop();
30
+ continue;
31
+ }
32
+ parts.push(seg);
33
+ }
34
+ return parts.join('/');
35
+ }
36
+ return ref;
37
+ }
38
+ function findNodeByNormalizedPath(normalized, allNodes) {
39
+ return allNodes.find(n => n.path === normalized || n.path.endsWith('/' + normalized));
40
+ }
41
+ // ── Main Extractor ────────────────────────────────────────────────────────────
42
+ /**
43
+ * Extract relations from a YAML or JSON config file.
44
+ *
45
+ * Creates 'configured_by' relations from the referenced code file TO the config.
46
+ * Weight: 0.8 for explicit path references, 0.6 for inferred ($schema).
47
+ */
48
+ export function extractYamlRelations(node, allNodes, content) {
49
+ if (node.language !== 'yaml' && node.language !== 'json')
50
+ return [];
51
+ const relations = [];
52
+ const configDir = node.path.split('/').slice(0, -1).join('/');
53
+ const seen = new Set();
54
+ // ── Explicit path references ──────────────────────────────────────────────
55
+ const pathPatterns = [QUOTED_PATH_RE, YAML_UNQUOTED_PATH_RE];
56
+ for (const re of pathPatterns) {
57
+ re.lastIndex = 0;
58
+ let match;
59
+ while ((match = re.exec(content)) !== null) {
60
+ const raw = match[1];
61
+ if (!raw)
62
+ continue;
63
+ const normalized = normalizePath(raw, configDir);
64
+ const target = findNodeByNormalizedPath(normalized, allNodes);
65
+ if (!target || target.id === node.id)
66
+ continue;
67
+ // Relation: referenced code file is configured_by this config file
68
+ const key = `${target.id}→${node.id}:configured_by`;
69
+ if (seen.has(key))
70
+ continue;
71
+ seen.add(key);
72
+ relations.push({
73
+ sourceFile: target.id,
74
+ targetFile: node.id,
75
+ kind: 'configured_by',
76
+ weight: 0.8,
77
+ });
78
+ }
79
+ }
80
+ // ── JSON Schema cross-references ($schema key) ────────────────────────────
81
+ JSON_SCHEMA_KEY_RE.lastIndex = 0;
82
+ let schemaMatch;
83
+ while ((schemaMatch = JSON_SCHEMA_KEY_RE.exec(content)) !== null) {
84
+ const raw = schemaMatch[1];
85
+ if (!raw)
86
+ continue;
87
+ const normalized = normalizePath(raw, configDir);
88
+ const target = findNodeByNormalizedPath(normalized, allNodes);
89
+ if (!target || target.id === node.id)
90
+ continue;
91
+ // Relation: this config is configured_by (validated against) the schema
92
+ const key = `${node.id}→${target.id}:configured_by`;
93
+ if (seen.has(key))
94
+ continue;
95
+ seen.add(key);
96
+ relations.push({
97
+ sourceFile: node.id,
98
+ targetFile: target.id,
99
+ kind: 'configured_by',
100
+ weight: 0.6,
101
+ });
102
+ }
103
+ return relations;
104
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Context Graph — Public API
3
+ *
4
+ * Unified interface: scan → query → pack.
5
+ */
6
+ export { GraphDB } from './db.js';
7
+ export { fullScan, updateFiles, buildFileNode, shouldIndex, fileId, hashContent } from './scanner.js';
8
+ export { resolveEntryPoints } from './resolver.js';
9
+ export { traverseGraph, traverseForTask } from './traverser.js';
10
+ export { packContext } from './packer.js';
11
+ export { extractCodeRelations } from './extractors/code.js';
12
+ export { extractMarkdownRelations, extractMarkdownSymbols, collectDefinedTerms } from './extractors/markdown.js';
13
+ export { extractYamlRelations } from './extractors/yaml.js';
14
+ export { extractCrossTypeRelations } from './extractors/cross-type.js';
15
+ export { detectTaskType, TRAVERSAL_PRESETS } from './types.js';
16
+ export type { FileNode, FileLanguage, SymbolDef, SymbolKind, Relation, RelationKind, ContextGraph, TraversalConfig, TraversalResult, TraversalFile, EntryPoint, PackedContext, PackedItem, UpdateResult, ScanResult, TaskType, } from './types.js';
17
+ import { GraphDB } from './db.js';
18
+ import type { PackedContext, ScanResult, UpdateResult, TaskType } from './types.js';
19
+ /**
20
+ * High-level: scan files → build graph → query → get packed context.
21
+ */
22
+ export declare class ContextGraphEngine {
23
+ private db;
24
+ private rootPath;
25
+ /**
26
+ * Full scan from a list of files.
27
+ */
28
+ scan(rootPath: string, files: Array<{
29
+ path: string;
30
+ content: string;
31
+ mtime?: number;
32
+ }>): ScanResult;
33
+ /**
34
+ * Incremental update for changed files.
35
+ */
36
+ update(changedFiles: Array<{
37
+ path: string;
38
+ content: string;
39
+ mtime?: number;
40
+ }>): UpdateResult;
41
+ /**
42
+ * Query: natural language → packed context.
43
+ */
44
+ query(query: string, tokenBudget?: number, taskType?: TaskType): PackedContext;
45
+ /**
46
+ * Get graph stats.
47
+ */
48
+ getStats(): {
49
+ nodes: number;
50
+ symbols: number;
51
+ relations: number;
52
+ };
53
+ /**
54
+ * Get the full graph for visualization.
55
+ */
56
+ getGraph(): import("./types.js").ContextGraph;
57
+ /**
58
+ * Get DB instance for direct access.
59
+ */
60
+ getDB(): GraphDB;
61
+ }
62
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/graph/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACtG,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACjH,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/D,YAAY,EACV,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAC7C,QAAQ,EAAE,YAAY,EACtB,YAAY,EACZ,eAAe,EAAE,eAAe,EAAE,aAAa,EAC/C,UAAU,EACV,aAAa,EAAE,UAAU,EACzB,YAAY,EAAE,UAAU,EACxB,QAAQ,GACT,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAKlC,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEpF;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,QAAQ,CAAM;IAEtB;;OAEG;IACH,IAAI,CACF,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAC9D,UAAU;IAKb;;OAEG;IACH,MAAM,CACJ,YAAY,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GACrE,YAAY;IAIf;;OAEG;IACH,KAAK,CACH,KAAK,EAAE,MAAM,EACb,WAAW,GAAE,MAAe,EAC5B,QAAQ,CAAC,EAAE,QAAQ,GAClB,aAAa;IAOhB;;OAEG;IACH,QAAQ;;;;;IAIR;;OAEG;IACH,QAAQ;IAIR;;OAEG;IACH,KAAK;CAGN"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Context Graph — Public API
3
+ *
4
+ * Unified interface: scan → query → pack.
5
+ */
6
+ export { GraphDB } from './db.js';
7
+ export { fullScan, updateFiles, buildFileNode, shouldIndex, fileId, hashContent } from './scanner.js';
8
+ export { resolveEntryPoints } from './resolver.js';
9
+ export { traverseGraph, traverseForTask } from './traverser.js';
10
+ export { packContext } from './packer.js';
11
+ export { extractCodeRelations } from './extractors/code.js';
12
+ export { extractMarkdownRelations, extractMarkdownSymbols, collectDefinedTerms } from './extractors/markdown.js';
13
+ export { extractYamlRelations } from './extractors/yaml.js';
14
+ export { extractCrossTypeRelations } from './extractors/cross-type.js';
15
+ export { detectTaskType, TRAVERSAL_PRESETS } from './types.js';
16
+ import { GraphDB } from './db.js';
17
+ import { fullScan, updateFiles } from './scanner.js';
18
+ import { resolveEntryPoints } from './resolver.js';
19
+ import { traverseForTask } from './traverser.js';
20
+ import { packContext } from './packer.js';
21
+ /**
22
+ * High-level: scan files → build graph → query → get packed context.
23
+ */
24
+ export class ContextGraphEngine {
25
+ db = new GraphDB();
26
+ rootPath = '';
27
+ /**
28
+ * Full scan from a list of files.
29
+ */
30
+ scan(rootPath, files) {
31
+ this.rootPath = rootPath;
32
+ return fullScan(files, this.db);
33
+ }
34
+ /**
35
+ * Incremental update for changed files.
36
+ */
37
+ update(changedFiles) {
38
+ return updateFiles(changedFiles, this.db);
39
+ }
40
+ /**
41
+ * Query: natural language → packed context.
42
+ */
43
+ query(query, tokenBudget = 100000, taskType) {
44
+ const graph = this.db.toContextGraph(this.rootPath);
45
+ const entryPoints = resolveEntryPoints(query, graph);
46
+ const traversal = traverseForTask(query, entryPoints, graph, taskType);
47
+ return packContext(traversal, tokenBudget);
48
+ }
49
+ /**
50
+ * Get graph stats.
51
+ */
52
+ getStats() {
53
+ return this.db.getStats();
54
+ }
55
+ /**
56
+ * Get the full graph for visualization.
57
+ */
58
+ getGraph() {
59
+ return this.db.toContextGraph(this.rootPath);
60
+ }
61
+ /**
62
+ * Get DB instance for direct access.
63
+ */
64
+ getDB() {
65
+ return this.db;
66
+ }
67
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Budget Packer — Relevance-weighted depth allocation
3
+ *
4
+ * Given traversal results and a token budget, decide how much of each file
5
+ * to include using existing depthFilter depth levels:
6
+ * 0 = Full, 1 = Detail, 2 = Summary, 3 = Headlines, 4 = Mention
7
+ */
8
+ import type { TraversalResult, PackedContext } from './types.js';
9
+ /**
10
+ * Pack traversal results into a context budget.
11
+ *
12
+ * Strategy:
13
+ * 1. Assign initial depth based on relevance
14
+ * 2. If budget exceeded, demote lowest-relevance files to higher depth
15
+ * 3. If budget still exceeded, drop lowest-relevance files
16
+ * 4. If budget has room, promote highest-relevance files to lower depth
17
+ */
18
+ export declare function packContext(traversalResult: TraversalResult, tokenBudget: number): PackedContext;
19
+ //# sourceMappingURL=packer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packer.d.ts","sourceRoot":"","sources":["../../../src/graph/packer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAwB,MAAM,YAAY,CAAC;AAmEvF;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,eAAe,EAAE,eAAe,EAChC,WAAW,EAAE,MAAM,GAClB,aAAa,CAgFf"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Budget Packer — Relevance-weighted depth allocation
3
+ *
4
+ * Given traversal results and a token budget, decide how much of each file
5
+ * to include using existing depthFilter depth levels:
6
+ * 0 = Full, 1 = Detail, 2 = Summary, 3 = Headlines, 4 = Mention
7
+ */
8
+ // Approximate token costs per depth level (as fraction of full)
9
+ const DEPTH_COST_RATIOS = {
10
+ 0: 1.0, // Full
11
+ 1: 0.75, // Detail: signatures + docstrings
12
+ 2: 0.50, // Summary: signatures only
13
+ 3: 0.25, // Headlines: section names
14
+ 4: 0.10, // Mention: file purpose only
15
+ };
16
+ /**
17
+ * Estimate token cost at a given depth level.
18
+ */
19
+ function estimateAtDepth(fileTokens, depth) {
20
+ const ratio = DEPTH_COST_RATIOS[depth] ?? 0.1;
21
+ return Math.max(10, Math.ceil(fileTokens * ratio));
22
+ }
23
+ /**
24
+ * Generate content stub at a given depth level.
25
+ * In production, this would call depthFilter.ts — here we generate a summary.
26
+ */
27
+ function contentAtDepth(file, depth) {
28
+ const symbols = file.symbols;
29
+ switch (depth) {
30
+ case 0: // Full — would return full file content
31
+ return `[Full content of ${file.path}]\n` +
32
+ symbols.map(s => `${s.kind} ${s.name}${s.signature ? s.signature : ''}`).join('\n');
33
+ case 1: // Detail — signatures + docstrings
34
+ return `// ${file.path} (detail)\n` +
35
+ symbols.map(s => `${s.isExported ? 'export ' : ''}${s.kind} ${s.name}${s.signature ?? ''}${s.docstring ? ` // ${s.docstring}` : ''}`).join('\n');
36
+ case 2: // Summary — signatures only
37
+ return `// ${file.path} (summary)\n` +
38
+ symbols.filter(s => s.isExported).map(s => `${s.kind} ${s.name}${s.signature ?? ''}`).join('\n');
39
+ case 3: // Headlines — section/symbol names
40
+ return `// ${file.path}: ` +
41
+ symbols.filter(s => s.isExported).map(s => s.name).join(', ');
42
+ case 4: // Mention — file purpose
43
+ return `// ${file.path} (${file.language}, ${file.tokens} tokens)`;
44
+ default:
45
+ return `// ${file.path}`;
46
+ }
47
+ }
48
+ /**
49
+ * Determine depth level based on relevance score.
50
+ */
51
+ function relevanceToDepth(relevance) {
52
+ if (relevance >= 0.8)
53
+ return 0; // Full
54
+ if (relevance >= 0.6)
55
+ return 1; // Detail
56
+ if (relevance >= 0.4)
57
+ return 2; // Summary
58
+ if (relevance >= 0.2)
59
+ return 3; // Headlines
60
+ return 4; // Mention
61
+ }
62
+ /**
63
+ * Pack traversal results into a context budget.
64
+ *
65
+ * Strategy:
66
+ * 1. Assign initial depth based on relevance
67
+ * 2. If budget exceeded, demote lowest-relevance files to higher depth
68
+ * 3. If budget still exceeded, drop lowest-relevance files
69
+ * 4. If budget has room, promote highest-relevance files to lower depth
70
+ */
71
+ export function packContext(traversalResult, tokenBudget) {
72
+ const { files } = traversalResult;
73
+ if (files.length === 0) {
74
+ return { items: [], totalTokens: 0, budgetUtilization: 0 };
75
+ }
76
+ // Sort by relevance descending
77
+ const sorted = [...files].sort((a, b) => b.relevance - a.relevance);
78
+ const items = sorted.map(f => {
79
+ const depth = relevanceToDepth(f.relevance);
80
+ return {
81
+ file: f.node,
82
+ relevance: f.relevance,
83
+ depth,
84
+ tokens: estimateAtDepth(f.node.tokens, depth),
85
+ };
86
+ });
87
+ // Phase 2: Fit within budget — demote from bottom up
88
+ let totalTokens = items.reduce((sum, it) => sum + it.tokens, 0);
89
+ if (totalTokens > tokenBudget) {
90
+ // Demote least relevant files first
91
+ for (let i = items.length - 1; i >= 0 && totalTokens > tokenBudget; i--) {
92
+ const item = items[i];
93
+ while (item.depth < 4 && totalTokens > tokenBudget) {
94
+ const oldTokens = item.tokens;
95
+ item.depth++;
96
+ item.tokens = estimateAtDepth(item.file.tokens, item.depth);
97
+ totalTokens -= (oldTokens - item.tokens);
98
+ }
99
+ }
100
+ // If still over budget, drop from bottom
101
+ while (items.length > 0 && totalTokens > tokenBudget) {
102
+ const removed = items.pop();
103
+ totalTokens -= removed.tokens;
104
+ }
105
+ }
106
+ // Phase 3: If budget has room, promote top files
107
+ if (totalTokens < tokenBudget * 0.8) {
108
+ for (let i = 0; i < items.length && totalTokens < tokenBudget * 0.9; i++) {
109
+ const item = items[i];
110
+ if (item.depth > 0) {
111
+ const newTokens = estimateAtDepth(item.file.tokens, item.depth - 1);
112
+ const delta = newTokens - item.tokens;
113
+ if (totalTokens + delta <= tokenBudget) {
114
+ item.depth--;
115
+ item.tokens = newTokens;
116
+ totalTokens += delta;
117
+ }
118
+ }
119
+ }
120
+ }
121
+ // Build final output
122
+ const packed = items.map(it => ({
123
+ file: it.file,
124
+ content: contentAtDepth(it.file, it.depth),
125
+ depth: it.depth,
126
+ tokens: it.tokens,
127
+ relevance: it.relevance,
128
+ }));
129
+ return {
130
+ items: packed,
131
+ totalTokens,
132
+ budgetUtilization: totalTokens / tokenBudget,
133
+ };
134
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Entry Point Resolver
3
+ *
4
+ * From a natural language query, find entry points into the context graph.
5
+ * Three strategies: symbol match, filename match, semantic match (fallback).
6
+ */
7
+ import type { ContextGraph, EntryPoint } from './types.js';
8
+ /**
9
+ * Resolve entry points from a query against the graph.
10
+ */
11
+ export declare function resolveEntryPoints(query: string, graph: ContextGraph): EntryPoint[];
12
+ //# sourceMappingURL=resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../../src/graph/resolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE3D;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,GAClB,UAAU,EAAE,CA4Ed"}