mincut-context 1.0.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 (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +268 -0
  3. package/dist/adapters/cli/bin.d.ts +3 -0
  4. package/dist/adapters/cli/bin.d.ts.map +1 -0
  5. package/dist/adapters/cli/bin.js +119 -0
  6. package/dist/adapters/cli/bin.js.map +1 -0
  7. package/dist/adapters/cli/render.d.ts +10 -0
  8. package/dist/adapters/cli/render.d.ts.map +1 -0
  9. package/dist/adapters/cli/render.js +65 -0
  10. package/dist/adapters/cli/render.js.map +1 -0
  11. package/dist/adapters/cli/tui.d.ts +9 -0
  12. package/dist/adapters/cli/tui.d.ts.map +1 -0
  13. package/dist/adapters/cli/tui.js +57 -0
  14. package/dist/adapters/cli/tui.js.map +1 -0
  15. package/dist/adapters/lib/index.d.ts +6 -0
  16. package/dist/adapters/lib/index.d.ts.map +1 -0
  17. package/dist/adapters/lib/index.js +4 -0
  18. package/dist/adapters/lib/index.js.map +1 -0
  19. package/dist/adapters/mcp/handler.d.ts +112 -0
  20. package/dist/adapters/mcp/handler.d.ts.map +1 -0
  21. package/dist/adapters/mcp/handler.js +128 -0
  22. package/dist/adapters/mcp/handler.js.map +1 -0
  23. package/dist/adapters/mcp/index.d.ts +6 -0
  24. package/dist/adapters/mcp/index.d.ts.map +1 -0
  25. package/dist/adapters/mcp/index.js +32 -0
  26. package/dist/adapters/mcp/index.js.map +1 -0
  27. package/dist/core/graph.d.ts +50 -0
  28. package/dist/core/graph.d.ts.map +1 -0
  29. package/dist/core/graph.js +110 -0
  30. package/dist/core/graph.js.map +1 -0
  31. package/dist/core/index.d.ts +7 -0
  32. package/dist/core/index.d.ts.map +1 -0
  33. package/dist/core/index.js +4 -0
  34. package/dist/core/index.js.map +1 -0
  35. package/dist/core/pagerank.d.ts +30 -0
  36. package/dist/core/pagerank.d.ts.map +1 -0
  37. package/dist/core/pagerank.js +88 -0
  38. package/dist/core/pagerank.js.map +1 -0
  39. package/dist/core/select.d.ts +60 -0
  40. package/dist/core/select.d.ts.map +1 -0
  41. package/dist/core/select.js +121 -0
  42. package/dist/core/select.js.map +1 -0
  43. package/dist/index/builder.d.ts +13 -0
  44. package/dist/index/builder.d.ts.map +1 -0
  45. package/dist/index/builder.js +186 -0
  46. package/dist/index/builder.js.map +1 -0
  47. package/dist/index/walker.d.ts +15 -0
  48. package/dist/index/walker.d.ts.map +1 -0
  49. package/dist/index/walker.js +103 -0
  50. package/dist/index/walker.js.map +1 -0
  51. package/dist/parsers/parser.d.ts +35 -0
  52. package/dist/parsers/parser.d.ts.map +1 -0
  53. package/dist/parsers/parser.js +8 -0
  54. package/dist/parsers/parser.js.map +1 -0
  55. package/dist/parsers/py.d.ts +3 -0
  56. package/dist/parsers/py.d.ts.map +1 -0
  57. package/dist/parsers/py.js +169 -0
  58. package/dist/parsers/py.js.map +1 -0
  59. package/dist/parsers/ts.d.ts +3 -0
  60. package/dist/parsers/ts.d.ts.map +1 -0
  61. package/dist/parsers/ts.js +240 -0
  62. package/dist/parsers/ts.js.map +1 -0
  63. package/dist/seeds/embedding.d.ts +27 -0
  64. package/dist/seeds/embedding.d.ts.map +1 -0
  65. package/dist/seeds/embedding.js +90 -0
  66. package/dist/seeds/embedding.js.map +1 -0
  67. package/dist/seeds/keyword.d.ts +22 -0
  68. package/dist/seeds/keyword.d.ts.map +1 -0
  69. package/dist/seeds/keyword.js +106 -0
  70. package/dist/seeds/keyword.js.map +1 -0
  71. package/dist/seeds/transformers-embedder.d.ts +21 -0
  72. package/dist/seeds/transformers-embedder.d.ts.map +1 -0
  73. package/dist/seeds/transformers-embedder.js +26 -0
  74. package/dist/seeds/transformers-embedder.js.map +1 -0
  75. package/dist/select/pack.d.ts +48 -0
  76. package/dist/select/pack.d.ts.map +1 -0
  77. package/dist/select/pack.js +135 -0
  78. package/dist/select/pack.js.map +1 -0
  79. package/package.json +94 -0
@@ -0,0 +1,60 @@
1
+ import type { SymbolGraph } from './graph.js';
2
+ export interface SelectOptions {
3
+ /** Seed node ids — always included in the result. */
4
+ seeds: ReadonlySet<string>;
5
+ /** Personalized PageRank values per node (or any node-relevance scoring). */
6
+ ranks: ReadonlyMap<string, number>;
7
+ /** Token budget the selection must respect. */
8
+ budget: number;
9
+ /**
10
+ * Weight on the rank term in the greedy objective. Default 1.
11
+ * Higher → favor task-relevant nodes more, even if loosely attached.
12
+ */
13
+ rankWeight?: number;
14
+ /**
15
+ * Weight on the attachment term. Default 1.
16
+ * Higher → favor nodes that close off the cut boundary,
17
+ * even at the cost of some rank.
18
+ */
19
+ attachmentWeight?: number;
20
+ }
21
+ export interface SelectionEntry {
22
+ id: string;
23
+ tokens: number;
24
+ rank: number;
25
+ reason: string;
26
+ }
27
+ export interface SelectionResult {
28
+ selected: Set<string>;
29
+ entries: SelectionEntry[];
30
+ tokens: number;
31
+ cutCost: number;
32
+ }
33
+ /**
34
+ * Greedy budget-constrained min-cut approximation.
35
+ *
36
+ * Given a graph G, seed set S, node-relevance r, and token budget B,
37
+ * find T ⊇ S with Σ tokens(T) ≤ B that approximately maximizes
38
+ *
39
+ * f(T) = Σ_{v∈T} r(v) − λ · cut(T, V\T) / (cut(∅,V) + 1)
40
+ *
41
+ * The objective is monotone submodular over the relevance term and
42
+ * the negative-cut term is submodular w.r.t. inclusion, so the classic
43
+ * greedy algorithm achieves a (1 − 1/e) approximation under a
44
+ * knapsack constraint (Sviridenko 2004 / Krause & Guestrin 2005).
45
+ *
46
+ * Implementation note: instead of recomputing cut(T) at every step (O(|V|)),
47
+ * we track each candidate's incremental "attachment ratio":
48
+ *
49
+ * attach(v, T) = w(edges(v) ∩ T) / w(edges(v))
50
+ *
51
+ * which is monotone increasing as T grows and gives a per-token figure of
52
+ * merit:
53
+ *
54
+ * score(v, T) = ( rankWeight · r(v) · (attach(v, T) + ε) ) / tokens(v)
55
+ *
56
+ * Greedy picks the unselected v with the highest score that still fits in
57
+ * the remaining budget.
58
+ */
59
+ export declare function greedySelect(graph: SymbolGraph, options: SelectOptions): SelectionResult;
60
+ //# sourceMappingURL=select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/core/select.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,6EAA6E;IAC7E,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,GAAG,eAAe,CAoFxF"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Greedy budget-constrained min-cut approximation.
3
+ *
4
+ * Given a graph G, seed set S, node-relevance r, and token budget B,
5
+ * find T ⊇ S with Σ tokens(T) ≤ B that approximately maximizes
6
+ *
7
+ * f(T) = Σ_{v∈T} r(v) − λ · cut(T, V\T) / (cut(∅,V) + 1)
8
+ *
9
+ * The objective is monotone submodular over the relevance term and
10
+ * the negative-cut term is submodular w.r.t. inclusion, so the classic
11
+ * greedy algorithm achieves a (1 − 1/e) approximation under a
12
+ * knapsack constraint (Sviridenko 2004 / Krause & Guestrin 2005).
13
+ *
14
+ * Implementation note: instead of recomputing cut(T) at every step (O(|V|)),
15
+ * we track each candidate's incremental "attachment ratio":
16
+ *
17
+ * attach(v, T) = w(edges(v) ∩ T) / w(edges(v))
18
+ *
19
+ * which is monotone increasing as T grows and gives a per-token figure of
20
+ * merit:
21
+ *
22
+ * score(v, T) = ( rankWeight · r(v) · (attach(v, T) + ε) ) / tokens(v)
23
+ *
24
+ * Greedy picks the unselected v with the highest score that still fits in
25
+ * the remaining budget.
26
+ */
27
+ export function greedySelect(graph, options) {
28
+ const { seeds, ranks, budget, rankWeight = 1, attachmentWeight = 1, } = options;
29
+ const selected = new Set();
30
+ const entries = [];
31
+ let usedTokens = 0;
32
+ // 1. Seeds first. They must all fit.
33
+ for (const id of seeds) {
34
+ const data = graph.getNode(id);
35
+ if (!data)
36
+ throw new Error(`seed not in graph: ${id}`);
37
+ if (usedTokens + data.tokens > budget) {
38
+ throw new Error(`seeds exceed budget: seed "${id}" needs ${data.tokens} tokens, ${budget - usedTokens} remaining of budget ${budget}`);
39
+ }
40
+ selected.add(id);
41
+ usedTokens += data.tokens;
42
+ entries.push({
43
+ id,
44
+ tokens: data.tokens,
45
+ rank: ranks.get(id) ?? 0,
46
+ reason: 'seed — matched directly by task',
47
+ });
48
+ }
49
+ // 2. Greedy fill.
50
+ while (true) {
51
+ const remaining = budget - usedTokens;
52
+ if (remaining <= 0)
53
+ break;
54
+ let best = null;
55
+ for (const id of graph.nodes()) {
56
+ if (selected.has(id))
57
+ continue;
58
+ const data = graph.getNode(id);
59
+ if (!data || data.tokens > remaining)
60
+ continue;
61
+ const attach = attachmentRatio(graph, id, selected);
62
+ // Hard cut-boundary constraint: never extend into a disconnected node.
63
+ // Adding it would strictly increase cut(T,V\T) without benefit, which
64
+ // contradicts the min-cut objective. This is also what gives us the
65
+ // "auth-only for an auth task" cohesion.
66
+ if (attach === 0)
67
+ continue;
68
+ const rank = ranks.get(id) ?? 0;
69
+ const score = (rankWeight * rank * attach * attachmentWeight) / Math.max(data.tokens, 1);
70
+ if (!best || score > best.score) {
71
+ best = { id, score, tokens: data.tokens, rank, attach };
72
+ }
73
+ }
74
+ if (!best)
75
+ break;
76
+ selected.add(best.id);
77
+ usedTokens += best.tokens;
78
+ entries.push({
79
+ id: best.id,
80
+ tokens: best.tokens,
81
+ rank: best.rank,
82
+ reason: reasonFor(best.attach, best.rank),
83
+ });
84
+ }
85
+ return {
86
+ selected,
87
+ entries,
88
+ tokens: usedTokens,
89
+ cutCost: graph.cutCost(selected),
90
+ };
91
+ }
92
+ function attachmentRatio(graph, id, t) {
93
+ let inside = 0;
94
+ let total = 0;
95
+ for (const e of graph.outEdges(id)) {
96
+ total += e.data.weight;
97
+ if (t.has(e.target))
98
+ inside += e.data.weight;
99
+ }
100
+ for (const e of graph.inEdges(id)) {
101
+ total += e.data.weight;
102
+ if (t.has(e.target))
103
+ inside += e.data.weight;
104
+ }
105
+ if (total === 0)
106
+ return 0;
107
+ return inside / total;
108
+ }
109
+ function reasonFor(attach, rank) {
110
+ if (attach >= 0.5 && rank > 0)
111
+ return `attached (${pct(attach)}) + ranked (${rank.toFixed(3)})`;
112
+ if (attach > 0)
113
+ return `attached (${pct(attach)})`;
114
+ if (rank > 0)
115
+ return `ranked (${rank.toFixed(3)})`;
116
+ return 'opportunistic';
117
+ }
118
+ function pct(x) {
119
+ return `${Math.round(x * 100)}%`;
120
+ }
121
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/core/select.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { SymbolGraph } from '../core/graph.js';
2
+ import { type WalkOptions } from './walker.js';
3
+ export interface IndexResult {
4
+ graph: SymbolGraph;
5
+ stats: {
6
+ files: number;
7
+ symbols: number;
8
+ edges: number;
9
+ unresolvedCalls: number;
10
+ };
11
+ }
12
+ export declare function indexRepo(root: string, options?: WalkOptions): IndexResult;
13
+ //# sourceMappingURL=builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/index/builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAI/C,OAAO,EAAQ,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAYrD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,WAAW,CAwF9E"}
@@ -0,0 +1,186 @@
1
+ import path from 'node:path';
2
+ import { SymbolGraph } from '../core/graph.js';
3
+ import { parseTypeScript } from '../parsers/ts.js';
4
+ import { parsePython } from '../parsers/py.js';
5
+ import { walk } from './walker.js';
6
+ const TS_EXT = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']);
7
+ const PY_EXT = new Set(['.py', '.pyi']);
8
+ function parseForExt(file, source) {
9
+ const ext = path.extname(file);
10
+ if (TS_EXT.has(ext))
11
+ return parseTypeScript(file, source);
12
+ if (PY_EXT.has(ext))
13
+ return parsePython(file, source);
14
+ return null;
15
+ }
16
+ export function indexRepo(root, options = {}) {
17
+ const graph = new SymbolGraph();
18
+ // Per-file accumulators we need for cross-file resolution.
19
+ const fileImports = new Map();
20
+ const symbolsByFile = new Map();
21
+ const symbolByName = new Map();
22
+ const pendingCalls = [];
23
+ let fileCount = 0;
24
+ let unresolved = 0;
25
+ for (const file of walk(root, options)) {
26
+ const parsed = parseForExt(file.relPath, file.source);
27
+ if (!parsed)
28
+ continue;
29
+ fileCount += 1;
30
+ fileImports.set(file.relPath, parsed.imports);
31
+ symbolsByFile.set(file.relPath, parsed.symbols);
32
+ for (const sym of parsed.symbols) {
33
+ if (graph.hasNode(sym.id))
34
+ continue;
35
+ graph.addNode(sym.id, {
36
+ tokens: sym.tokens,
37
+ file: sym.file,
38
+ kind: sym.kind,
39
+ name: sym.name,
40
+ startLine: sym.startLine,
41
+ endLine: sym.endLine,
42
+ });
43
+ const arr = symbolByName.get(sym.name) ?? [];
44
+ arr.push(sym.id);
45
+ symbolByName.set(sym.name, arr);
46
+ }
47
+ for (const call of parsed.calls) {
48
+ pendingCalls.push({ from: call.from, toName: call.toName, file: file.relPath });
49
+ }
50
+ }
51
+ const knownFiles = new Set(symbolsByFile.keys());
52
+ const resolve = (file, spec) => resolveImportPath(file, spec, knownFiles);
53
+ // Resolve calls in a second pass.
54
+ for (const call of pendingCalls) {
55
+ const target = resolveCall(call.from, call.toName, call.file, fileImports, symbolsByFile, symbolByName, resolve);
56
+ if (!target) {
57
+ unresolved += 1;
58
+ continue;
59
+ }
60
+ if (!graph.hasNode(call.from) || !graph.hasNode(target))
61
+ continue;
62
+ if (call.from === target)
63
+ continue;
64
+ graph.addEdge(call.from, target, { weight: 1, kind: 'call' });
65
+ }
66
+ // Add import-level structural edges (lower weight than calls).
67
+ for (const [file, imports] of fileImports) {
68
+ const callers = (symbolsByFile.get(file) ?? []).map((s) => s.id);
69
+ if (callers.length === 0)
70
+ continue;
71
+ for (const imp of imports) {
72
+ const resolvedFile = resolve(file, imp.source);
73
+ if (!resolvedFile)
74
+ continue;
75
+ const targets = symbolsByFile.get(resolvedFile);
76
+ if (!targets)
77
+ continue;
78
+ for (const name of imp.names) {
79
+ const targetSym = targets.find((s) => s.name === name);
80
+ if (!targetSym)
81
+ continue;
82
+ for (const caller of callers) {
83
+ if (caller === targetSym.id)
84
+ continue;
85
+ if (!graph.hasNode(caller) || !graph.hasNode(targetSym.id))
86
+ continue;
87
+ if (graph.hasEdge(caller, targetSym.id))
88
+ continue;
89
+ graph.addEdge(caller, targetSym.id, { weight: 0.5, kind: 'import' });
90
+ }
91
+ }
92
+ }
93
+ }
94
+ return {
95
+ graph,
96
+ stats: {
97
+ files: fileCount,
98
+ symbols: graph.order(),
99
+ edges: graph.size(),
100
+ unresolvedCalls: unresolved,
101
+ },
102
+ };
103
+ }
104
+ function resolveCall(fromId, name, file, fileImports, symbolsByFile, symbolByName, resolve) {
105
+ // 1. Try imports in the caller's file.
106
+ const imports = fileImports.get(file) ?? [];
107
+ for (const imp of imports) {
108
+ if (!imp.names.includes(name))
109
+ continue;
110
+ const resolved = resolve(file, imp.source);
111
+ if (!resolved)
112
+ continue;
113
+ const targetSym = symbolsByFile.get(resolved)?.find((s) => s.name === name);
114
+ if (targetSym)
115
+ return targetSym.id;
116
+ }
117
+ // 2. Same-file lookup.
118
+ const candidates = symbolByName.get(name) ?? [];
119
+ const sameFile = candidates.find((id) => id.startsWith(`${file}:`));
120
+ if (sameFile && sameFile !== fromId)
121
+ return sameFile;
122
+ // 3. Unique global match (heuristic).
123
+ if (candidates.length === 1 && candidates[0] !== fromId)
124
+ return candidates[0];
125
+ return null;
126
+ }
127
+ function resolveImportPath(fromFile, spec, knownFiles) {
128
+ const isPython = fromFile.endsWith('.py') || fromFile.endsWith('.pyi');
129
+ if (isPython)
130
+ return resolvePythonImport(fromFile, spec, knownFiles);
131
+ return resolveJsImport(fromFile, spec, knownFiles);
132
+ }
133
+ function resolveJsImport(fromFile, spec, knownFiles) {
134
+ if (!spec.startsWith('.'))
135
+ return null;
136
+ const fromDir = path.posix.dirname(fromFile);
137
+ const base = path.posix.normalize(path.posix.join(fromDir, spec));
138
+ const candidates = [
139
+ base,
140
+ `${base}.ts`, `${base}.tsx`, `${base}.js`, `${base}.jsx`, `${base}.mjs`, `${base}.cjs`,
141
+ `${base}/index.ts`, `${base}/index.tsx`, `${base}/index.js`,
142
+ ];
143
+ for (const c of candidates)
144
+ if (knownFiles.has(c))
145
+ return c;
146
+ return null;
147
+ }
148
+ /**
149
+ * Python import resolution. Maps:
150
+ * `from .session import X` → same-dir/session.py
151
+ * `from ..auth import X` → parent-dir/auth.py
152
+ * `from pkg.sub import X` → pkg/sub.py
153
+ * `from . import X` → same-dir/X.py
154
+ * Falls back to same-package layout.
155
+ */
156
+ function resolvePythonImport(fromFile, spec, knownFiles) {
157
+ const fromDir = path.posix.dirname(fromFile);
158
+ let resolvedDir = fromDir;
159
+ let remainder = spec;
160
+ // Leading dots = relative level.
161
+ while (remainder.startsWith('.')) {
162
+ if (remainder.startsWith('..')) {
163
+ resolvedDir = path.posix.dirname(resolvedDir);
164
+ remainder = remainder.slice(1);
165
+ }
166
+ else {
167
+ remainder = remainder.slice(1);
168
+ }
169
+ }
170
+ // dotted_name → path segments.
171
+ const moduleSegments = remainder ? remainder.split('.') : [];
172
+ const base = moduleSegments.length
173
+ ? path.posix.normalize(path.posix.join(resolvedDir, ...moduleSegments))
174
+ : path.posix.normalize(resolvedDir);
175
+ const candidates = [
176
+ `${base}.py`,
177
+ `${base}.pyi`,
178
+ `${base}/__init__.py`,
179
+ base,
180
+ ];
181
+ for (const c of candidates)
182
+ if (knownFiles.has(c))
183
+ return c;
184
+ return null;
185
+ }
186
+ //# sourceMappingURL=builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/index/builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface WalkOptions {
2
+ /** Glob-like patterns of files to include (matched against POSIX-style relative paths). */
3
+ include?: string[];
4
+ /** Extra ignore patterns appended to .gitignore rules. */
5
+ exclude?: string[];
6
+ /** Max bytes per file before we skip (default 256 KB). */
7
+ maxBytes?: number;
8
+ }
9
+ export interface WalkedFile {
10
+ absPath: string;
11
+ relPath: string;
12
+ source: string;
13
+ }
14
+ export declare function walk(root: string, options?: WalkOptions): IterableIterator<WalkedFile>;
15
+ //# sourceMappingURL=walker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walker.d.ts","sourceRoot":"","sources":["../../src/index/walker.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,2FAA2F;IAC3F,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AA0BD,wBAAiB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,gBAAgB,CAAC,UAAU,CAAC,CA2C3F"}
@@ -0,0 +1,103 @@
1
+ import { readFileSync, statSync, readdirSync, existsSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import ignore from 'ignore';
4
+ const DEFAULT_EXCLUDES = [
5
+ '.git/',
6
+ 'node_modules/',
7
+ 'dist/',
8
+ 'build/',
9
+ 'coverage/',
10
+ '.next/',
11
+ '.nuxt/',
12
+ '.turbo/',
13
+ '.cache/',
14
+ '.parcel-cache/',
15
+ '.svelte-kit/',
16
+ '.pnpm-store/',
17
+ '.idea/',
18
+ '.vscode/',
19
+ '.DS_Store',
20
+ '*.min.js',
21
+ '*.min.css',
22
+ '*.map',
23
+ '*.log',
24
+ ];
25
+ const SUPPORTED_EXT = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.py', '.pyi']);
26
+ export function* walk(root, options = {}) {
27
+ const maxBytes = options.maxBytes ?? 256 * 1024;
28
+ const ig = buildIgnore(root, options.exclude);
29
+ const includePatterns = options.include?.map(globToPrefix) ?? null;
30
+ function* walkDir(dir) {
31
+ let entries;
32
+ try {
33
+ entries = readdirSync(dir);
34
+ }
35
+ catch {
36
+ return;
37
+ }
38
+ for (const name of entries) {
39
+ const abs = path.join(dir, name);
40
+ const rel = toPosix(path.relative(root, abs));
41
+ let stat;
42
+ try {
43
+ stat = statSync(abs);
44
+ }
45
+ catch {
46
+ continue;
47
+ }
48
+ const relForIgnore = stat.isDirectory() ? `${rel}/` : rel;
49
+ if (ig.ignores(relForIgnore))
50
+ continue;
51
+ if (stat.isDirectory()) {
52
+ yield* walkDir(abs);
53
+ continue;
54
+ }
55
+ if (!stat.isFile())
56
+ continue;
57
+ const ext = path.extname(name);
58
+ if (!SUPPORTED_EXT.has(ext))
59
+ continue;
60
+ if (stat.size > maxBytes)
61
+ continue;
62
+ if (includePatterns && !includePatterns.some((p) => rel.startsWith(p)))
63
+ continue;
64
+ let source;
65
+ try {
66
+ source = readFileSync(abs, 'utf8');
67
+ }
68
+ catch {
69
+ continue;
70
+ }
71
+ yield { absPath: abs, relPath: rel, source };
72
+ }
73
+ }
74
+ yield* walkDir(root);
75
+ }
76
+ function buildIgnore(root, extraExcludes) {
77
+ const ig = ignore();
78
+ ig.add(DEFAULT_EXCLUDES);
79
+ const gitignore = path.join(root, '.gitignore');
80
+ if (existsSync(gitignore)) {
81
+ try {
82
+ ig.add(readFileSync(gitignore, 'utf8'));
83
+ }
84
+ catch {
85
+ // ignore
86
+ }
87
+ }
88
+ if (extraExcludes?.length)
89
+ ig.add(extraExcludes);
90
+ return ig;
91
+ }
92
+ function toPosix(p) {
93
+ return p.replace(/\\/g, '/');
94
+ }
95
+ /**
96
+ * Convert simple glob like 'src/auth/**' into a path prefix. For v1.0 we
97
+ * support only the trailing `**` / `*` wildcard form; anything fancier should
98
+ * fall back to a full glob library if needed.
99
+ */
100
+ function globToPrefix(glob) {
101
+ return glob.replace(/\/\*\*$/, '/').replace(/\/\*$/, '/').replace(/\*\*$/, '');
102
+ }
103
+ //# sourceMappingURL=walker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walker.js","sourceRoot":"","sources":["../../src/index/walker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { NodeKind } from '../core/graph.js';
2
+ export interface ParsedSymbol {
3
+ id: string;
4
+ name: string;
5
+ file: string;
6
+ kind: NodeKind;
7
+ startLine: number;
8
+ endLine: number;
9
+ tokens: number;
10
+ }
11
+ export interface ParsedImport {
12
+ source: string;
13
+ names: string[];
14
+ namespace?: string;
15
+ }
16
+ export interface ParsedCall {
17
+ from: string;
18
+ toName: string;
19
+ }
20
+ export interface ParseResult {
21
+ symbols: ParsedSymbol[];
22
+ imports: ParsedImport[];
23
+ calls: ParsedCall[];
24
+ }
25
+ export interface LanguageParser {
26
+ /** File extensions this parser claims, e.g. ['.ts', '.tsx']. */
27
+ extensions: string[];
28
+ parse(file: string, source: string): ParseResult;
29
+ }
30
+ /**
31
+ * Approximate token count from a character count.
32
+ * 4 chars/token is the canonical OpenAI rule-of-thumb. Good enough for budgeting.
33
+ */
34
+ export declare function approxTokens(text: string): number;
35
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/parsers/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,gEAAgE;IAChE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC;CAClD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Approximate token count from a character count.
3
+ * 4 chars/token is the canonical OpenAI rule-of-thumb. Good enough for budgeting.
4
+ */
5
+ export function approxTokens(text) {
6
+ return Math.ceil(text.length / 4);
7
+ }
8
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/parsers/parser.ts"],"names":[],"mappings":"AAmCA;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type ParseResult } from './parser.js';
2
+ export declare function parsePython(file: string, source: string): ParseResult;
3
+ //# sourceMappingURL=py.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"py.d.ts","sourceRoot":"","sources":["../../src/parsers/py.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,aAAa,CAAC;AAQrB,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAmBrE"}