@shanepadgett/tau-agent 0.27.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 (113) hide show
  1. package/extensions/context/sync.ts +1 -9
  2. package/extensions/context-pruning/prune.ts +2 -2
  3. package/extensions/explore/README.md +13 -21
  4. package/extensions/explore/ast/adapter.ts +97 -0
  5. package/extensions/explore/ast/engine.ts +470 -0
  6. package/extensions/explore/ast/format/ast-search.ts +97 -0
  7. package/extensions/explore/ast/format/composite.ts +26 -0
  8. package/extensions/explore/ast/format/context.ts +66 -0
  9. package/extensions/explore/ast/format/deps.ts +86 -0
  10. package/extensions/explore/ast/format/discover.ts +85 -0
  11. package/extensions/explore/ast/format/impact.ts +105 -0
  12. package/extensions/explore/ast/format/outline.ts +66 -0
  13. package/extensions/explore/ast/format/relationships.ts +81 -0
  14. package/extensions/explore/ast/format/show.ts +38 -0
  15. package/extensions/explore/ast/grammars/kotlin.wasm +0 -0
  16. package/extensions/explore/ast/grammars/manifest.json +41 -0
  17. package/extensions/explore/ast/grammars/manifest.ts +99 -0
  18. package/extensions/explore/ast/grammars/odin.wasm +0 -0
  19. package/extensions/explore/ast/grammars/swift.wasm +0 -0
  20. package/extensions/explore/ast/graph/file-graph.ts +360 -0
  21. package/extensions/explore/ast/graph/relationships.ts +597 -0
  22. package/extensions/explore/ast/identity.ts +119 -0
  23. package/extensions/explore/ast/ir.ts +130 -0
  24. package/extensions/explore/ast/languages/csharp-file-deps.ts +189 -0
  25. package/extensions/explore/ast/languages/csharp.ts +493 -0
  26. package/extensions/explore/ast/languages/file-dep-util.ts +120 -0
  27. package/extensions/explore/ast/languages/fixtures/sample.cs +17 -0
  28. package/extensions/explore/ast/languages/fixtures/sample.java +21 -0
  29. package/extensions/explore/ast/languages/fixtures/sample.kt +15 -0
  30. package/extensions/explore/ast/languages/fixtures/sample.odin +28 -0
  31. package/extensions/explore/ast/languages/fixtures/sample.rs +31 -0
  32. package/extensions/explore/ast/languages/fixtures/sample.swift +25 -0
  33. package/extensions/explore/ast/languages/go-file-deps.ts +139 -0
  34. package/extensions/explore/ast/languages/go.ts +545 -0
  35. package/extensions/explore/ast/languages/java.ts +412 -0
  36. package/extensions/explore/ast/languages/jvm-file-deps.ts +217 -0
  37. package/extensions/explore/ast/languages/kotlin.ts +611 -0
  38. package/extensions/explore/ast/languages/odin-file-deps.ts +175 -0
  39. package/extensions/explore/ast/languages/odin.ts +407 -0
  40. package/extensions/explore/ast/languages/rust-file-deps.ts +159 -0
  41. package/extensions/explore/ast/languages/rust.ts +506 -0
  42. package/extensions/explore/ast/languages/swift-file-deps.ts +59 -0
  43. package/extensions/explore/ast/languages/swift.ts +466 -0
  44. package/extensions/explore/ast/languages/tree.ts +220 -0
  45. package/extensions/explore/ast/languages/typescript-file-deps.ts +259 -0
  46. package/extensions/explore/ast/languages/typescript-package-surface.ts +440 -0
  47. package/extensions/explore/ast/languages/typescript.ts +716 -0
  48. package/extensions/explore/ast/markdown.ts +145 -0
  49. package/extensions/explore/ast/package-surface.ts +42 -0
  50. package/extensions/explore/ast/queries/ast-search.ts +306 -0
  51. package/extensions/explore/ast/queries/composite-target.ts +77 -0
  52. package/extensions/explore/ast/queries/context.ts +406 -0
  53. package/extensions/explore/ast/queries/discover.ts +427 -0
  54. package/extensions/explore/ast/queries/impact.ts +250 -0
  55. package/extensions/explore/ast/queries/outline.ts +203 -0
  56. package/extensions/explore/ast/queries/show.ts +262 -0
  57. package/extensions/explore/ast/query.ts +48 -0
  58. package/extensions/explore/ast/read/hook.ts +125 -0
  59. package/extensions/explore/ast/read/policy.ts +55 -0
  60. package/extensions/explore/ast/registry.ts +120 -0
  61. package/extensions/explore/ast/scan.ts +76 -0
  62. package/extensions/explore/ast/slice.ts +31 -0
  63. package/extensions/explore/ast/tools/ast-search.ts +138 -0
  64. package/extensions/explore/ast/tools/context.ts +126 -0
  65. package/extensions/explore/ast/tools/deps.ts +72 -0
  66. package/extensions/explore/ast/tools/discover.ts +208 -0
  67. package/extensions/explore/ast/tools/impact.ts +135 -0
  68. package/extensions/explore/ast/tools/outline.ts +200 -0
  69. package/extensions/explore/ast/tools/relationships.ts +160 -0
  70. package/extensions/explore/ast/tools/render.ts +121 -0
  71. package/extensions/explore/ast/tools/reverse-deps.ts +72 -0
  72. package/extensions/explore/ast/tools/show.ts +116 -0
  73. package/extensions/explore/guidance.ts +52 -0
  74. package/extensions/explore/index.ts +82 -92
  75. package/extensions/explore/read/autoread.ts +118 -0
  76. package/extensions/explore/settings.ts +49 -31
  77. package/extensions/explore/traverse.ts +254 -91
  78. package/extensions/handoff/index.ts +1 -1
  79. package/extensions/publish/index.ts +18 -85
  80. package/extensions/publish/publish-ui.ts +0 -4
  81. package/extensions/soul/README.md +7 -4
  82. package/extensions/soul/index.ts +11 -5
  83. package/extensions/soul/prompt.ts +31 -13
  84. package/extensions/soul/settings.ts +7 -2
  85. package/extensions/subagent/agents/context-sync.md +6 -10
  86. package/extensions/subagent/agents/review.md +24 -55
  87. package/extensions/subagent/agents/scout.md +38 -115
  88. package/extensions/subagent/run.ts +1 -1
  89. package/extensions/tau-help/help.md +2 -4
  90. package/package.json +6 -4
  91. package/schemas/tau.schema.json +35 -30
  92. package/{extensions/explore → shared}/autoread.ts +21 -7
  93. package/shared/events.ts +1 -1
  94. package/shared/full-file-knowledge.ts +49 -0
  95. package/extensions/explore/ast-guidance.ts +0 -67
  96. package/extensions/explore/ast-languages.ts +0 -61
  97. package/extensions/explore/ast-tools.ts +0 -1994
  98. package/extensions/explore/ast-worker.ts +0 -1025
  99. package/extensions/explore/find.ts +0 -147
  100. package/extensions/explore/full-file-knowledge.ts +0 -234
  101. package/extensions/explore/grep.ts +0 -749
  102. package/extensions/explore/limits.ts +0 -22
  103. package/extensions/explore/ls.ts +0 -113
  104. package/extensions/explore/orientation-state.ts +0 -280
  105. package/extensions/explore/path-display.ts +0 -41
  106. package/extensions/explore/path-tree.ts +0 -150
  107. package/extensions/explore/read-cache.ts +0 -273
  108. package/extensions/explore/read-snapshots.ts +0 -57
  109. package/extensions/explore/read-stats-panel.ts +0 -176
  110. package/extensions/explore/read-stats.ts +0 -138
  111. package/extensions/explore/read.ts +0 -372
  112. package/extensions/explore/result.ts +0 -29
  113. package/native-bin/darwin-arm64/tau-ast +0 -0
@@ -1,113 +1,103 @@
1
1
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import { resolve } from "node:path";
3
- import { emitTauEvent, onTauEvent } from "../../shared/events.js";
4
- import { loadTauExtensionSettings } from "../../shared/settings/load.ts";
3
+ import { onTauEvent } from "../../shared/events.ts";
5
4
  import { createTemporaryOutputStore } from "../../shared/temporary-output-store.ts";
6
- import { createToolRowStateStore } from "../../shared/tool-row-state.js";
7
- import { AST_DISCOVERY_BUDGET, effectiveAstGuidance } from "./ast-guidance.ts";
8
- import { createAstTools } from "./ast-tools.ts";
9
- import { AstWorkerClient } from "./ast-worker.ts";
10
- import { registerAutoread } from "./autoread.ts";
11
- import { createFindTool } from "./find.ts";
12
- import { createGrepTool } from "./grep.ts";
13
- import { createLsTool } from "./ls.ts";
14
- import { createOrientationState } from "./orientation-state.ts";
15
- import { createReadCacheStore } from "./read-cache.ts";
16
- import { createReadSnapshotStore } from "./read-snapshots.ts";
17
- import { showReadStats } from "./read-stats.ts";
18
- import { createExploreReadTool } from "./read.ts";
19
- import exploreSettings from "./settings.ts";
5
+ import { createToolRowStateStore } from "../../shared/tool-row-state.ts";
6
+ import { createExploreEngine, type ExploreEngine } from "./ast/engine.ts";
7
+ import { createFileGraph, type ExploreFileGraph } from "./ast/graph/file-graph.ts";
8
+ import { registerReadOutlineHook } from "./ast/read/hook.ts";
9
+ import { createAstSearchTool } from "./ast/tools/ast-search.ts";
10
+ import { createContextTool } from "./ast/tools/context.ts";
11
+ import { createDepsTool } from "./ast/tools/deps.ts";
12
+ import { createDiscoverTool } from "./ast/tools/discover.ts";
13
+ import { createImpactTool } from "./ast/tools/impact.ts";
14
+ import { createOutlineTool } from "./ast/tools/outline.ts";
15
+ import {
16
+ createCalleesTool,
17
+ createCallersTool,
18
+ createImplementationsTool,
19
+ createReferencesTool,
20
+ } from "./ast/tools/relationships.ts";
21
+ import { createReverseDepsTool } from "./ast/tools/reverse-deps.ts";
22
+ import { createShowTool } from "./ast/tools/show.ts";
23
+ import { registerExploreGuidance } from "./guidance.ts";
24
+ import { registerExploreAutoread } from "./read/autoread.ts";
20
25
 
21
26
  export default function exploreExtension(pi: ExtensionAPI): void {
22
- let settings = exploreSettings.defaults;
23
27
  const rowState = createToolRowStateStore(pi, "explore.tool-row-state");
24
- const readCache = createReadCacheStore();
25
- const readSnapshots = createReadSnapshotStore();
26
- const astClient = new AstWorkerClient();
27
- const orientation = createOrientationState(() => astClient.supportedLanguages());
28
28
  const temporaryOutput = createTemporaryOutputStore();
29
- const ast = createAstTools(astClient, rowState, temporaryOutput, orientation, (toolCallId, cwd, summary) => {
30
- emitTauEvent(pi, "tau:file-mutation.applied", {
31
- source: "locatorEdit",
32
- toolCallId,
33
- cwd,
34
- status: summary.status,
35
- changes: summary.changes.map((change) => ({
36
- path: change.path,
37
- kind: change.kind,
38
- move: change.move,
39
- linesAdded: change.linesAdded,
40
- linesRemoved: change.linesRemoved,
41
- resultingFingerprint: change.resultingFingerprint,
42
- snapshotRanges: change.snapshotRanges,
43
- })),
44
- });
45
- });
46
- registerAutoread(pi, rowState);
47
- pi.registerTool(ast.outline);
48
- pi.registerTool(ast.symbol);
49
- pi.registerTool(ast.replace_declaration);
50
- pi.registerTool(ast.replace_body);
51
- pi.registerTool(ast.insert_declaration);
52
- pi.registerTool(ast.rename_declaration);
53
- pi.registerTool(ast.api_discover);
54
- pi.registerTool(ast.ast_search);
55
- pi.registerTool(ast.references);
56
- pi.registerTool(ast.callers);
57
- pi.registerTool(ast.callees);
58
- pi.registerTool(ast.implementations);
59
- pi.registerTool(ast.tests);
60
- pi.registerTool(createLsTool(rowState));
61
- pi.registerTool(createFindTool(rowState));
62
- pi.registerTool(createGrepTool(rowState));
63
- pi.registerTool(createExploreReadTool(rowState, orientation, readCache, readSnapshots, () => settings.readGate));
64
- pi.on("before_agent_start", async (event, ctx) => {
65
- const guidance = await effectiveAstGuidance({
66
- cwd: ctx.cwd,
67
- workerLanguages: () => astClient.supportedLanguages(),
68
- discoveryBudget: AST_DISCOVERY_BUDGET,
69
- });
70
- return guidance ? { systemPrompt: `${event.systemPrompt}\n\n${guidance}` } : undefined;
71
- });
72
- pi.registerCommand("read-stats", {
73
- description: "Show estimated read token and cost savings for this session",
74
- async handler(_args, ctx) {
75
- if (ctx.mode !== "tui") {
76
- ctx.ui.notify("Read stats require TUI mode", "error");
77
- return;
78
- }
79
- await showReadStats(ctx, orientation);
80
- },
81
- });
29
+ let engine: ExploreEngine | undefined;
30
+ let graph: ExploreFileGraph | undefined;
31
+
32
+ const engineFor = (cwd: string): ExploreEngine => {
33
+ const absoluteCwd = resolve(cwd);
34
+ if (engine !== undefined && engine.cwd === absoluteCwd) return engine;
35
+ engine?.shutdown();
36
+ graph?.clear();
37
+ engine = createExploreEngine({ cwd: absoluteCwd });
38
+ graph = createFileGraph(engine);
39
+ return engine;
40
+ };
41
+
42
+ const graphFor = (cwd: string): ExploreFileGraph => {
43
+ engineFor(cwd);
44
+ if (graph === undefined) {
45
+ throw new Error("Explore file graph failed to initialize");
46
+ }
47
+ return graph;
48
+ };
49
+
50
+ pi.registerTool(createOutlineTool(rowState, temporaryOutput, engineFor));
51
+ pi.registerTool(createShowTool(rowState, engineFor));
52
+ pi.registerTool(createDiscoverTool(rowState, temporaryOutput, engineFor));
53
+ pi.registerTool(createAstSearchTool(rowState, temporaryOutput, engineFor));
54
+ pi.registerTool(createDepsTool(rowState, engineFor, graphFor));
55
+ pi.registerTool(createReverseDepsTool(rowState, engineFor, graphFor));
56
+ pi.registerTool(createCallersTool(rowState, engineFor, graphFor));
57
+ pi.registerTool(createCalleesTool(rowState, engineFor, graphFor));
58
+ pi.registerTool(createReferencesTool(rowState, engineFor, graphFor));
59
+ pi.registerTool(createImplementationsTool(rowState, engineFor, graphFor));
60
+ pi.registerTool(createImpactTool(rowState, temporaryOutput, engineFor, graphFor));
61
+ pi.registerTool(createContextTool(rowState, temporaryOutput, engineFor, graphFor));
62
+ registerReadOutlineHook(pi, engineFor);
63
+ registerExploreAutoread(pi, rowState, engineFor);
64
+ registerExploreGuidance(pi, engineFor);
65
+
82
66
  pi.on("session_start", async (_event, ctx) => {
83
- settings = await loadTauExtensionSettings(ctx, exploreSettings);
84
67
  await temporaryOutput.shutdown();
85
68
  await temporaryOutput.start();
86
69
  rowState.clear();
87
- readSnapshots.clear();
88
- ast.clear();
70
+ engine?.shutdown();
71
+ graph?.clear();
72
+ engine = createExploreEngine({ cwd: ctx.cwd });
73
+ graph = createFileGraph(engine);
89
74
  });
75
+
90
76
  onTauEvent(pi, "explore.ast", "tau:file-mutation.applied", (event) => {
91
- const paths = event.changes.flatMap((change) => [
92
- resolve(event.cwd, change.path),
93
- ...(change.move ? [resolve(event.cwd, change.move.from), resolve(event.cwd, change.move.to)] : []),
94
- ]);
95
- ast.invalidate(paths);
96
- orientation.recordPatched(
97
- event.changes.map((change) => ({
98
- path: resolve(event.cwd, change.path),
99
- resultingFingerprint: change.resultingFingerprint,
100
- })),
77
+ if (engine === undefined) return;
78
+ const paths = event.changes.flatMap((change) => {
79
+ const main = resolve(event.cwd, change.path);
80
+ if (change.move === undefined) return [main];
81
+ return [main, resolve(event.cwd, change.move.from), resolve(event.cwd, change.move.to)];
82
+ });
83
+ engine.invalidate(paths);
84
+ const topologyChanged = event.changes.some(
85
+ (change) => change.kind === "add" || change.kind === "delete" || change.move !== undefined,
101
86
  );
87
+ if (topologyChanged) graph?.clear();
88
+ else graph?.invalidate(paths);
102
89
  });
103
- pi.on("session_compact", () => readSnapshots.clear());
90
+
104
91
  pi.on("session_tree", () => {
105
- readSnapshots.clear();
106
- ast.resetForTree();
92
+ engine?.clear();
93
+ graph?.clear();
107
94
  });
95
+
108
96
  pi.on("session_shutdown", async () => {
109
- ast.clear();
110
- await astClient.shutdown();
97
+ engine?.shutdown();
98
+ engine = undefined;
99
+ graph?.clear();
100
+ graph = undefined;
111
101
  await temporaryOutput.shutdown();
112
102
  });
113
103
  }
@@ -0,0 +1,118 @@
1
+ import { createHash } from "node:crypto";
2
+ import { resolve } from "node:path";
3
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
4
+ import { prepareAutoreadMessage, registerAutoread, type PreparedAutoreadMessage } from "../../../shared/autoread.ts";
5
+ import { createCompleteFileMeta } from "../../../shared/full-file-knowledge.ts";
6
+ import { loadTauExtensionSettings } from "../../../shared/settings/load.ts";
7
+ import type { ToolRowStateStore } from "../../../shared/tool-row-state.ts";
8
+ import type { ExploreEngine } from "../ast/engine.ts";
9
+ import { formatOutlineFile } from "../ast/format/outline.ts";
10
+ import { formatLargeReadOutline, shouldOutlineFullRead, type ExploreReadSettings } from "../ast/read/policy.ts";
11
+ import { outlinePath } from "../ast/queries/outline.ts";
12
+ import exploreSettings from "../settings.ts";
13
+ import { resolveExplorePath } from "../traverse.ts";
14
+
15
+ const DEFAULT_OUTLINE_OPTIONS = {
16
+ includePrivate: false,
17
+ includeDocs: false,
18
+ names: [] as readonly string[],
19
+ };
20
+
21
+ export function registerExploreAutoread(
22
+ pi: ExtensionAPI,
23
+ rowState: ToolRowStateStore,
24
+ engineFor: (cwd: string) => ExploreEngine,
25
+ ): void {
26
+ let readSettings: ExploreReadSettings = exploreSettings.defaults.read;
27
+
28
+ pi.on("session_start", async (_event, ctx) => {
29
+ const settings = await loadTauExtensionSettings(ctx, exploreSettings);
30
+ readSettings = settings.read;
31
+ });
32
+
33
+ registerAutoread(pi, rowState, async (options) => {
34
+ return prepareExploreAutoreadMessage({
35
+ ...options,
36
+ engine: engineFor(options.cwd),
37
+ readSettings,
38
+ });
39
+ });
40
+ }
41
+
42
+ async function prepareExploreAutoreadMessage(options: {
43
+ rowId: string;
44
+ path: string;
45
+ cwd: string;
46
+ source: string;
47
+ batchId: string;
48
+ signal: AbortSignal | undefined;
49
+ isLifecycleCurrent: () => boolean;
50
+ maximumBytes?: number;
51
+ engine: ExploreEngine;
52
+ readSettings: ExploreReadSettings;
53
+ }): Promise<PreparedAutoreadMessage> {
54
+ const { engine, readSettings, ...shared } = options;
55
+ if (!readSettings.enabled) return prepareAutoreadMessage(shared);
56
+
57
+ const absolutePath = resolveExplorePath(options.cwd, options.path);
58
+ if (engine.registry.adapterForPath(absolutePath) === undefined) {
59
+ return prepareAutoreadMessage(shared);
60
+ }
61
+
62
+ assertPreparationCurrent(options.signal, options.isLifecycleCurrent);
63
+
64
+ let lineCount: number;
65
+ try {
66
+ const source = await engine.sourceForFile(absolutePath);
67
+ lineCount = source.ir.lineCount;
68
+ } catch {
69
+ return prepareAutoreadMessage(shared);
70
+ }
71
+
72
+ if (!shouldOutlineFullRead(lineCount, readSettings.structureThresholdLines)) {
73
+ return prepareAutoreadMessage(shared);
74
+ }
75
+
76
+ const abort = options.signal ?? new AbortController().signal;
77
+ const result = await outlinePath(engine, options.path, DEFAULT_OUTLINE_OPTIONS, abort);
78
+ assertPreparationCurrent(options.signal, options.isLifecycleCurrent);
79
+ if (result.mode !== "file") {
80
+ return prepareAutoreadMessage(shared);
81
+ }
82
+
83
+ const outlineBody =
84
+ result.file.rows.length === 0 ? "No declarations" : formatOutlineFile(result.file, engine.cwd, false);
85
+ const outlineText = formatLargeReadOutline(outlineBody);
86
+ const messageContent = `${options.path}\n${outlineText}`;
87
+ const pathKey = resolve(options.cwd, options.path);
88
+ const readCache = createCompleteFileMeta({
89
+ pathKey,
90
+ presentation: "plain",
91
+ servedHash: createHash("sha256").update(outlineText, "utf8").digest("hex"),
92
+ mode: "baseline",
93
+ sourceText: outlineText,
94
+ returnedText: messageContent,
95
+ totalLines: lineCount,
96
+ summary: `outline (${lineCount} lines)`,
97
+ });
98
+
99
+ return {
100
+ customType: "tau.autoread",
101
+ content: messageContent,
102
+ display: true,
103
+ details: {
104
+ rowId: options.rowId,
105
+ path: options.path,
106
+ cwd: options.cwd,
107
+ source: options.source,
108
+ batchId: options.batchId,
109
+ status: "read",
110
+ readCache,
111
+ },
112
+ };
113
+ }
114
+
115
+ function assertPreparationCurrent(signal: AbortSignal | undefined, isLifecycleCurrent: () => boolean): void {
116
+ signal?.throwIfAborted();
117
+ if (!isLifecycleCurrent()) throw new Error("Autoread preparation crossed a session lifecycle boundary");
118
+ }
@@ -1,46 +1,64 @@
1
- import { relative, resolve } from "node:path";
2
1
  import { Type } from "typebox";
3
- import { matchGlob, posixPath } from "../../shared/glob.ts";
4
2
  import { defineTauExtensionSettings } from "../../shared/settings/define.ts";
5
3
 
6
- export interface ExploreReadGateSettings {
7
- includeGlobs: string[];
8
- excludeGlobs: string[];
9
- }
10
-
11
4
  export default defineTauExtensionSettings({
12
5
  key: "explore",
13
6
  defaults: {
14
- readGate: {
15
- includeGlobs: ["**/*"] as string[],
16
- excludeGlobs: ["**/*.md", "**/*.markdown", "**/*.mdown"] as string[],
7
+ context: {
8
+ defaultBudgetTokens: 8000 as number,
9
+ },
10
+ read: {
11
+ enabled: true as boolean,
12
+ structureThresholdLines: 200 as number,
13
+ maxRangeLines: 200 as number,
17
14
  },
18
15
  },
19
16
  schema: Type.Object(
20
17
  {
21
- readGate: Type.Object(
22
- {
23
- includeGlobs: Type.Array(Type.String(), {
24
- default: ["**/*"],
25
- description:
26
- "Working-directory-relative supported source paths that require a structural attempt before read.",
27
- }),
28
- excludeGlobs: Type.Array(Type.String(), {
29
- default: ["**/*.md", "**/*.markdown", "**/*.mdown"],
30
- description: "Working-directory-relative paths excluded from the Explore read gate. Exclusions win.",
31
- }),
32
- },
33
- { additionalProperties: false },
18
+ context: Type.Optional(
19
+ Type.Object(
20
+ {
21
+ defaultBudgetTokens: Type.Optional(
22
+ Type.Integer({
23
+ default: 8000,
24
+ minimum: 1,
25
+ description: "Default token budget for context when the caller omits budget.",
26
+ }),
27
+ ),
28
+ },
29
+ { additionalProperties: false },
30
+ ),
31
+ ),
32
+ read: Type.Optional(
33
+ Type.Object(
34
+ {
35
+ enabled: Type.Optional(
36
+ Type.Boolean({
37
+ default: true,
38
+ description:
39
+ "Master switch for Explore structural read overlay and large-source autoread outline path. When false, Pi read and autoread keep ordinary full bodies.",
40
+ }),
41
+ ),
42
+ structureThresholdLines: Type.Optional(
43
+ Type.Integer({
44
+ default: 200,
45
+ minimum: 1,
46
+ description:
47
+ "Registered source at or under this line count may be full-read. Above it, full read model-visible result is outline only.",
48
+ }),
49
+ ),
50
+ maxRangeLines: Type.Optional(
51
+ Type.Integer({
52
+ default: 200,
53
+ minimum: 1,
54
+ description: "Maximum lines returned by one ranged read on registered source.",
55
+ }),
56
+ ),
57
+ },
58
+ { additionalProperties: false },
59
+ ),
34
60
  ),
35
61
  },
36
62
  { additionalProperties: false },
37
63
  ),
38
64
  });
39
-
40
- export function matchesExploreReadGate(path: string, cwd: string, settings: ExploreReadGateSettings): boolean {
41
- const projectPath = posixPath(relative(resolve(cwd), resolve(path)));
42
- return (
43
- settings.includeGlobs.some((pattern) => matchGlob(pattern, projectPath)) &&
44
- !settings.excludeGlobs.some((pattern) => matchGlob(pattern, projectPath))
45
- );
46
- }