pi-hashline-edit-pro 6.1.2 → 6.2.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 (66) hide show
  1. package/README.md +14 -12
  2. package/index.ts +20 -12
  3. package/package.json +3 -2
  4. package/src/auto-read-all.ts +39 -21
  5. package/src/config-ui.ts +135 -55
  6. package/src/config.ts +27 -9
  7. package/src/copy-move.ts +4 -4
  8. package/src/grep.ts +3 -3
  9. package/src/insert.ts +3 -3
  10. package/src/outline/index.ts +45 -0
  11. package/src/outline/parsers.ts +42 -0
  12. package/src/outline/render.ts +166 -0
  13. package/src/outline/vendor/LICENSE +201 -0
  14. package/src/outline/vendor/README.md +17 -0
  15. package/src/outline/vendor/parsers/blade.ts +138 -0
  16. package/src/outline/vendor/parsers/index.ts +75 -0
  17. package/src/outline/vendor/parsers/java.ts +501 -0
  18. package/src/outline/vendor/parsers/manager.ts +1721 -0
  19. package/src/outline/vendor/parsers/php.ts +332 -0
  20. package/src/outline/vendor/parsers/sass.ts +416 -0
  21. package/src/outline/vendor/parsers/scss.ts +566 -0
  22. package/src/outline/vendor/types.ts +82 -0
  23. package/src/outline/vendor/wasm/LICENSES.md +37 -0
  24. package/src/outline/vendor/wasm/tree-sitter-blade.wasm +0 -0
  25. package/src/outline/vendor/wasm/tree-sitter-go.wasm +0 -0
  26. package/src/outline/vendor/wasm/tree-sitter-java.wasm +0 -0
  27. package/src/outline/vendor/wasm/tree-sitter-javascript.wasm +0 -0
  28. package/src/outline/vendor/wasm/tree-sitter-php.wasm +0 -0
  29. package/src/outline/vendor/wasm/tree-sitter-python.wasm +0 -0
  30. package/src/outline/vendor/wasm/tree-sitter-rust.wasm +0 -0
  31. package/src/outline/vendor/wasm/tree-sitter-sass.wasm +0 -0
  32. package/src/outline/vendor/wasm/tree-sitter-scss.wasm +0 -0
  33. package/src/outline/vendor/wasm/tree-sitter-solidity.wasm +0 -0
  34. package/src/outline/vendor/wasm/tree-sitter-tsx.wasm +0 -0
  35. package/src/outline/vendor/wasm/tree-sitter-typescript.wasm +0 -0
  36. package/src/read.ts +108 -36
  37. package/src/replace-match.ts +3 -3
  38. package/src/replace-undo.ts +3 -3
  39. package/src/replace.ts +3 -3
  40. package/tool-prompts/read-guidelines.md +3 -0
  41. package/{prompts → tool-prompts}/read.md +2 -0
  42. package/prompts/read-guidelines.md +0 -1
  43. package/src/auto-read-all-state.ts +0 -27
  44. /package/{prompts → tool-prompts}/copy-guidelines.md +0 -0
  45. /package/{prompts → tool-prompts}/copy-snippet.md +0 -0
  46. /package/{prompts → tool-prompts}/copy.md +0 -0
  47. /package/{prompts → tool-prompts}/grep-guidelines.md +0 -0
  48. /package/{prompts → tool-prompts}/grep-snippet.md +0 -0
  49. /package/{prompts → tool-prompts}/grep.md +0 -0
  50. /package/{prompts → tool-prompts}/insert-guidelines.md +0 -0
  51. /package/{prompts → tool-prompts}/insert-snippet.md +0 -0
  52. /package/{prompts → tool-prompts}/insert.md +0 -0
  53. /package/{prompts → tool-prompts}/move-guidelines.md +0 -0
  54. /package/{prompts → tool-prompts}/move-snippet.md +0 -0
  55. /package/{prompts → tool-prompts}/move.md +0 -0
  56. /package/{prompts → tool-prompts}/read-snippet.md +0 -0
  57. /package/{prompts → tool-prompts}/replace-guidelines.md +0 -0
  58. /package/{prompts → tool-prompts}/replace-match-guidelines.md +0 -0
  59. /package/{prompts → tool-prompts}/replace-match-snippet.md +0 -0
  60. /package/{prompts → tool-prompts}/replace-match.md +0 -0
  61. /package/{prompts → tool-prompts}/replace-snippet.md +0 -0
  62. /package/{prompts → tool-prompts}/replace.md +0 -0
  63. /package/{prompts → tool-prompts}/transfer-guidelines.md +0 -0
  64. /package/{prompts → tool-prompts}/undo-last-change-guidelines.md +0 -0
  65. /package/{prompts → tool-prompts}/undo-last-change-snippet.md +0 -0
  66. /package/{prompts → tool-prompts}/undo-last-change.md +0 -0
@@ -0,0 +1,566 @@
1
+ /**
2
+ * SCSS tree-sitter symbol extractor.
3
+ *
4
+ * Tree-sitter grammar: tree-sitter-scss (https://github.com/tree-sitter-grammars/tree-sitter-scss)
5
+ * The grammar extends tree-sitter-css with SCSS-specific constructs: variables,
6
+ * mixins, functions, @use/@forward/@import, @include, @extend, interpolation,
7
+ * and nesting.
8
+ *
9
+ * The npm package (tree-sitter-scss@1.0.0) does not ship a prebuilt WASM module,
10
+ * so the repo vendors a compiled tree-sitter-scss.wasm under src/parsers/vendor/.
11
+ *
12
+ * Scope note: this grammar covers the SCSS bracket syntax (`.scss` files). The
13
+ * indented `.sass` dialect uses a separate vendored grammar — see sass.ts.
14
+ *
15
+ * Notes on grammar behavior the extractor accounts for:
16
+ * - `$var: value;` parses as a `declaration` whose `property_name` starts with `$`.
17
+ * - `@use "x" as y;` and `@forward "x" as cfg-*;` produce ERROR subtrees, but the
18
+ * `string_value` with the module path is still present and recoverable.
19
+ * - `@extend %placeholder;` parses as an ERROR node containing a `placeholder`
20
+ * child; `@extend .class;` parses cleanly as `extend_statement`.
21
+ */
22
+
23
+ import type { Node } from "web-tree-sitter";
24
+ import type { SymbolInfo, ImportInfo } from "../types.js";
25
+
26
+ /**
27
+ * Extract structural symbols from SCSS source code.
28
+ */
29
+ export function extractScss(
30
+ node: Node,
31
+ source: string,
32
+ depth: number,
33
+ ): SymbolInfo[] {
34
+ const results: SymbolInfo[] = [];
35
+ const MAX_DEPTH = depth + 10;
36
+
37
+ for (let i = 0; i < node.namedChildCount; i++) {
38
+ const child = node.namedChild(i);
39
+ if (!child) continue;
40
+
41
+ const symbol = extractScssChild(child, source, depth, MAX_DEPTH);
42
+ if (symbol) results.push(symbol);
43
+ }
44
+
45
+ return results;
46
+ }
47
+
48
+ function extractScssChild(
49
+ child: Node,
50
+ source: string,
51
+ depth: number,
52
+ MAX_DEPTH: number,
53
+ ): SymbolInfo | null {
54
+ switch (child.type) {
55
+ case "rule_set":
56
+ return extractRuleSet(child, source, depth, MAX_DEPTH);
57
+ case "mixin_statement":
58
+ return extractNamedBlock(
59
+ child,
60
+ source,
61
+ depth,
62
+ MAX_DEPTH,
63
+ "mixin",
64
+ "identifier",
65
+ );
66
+ case "function_statement":
67
+ return extractNamedBlock(
68
+ child,
69
+ source,
70
+ depth,
71
+ MAX_DEPTH,
72
+ "function",
73
+ "identifier",
74
+ );
75
+ case "media_statement":
76
+ return extractAtBlock(
77
+ child,
78
+ source,
79
+ depth,
80
+ MAX_DEPTH,
81
+ extractMediaName,
82
+ );
83
+ case "keyframes_statement":
84
+ return extractKeyframes(child, source, depth, MAX_DEPTH);
85
+ case "declaration": {
86
+ // Top-level `$var: value;` parses as a declaration whose property_name
87
+ // starts with `$`. Regular CSS declarations are structural noise and are
88
+ // skipped here (they only matter inside rule bodies, where they are
89
+ // filtered out of children anyway).
90
+ const prop = childTextOfType(child, source, 0, "property_name");
91
+ if (prop && prop.startsWith("$")) {
92
+ return {
93
+ name: prop,
94
+ type: "variable",
95
+ startLine: child.startPosition.row + 1,
96
+ endLine: child.endPosition.row + 1,
97
+ };
98
+ }
99
+ return null;
100
+ }
101
+ default:
102
+ return null;
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Extract a named block construct (mixin / function):
108
+ * `@mixin name(params) { ... }` or `@function name(params) { ... }`.
109
+ */
110
+ function extractNamedBlock(
111
+ child: Node,
112
+ source: string,
113
+ depth: number,
114
+ MAX_DEPTH: number,
115
+ label: string,
116
+ nameField: string,
117
+ ): SymbolInfo | null {
118
+ let name = "<unknown>";
119
+ let detail: string | undefined;
120
+
121
+ for (let i = 0; i < child.namedChildCount; i++) {
122
+ const c = child.namedChild(i);
123
+ if (!c) continue;
124
+ if (c.type === nameField) {
125
+ name = source.slice(c.startIndex, c.endIndex);
126
+ } else if (c.type === "parameters") {
127
+ detail = "(" + source.slice(c.startIndex, c.endIndex).replace(/^\(|\)$/g, "") + ")";
128
+ }
129
+ }
130
+
131
+ const [sl, el] = [child.startPosition.row + 1, child.endPosition.row + 1];
132
+ const symbol: SymbolInfo = {
133
+ name,
134
+ type: label,
135
+ startLine: sl,
136
+ endLine: el,
137
+ detail,
138
+ };
139
+
140
+ if (depth < MAX_DEPTH) {
141
+ const block = findChildByType(child, ["block"]);
142
+ if (block) {
143
+ const children = extractBlockChildren(block, source, depth + 1, MAX_DEPTH);
144
+ if (children.length > 0) symbol.children = children;
145
+ }
146
+ }
147
+
148
+ return symbol;
149
+ }
150
+
151
+ /**
152
+ * Extract a rule set: a selector group with a body. Nested rule sets, mixin
153
+ * includes, extends, and variable declarations inside the body become child
154
+ * symbols. Placeholder selectors (`%name`) are typed as `placeholder`.
155
+ */
156
+ function extractRuleSet(
157
+ child: Node,
158
+ source: string,
159
+ depth: number,
160
+ MAX_DEPTH: number,
161
+ ): SymbolInfo | null {
162
+ const selectors = findChildByType(child, ["selectors"]);
163
+ const name = selectors
164
+ ? source.slice(selectors.startIndex, selectors.endIndex).trim()
165
+ : "<unknown>";
166
+
167
+ const [sl, el] = [child.startPosition.row + 1, child.endPosition.row + 1];
168
+ const symbol: SymbolInfo = {
169
+ name,
170
+ // `%placeholder` selectors get their own type; everything else is a plain
171
+ // ruleset.
172
+ type: name.startsWith("%") ? "placeholder" : "ruleset",
173
+ startLine: sl,
174
+ endLine: el,
175
+ };
176
+
177
+ if (depth < MAX_DEPTH) {
178
+ const block = findChildByType(child, ["block"]);
179
+ if (block) {
180
+ const children = extractBlockChildren(block, source, depth + 1, MAX_DEPTH);
181
+ if (children.length > 0) symbol.children = children;
182
+ }
183
+ }
184
+
185
+ return symbol;
186
+ }
187
+
188
+ /**
189
+ * Extract the `@media`/`@supports`-style at-rule name: the keyword plus the
190
+ * query feature, without the trailing body.
191
+ */
192
+ function extractMediaName(node: Node, source: string): string {
193
+ const start = source.slice(node.startIndex, node.endIndex).trim();
194
+ const brace = start.indexOf("{");
195
+ return brace >= 0 ? start.slice(0, brace).trim() : start;
196
+ }
197
+
198
+ /**
199
+ * Extract an `@media`/`@supports`-style at-block: emit a container symbol with
200
+ * the query as its name and recurse into the body.
201
+ */
202
+ function extractAtBlock(
203
+ child: Node,
204
+ source: string,
205
+ depth: number,
206
+ MAX_DEPTH: number,
207
+ nameOf: (node: Node, source: string) => string,
208
+ ): SymbolInfo | null {
209
+ const name = nameOf(child, source);
210
+ const [sl, el] = [child.startPosition.row + 1, child.endPosition.row + 1];
211
+ const symbol: SymbolInfo = {
212
+ name,
213
+ type: "at-rule",
214
+ startLine: sl,
215
+ endLine: el,
216
+ };
217
+
218
+ if (depth < MAX_DEPTH) {
219
+ const block = findChildByType(child, ["block"]);
220
+ if (block) {
221
+ const children = extractBlockChildren(block, source, depth + 1, MAX_DEPTH);
222
+ if (children.length > 0) symbol.children = children;
223
+ }
224
+ }
225
+
226
+ return symbol;
227
+ }
228
+
229
+ /**
230
+ * Extract `@keyframes name { from {...} to {...} }`.
231
+ */
232
+ function extractKeyframes(
233
+ child: Node,
234
+ source: string,
235
+ depth: number,
236
+ MAX_DEPTH: number,
237
+ ): SymbolInfo | null {
238
+ let name = "<unknown>";
239
+ const nameNode = findChildByType(child, ["keyframes_name"]);
240
+ if (nameNode) name = source.slice(nameNode.startIndex, nameNode.endIndex);
241
+
242
+ const [sl, el] = [child.startPosition.row + 1, child.endPosition.row + 1];
243
+ const symbol: SymbolInfo = {
244
+ name: `@keyframes ${name}`,
245
+ type: "keyframes",
246
+ startLine: sl,
247
+ endLine: el,
248
+ };
249
+
250
+ if (depth < MAX_DEPTH) {
251
+ const blockList = findChildByType(child, ["keyframe_block_list"]);
252
+ if (blockList) {
253
+ const children: SymbolInfo[] = [];
254
+ for (let i = 0; i < blockList.namedChildCount; i++) {
255
+ const kb = blockList.namedChild(i);
256
+ if (!kb) continue;
257
+ if (kb.type === "keyframe_block") {
258
+ const step = source
259
+ .slice(kb.startIndex, kb.endIndex)
260
+ .split("{")[0]
261
+ .trim();
262
+ children.push({
263
+ name: step,
264
+ type: "keyframe",
265
+ startLine: kb.startPosition.row + 1,
266
+ endLine: kb.endPosition.row + 1,
267
+ });
268
+ }
269
+ }
270
+ if (children.length > 0) symbol.children = children;
271
+ }
272
+ }
273
+
274
+ return symbol;
275
+ }
276
+
277
+ /**
278
+ * Extract symbols from a block body: nested rule sets, mixins, functions,
279
+ * includes, extends, and `$var` declarations.
280
+ */
281
+ function extractBlockChildren(
282
+ block: Node,
283
+ source: string,
284
+ depth: number,
285
+ MAX_DEPTH: number,
286
+ ): SymbolInfo[] {
287
+ const results: SymbolInfo[] = [];
288
+
289
+ for (let i = 0; i < block.namedChildCount; i++) {
290
+ const child = block.namedChild(i);
291
+ if (!child) continue;
292
+
293
+ switch (child.type) {
294
+ case "rule_set":
295
+ case "media_statement":
296
+ case "keyframes_statement": {
297
+ const inner = extractScssChild(child, source, depth, MAX_DEPTH);
298
+ if (inner) results.push(inner);
299
+ break;
300
+ }
301
+ case "mixin_statement":
302
+ case "function_statement": {
303
+ const inner = extractScssChild(child, source, depth, MAX_DEPTH);
304
+ if (inner) results.push(inner);
305
+ break;
306
+ }
307
+ case "include_statement": {
308
+ const inc = extractInclude(child, source);
309
+ if (inc) results.push(inc);
310
+ break;
311
+ }
312
+ case "extend_statement": {
313
+ const ext = extractExtend(child, source);
314
+ if (ext) results.push(ext);
315
+ break;
316
+ }
317
+ case "declaration": {
318
+ // `$var: value;` inside a block should surface as a variable.
319
+ const prop = childTextOfType(child, source, 0, "property_name");
320
+ if (prop && prop.startsWith("$")) {
321
+ results.push({
322
+ name: prop,
323
+ type: "variable",
324
+ startLine: child.startPosition.row + 1,
325
+ endLine: child.endPosition.row + 1,
326
+ });
327
+ }
328
+ break;
329
+ }
330
+ case "ERROR": {
331
+ // `@extend %placeholder;` and `@include foo;` after error recovery can
332
+ // surface inside an ERROR node. Recover placeholder extends here.
333
+ const ext = extractExtendFromError(child, source);
334
+ if (ext) results.push(ext);
335
+ break;
336
+ }
337
+ }
338
+ }
339
+
340
+ return results;
341
+ }
342
+
343
+ /**
344
+ * Extract `@include name(...);` as a usage symbol.
345
+ */
346
+ function extractInclude(child: Node, source: string): SymbolInfo | null {
347
+ let name: string | undefined;
348
+ let detail: string | undefined;
349
+
350
+ for (let i = 0; i < child.namedChildCount; i++) {
351
+ const c = child.namedChild(i);
352
+ if (!c) continue;
353
+ if (c.type === "identifier") {
354
+ name = source.slice(c.startIndex, c.endIndex);
355
+ } else if (c.type === "arguments") {
356
+ detail = source.slice(c.startIndex, c.endIndex);
357
+ }
358
+ }
359
+ if (!name) return null;
360
+
361
+ return {
362
+ name: `@include ${name}`,
363
+ type: "include",
364
+ startLine: child.startPosition.row + 1,
365
+ endLine: child.endPosition.row + 1,
366
+ detail,
367
+ };
368
+ }
369
+
370
+ /**
371
+ * Extract `@extend selector;` as a usage symbol.
372
+ */
373
+ function extractExtend(child: Node, source: string): SymbolInfo | null {
374
+ let target: string | undefined;
375
+ for (let i = 0; i < child.namedChildCount; i++) {
376
+ const c = child.namedChild(i);
377
+ if (!c) continue;
378
+ if (
379
+ c.type === "class_selector" ||
380
+ c.type === "placeholder" ||
381
+ c.type === "id_selector" ||
382
+ c.type === "identifier" ||
383
+ c.type === "type_selector"
384
+ ) {
385
+ target = source.slice(c.startIndex, c.endIndex);
386
+ break;
387
+ }
388
+ }
389
+ if (!target) return null;
390
+
391
+ return {
392
+ name: `@extend ${target}`,
393
+ type: "extend",
394
+ startLine: child.startPosition.row + 1,
395
+ endLine: child.endPosition.row + 1,
396
+ };
397
+ }
398
+
399
+ /**
400
+ * Recover `@extend %placeholder;` from an ERROR node that grammar failed to
401
+ * parse as extend_statement.
402
+ */
403
+ function extractExtendFromError(child: Node, source: string): SymbolInfo | null {
404
+ // Look for a placeholder / selector descendant.
405
+ const target = findAnyText(child, source, [
406
+ "placeholder",
407
+ "class_selector",
408
+ "id_selector",
409
+ ]);
410
+ if (!target) return null;
411
+
412
+ return {
413
+ name: `@extend ${target}`,
414
+ type: "extend",
415
+ startLine: child.startPosition.row + 1,
416
+ endLine: child.endPosition.row + 1,
417
+ };
418
+ }
419
+
420
+ // ---- SCSS imports ----
421
+
422
+ /**
423
+ * Extract SCSS imports: `@use`, `@forward`, and `@import` statements.
424
+ *
425
+ * Grammar quirks handled:
426
+ * - `@use "x" as y;` / `@forward "x" as cfg-*;` produce ERROR children, but the
427
+ * authoritative module path survives as a `string_value` descendant.
428
+ * - Plain `@use "x";`, `@forward "x";`, `@import "x";` parse cleanly.
429
+ */
430
+ export function extractScssImports(
431
+ node: Node,
432
+ source: string,
433
+ ): ImportInfo[] {
434
+ const results: ImportInfo[] = [];
435
+ const visited = new Set<string>();
436
+
437
+ for (let i = 0; i < node.namedChildCount; i++) {
438
+ const child = node.namedChild(i);
439
+ if (!child) continue;
440
+
441
+ let kind: string | null = "import";
442
+ if (child.type === "use_statement") kind = "use";
443
+ else if (child.type === "forward_statement") kind = "forward";
444
+ else if (child.type === "import_statement") kind = "import";
445
+ else if (child.type === "ERROR") {
446
+ // `@forward "x" as cfg-*;` collapses into ERROR at top level.
447
+ const fwd = isForwardError(child, source);
448
+ if (fwd) {
449
+ const p = valueStringOf(child, source);
450
+ if (p) {
451
+ const dedupe = `forward:${p}`;
452
+ if (!visited.has(dedupe)) {
453
+ visited.add(dedupe);
454
+ results.push({
455
+ source: p,
456
+ names: [p],
457
+ lineNumber: child.startPosition.row + 1,
458
+ });
459
+ }
460
+ }
461
+ }
462
+ continue;
463
+ } else {
464
+ continue;
465
+ }
466
+
467
+ const path = valueStringOf(child, source);
468
+ if (!path) continue;
469
+
470
+ const dedupe = `${kind}:${path}`;
471
+ if (visited.has(dedupe)) continue;
472
+ visited.add(dedupe);
473
+
474
+ results.push({
475
+ source: path,
476
+ names: [path],
477
+ lineNumber: child.startPosition.row + 1,
478
+ });
479
+ }
480
+
481
+ return results;
482
+ }
483
+
484
+ /**
485
+ * Detect a top-level ERROR node that is actually `@forward "path" as ...;`.
486
+ */
487
+ function isForwardError(node: Node, source: string): boolean {
488
+ const start = source.slice(node.startIndex, node.startIndex + 9);
489
+ return start.trim() === "@forward";
490
+ }
491
+
492
+ /**
493
+ * Extract the module path (string literal) from a use/forward/import statement,
494
+ * working around ERROR subtrees.
495
+ */
496
+ function valueStringOf(node: Node, source: string): string | undefined {
497
+ // Prefer a string_value first (it holds the module path).
498
+ const str = findAnyText(node, source, ["string_value"]);
499
+ if (str) return stripQuotes(str);
500
+
501
+ // Fallback: inside ERROR nodes the path may parse as a plain tag or
502
+ // concatenated identifier.
503
+ const fallback = findAnyText(node, source, ["tag_name", "_concatenated_identifier"]);
504
+ if (fallback) return fallback;
505
+
506
+ return undefined;
507
+ }
508
+
509
+ function stripQuotes(s: string): string {
510
+ return s.replace(/^["']|["']$/g, "");
511
+ }
512
+
513
+ // ---- Shared helpers ----
514
+
515
+ /** Find the first named descendant with one of the given types, returning its source text. */
516
+ function findAnyText(
517
+ node: Node,
518
+ source: string,
519
+ types: string[],
520
+ ): string | undefined {
521
+ // BFS over named children so recovery works even through ERROR nodes.
522
+ const queue: Node[] = [node];
523
+ while (queue.length > 0) {
524
+ const cur = queue.shift()!;
525
+ for (let i = 0; i < cur.namedChildCount; i++) {
526
+ const c = cur.namedChild(i);
527
+ if (!c) continue;
528
+ if (types.includes(c.type)) {
529
+ return source.slice(c.startIndex, c.endIndex);
530
+ }
531
+ queue.push(c);
532
+ }
533
+ }
534
+ return undefined;
535
+ }
536
+
537
+ /** Find the first direct named child with one of the given types. */
538
+ function findChildByType(node: Node, types: string[]): Node | null {
539
+ for (let i = 0; i < node.namedChildCount; i++) {
540
+ const c = node.namedChild(i);
541
+ if (c && types.includes(c.type)) return c;
542
+ }
543
+ return null;
544
+ }
545
+
546
+ /** Return the text of the nth direct named child of a given type. */
547
+ function childTextOfType(
548
+ node: Node,
549
+ source: string,
550
+ index: number,
551
+ type: string,
552
+ ): string | undefined {
553
+ let seen = 0;
554
+ for (let i = 0; i < node.namedChildCount; i++) {
555
+ const c = node.namedChild(i);
556
+ if (c && c.type === type) {
557
+ if (seen === index) return source.slice(c.startIndex, c.endIndex);
558
+ seen++;
559
+ }
560
+ }
561
+ return undefined;
562
+ }
563
+
564
+ function nodeTextOf(node: Node, source: string): string {
565
+ return source.slice(node.startIndex, node.endIndex);
566
+ }
@@ -0,0 +1,82 @@
1
+ /** A single structural symbol extracted from source code. */
2
+ export interface SymbolInfo {
3
+ name: string;
4
+ type: string; // e.g. "class", "function", "method", "interface", "enum", "trait"
5
+ startLine: number; // 1-indexed
6
+ endLine: number;
7
+ children?: SymbolInfo[];
8
+ detail?: string; // optional extra info (e.g. parameters, visibility)
9
+ }
10
+
11
+ /** Result of parsing a source file. */
12
+ export interface ParseResult {
13
+ symbols: SymbolInfo[];
14
+ }
15
+
16
+ /** Information about a single import/require statement. */
17
+ export interface ImportInfo {
18
+ source: string;
19
+ names: string[];
20
+ lineNumber: number;
21
+ }
22
+
23
+ /** Configuration stored in .toml file. */
24
+ export interface CodebaseReaderConfig {
25
+ general: {
26
+ enabled: boolean;
27
+ threshold_tokens: number;
28
+ suggest_similar: boolean;
29
+ };
30
+ explorer: {
31
+ model: string;
32
+ thinking: string;
33
+ max_turns: number;
34
+ };
35
+ parsing: {
36
+ max_outline_depth: number;
37
+ };
38
+ /**
39
+ * Optional subagent library preference.
40
+ * One of "@tintinweb/pi-subagents", "pi-subagents" (nicobailon), or "" (auto-detect).
41
+ * Used for informational logging and to guide install instructions.
42
+ */
43
+ subagent?: {
44
+ library: string;
45
+ };
46
+ }
47
+
48
+ export const DEFAULT_CONFIG: CodebaseReaderConfig = {
49
+ general: {
50
+ enabled: true,
51
+ threshold_tokens: 10_000,
52
+ suggest_similar: true,
53
+ },
54
+ explorer: {
55
+ model: "anthropic/claude-sonnet-4-20250514",
56
+ thinking: "medium",
57
+ max_turns: 30,
58
+ },
59
+ parsing: {
60
+ max_outline_depth: 10,
61
+ },
62
+ subagent: {
63
+ library: "",
64
+ },
65
+ };
66
+
67
+ export interface ExplorerAgentConfig {
68
+ model: string;
69
+ thinking: string;
70
+ maxTurns: number;
71
+ /** When true, register the tool as `short_read` instead of `read` (for pi-hashline-edit-pro compatibility). */
72
+ useShortRead?: boolean;
73
+ }
74
+
75
+ /** Parsed file info used to decide read strategy. */
76
+ export interface FileInfo {
77
+ path: string;
78
+ content: string;
79
+ language: string | null; // null = unknown/not supported
80
+ lineCount: number;
81
+ byteLength: number;
82
+ }
@@ -0,0 +1,37 @@
1
+ # Grammar licenses
2
+
3
+ The `.wasm` files in this directory are compiled from the following MIT-licensed grammars:
4
+
5
+ | File | Grammar | Copyright |
6
+ | --- | --- | --- |
7
+ | `tree-sitter-javascript.wasm` | [tree-sitter/tree-sitter-javascript](https://github.com/tree-sitter/tree-sitter-javascript) | Copyright (c) 2014 Max Brunsfeld |
8
+ | `tree-sitter-typescript.wasm`, `tree-sitter-tsx.wasm` | [tree-sitter/tree-sitter-typescript](https://github.com/tree-sitter/tree-sitter-typescript) | Copyright (c) 2017 Max Brunsfeld |
9
+ | `tree-sitter-python.wasm` | [tree-sitter/tree-sitter-python](https://github.com/tree-sitter/tree-sitter-python) | Copyright (c) 2016 Max Brunsfeld |
10
+ | `tree-sitter-go.wasm` | [tree-sitter/tree-sitter-go](https://github.com/tree-sitter/tree-sitter-go) | Copyright (c) 2014 Max Brunsfeld |
11
+ | `tree-sitter-rust.wasm` | [tree-sitter/tree-sitter-rust](https://github.com/tree-sitter/tree-sitter-rust) | Copyright (c) 2017 Maxim Sokolov |
12
+ | `tree-sitter-solidity.wasm` | [JoranHonig/tree-sitter-solidity](https://github.com/JoranHonig/tree-sitter-solidity) | Copyright (c) 2020 Joran Honig |
13
+ | `tree-sitter-java.wasm` | [tree-sitter/tree-sitter-java](https://github.com/tree-sitter/tree-sitter-java) | Copyright (c) 2017 Ayman Nadeem |
14
+ | `tree-sitter-php.wasm` | [tree-sitter/tree-sitter-php](https://github.com/tree-sitter/tree-sitter-php) | Copyright (c) 2017 Josh Vera, GitHub; Copyright (c) 2019 Max Brunsfeld, Amaan Qureshi, Christian Frøystad, Caleb White |
15
+ | `tree-sitter-blade.wasm` | [EmranMR/tree-sitter-blade](https://github.com/EmranMR/tree-sitter-blade) | Copyright (c) 2023 Emran Mashhadi Ramezan |
16
+ | `tree-sitter-scss.wasm` | [tree-sitter-grammars/tree-sitter-scss](https://github.com/tree-sitter-grammars/tree-sitter-scss) | Copyright (c) 2024 Amaan Qureshi |
17
+ | `tree-sitter-sass.wasm` | [bajrangCoder/tree-sitter-sass](https://github.com/bajrangCoder/tree-sitter-sass) | Copyright (c) 2024 Tree-sitter Community |
18
+
19
+ ## MIT License
20
+
21
+ Permission is hereby granted, free of charge, to any person obtaining a copy
22
+ of this software and associated documentation files (the "Software"), to deal
23
+ in the Software without restriction, including without limitation the rights
24
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25
+ copies of the Software, and to permit persons to whom the Software is
26
+ furnished to do so, subject to the following conditions:
27
+
28
+ The above copyright notice and this permission notice shall be included in all
29
+ copies or substantial portions of the Software.
30
+
31
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37
+ SOFTWARE.