@shanepadgett/tau-agent 0.26.0 → 0.28.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 (121) hide show
  1. package/docs/subagents.md +1 -1
  2. package/extensions/appshot/README.md +1 -1
  3. package/extensions/appshot/index.ts +5 -11
  4. package/extensions/context/sync.ts +1 -9
  5. package/extensions/context-pruning/README.md +2 -2
  6. package/extensions/context-pruning/index.ts +58 -57
  7. package/extensions/context-pruning/prune.ts +2 -2
  8. package/extensions/context-pruning/render.ts +51 -39
  9. package/extensions/context-pruning/settings.ts +4 -5
  10. package/extensions/explore/README.md +13 -14
  11. package/extensions/explore/ast/adapter.ts +97 -0
  12. package/extensions/explore/ast/engine.ts +470 -0
  13. package/extensions/explore/ast/format/ast-search.ts +97 -0
  14. package/extensions/explore/ast/format/composite.ts +26 -0
  15. package/extensions/explore/ast/format/context.ts +66 -0
  16. package/extensions/explore/ast/format/deps.ts +86 -0
  17. package/extensions/explore/ast/format/discover.ts +85 -0
  18. package/extensions/explore/ast/format/impact.ts +105 -0
  19. package/extensions/explore/ast/format/outline.ts +66 -0
  20. package/extensions/explore/ast/format/relationships.ts +81 -0
  21. package/extensions/explore/ast/format/show.ts +38 -0
  22. package/extensions/explore/ast/grammars/kotlin.wasm +0 -0
  23. package/extensions/explore/ast/grammars/manifest.json +41 -0
  24. package/extensions/explore/ast/grammars/manifest.ts +99 -0
  25. package/extensions/explore/ast/grammars/odin.wasm +0 -0
  26. package/extensions/explore/ast/grammars/swift.wasm +0 -0
  27. package/extensions/explore/ast/graph/file-graph.ts +360 -0
  28. package/extensions/explore/ast/graph/relationships.ts +597 -0
  29. package/extensions/explore/ast/identity.ts +119 -0
  30. package/extensions/explore/ast/ir.ts +130 -0
  31. package/extensions/explore/ast/languages/csharp-file-deps.ts +189 -0
  32. package/extensions/explore/ast/languages/csharp.ts +493 -0
  33. package/extensions/explore/ast/languages/file-dep-util.ts +120 -0
  34. package/extensions/explore/ast/languages/fixtures/sample.cs +17 -0
  35. package/extensions/explore/ast/languages/fixtures/sample.java +21 -0
  36. package/extensions/explore/ast/languages/fixtures/sample.kt +15 -0
  37. package/extensions/explore/ast/languages/fixtures/sample.odin +28 -0
  38. package/extensions/explore/ast/languages/fixtures/sample.rs +31 -0
  39. package/extensions/explore/ast/languages/fixtures/sample.swift +25 -0
  40. package/extensions/explore/ast/languages/go-file-deps.ts +139 -0
  41. package/extensions/explore/ast/languages/go.ts +545 -0
  42. package/extensions/explore/ast/languages/java.ts +412 -0
  43. package/extensions/explore/ast/languages/jvm-file-deps.ts +217 -0
  44. package/extensions/explore/ast/languages/kotlin.ts +611 -0
  45. package/extensions/explore/ast/languages/odin-file-deps.ts +175 -0
  46. package/extensions/explore/ast/languages/odin.ts +407 -0
  47. package/extensions/explore/ast/languages/rust-file-deps.ts +159 -0
  48. package/extensions/explore/ast/languages/rust.ts +506 -0
  49. package/extensions/explore/ast/languages/swift-file-deps.ts +59 -0
  50. package/extensions/explore/ast/languages/swift.ts +466 -0
  51. package/extensions/explore/ast/languages/tree.ts +220 -0
  52. package/extensions/explore/ast/languages/typescript-file-deps.ts +259 -0
  53. package/extensions/explore/ast/languages/typescript-package-surface.ts +440 -0
  54. package/extensions/explore/ast/languages/typescript.ts +716 -0
  55. package/extensions/explore/ast/markdown.ts +145 -0
  56. package/extensions/explore/ast/package-surface.ts +42 -0
  57. package/extensions/explore/ast/queries/ast-search.ts +306 -0
  58. package/extensions/explore/ast/queries/composite-target.ts +77 -0
  59. package/extensions/explore/ast/queries/context.ts +406 -0
  60. package/extensions/explore/ast/queries/discover.ts +427 -0
  61. package/extensions/explore/ast/queries/impact.ts +250 -0
  62. package/extensions/explore/ast/queries/outline.ts +203 -0
  63. package/extensions/explore/ast/queries/show.ts +262 -0
  64. package/extensions/explore/ast/query.ts +48 -0
  65. package/extensions/explore/ast/read/hook.ts +125 -0
  66. package/extensions/explore/ast/read/policy.ts +55 -0
  67. package/extensions/explore/ast/registry.ts +120 -0
  68. package/extensions/explore/ast/scan.ts +76 -0
  69. package/extensions/explore/ast/slice.ts +31 -0
  70. package/extensions/explore/ast/tools/ast-search.ts +138 -0
  71. package/extensions/explore/ast/tools/context.ts +126 -0
  72. package/extensions/explore/ast/tools/deps.ts +72 -0
  73. package/extensions/explore/ast/tools/discover.ts +208 -0
  74. package/extensions/explore/ast/tools/impact.ts +135 -0
  75. package/extensions/explore/ast/tools/outline.ts +200 -0
  76. package/extensions/explore/ast/tools/relationships.ts +160 -0
  77. package/extensions/explore/ast/tools/render.ts +121 -0
  78. package/extensions/explore/ast/tools/reverse-deps.ts +72 -0
  79. package/extensions/explore/ast/tools/show.ts +116 -0
  80. package/extensions/explore/guidance.ts +52 -0
  81. package/extensions/explore/index.ts +91 -45
  82. package/extensions/explore/read/autoread.ts +118 -0
  83. package/extensions/explore/settings.ts +64 -0
  84. package/extensions/explore/traverse.ts +260 -86
  85. package/extensions/handoff/index.ts +1 -1
  86. package/extensions/patch/executor.ts +95 -1
  87. package/extensions/patch/index.ts +1 -0
  88. package/extensions/publish/index.ts +18 -85
  89. package/extensions/publish/publish-ui.ts +0 -4
  90. package/extensions/soul/README.md +7 -4
  91. package/extensions/soul/index.ts +11 -5
  92. package/extensions/soul/prompt.ts +30 -14
  93. package/extensions/soul/settings.ts +7 -2
  94. package/extensions/subagent/agents/context-sync.md +6 -10
  95. package/extensions/subagent/agents/review.md +44 -24
  96. package/extensions/subagent/agents/scout.md +53 -34
  97. package/extensions/subagent/run.ts +1 -1
  98. package/extensions/tau-help/help.md +2 -2
  99. package/package.json +6 -5
  100. package/schemas/tau.schema.json +51 -6
  101. package/{extensions/explore → shared}/autoread.ts +21 -7
  102. package/shared/bounded-text-result.ts +304 -0
  103. package/shared/events.ts +1 -0
  104. package/shared/full-file-knowledge.ts +49 -0
  105. package/shared/temporary-output-store.ts +275 -0
  106. package/extensions/explore/ast-tools.ts +0 -828
  107. package/extensions/explore/ast-worker.ts +0 -356
  108. package/extensions/explore/find.ts +0 -147
  109. package/extensions/explore/full-file-knowledge.ts +0 -234
  110. package/extensions/explore/grep.ts +0 -749
  111. package/extensions/explore/limits.ts +0 -22
  112. package/extensions/explore/ls.ts +0 -113
  113. package/extensions/explore/path-display.ts +0 -41
  114. package/extensions/explore/path-tree.ts +0 -150
  115. package/extensions/explore/read-cache.ts +0 -273
  116. package/extensions/explore/read-snapshots.ts +0 -57
  117. package/extensions/explore/read-stats-panel.ts +0 -154
  118. package/extensions/explore/read-stats.ts +0 -120
  119. package/extensions/explore/read.ts +0 -335
  120. package/extensions/explore/result.ts +0 -29
  121. package/native-bin/darwin-arm64/tau-ast +0 -0
@@ -0,0 +1,716 @@
1
+ import type { Node, Tree } from "web-tree-sitter";
2
+ import type { ExtractResult, GrammarAdapter, LanguageCapabilities } from "../adapter.ts";
3
+ import type { CallSite, Decl, ImportBinding, ImportRef, Visibility } from "../ir.ts";
4
+ import {
5
+ applyDoc,
6
+ callSite,
7
+ declFromNode,
8
+ docSpanBefore,
9
+ endLine,
10
+ field,
11
+ finishDecl,
12
+ nameText,
13
+ qualify,
14
+ startLine,
15
+ unquote,
16
+ walkBodyNodes,
17
+ type DocSpan,
18
+ } from "./tree.ts";
19
+ import { resolveTypescriptFileDep } from "./typescript-file-deps.ts";
20
+ import { resolveTypescriptPackageSurface } from "./typescript-package-surface.ts";
21
+
22
+ const CAPABILITIES: LanguageCapabilities = {
23
+ shape: true,
24
+ search: true,
25
+ fileDeps: true,
26
+ callEdges: true,
27
+ packageSurface: true,
28
+ };
29
+
30
+ /** Keywords/types skipped when matching imports to a decl slice. */
31
+ const IMPORT_NOISE = new Set([
32
+ "abstract",
33
+ "as",
34
+ "async",
35
+ "await",
36
+ "boolean",
37
+ "break",
38
+ "case",
39
+ "catch",
40
+ "class",
41
+ "const",
42
+ "continue",
43
+ "debugger",
44
+ "declare",
45
+ "default",
46
+ "delete",
47
+ "do",
48
+ "else",
49
+ "enum",
50
+ "export",
51
+ "extends",
52
+ "false",
53
+ "finally",
54
+ "for",
55
+ "from",
56
+ "function",
57
+ "get",
58
+ "if",
59
+ "implements",
60
+ "import",
61
+ "in",
62
+ "infer",
63
+ "instanceof",
64
+ "interface",
65
+ "keyof",
66
+ "let",
67
+ "module",
68
+ "namespace",
69
+ "new",
70
+ "null",
71
+ "number",
72
+ "of",
73
+ "package",
74
+ "private",
75
+ "protected",
76
+ "public",
77
+ "readonly",
78
+ "return",
79
+ "satisfies",
80
+ "set",
81
+ "static",
82
+ "string",
83
+ "super",
84
+ "switch",
85
+ "symbol",
86
+ "this",
87
+ "throw",
88
+ "true",
89
+ "try",
90
+ "type",
91
+ "typeof",
92
+ "undefined",
93
+ "unique",
94
+ "var",
95
+ "void",
96
+ "while",
97
+ "with",
98
+ "yield",
99
+ "any",
100
+ ]);
101
+
102
+ const TS_EXTENSIONS = [".ts", ".mts", ".cts"] as const;
103
+ const TSX_EXTENSIONS = [".tsx", ".mtsx"] as const;
104
+
105
+ // Node-type constants — owned by this adapter.
106
+ const DECORATOR = "decorator";
107
+ const EXPORT_STATEMENT = "export_statement";
108
+ const IMPORT_STATEMENT = "import_statement";
109
+ const FUNCTION_DECLARATION = "function_declaration";
110
+ const FUNCTION_EXPRESSION = "function_expression";
111
+ const FUNCTION_SIGNATURE = "function_signature";
112
+ const GENERATOR_FUNCTION_DECLARATION = "generator_function_declaration";
113
+ const CLASS_DECLARATION = "class_declaration";
114
+ const ABSTRACT_CLASS_DECLARATION = "abstract_class_declaration";
115
+ const CLASS = "class";
116
+ const INTERFACE_DECLARATION = "interface_declaration";
117
+ const TYPE_ALIAS_DECLARATION = "type_alias_declaration";
118
+ const ENUM_DECLARATION = "enum_declaration";
119
+ const LEXICAL_DECLARATION = "lexical_declaration";
120
+ const VARIABLE_DECLARATION = "variable_declaration";
121
+ const VARIABLE_DECLARATOR = "variable_declarator";
122
+ const INTERNAL_MODULE = "internal_module";
123
+ const MODULE = "module";
124
+ const AMBIENT_DECLARATION = "ambient_declaration";
125
+ const EXPRESSION_STATEMENT = "expression_statement";
126
+ const METHOD_DEFINITION = "method_definition";
127
+ const PUBLIC_FIELD_DEFINITION = "public_field_definition";
128
+ const ABSTRACT_METHOD_SIGNATURE = "abstract_method_signature";
129
+ const METHOD_SIGNATURE = "method_signature";
130
+ const PROPERTY_SIGNATURE = "property_signature";
131
+ const ARROW_FUNCTION = "arrow_function";
132
+ const ACCESSIBILITY_MODIFIER = "accessibility_modifier";
133
+ const PRIVATE_PROPERTY_IDENTIFIER = "private_property_identifier";
134
+ const PROPERTY_IDENTIFIER = "property_identifier";
135
+ const ENUM_ASSIGNMENT = "enum_assignment";
136
+ const COMMENT = "comment";
137
+ const CALL_EXPRESSION = "call_expression";
138
+ const NEW_EXPRESSION = "new_expression";
139
+ const MEMBER_EXPRESSION = "member_expression";
140
+ const OPTIONAL_CHAIN = "optional_chain";
141
+ const IDENTIFIER = "identifier";
142
+ const TYPE_IDENTIFIER = "type_identifier";
143
+ const EXTENDS_CLAUSE = "extends_clause";
144
+ const IMPLEMENTS_CLAUSE = "implements_clause";
145
+ const EXTENDS_TYPE_CLAUSE = "extends_type_clause";
146
+ const CLASS_HERITAGE = "class_heritage";
147
+ const IMPORT_CLAUSE = "import_clause";
148
+ const IMPORT_SPECIFIER = "import_specifier";
149
+ const NAMESPACE_IMPORT = "namespace_import";
150
+ const NAMED_IMPORTS = "named_imports";
151
+ const EXPORT_CLAUSE = "export_clause";
152
+ const EXPORT_SPECIFIER = "export_specifier";
153
+
154
+ const NESTED_CALLABLE = new Set([
155
+ FUNCTION_DECLARATION,
156
+ FUNCTION_EXPRESSION,
157
+ GENERATOR_FUNCTION_DECLARATION,
158
+ ARROW_FUNCTION,
159
+ METHOD_DEFINITION,
160
+ CLASS_DECLARATION,
161
+ ABSTRACT_CLASS_DECLARATION,
162
+ CLASS,
163
+ ]);
164
+
165
+ function bareNameNode(node: Node): Node | null {
166
+ if (node.type === IDENTIFIER || node.type === PROPERTY_IDENTIFIER || node.type === TYPE_IDENTIFIER) return node;
167
+ if (node.type === MEMBER_EXPRESSION || node.type === OPTIONAL_CHAIN) {
168
+ const prop = field(node, "property");
169
+ return prop;
170
+ }
171
+ return null;
172
+ }
173
+
174
+ function extractCalls(body: Node | null): CallSite[] {
175
+ if (body === null) return [];
176
+ const out: CallSite[] = [];
177
+ walkBodyNodes(
178
+ body,
179
+ (node) => NESTED_CALLABLE.has(node.type),
180
+ (node) => {
181
+ if (node.type === CALL_EXPRESSION) {
182
+ const fn = field(node, "function");
183
+ if (fn === null) return;
184
+ const leaf = bareNameNode(fn);
185
+ if (leaf === null) return;
186
+ let receiver = "";
187
+ if (fn.type === MEMBER_EXPRESSION || fn.type === OPTIONAL_CHAIN) {
188
+ const obj = field(fn, "object");
189
+ receiver = obj === null ? "" : obj.text;
190
+ }
191
+ const site = callSite(leaf.text, startLine(leaf), leaf.startIndex, leaf.endIndex, "call", receiver);
192
+ if (site !== undefined) out.push(site);
193
+ return;
194
+ }
195
+ if (node.type === NEW_EXPRESSION) {
196
+ const ctor = field(node, "constructor");
197
+ if (ctor === null) return;
198
+ const leaf =
199
+ bareNameNode(ctor) ?? (ctor.type === IDENTIFIER || ctor.type === TYPE_IDENTIFIER ? ctor : null);
200
+ if (leaf === null) return;
201
+ const site = callSite(leaf.text, startLine(leaf), leaf.startIndex, leaf.endIndex, "construct");
202
+ if (site !== undefined) out.push(site);
203
+ }
204
+ },
205
+ );
206
+ return out;
207
+ }
208
+
209
+ function collectTypeNames(node: Node, into: string[]): void {
210
+ if (node.type === TYPE_IDENTIFIER || node.type === IDENTIFIER) {
211
+ if (node.text.length > 0) into.push(node.text);
212
+ return;
213
+ }
214
+ for (const child of node.namedChildren) collectTypeNames(child, into);
215
+ }
216
+
217
+ function heritageBases(node: Node): string[] {
218
+ const bases: string[] = [];
219
+ const visit = (n: Node): void => {
220
+ if (
221
+ n.type === EXTENDS_CLAUSE ||
222
+ n.type === IMPLEMENTS_CLAUSE ||
223
+ n.type === EXTENDS_TYPE_CLAUSE ||
224
+ n.type === CLASS_HERITAGE
225
+ ) {
226
+ collectTypeNames(n, bases);
227
+ return;
228
+ }
229
+ for (const child of n.namedChildren) {
230
+ if (
231
+ child.type === EXTENDS_CLAUSE ||
232
+ child.type === IMPLEMENTS_CLAUSE ||
233
+ child.type === EXTENDS_TYPE_CLAUSE ||
234
+ child.type === CLASS_HERITAGE
235
+ ) {
236
+ collectTypeNames(child, bases);
237
+ }
238
+ }
239
+ };
240
+ visit(node);
241
+ return [...new Set(bases)];
242
+ }
243
+
244
+ function withCallsAndBases(decl: Decl | undefined, body: Node | null, heritageNode: Node | null): Decl | undefined {
245
+ if (decl === undefined) return undefined;
246
+ decl.calls = extractCalls(body);
247
+ decl.bases = heritageNode === null ? [] : heritageBases(heritageNode);
248
+ return decl;
249
+ }
250
+
251
+ function importBindingsFromClause(clause: Node | null): ImportBinding[] {
252
+ if (clause === null) return [];
253
+ const out: ImportBinding[] = [];
254
+ const defaultBind = field(clause, "name");
255
+ if (defaultBind !== null && (defaultBind.type === IDENTIFIER || defaultBind.type === PROPERTY_IDENTIFIER)) {
256
+ out.push({ local: defaultBind.text, imported: "default" });
257
+ }
258
+ for (const child of clause.namedChildren) {
259
+ if (child.type === NAMESPACE_IMPORT) {
260
+ const name = field(child, "name");
261
+ if (name !== null) out.push({ local: name.text, imported: "*" });
262
+ continue;
263
+ }
264
+ if (child.type === NAMED_IMPORTS) {
265
+ for (const spec of child.namedChildren) {
266
+ if (spec.type !== IMPORT_SPECIFIER) continue;
267
+ const imported = field(spec, "name");
268
+ const local = field(spec, "alias") ?? imported;
269
+ if (local === null || imported === null) continue;
270
+ out.push({ local: local.text, imported: imported.text });
271
+ }
272
+ }
273
+ }
274
+ return out;
275
+ }
276
+
277
+ function tsDoc(node: Node, source: string): DocSpan | undefined {
278
+ return docSpanBefore(node, source, [DECORATOR]);
279
+ }
280
+
281
+ function visibilityOf(node: Node): Visibility {
282
+ for (const child of node.namedChildren) {
283
+ if (child.type === ACCESSIBILITY_MODIFIER) {
284
+ const text = child.text;
285
+ if (text === "private" || text === "protected" || text === "public") return text;
286
+ }
287
+ }
288
+ const name = field(node, "name");
289
+ if (name !== null && name.type === PRIVATE_PROPERTY_IDENTIFIER) return "private";
290
+ return "public";
291
+ }
292
+
293
+ function valueIsFunction(value: Node | null): boolean {
294
+ if (value === null) return false;
295
+ return (
296
+ value.type === ARROW_FUNCTION ||
297
+ value.type === FUNCTION_EXPRESSION ||
298
+ value.type === FUNCTION_DECLARATION ||
299
+ value.type === GENERATOR_FUNCTION_DECLARATION
300
+ );
301
+ }
302
+
303
+ function walkStatementList(nodes: readonly Node[], owner: string, source: string, exportedDefault: boolean): Decl[] {
304
+ const decls: Decl[] = [];
305
+ for (const node of nodes) {
306
+ decls.push(...declsFromStatement(node, owner, source, exportedDefault));
307
+ }
308
+ return decls;
309
+ }
310
+
311
+ function asList(decl: Decl | undefined): Decl[] {
312
+ return decl === undefined ? [] : [decl];
313
+ }
314
+
315
+ function declsFromStatement(node: Node, owner: string, source: string, parentExported: boolean): Decl[] {
316
+ // ERROR recovery: keep walking recognizable decls nested under broken nodes.
317
+ if (node.isError || node.type === "ERROR") {
318
+ const out: Decl[] = [];
319
+ for (const child of node.children) {
320
+ if (child.isNamed || child.isError) {
321
+ out.push(...declsFromStatement(child, owner, source, parentExported));
322
+ }
323
+ }
324
+ return out;
325
+ }
326
+ if (node.type === EXPRESSION_STATEMENT) {
327
+ const out: Decl[] = [];
328
+ for (const child of node.children) {
329
+ if (child.isNamed || child.isError) {
330
+ out.push(...declsFromStatement(child, owner, source, parentExported));
331
+ }
332
+ }
333
+ return out;
334
+ }
335
+ if (node.type === EXPORT_STATEMENT) {
336
+ return declsFromExport(node, owner, source);
337
+ }
338
+ if (node.type === AMBIENT_DECLARATION) {
339
+ const inner = node.namedChildren.find((child) => child.type !== COMMENT);
340
+ if (inner === undefined) return [];
341
+ const doc = tsDoc(node, source);
342
+ return declsFromStatement(inner, owner, source, parentExported).map((decl, index) =>
343
+ index === 0 ? applyDoc(decl, doc) : decl,
344
+ );
345
+ }
346
+ if (node.type === IMPORT_STATEMENT) return [];
347
+
348
+ const doc = tsDoc(node, source);
349
+
350
+ switch (node.type) {
351
+ case FUNCTION_DECLARATION:
352
+ case GENERATOR_FUNCTION_DECLARATION:
353
+ case FUNCTION_SIGNATURE: {
354
+ const name = nameText(field(node, "name")) || "default";
355
+ const body = field(node, "body");
356
+ return asList(
357
+ withCallsAndBases(declFromNode(node, owner, "function", name, parentExported, body, [], doc), body, null),
358
+ );
359
+ }
360
+ case CLASS_DECLARATION:
361
+ case ABSTRACT_CLASS_DECLARATION:
362
+ case CLASS: {
363
+ const name = nameText(field(node, "name")) || (parentExported ? "default" : "");
364
+ const body = field(node, "body");
365
+ const children = body === null ? [] : classMembers(body, qualify(owner, name), source);
366
+ return asList(
367
+ withCallsAndBases(
368
+ declFromNode(node, owner, "class", name, parentExported, body, children, doc),
369
+ null,
370
+ node,
371
+ ),
372
+ );
373
+ }
374
+ case INTERFACE_DECLARATION: {
375
+ // Judgment: TS type aliases also map to interface; this is the real interface kind.
376
+ const name = nameText(field(node, "name"));
377
+ const body = field(node, "body");
378
+ const children = body === null ? [] : interfaceMembers(body, qualify(owner, name), source);
379
+ return asList(
380
+ withCallsAndBases(
381
+ declFromNode(node, owner, "interface", name, parentExported, body, children, doc),
382
+ null,
383
+ node,
384
+ ),
385
+ );
386
+ }
387
+ case TYPE_ALIAS_DECLARATION: {
388
+ const name = nameText(field(node, "name"));
389
+ return asList(declFromNode(node, owner, "typeAlias", name, parentExported, null, [], doc));
390
+ }
391
+ case ENUM_DECLARATION: {
392
+ const name = nameText(field(node, "name"));
393
+ const body = field(node, "body");
394
+ const children = body === null ? [] : enumMembers(body, qualify(owner, name));
395
+ return asList(declFromNode(node, owner, "enum", name, parentExported, body, children, doc));
396
+ }
397
+ case LEXICAL_DECLARATION:
398
+ case VARIABLE_DECLARATION:
399
+ return variableDecls(node, owner, parentExported, doc);
400
+ case INTERNAL_MODULE:
401
+ case MODULE: {
402
+ const nameNode = field(node, "name");
403
+ const name = nameNode === null ? "" : unquote(nameNode.text);
404
+ const body = field(node, "body");
405
+ const children =
406
+ body === null ? [] : walkStatementList(body.namedChildren, qualify(owner, name), source, false);
407
+ const kind = node.type === INTERNAL_MODULE ? "namespace" : "module";
408
+ return asList(declFromNode(node, owner, kind, name, parentExported, body, children, doc));
409
+ }
410
+ default:
411
+ return [];
412
+ }
413
+ }
414
+
415
+ function declsFromExport(node: Node, owner: string, source: string): Decl[] {
416
+ const doc = tsDoc(node, source);
417
+ const declaration = field(node, "declaration");
418
+ const value = field(node, "value");
419
+ const isDefault = node.children.some((child) => child.type === "default");
420
+
421
+ if (declaration !== null) {
422
+ // export declare … arrives as ambient_declaration under declaration field.
423
+ const decls = declsFromStatement(declaration, owner, source, true);
424
+ if (isDefault) {
425
+ for (const decl of decls) {
426
+ if (decl.name.length === 0) decl.name = "default";
427
+ decl.exported = true;
428
+ decl.qualifiedName = qualify(owner, decl.name);
429
+ }
430
+ }
431
+ if (decls[0] !== undefined) decls[0] = applyDoc(decls[0], doc);
432
+ // Re-span so line/byte range covers the `export` keyword.
433
+ for (const decl of decls) {
434
+ decl.startOffset = node.startIndex;
435
+ decl.endOffset = node.endIndex;
436
+ decl.startLine = startLine(node);
437
+ decl.endLine = endLine(node);
438
+ if (decl.bodyStartOffset === undefined) decl.signatureEndOffset = node.endIndex;
439
+ }
440
+ return decls;
441
+ }
442
+
443
+ if (value !== null) {
444
+ // export default function() {} / class {} / expression
445
+ let name = "default";
446
+ let kind: Decl["kind"] = "variable";
447
+ let body: Node | null = null;
448
+ let children: Decl[] = [];
449
+
450
+ if (
451
+ value.type === FUNCTION_EXPRESSION ||
452
+ value.type === FUNCTION_DECLARATION ||
453
+ value.type === GENERATOR_FUNCTION_DECLARATION ||
454
+ value.type === ARROW_FUNCTION
455
+ ) {
456
+ const named = nameText(field(value, "name"));
457
+ name = named.length > 0 ? named : "default";
458
+ kind = "function";
459
+ body = field(value, "body");
460
+ } else if (value.type === CLASS || value.type === CLASS_DECLARATION) {
461
+ const named = nameText(field(value, "name"));
462
+ name = named.length > 0 ? named : "default";
463
+ kind = "class";
464
+ body = field(value, "body");
465
+ children = body === null ? [] : classMembers(body, qualify(owner, name), source);
466
+ }
467
+
468
+ const decl = finishDecl(
469
+ {
470
+ kind,
471
+ name,
472
+ qualifiedName: qualify(owner, name),
473
+ startLine: startLine(node),
474
+ endLine: endLine(node),
475
+ startOffset: node.startIndex,
476
+ endOffset: node.endIndex,
477
+ visibility: "public",
478
+ exported: true,
479
+ children,
480
+ calls: kind === "function" ? extractCalls(body) : [],
481
+ bases: kind === "class" && value !== null ? heritageBases(value) : [],
482
+ },
483
+ body,
484
+ );
485
+ if (body === null) decl.signatureEndOffset = node.endIndex;
486
+ return [applyDoc(decl, doc)];
487
+ }
488
+
489
+ return [];
490
+ }
491
+
492
+ function variableDecls(node: Node, owner: string, exported: boolean, doc: DocSpan | undefined): Decl[] {
493
+ const kindKeyword = node.type === LEXICAL_DECLARATION ? (field(node, "kind")?.text ?? "let") : "var";
494
+ const declarators = node.namedChildren.filter((child) => child.type === VARIABLE_DECLARATOR);
495
+ const multi = declarators.length > 1;
496
+ const out: Decl[] = [];
497
+
498
+ for (let i = 0; i < declarators.length; i += 1) {
499
+ const declarator = declarators[i];
500
+ if (declarator === undefined) continue;
501
+ const name = nameText(field(declarator, "name"));
502
+ if (name.length === 0) continue;
503
+ const value = field(declarator, "value");
504
+ const isFn = valueIsFunction(value);
505
+ const isConst = kindKeyword === "const";
506
+ let kind: Decl["kind"] = isFn ? "function" : isConst ? "constant" : "variable";
507
+ if (!isFn && value !== null && value.type === "object") kind = "object";
508
+
509
+ const spanNode = multi ? declarator : node;
510
+ const body = isFn && value !== null ? field(value, "body") : null;
511
+ const decl = finishDecl(
512
+ {
513
+ kind,
514
+ name,
515
+ qualifiedName: qualify(owner, name),
516
+ startLine: startLine(spanNode),
517
+ endLine: endLine(spanNode),
518
+ startOffset: spanNode.startIndex,
519
+ endOffset: spanNode.endIndex,
520
+ visibility: "public",
521
+ exported,
522
+ calls: isFn ? extractCalls(body) : [],
523
+ },
524
+ body,
525
+ );
526
+ if (body === null) decl.signatureEndOffset = spanNode.endIndex;
527
+ out.push(i === 0 ? applyDoc(decl, doc) : decl);
528
+ }
529
+ return out;
530
+ }
531
+
532
+ function memberDecl(
533
+ node: Node,
534
+ owner: string,
535
+ kind: Decl["kind"],
536
+ name: string,
537
+ body: Node | null,
538
+ doc: DocSpan | undefined,
539
+ visibility: Visibility = "public",
540
+ ): Decl | undefined {
541
+ if (name.length === 0) return undefined;
542
+ const decl = finishDecl(
543
+ {
544
+ kind,
545
+ name,
546
+ qualifiedName: qualify(owner, name),
547
+ startLine: startLine(node),
548
+ endLine: endLine(node),
549
+ startOffset: node.startIndex,
550
+ endOffset: node.endIndex,
551
+ visibility,
552
+ exported: false,
553
+ calls: kind === "method" || kind === "constructor" ? extractCalls(body) : [],
554
+ },
555
+ body,
556
+ );
557
+ if (body === null) decl.signatureEndOffset = node.endIndex;
558
+ return applyDoc(decl, doc);
559
+ }
560
+
561
+ function classMembers(body: Node, owner: string, source: string): Decl[] {
562
+ const out: Decl[] = [];
563
+ for (const node of body.namedChildren) {
564
+ const doc = tsDoc(node, source);
565
+ if (node.type === METHOD_DEFINITION) {
566
+ const rawName = nameText(field(node, "name"));
567
+ const name = rawName.length === 0 ? "" : unquote(rawName);
568
+ const kind = name === "constructor" ? "constructor" : "method";
569
+ const decl = memberDecl(node, owner, kind, name, field(node, "body"), doc, visibilityOf(node));
570
+ if (decl !== undefined) out.push(decl);
571
+ continue;
572
+ }
573
+ if (node.type === PUBLIC_FIELD_DEFINITION) {
574
+ const name = nameText(field(node, "name"));
575
+ const value = field(node, "value");
576
+ const isFn = valueIsFunction(value);
577
+ const decl = memberDecl(
578
+ node,
579
+ owner,
580
+ isFn ? "method" : "field",
581
+ name,
582
+ isFn && value !== null ? field(value, "body") : null,
583
+ doc,
584
+ visibilityOf(node),
585
+ );
586
+ if (decl !== undefined) out.push(decl);
587
+ continue;
588
+ }
589
+ if (node.type === ABSTRACT_METHOD_SIGNATURE || node.type === METHOD_SIGNATURE) {
590
+ const name = nameText(field(node, "name"));
591
+ const decl = memberDecl(node, owner, "method", name, null, doc, visibilityOf(node));
592
+ if (decl !== undefined) out.push(decl);
593
+ }
594
+ }
595
+ return out;
596
+ }
597
+
598
+ function interfaceMembers(body: Node, owner: string, source: string): Decl[] {
599
+ const out: Decl[] = [];
600
+ for (const node of body.namedChildren) {
601
+ const doc = tsDoc(node, source);
602
+ if (node.type === METHOD_SIGNATURE) {
603
+ const decl = memberDecl(node, owner, "method", nameText(field(node, "name")), null, doc);
604
+ if (decl !== undefined) out.push(decl);
605
+ continue;
606
+ }
607
+ if (node.type === PROPERTY_SIGNATURE) {
608
+ const decl = memberDecl(node, owner, "property", nameText(field(node, "name")), null, doc);
609
+ if (decl !== undefined) out.push(decl);
610
+ }
611
+ }
612
+ return out;
613
+ }
614
+
615
+ function enumMembers(body: Node, owner: string): Decl[] {
616
+ const out: Decl[] = [];
617
+ for (const node of body.namedChildren) {
618
+ if (node.type === PROPERTY_IDENTIFIER) {
619
+ const decl = memberDecl(node, owner, "enumMember", node.text, null, undefined);
620
+ if (decl !== undefined) out.push(decl);
621
+ continue;
622
+ }
623
+ if (node.type === ENUM_ASSIGNMENT) {
624
+ const nameNode = node.namedChildren[0];
625
+ if (nameNode === undefined) continue;
626
+ const decl = memberDecl(node, owner, "enumMember", nameNode.text, null, undefined);
627
+ if (decl !== undefined) out.push(decl);
628
+ }
629
+ }
630
+ return out;
631
+ }
632
+
633
+ function collectImportsFrom(node: Node, imports: ImportRef[]): void {
634
+ for (const child of node.namedChildren) {
635
+ if (child.type === IMPORT_STATEMENT) {
636
+ const source = field(child, "source");
637
+ if (source !== null) {
638
+ imports.push({
639
+ specifier: unquote(source.text),
640
+ startLine: startLine(child),
641
+ startOffset: child.startIndex,
642
+ endOffset: child.endIndex,
643
+ bindings: importBindingsFromClause(
644
+ child.namedChildren.find((c) => c.type === IMPORT_CLAUSE) ?? field(child, "import"),
645
+ ),
646
+ });
647
+ }
648
+ continue;
649
+ }
650
+ if (child.type === EXPORT_STATEMENT) {
651
+ // re-export: export { X } from "mod"
652
+ const source = field(child, "source");
653
+ if (source !== null) {
654
+ const bindings: ImportBinding[] = [];
655
+ const clause = child.namedChildren.find((c) => c.type === EXPORT_CLAUSE);
656
+ if (clause !== undefined) {
657
+ for (const spec of clause.namedChildren) {
658
+ if (spec.type !== EXPORT_SPECIFIER) continue;
659
+ const exported = field(spec, "name");
660
+ const local = field(spec, "alias") ?? exported;
661
+ if (local === null || exported === null) continue;
662
+ bindings.push({ local: local.text, imported: exported.text });
663
+ }
664
+ }
665
+ imports.push({
666
+ specifier: unquote(source.text),
667
+ startLine: startLine(child),
668
+ startOffset: child.startIndex,
669
+ endOffset: child.endIndex,
670
+ bindings,
671
+ });
672
+ }
673
+ continue;
674
+ }
675
+ if (child.type === EXPRESSION_STATEMENT || child.type === AMBIENT_DECLARATION) {
676
+ collectImportsFrom(child, imports);
677
+ continue;
678
+ }
679
+ if (child.type === MODULE || child.type === INTERNAL_MODULE) {
680
+ const body = field(child, "body");
681
+ if (body !== null) collectImportsFrom(body, imports);
682
+ }
683
+ }
684
+ }
685
+
686
+ function extractTypeScript(tree: Tree, source: string): ExtractResult {
687
+ const root = tree.rootNode;
688
+ // Include ERROR siblings so degraded parses still yield surrounding decls.
689
+ const top = root.children.filter((child) => child.isNamed || child.isError);
690
+ const decls = walkStatementList(top, "", source, false);
691
+ const imports: ImportRef[] = [];
692
+ collectImportsFrom(root, imports);
693
+ return { decls, imports };
694
+ }
695
+
696
+ function makeAdapter(id: "typescript" | "tsx", extensions: readonly string[]): GrammarAdapter {
697
+ return {
698
+ mode: "grammar",
699
+ id,
700
+ extensions,
701
+ capabilities: CAPABILITIES,
702
+ importNoiseIdentifiers: IMPORT_NOISE,
703
+ extract: extractTypeScript,
704
+ // Same function identity for both adapters — registry dedupes resolvers.
705
+ resolveFileDep: resolveTypescriptFileDep,
706
+ resolvePackageSurface: resolveTypescriptPackageSurface,
707
+ };
708
+ }
709
+
710
+ export function typescriptAdapter(): GrammarAdapter {
711
+ return makeAdapter("typescript", TS_EXTENSIONS);
712
+ }
713
+
714
+ export function tsxAdapter(): GrammarAdapter {
715
+ return makeAdapter("tsx", TSX_EXTENSIONS);
716
+ }