@shanepadgett/tau-agent 0.33.0 → 0.34.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.
- package/docs/context.md +29 -20
- package/docs/extending-tau-agent.md +63 -24
- package/extensions/appshot/index.ts +112 -111
- package/extensions/aside/README.md +7 -0
- package/extensions/aside/index.ts +168 -0
- package/extensions/aside/panel.ts +83 -0
- package/extensions/branch/index.ts +38 -21
- package/extensions/cache-diagnostics/index.ts +70 -58
- package/extensions/checkpoint/README.md +9 -0
- package/extensions/checkpoint/checkpoint-budget.ts +79 -0
- package/extensions/checkpoint/checkpoint.ts +277 -0
- package/extensions/checkpoint/index.ts +102 -0
- package/extensions/checkpoint/messages.ts +169 -0
- package/extensions/checkpoint/prompt.ts +24 -0
- package/extensions/checkpoint/settings.ts +27 -0
- package/extensions/commit/commit-effort.ts +3 -3
- package/extensions/context/README.md +12 -8
- package/extensions/context/definitions.ts +178 -55
- package/extensions/context/index.ts +192 -160
- package/extensions/context/panel.ts +57 -37
- package/extensions/context/sync.ts +139 -89
- package/extensions/context/validation.ts +37 -25
- package/extensions/effort/README.md +1 -1
- package/extensions/effort/index.ts +3 -3
- package/extensions/effort/state.ts +3 -18
- package/extensions/explore/guidance.ts +6 -47
- package/extensions/explore/index.ts +38 -53
- package/extensions/explore/{ast/read → read}/hook.ts +12 -7
- package/extensions/explore/{ast/tools → tools}/ast-search.ts +15 -19
- package/extensions/explore/{ast/tools → tools}/context.ts +16 -23
- package/extensions/explore/{ast/tools → tools}/deps.ts +11 -15
- package/extensions/explore/{ast/tools → tools}/discover.ts +15 -17
- package/extensions/explore/{ast/tools → tools}/impact.ts +20 -23
- package/extensions/explore/{ast/tools → tools}/outline.ts +21 -24
- package/extensions/explore/{ast/tools → tools}/relationships.ts +23 -32
- package/extensions/explore/{ast/tools → tools}/render.ts +1 -1
- package/extensions/explore/{ast/tools → tools}/reverse-deps.ts +11 -15
- package/extensions/explore/{ast/tools → tools}/show.ts +16 -19
- package/extensions/explore/tools/target-params.ts +9 -0
- package/extensions/footer/index.ts +75 -56
- package/extensions/handoff/index.ts +8 -30
- package/extensions/image-gen/index.ts +46 -40
- package/extensions/patch/executor.ts +190 -135
- package/extensions/patch/matcher.ts +82 -48
- package/extensions/patch/parser.ts +149 -105
- package/extensions/patch/render.ts +32 -39
- package/extensions/patch/summary.ts +30 -26
- package/extensions/ready/README.md +7 -0
- package/extensions/ready/index.ts +58 -0
- package/extensions/ready/model.ts +128 -0
- package/extensions/ready/packs.ts +272 -0
- package/extensions/ready/render.ts +445 -0
- package/extensions/ready/scan.ts +760 -0
- package/extensions/reference/panel.ts +28 -16
- package/extensions/review/index.ts +63 -51
- package/extensions/review/panel.ts +5 -34
- package/extensions/runtime-context/context.ts +30 -26
- package/extensions/script-runner/README.md +2 -2
- package/extensions/script-runner/index.ts +130 -93
- package/extensions/silent-command-runner/index.ts +38 -23
- package/extensions/subagent/agents/context-sync.md +185 -33
- package/extensions/subagent/agents/scout.md +2 -2
- package/extensions/subagent/agents.ts +137 -84
- package/extensions/subagent/cmux-dashboard.ts +39 -30
- package/extensions/subagent/index.ts +79 -59
- package/extensions/subagent/resume.ts +1 -1
- package/extensions/subagent/run.ts +304 -193
- package/extensions/subagent/runtime.ts +781 -343
- package/extensions/tau/index.ts +47 -38
- package/extensions/tau-help/help.md +14 -6
- package/extensions/tool-loader/README.md +4 -2
- package/extensions/tool-loader/index.ts +77 -52
- package/extensions/web/index.ts +6 -3
- package/extensions/web/webfetch.ts +114 -86
- package/package.json +3 -3
- package/schemas/tau.schema.json +20 -33
- package/shared/bounded-text-result.ts +1 -0
- package/shared/checkpoint-visibility.ts +9 -0
- package/shared/events.ts +28 -10
- package/shared/isolated-session.ts +71 -29
- package/shared/model-effort.ts +9 -19
- package/shared/model-fallback/index.ts +66 -41
- package/shared/settings/load.ts +45 -38
- package/shared/temporary-output-store.ts +16 -10
- package/{extensions/explore → src}/ast/adapter.ts +11 -2
- package/{extensions/explore → src}/ast/engine.ts +54 -38
- package/{extensions/explore → src}/ast/format/ast-search.ts +15 -6
- package/{extensions/explore → src}/ast/format/context.ts +3 -6
- package/src/ast/format/deps.ts +94 -0
- package/{extensions/explore → src}/ast/format/discover.ts +2 -2
- package/{extensions/explore → src}/ast/format/impact.ts +9 -11
- package/{extensions/explore → src}/ast/format/outline.ts +2 -2
- package/{extensions/explore → src}/ast/format/relationships.ts +11 -7
- package/{extensions/explore → src}/ast/format/show.ts +1 -1
- package/src/ast/format/targeted-result.ts +20 -0
- package/src/ast/grammars/c_sharp.wasm +0 -0
- package/{extensions/explore → src}/ast/grammars/manifest.json +9 -12
- package/{extensions/explore → src}/ast/grammars/manifest.ts +0 -4
- package/{extensions/explore → src}/ast/graph/file-graph.ts +210 -98
- package/{extensions/explore → src}/ast/graph/relationships.ts +285 -72
- package/{extensions/explore → src}/ast/ir.ts +6 -0
- package/src/ast/languages/csharp-file-deps.ts +90 -0
- package/{extensions/explore → src}/ast/languages/csharp.ts +9 -40
- package/src/ast/languages/dotted-index.ts +131 -0
- package/{extensions/explore → src}/ast/languages/file-dep-util.ts +22 -13
- package/src/ast/languages/fixtures/sample.cs +53 -0
- package/src/ast/languages/fixtures/sample.cs.expected.json +156 -0
- package/src/ast/languages/fixtures/sample.go +37 -0
- package/src/ast/languages/fixtures/sample.go.expected.json +96 -0
- package/src/ast/languages/fixtures/sample.java +40 -0
- package/src/ast/languages/fixtures/sample.java.expected.json +126 -0
- package/src/ast/languages/fixtures/sample.kt +31 -0
- package/src/ast/languages/fixtures/sample.kt.expected.json +134 -0
- package/src/ast/languages/fixtures/sample.md +23 -0
- package/src/ast/languages/fixtures/sample.md.expected.json +44 -0
- package/src/ast/languages/fixtures/sample.rs +54 -0
- package/src/ast/languages/fixtures/sample.rs.expected.json +178 -0
- package/src/ast/languages/fixtures/sample.swift +45 -0
- package/src/ast/languages/fixtures/sample.swift.expected.json +147 -0
- package/src/ast/languages/fixtures/sample.ts +45 -0
- package/src/ast/languages/fixtures/sample.ts.expected.json +141 -0
- package/src/ast/languages/fixtures/sample.tsx +36 -0
- package/src/ast/languages/fixtures/sample.tsx.expected.json +59 -0
- package/{extensions/explore → src}/ast/languages/go-file-deps.ts +6 -0
- package/{extensions/explore → src}/ast/languages/go.ts +21 -3
- package/{extensions/explore → src}/ast/languages/java.ts +5 -38
- package/src/ast/languages/jvm-file-deps.ts +135 -0
- package/{extensions/explore → src}/ast/languages/kotlin.ts +5 -39
- package/{extensions/explore → src}/ast/languages/rust-file-deps.ts +3 -3
- package/{extensions/explore → src}/ast/languages/rust.ts +21 -13
- package/{extensions/explore → src}/ast/languages/swift-file-deps.ts +22 -15
- package/{extensions/explore → src}/ast/languages/swift.ts +9 -39
- package/{extensions/explore → src}/ast/languages/tree.ts +47 -0
- package/{extensions/explore → src}/ast/languages/typescript-file-deps.ts +108 -0
- package/{extensions/explore → src}/ast/languages/typescript-package-surface.ts +4 -3
- package/{extensions/explore → src}/ast/languages/typescript.ts +3 -5
- package/{extensions/explore → src}/ast/markdown.ts +72 -47
- package/{extensions/explore → src}/ast/queries/ast-search.ts +164 -146
- package/{extensions/explore → src}/ast/queries/composite-target.ts +1 -1
- package/{extensions/explore → src}/ast/queries/context.ts +116 -80
- package/{extensions/explore → src}/ast/queries/discover.ts +154 -105
- package/src/ast/queries/impact.ts +291 -0
- package/{extensions/explore → src}/ast/queries/outline.ts +4 -2
- package/{extensions/explore → src}/ast/queries/show.ts +46 -42
- package/{extensions/explore → src}/ast/query.ts +1 -1
- package/{extensions/explore → src}/ast/registry.ts +1 -2
- package/{extensions/explore → src}/ast/scan.ts +1 -1
- package/src/ast/session.ts +50 -0
- package/{extensions/explore → src}/ast/slice.ts +8 -0
- package/{extensions/explore → src/ast}/traverse.ts +32 -20
- package/src/file-injection/index.ts +547 -0
- package/src/image-generation/client.ts +50 -31
- package/src/image-generation/index.ts +177 -134
- package/src/index.ts +2 -0
- package/src/tool-loading/index.ts +58 -0
- package/extensions/context/evidence.ts +0 -517
- package/extensions/context/projection.ts +0 -141
- package/extensions/context/state.ts +0 -30
- package/extensions/context/write-scope.ts +0 -109
- package/extensions/explore/ast/format/deps.ts +0 -86
- package/extensions/explore/ast/grammars/odin.wasm +0 -0
- package/extensions/explore/ast/languages/csharp-file-deps.ts +0 -189
- package/extensions/explore/ast/languages/fixtures/sample.cs +0 -17
- package/extensions/explore/ast/languages/fixtures/sample.java +0 -21
- package/extensions/explore/ast/languages/fixtures/sample.kt +0 -15
- package/extensions/explore/ast/languages/fixtures/sample.odin +0 -28
- package/extensions/explore/ast/languages/fixtures/sample.rs +0 -31
- package/extensions/explore/ast/languages/fixtures/sample.swift +0 -25
- package/extensions/explore/ast/languages/jvm-file-deps.ts +0 -217
- package/extensions/explore/ast/languages/odin-file-deps.ts +0 -175
- package/extensions/explore/ast/languages/odin.ts +0 -407
- package/extensions/explore/ast/queries/impact.ts +0 -250
- package/extensions/explore/outline-injection.ts +0 -151
- package/extensions/explore/read/autoread.ts +0 -118
- package/extensions/working-memory/README.md +0 -17
- package/extensions/working-memory/checkpoint.ts +0 -242
- package/extensions/working-memory/index.ts +0 -341
- package/extensions/working-memory/memory.ts +0 -235
- package/extensions/working-memory/render.ts +0 -185
- package/extensions/working-memory/settings.ts +0 -38
- package/extensions/working-memory/state.ts +0 -158
- package/shared/autoread.ts +0 -234
- package/shared/context-messages.ts +0 -19
- package/shared/outline-injection.ts +0 -56
- /package/{extensions/explore → src}/ast/format/composite.ts +0 -0
- /package/{extensions/explore → src}/ast/grammars/kotlin.wasm +0 -0
- /package/{extensions/explore → src}/ast/grammars/swift.wasm +0 -0
- /package/{extensions/explore → src}/ast/identity.ts +0 -0
- /package/{extensions/explore → src}/ast/package-surface.ts +0 -0
- /package/{extensions/explore/ast/read/policy.ts → src/ast/read-policy.ts} +0 -0
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { lstat, opendir } from "node:fs/promises";
|
|
2
2
|
import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
3
|
-
import type { FileDepHost, LanguageAdapter } from "../adapter.ts";
|
|
3
|
+
import type { FileDepHost, FileDepResolution, LanguageAdapter } from "../adapter.ts";
|
|
4
4
|
import type { ExploreEngine } from "../engine.ts";
|
|
5
5
|
import { scanSources } from "../scan.ts";
|
|
6
|
-
import { formatPathForDisplay, pathResolutionError, resolveExplorePath } from "
|
|
6
|
+
import { formatPathForDisplay, pathResolutionError, resolveExplorePath } from "../traverse.ts";
|
|
7
7
|
|
|
8
8
|
export type FileGraphEdge =
|
|
9
9
|
| { kind: "internal"; from: string; to: string }
|
|
10
|
+
| { kind: "package"; from: string; id: string; dir: string; fileCount: number }
|
|
10
11
|
| { kind: "external"; from: string; id: string };
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
/** One resolved dependency endpoint, independent of traversal depth. */
|
|
14
|
+
export type FileDepTarget =
|
|
15
|
+
| { kind: "internal"; path: string }
|
|
16
|
+
/** In-repo directory too large to list; `id` is the import as written. */
|
|
17
|
+
| { kind: "package"; id: string; dir: string; fileCount: number }
|
|
18
|
+
| { kind: "external"; id: string };
|
|
19
|
+
|
|
20
|
+
export type FileDepHit = { depth: number } & FileDepTarget;
|
|
19
21
|
|
|
20
22
|
export type FileDepQueryResult = {
|
|
21
23
|
seedPath: string;
|
|
@@ -23,6 +25,8 @@ export type FileDepQueryResult = {
|
|
|
23
25
|
hits: FileDepHit[];
|
|
24
26
|
resultLimit: number;
|
|
25
27
|
resultLimitReached: boolean;
|
|
28
|
+
/** External edges dropped after the external cap (internal edges keep the full limit). */
|
|
29
|
+
externalOmitted: number;
|
|
26
30
|
};
|
|
27
31
|
|
|
28
32
|
export type ExploreFileGraph = {
|
|
@@ -44,6 +48,9 @@ type ReverseIndex = {
|
|
|
44
48
|
byTarget: Map<string, string[]>;
|
|
45
49
|
};
|
|
46
50
|
|
|
51
|
+
/** External ids are cheap noise in bulk; in-repo edges get the caller's full budget. */
|
|
52
|
+
const EXTERNAL_HIT_LIMIT = 10;
|
|
53
|
+
|
|
47
54
|
function isWithin(parent: string, child: string): boolean {
|
|
48
55
|
const rel = relative(resolve(parent), resolve(child));
|
|
49
56
|
return rel === "" || (!rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute(rel));
|
|
@@ -112,6 +119,148 @@ function sortUnique(paths: readonly string[]): string[] {
|
|
|
112
119
|
return [...new Set(paths.map((path) => resolve(path)))].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
113
120
|
}
|
|
114
121
|
|
|
122
|
+
type EdgeSeen = {
|
|
123
|
+
internal: Set<string>;
|
|
124
|
+
package: Set<string>;
|
|
125
|
+
external: Set<string>;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
function emptyEdgeSeen(): EdgeSeen {
|
|
129
|
+
return { internal: new Set(), package: new Set(), external: new Set() };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function appendInternalPaths(
|
|
133
|
+
edges: FileGraphEdge[],
|
|
134
|
+
from: string,
|
|
135
|
+
paths: readonly string[],
|
|
136
|
+
scopeRoot: string,
|
|
137
|
+
ownsPath: (path: string) => boolean,
|
|
138
|
+
seen: Set<string>,
|
|
139
|
+
): void {
|
|
140
|
+
for (const target of sortUnique(paths)) {
|
|
141
|
+
if (!isWithin(scopeRoot, target)) continue;
|
|
142
|
+
if (!ownsPath(target)) continue;
|
|
143
|
+
if (target === from) continue;
|
|
144
|
+
if (seen.has(target)) continue;
|
|
145
|
+
seen.add(target);
|
|
146
|
+
edges.push({ kind: "internal", from, to: target });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function appendResolution(
|
|
151
|
+
edges: FileGraphEdge[],
|
|
152
|
+
from: string,
|
|
153
|
+
resolution: FileDepResolution,
|
|
154
|
+
scopeRoot: string,
|
|
155
|
+
ownsPath: (path: string) => boolean,
|
|
156
|
+
seen: EdgeSeen,
|
|
157
|
+
): void {
|
|
158
|
+
if (resolution.kind === "unresolved") return;
|
|
159
|
+
if (resolution.kind === "external") {
|
|
160
|
+
if (seen.external.has(resolution.id)) return;
|
|
161
|
+
seen.external.add(resolution.id);
|
|
162
|
+
edges.push({ kind: "external", from, id: resolution.id });
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (resolution.kind === "package") {
|
|
166
|
+
if (!isWithin(scopeRoot, resolution.dir) || seen.package.has(resolution.dir)) return;
|
|
167
|
+
seen.package.add(resolution.dir);
|
|
168
|
+
edges.push({
|
|
169
|
+
kind: "package",
|
|
170
|
+
from,
|
|
171
|
+
id: resolution.id,
|
|
172
|
+
dir: resolution.dir,
|
|
173
|
+
fileCount: resolution.fileCount,
|
|
174
|
+
});
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
appendInternalPaths(edges, from, resolution.paths, scopeRoot, ownsPath, seen.internal);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function recordImporter(byTarget: Map<string, string[]>, target: string, from: string): void {
|
|
181
|
+
const list = byTarget.get(target);
|
|
182
|
+
if (list === undefined) byTarget.set(target, [from]);
|
|
183
|
+
else if (!list.includes(from)) list.push(from);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
type ForwardHitState = {
|
|
187
|
+
hits: FileDepHit[];
|
|
188
|
+
resultLimitReached: boolean;
|
|
189
|
+
externalOmitted: number;
|
|
190
|
+
inRepoCount: number;
|
|
191
|
+
externalCount: number;
|
|
192
|
+
listedInternal: Set<string>;
|
|
193
|
+
listedPackage: Set<string>;
|
|
194
|
+
listedExternal: Set<string>;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
function pushForwardEdge(
|
|
198
|
+
state: ForwardHitState,
|
|
199
|
+
edge: FileGraphEdge,
|
|
200
|
+
nextDepth: number,
|
|
201
|
+
resultLimit: number,
|
|
202
|
+
enqueue: (next: string) => void,
|
|
203
|
+
): boolean {
|
|
204
|
+
if (edge.kind === "external") {
|
|
205
|
+
if (state.listedExternal.has(edge.id)) return true;
|
|
206
|
+
state.listedExternal.add(edge.id);
|
|
207
|
+
if (state.externalCount >= EXTERNAL_HIT_LIMIT) {
|
|
208
|
+
state.externalOmitted += 1;
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
state.externalCount += 1;
|
|
212
|
+
state.hits.push({ depth: nextDepth, kind: "external", id: edge.id });
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
if (state.inRepoCount >= resultLimit) {
|
|
216
|
+
state.resultLimitReached = true;
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
if (edge.kind === "package") {
|
|
220
|
+
if (state.listedPackage.has(edge.dir)) return true;
|
|
221
|
+
state.listedPackage.add(edge.dir);
|
|
222
|
+
state.inRepoCount += 1;
|
|
223
|
+
state.hits.push({
|
|
224
|
+
depth: nextDepth,
|
|
225
|
+
kind: "package",
|
|
226
|
+
id: edge.id,
|
|
227
|
+
dir: edge.dir,
|
|
228
|
+
fileCount: edge.fileCount,
|
|
229
|
+
});
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
if (state.listedInternal.has(edge.to)) return true;
|
|
233
|
+
state.listedInternal.add(edge.to);
|
|
234
|
+
state.inRepoCount += 1;
|
|
235
|
+
state.hits.push({ depth: nextDepth, kind: "internal", path: edge.to });
|
|
236
|
+
enqueue(edge.to);
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Breadth-first walk bounded by depth. `expand` returns false to stop the walk. */
|
|
241
|
+
async function walkDepth(
|
|
242
|
+
seedPath: string,
|
|
243
|
+
depth: number,
|
|
244
|
+
signal: AbortSignal,
|
|
245
|
+
expand: (path: string, nextDepth: number, enqueue: (next: string) => void) => Promise<boolean>,
|
|
246
|
+
): Promise<void> {
|
|
247
|
+
const queue: { path: string; depth: number }[] = [{ path: seedPath, depth: 0 }];
|
|
248
|
+
const visited = new Set<string>([seedPath]);
|
|
249
|
+
while (queue.length > 0) {
|
|
250
|
+
signal.throwIfAborted();
|
|
251
|
+
const current = queue.shift();
|
|
252
|
+
if (current === undefined) break;
|
|
253
|
+
if (current.depth >= depth) continue;
|
|
254
|
+
const nextDepth = current.depth + 1;
|
|
255
|
+
const enqueue = (next: string): void => {
|
|
256
|
+
if (nextDepth >= depth || visited.has(next)) return;
|
|
257
|
+
visited.add(next);
|
|
258
|
+
queue.push({ path: next, depth: nextDepth });
|
|
259
|
+
};
|
|
260
|
+
if (!(await expand(current.path, nextDepth, enqueue))) break;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
115
264
|
/**
|
|
116
265
|
* Session file-import graph. Shared code never interprets import syntax —
|
|
117
266
|
* adapters own resolveFileDep.
|
|
@@ -152,33 +301,35 @@ export function createFileGraph(engine: ExploreEngine): ExploreFileGraph {
|
|
|
152
301
|
|
|
153
302
|
const host = makeHost(scopeRoot);
|
|
154
303
|
const edges: FileGraphEdge[] = [];
|
|
155
|
-
const
|
|
156
|
-
const seenExternal = new Set<string>();
|
|
157
|
-
|
|
304
|
+
const seen = emptyEdgeSeen();
|
|
158
305
|
for (const imp of ir.imports) {
|
|
159
306
|
signal.throwIfAborted();
|
|
160
307
|
const resolution = await resolveFileDep(absolutePath, imp.specifier, host, signal);
|
|
161
|
-
|
|
162
|
-
if (resolution.kind === "external") {
|
|
163
|
-
if (seenExternal.has(resolution.id)) continue;
|
|
164
|
-
seenExternal.add(resolution.id);
|
|
165
|
-
edges.push({ kind: "external", from: absolutePath, id: resolution.id });
|
|
166
|
-
continue;
|
|
167
|
-
}
|
|
168
|
-
for (const target of sortUnique(resolution.paths)) {
|
|
169
|
-
if (!isWithin(scopeRoot, target)) continue;
|
|
170
|
-
if (!host.ownsPath(target)) continue;
|
|
171
|
-
if (target === absolutePath) continue;
|
|
172
|
-
if (seenInternal.has(target)) continue;
|
|
173
|
-
seenInternal.add(target);
|
|
174
|
-
edges.push({ kind: "internal", from: absolutePath, to: target });
|
|
175
|
-
}
|
|
308
|
+
appendResolution(edges, absolutePath, resolution, scopeRoot, host.ownsPath, seen);
|
|
176
309
|
}
|
|
177
310
|
|
|
178
311
|
forwardCache.set(absolutePath, { contentHash: ir.contentHash, edges });
|
|
179
312
|
return edges;
|
|
180
313
|
};
|
|
181
314
|
|
|
315
|
+
const indexForwardImporters = async (
|
|
316
|
+
filePath: string,
|
|
317
|
+
scopeRoot: string,
|
|
318
|
+
byTarget: Map<string, string[]>,
|
|
319
|
+
signal: AbortSignal,
|
|
320
|
+
): Promise<void> => {
|
|
321
|
+
const adapter = engine.registry.adapterForPath(filePath);
|
|
322
|
+
if (adapter?.capabilities.fileDeps !== true || adapter.resolveFileDep === undefined) return;
|
|
323
|
+
try {
|
|
324
|
+
const edges = await loadForward(filePath, scopeRoot, signal);
|
|
325
|
+
for (const edge of edges) {
|
|
326
|
+
if (edge.kind === "internal") recordImporter(byTarget, edge.to, edge.from);
|
|
327
|
+
}
|
|
328
|
+
} catch {
|
|
329
|
+
// Skip files that fail resolve/parse during reverse build; keep scanning.
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
|
|
182
333
|
const ensureReverse = async (scopeRoot: string, signal: AbortSignal): Promise<ReverseIndex> => {
|
|
183
334
|
const cached = reverseCache.get(scopeRoot);
|
|
184
335
|
if (cached !== undefined) return cached;
|
|
@@ -193,21 +344,7 @@ export function createFileGraph(engine: ExploreEngine): ExploreFileGraph {
|
|
|
193
344
|
let step = await scan.next();
|
|
194
345
|
while (!step.done) {
|
|
195
346
|
signal.throwIfAborted();
|
|
196
|
-
|
|
197
|
-
const adapter = engine.registry.adapterForPath(filePath);
|
|
198
|
-
if (adapter?.capabilities.fileDeps === true && adapter.resolveFileDep !== undefined) {
|
|
199
|
-
try {
|
|
200
|
-
const edges = await loadForward(filePath, scopeRoot, signal);
|
|
201
|
-
for (const edge of edges) {
|
|
202
|
-
if (edge.kind !== "internal") continue;
|
|
203
|
-
const list = byTarget.get(edge.to);
|
|
204
|
-
if (list === undefined) byTarget.set(edge.to, [edge.from]);
|
|
205
|
-
else if (!list.includes(edge.from)) list.push(edge.from);
|
|
206
|
-
}
|
|
207
|
-
} catch {
|
|
208
|
-
// Skip files that fail resolve/parse during reverse build; keep scanning.
|
|
209
|
-
}
|
|
210
|
-
}
|
|
347
|
+
await indexForwardImporters(step.value.ir.path, scopeRoot, byTarget, signal);
|
|
211
348
|
step = await scan.next();
|
|
212
349
|
}
|
|
213
350
|
|
|
@@ -227,46 +364,33 @@ export function createFileGraph(engine: ExploreEngine): ExploreFileGraph {
|
|
|
227
364
|
signal: AbortSignal,
|
|
228
365
|
): Promise<FileDepQueryResult> => {
|
|
229
366
|
const scopeRoot = await scopeRootFor(seedPath, engine.cwd);
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const edges = await loadForward(current.path, scopeRoot, signal);
|
|
245
|
-
const nextDepth = current.depth + 1;
|
|
246
|
-
|
|
367
|
+
const state: ForwardHitState = {
|
|
368
|
+
hits: [],
|
|
369
|
+
resultLimitReached: false,
|
|
370
|
+
externalOmitted: 0,
|
|
371
|
+
inRepoCount: 0,
|
|
372
|
+
externalCount: 0,
|
|
373
|
+
listedInternal: new Set(),
|
|
374
|
+
listedPackage: new Set(),
|
|
375
|
+
listedExternal: new Set(),
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
await walkDepth(seedPath, depth, signal, async (path, nextDepth, enqueue) => {
|
|
379
|
+
const edges = await loadForward(path, scopeRoot, signal);
|
|
247
380
|
for (const edge of edges) {
|
|
248
|
-
if (
|
|
249
|
-
resultLimitReached = true;
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
252
|
-
if (edge.kind === "external") {
|
|
253
|
-
if (listedExternal.has(edge.id)) continue;
|
|
254
|
-
listedExternal.add(edge.id);
|
|
255
|
-
hits.push({ depth: nextDepth, path: undefined, externalId: edge.id });
|
|
256
|
-
continue;
|
|
257
|
-
}
|
|
258
|
-
if (listedInternal.has(edge.to)) continue;
|
|
259
|
-
listedInternal.add(edge.to);
|
|
260
|
-
hits.push({ depth: nextDepth, path: edge.to, externalId: undefined });
|
|
261
|
-
if (nextDepth < depth && !visited.has(edge.to)) {
|
|
262
|
-
visited.add(edge.to);
|
|
263
|
-
queue.push({ path: edge.to, depth: nextDepth });
|
|
264
|
-
}
|
|
381
|
+
if (!pushForwardEdge(state, edge, nextDepth, resultLimit, enqueue)) break;
|
|
265
382
|
}
|
|
266
|
-
|
|
267
|
-
}
|
|
383
|
+
return !state.resultLimitReached;
|
|
384
|
+
});
|
|
268
385
|
|
|
269
|
-
return {
|
|
386
|
+
return {
|
|
387
|
+
seedPath,
|
|
388
|
+
depth,
|
|
389
|
+
hits: state.hits,
|
|
390
|
+
resultLimit,
|
|
391
|
+
resultLimitReached: state.resultLimitReached,
|
|
392
|
+
externalOmitted: state.externalOmitted,
|
|
393
|
+
};
|
|
270
394
|
};
|
|
271
395
|
|
|
272
396
|
const collectReverseHits = async (
|
|
@@ -281,17 +405,8 @@ export function createFileGraph(engine: ExploreEngine): ExploreFileGraph {
|
|
|
281
405
|
let resultLimitReached = false;
|
|
282
406
|
const listed = new Set<string>();
|
|
283
407
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
while (queue.length > 0) {
|
|
288
|
-
signal.throwIfAborted();
|
|
289
|
-
const current = queue.shift();
|
|
290
|
-
if (current === undefined) break;
|
|
291
|
-
if (current.depth >= depth) continue;
|
|
292
|
-
|
|
293
|
-
const importers = index.byTarget.get(current.path) ?? [];
|
|
294
|
-
const nextDepth = current.depth + 1;
|
|
408
|
+
await walkDepth(seedPath, depth, signal, async (path, nextDepth, enqueue) => {
|
|
409
|
+
const importers = index.byTarget.get(path) ?? [];
|
|
295
410
|
for (const importer of importers) {
|
|
296
411
|
if (hits.length >= resultLimit) {
|
|
297
412
|
resultLimitReached = true;
|
|
@@ -299,16 +414,13 @@ export function createFileGraph(engine: ExploreEngine): ExploreFileGraph {
|
|
|
299
414
|
}
|
|
300
415
|
if (listed.has(importer)) continue;
|
|
301
416
|
listed.add(importer);
|
|
302
|
-
hits.push({ depth: nextDepth,
|
|
303
|
-
|
|
304
|
-
visited.add(importer);
|
|
305
|
-
queue.push({ path: importer, depth: nextDepth });
|
|
306
|
-
}
|
|
417
|
+
hits.push({ depth: nextDepth, kind: "internal", path: importer });
|
|
418
|
+
enqueue(importer);
|
|
307
419
|
}
|
|
308
|
-
|
|
309
|
-
}
|
|
420
|
+
return !resultLimitReached;
|
|
421
|
+
});
|
|
310
422
|
|
|
311
|
-
return { seedPath, depth, hits, resultLimit, resultLimitReached };
|
|
423
|
+
return { seedPath, depth, hits, resultLimit, resultLimitReached, externalOmitted: 0 };
|
|
312
424
|
};
|
|
313
425
|
|
|
314
426
|
const resolveSeedFile = async (pathInput: string): Promise<string> => {
|