@mrclrchtr/supi-code-intelligence 2.0.6 → 2.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.
- package/README.md +88 -4
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/README.md +32 -23
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +2 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config.ts +22 -8
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/prompt-surface.ts +357 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -3
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -5
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/prompt-surface.ts +4 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/scoped-settings-list.ts +372 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-action-menu.ts +101 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-command.ts +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +55 -27
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-schema.ts +464 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-submenus.ts +124 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +72 -285
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -5
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings.ts +27 -5
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +10 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +2 -2
- package/node_modules/@mrclrchtr/supi-core/README.md +32 -23
- package/node_modules/@mrclrchtr/supi-core/package.json +2 -1
- package/node_modules/@mrclrchtr/supi-core/src/config/config.ts +22 -8
- package/node_modules/@mrclrchtr/supi-core/src/config/prompt-surface.ts +357 -0
- package/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -3
- package/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -5
- package/node_modules/@mrclrchtr/supi-core/src/prompt-surface.ts +4 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings/scoped-settings-list.ts +372 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-action-menu.ts +101 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-command.ts +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +55 -27
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-schema.ts +464 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-submenus.ts +124 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +72 -285
- package/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -5
- package/node_modules/@mrclrchtr/supi-core/src/settings.ts +27 -5
- package/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +10 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/README.md +32 -23
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +2 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config.ts +22 -8
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/prompt-surface.ts +357 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -3
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/prompt-surface.ts +4 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/scoped-settings-list.ts +372 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-action-menu.ts +101 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-command.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +55 -27
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-schema.ts +464 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-submenus.ts +124 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +72 -285
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings.ts +27 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +10 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +32 -23
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +2 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/config.ts +22 -8
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/prompt-surface.ts +357 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -3
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/prompt-surface.ts +4 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/scoped-settings-list.ts +372 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-action-menu.ts +101 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-command.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +55 -27
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-schema.ts +464 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-submenus.ts +124 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +72 -285
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings.ts +27 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +10 -0
- package/node_modules/@mrclrchtr/supi-lsp/package.json +3 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/config/lsp-settings.ts +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/README.md +32 -23
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +2 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config.ts +22 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/prompt-surface.ts +357 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/prompt-surface.ts +4 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/scoped-settings-list.ts +372 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-action-menu.ts +101 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-command.ts +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +55 -27
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-schema.ts +464 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-submenus.ts +124 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +72 -285
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/settings.ts +27 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +10 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +2 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +32 -23
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +2 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config.ts +22 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/prompt-surface.ts +357 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +0 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/prompt-surface.ts +4 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/scoped-settings-list.ts +372 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-action-menu.ts +101 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-command.ts +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +55 -27
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-schema.ts +464 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-submenus.ts +124 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +72 -285
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings.ts +27 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/tool-framework.ts +10 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +3 -3
- package/package.json +5 -5
- package/src/analysis/evidence.ts +13 -0
- package/src/analysis/instruction-files.ts +194 -0
- package/src/analysis/search/pattern.ts +24 -13
- package/src/analysis/search/ripgrep.ts +92 -7
- package/src/app/app.ts +6 -1
- package/src/config.ts +42 -0
- package/src/extension.ts +9 -1
- package/src/session/capability-adapter.ts +218 -0
- package/src/session/session.ts +106 -1
- package/src/session/target-workflow.ts +430 -0
- package/src/substrate/lsp/diagnostic-injection.ts +0 -15
- package/src/substrate/lsp/settings.ts +101 -175
- package/src/tool/find/execute.ts +23 -10
- package/src/tool/find/orchestrate.ts +67 -54
- package/src/tool/find/semantic-search.ts +30 -16
- package/src/tool/graph/collect-relation.ts +2 -1
- package/src/tool/graph/execute.ts +40 -12
- package/src/tool/graph/markdown-base.ts +5 -37
- package/src/tool/graph/orchestrate.ts +9 -35
- package/src/tool/graph/tui.ts +2 -0
- package/src/tool/guidance.ts +27 -38
- package/src/tool/health/markdown.ts +12 -70
- package/src/tool/health/orchestrate.ts +5 -13
- package/src/tool/impact/analysis.ts +0 -27
- package/src/tool/impact/change-set-impact.ts +3 -2
- package/src/tool/impact/execute.ts +27 -0
- package/src/tool/impact/file-level-impact.ts +3 -2
- package/src/tool/impact/result.ts +2 -21
- package/src/tool/impact/single-impact.ts +3 -2
- package/src/tool/infra/error-results.ts +18 -196
- package/src/tool/infra/pipeline.ts +24 -1
- package/src/tool/inspect/markdown.ts +4 -41
- package/src/tool/inspect/orchestrate.ts +27 -28
- package/src/tool/orientation/mode.ts +53 -2
- package/src/tool/orientation/orchestrate.ts +5 -8
- package/src/tool/orientation/precise-target.ts +65 -69
- package/src/tool/refactor-apply/orchestrate.ts +2 -7
- package/src/tool/refactor-plan/orchestrate.ts +31 -39
- package/src/tool/resolve/markdown.ts +5 -6
- package/src/tool/resolve/orchestrate.ts +7 -103
- package/src/tool/result/errors.ts +199 -0
- package/src/tool/result/find.ts +29 -0
- package/src/tool/result/graph.ts +93 -0
- package/src/tool/result/health.ts +94 -0
- package/src/tool/result/impact.ts +50 -0
- package/src/tool/result/inspect.ts +60 -0
- package/src/tool/result/orientation.ts +30 -0
- package/src/tool/result/refactor.ts +35 -0
- package/src/tool/result/resolve.ts +114 -0
- package/src/tool/result/types.ts +191 -0
- package/src/tool/schemas.ts +39 -28
- package/src/types/details.ts +17 -185
- package/src/ui/tui/common.ts +45 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -188
- package/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -188
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -188
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -188
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -188
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +0 -188
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// Directory-local instruction file discovery and rendering for code_orientation.
|
|
2
|
+
|
|
3
|
+
import { readFileSync, statSync } from "node:fs";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { isWithinOrEqual } from "@mrclrchtr/supi-core/project";
|
|
6
|
+
|
|
7
|
+
export const INSTRUCTION_FILE_LINE_LIMIT = 200;
|
|
8
|
+
|
|
9
|
+
/** Directory-local instruction file selected for orientation output. */
|
|
10
|
+
export interface InstructionFileMatch {
|
|
11
|
+
/** Absolute file path. */
|
|
12
|
+
absolutePath: string;
|
|
13
|
+
/** Workspace-relative file path. */
|
|
14
|
+
relativePath: string;
|
|
15
|
+
/** Absolute containing directory. */
|
|
16
|
+
directory: string;
|
|
17
|
+
/** Workspace-relative containing directory. */
|
|
18
|
+
relativeDirectory: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Agent-visible instruction file snippet plus metadata for details. */
|
|
22
|
+
export interface RenderedInstructionFile {
|
|
23
|
+
path: string;
|
|
24
|
+
directory: string;
|
|
25
|
+
shownLines: number;
|
|
26
|
+
totalLines: number;
|
|
27
|
+
truncated: boolean;
|
|
28
|
+
content: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Structured metadata stored in code_orientation details. */
|
|
32
|
+
export interface InstructionFilesMetadata {
|
|
33
|
+
files: Array<Omit<RenderedInstructionFile, "content">>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Find configured instruction files for a directory focus.
|
|
38
|
+
*
|
|
39
|
+
* Walks from cwd to the focused directory (shallowest first, deepest last),
|
|
40
|
+
* selecting the first configured file name that exists in each directory.
|
|
41
|
+
*/
|
|
42
|
+
export function findInstructionFilesForDirectory(options: {
|
|
43
|
+
directory: string;
|
|
44
|
+
cwd: string;
|
|
45
|
+
fileNames: string[];
|
|
46
|
+
nativeContextPaths: Set<string>;
|
|
47
|
+
surfacedDirectories: Set<string>;
|
|
48
|
+
}): InstructionFileMatch[] {
|
|
49
|
+
const cwd = path.resolve(options.cwd);
|
|
50
|
+
const directory = path.resolve(options.directory);
|
|
51
|
+
const fileNames = options.fileNames.filter((name) => name.trim().length > 0);
|
|
52
|
+
if (fileNames.length === 0) return [];
|
|
53
|
+
if (!isDirectoryWithinCwd(directory, cwd)) return [];
|
|
54
|
+
|
|
55
|
+
const dirs = collectDirsShallowestFirst(directory, cwd);
|
|
56
|
+
const matches: InstructionFileMatch[] = [];
|
|
57
|
+
|
|
58
|
+
for (const dir of dirs) {
|
|
59
|
+
if (options.surfacedDirectories.has(dir)) continue;
|
|
60
|
+
const match = findFirstInstructionFile(dir, cwd, fileNames);
|
|
61
|
+
if (!match) continue;
|
|
62
|
+
if (options.nativeContextPaths.has(match.absolutePath)) continue;
|
|
63
|
+
matches.push(match);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return matches;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isDirectoryWithinCwd(directory: string, cwd: string): boolean {
|
|
70
|
+
try {
|
|
71
|
+
return statSync(directory).isDirectory() && isWithinOrEqual(cwd, directory);
|
|
72
|
+
} catch {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function collectDirsShallowestFirst(directory: string, cwd: string): string[] {
|
|
78
|
+
const dirs: string[] = [];
|
|
79
|
+
let current = directory;
|
|
80
|
+
|
|
81
|
+
while (isWithinOrEqual(cwd, current)) {
|
|
82
|
+
dirs.push(current);
|
|
83
|
+
if (current === cwd) break;
|
|
84
|
+
const parent = path.dirname(current);
|
|
85
|
+
if (parent === current) break;
|
|
86
|
+
current = parent;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return dirs.reverse();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function findFirstInstructionFile(
|
|
93
|
+
dir: string,
|
|
94
|
+
cwd: string,
|
|
95
|
+
fileNames: string[],
|
|
96
|
+
): InstructionFileMatch | null {
|
|
97
|
+
for (const fileName of fileNames) {
|
|
98
|
+
const candidate = path.join(dir, fileName);
|
|
99
|
+
if (!isFile(candidate)) continue;
|
|
100
|
+
return {
|
|
101
|
+
absolutePath: candidate,
|
|
102
|
+
relativePath: path.relative(cwd, candidate),
|
|
103
|
+
directory: dir,
|
|
104
|
+
relativeDirectory: path.relative(cwd, dir) || ".",
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Render instruction files as a markdown section and structured metadata. */
|
|
111
|
+
export function renderInstructionFiles(
|
|
112
|
+
files: InstructionFileMatch[],
|
|
113
|
+
lineLimit = INSTRUCTION_FILE_LINE_LIMIT,
|
|
114
|
+
): { markdown: string; metadata: InstructionFilesMetadata } | null {
|
|
115
|
+
const rendered = files.map((file) => renderInstructionFile(file, lineLimit)).filter(isRendered);
|
|
116
|
+
if (rendered.length === 0) return null;
|
|
117
|
+
|
|
118
|
+
const lines: string[] = [];
|
|
119
|
+
lines.push("## Instructions");
|
|
120
|
+
lines.push("");
|
|
121
|
+
for (const file of rendered) {
|
|
122
|
+
lines.push(`### ${file.path}`);
|
|
123
|
+
lines.push("");
|
|
124
|
+
lines.push(file.content);
|
|
125
|
+
if (file.truncated) {
|
|
126
|
+
lines.push("");
|
|
127
|
+
lines.push(
|
|
128
|
+
`_Instruction file truncated to ${file.shownLines} of ${file.totalLines} lines. Use \`read\` on \`${file.path}\` for the full file._`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
lines.push("");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
markdown: lines.join("\n").trimEnd(),
|
|
136
|
+
metadata: {
|
|
137
|
+
files: rendered.map(({ content: _content, ...metadata }) => metadata),
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function isFile(candidate: string): boolean {
|
|
143
|
+
try {
|
|
144
|
+
return statSync(candidate).isFile();
|
|
145
|
+
} catch {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function renderInstructionFile(
|
|
151
|
+
file: InstructionFileMatch,
|
|
152
|
+
lineLimit: number,
|
|
153
|
+
): RenderedInstructionFile | null {
|
|
154
|
+
try {
|
|
155
|
+
const content = readFileSync(file.absolutePath, "utf-8").trim();
|
|
156
|
+
if (!content) return null;
|
|
157
|
+
|
|
158
|
+
const lines = content.split("\n");
|
|
159
|
+
const shown = lines.slice(0, lineLimit);
|
|
160
|
+
return {
|
|
161
|
+
path: file.relativePath,
|
|
162
|
+
directory: file.relativeDirectory,
|
|
163
|
+
shownLines: shown.length,
|
|
164
|
+
totalLines: lines.length,
|
|
165
|
+
truncated: lines.length > shown.length,
|
|
166
|
+
content: shown.join("\n"),
|
|
167
|
+
};
|
|
168
|
+
} catch {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function isRendered(value: RenderedInstructionFile | null): value is RenderedInstructionFile {
|
|
174
|
+
return value !== null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Insert instruction markdown after the opening title/summary block of a brief. */
|
|
178
|
+
export function insertInstructionsNearTop(content: string, instructionsMarkdown: string): string {
|
|
179
|
+
const lines = content.split("\n");
|
|
180
|
+
const insertAt = findFirstSectionIndexAfterTitle(lines);
|
|
181
|
+
const before = lines.slice(0, insertAt).join("\n").trimEnd();
|
|
182
|
+
const after = lines.slice(insertAt).join("\n").trimStart();
|
|
183
|
+
|
|
184
|
+
if (!before) return `${instructionsMarkdown}\n\n${after}`.trimEnd();
|
|
185
|
+
if (!after) return `${before}\n\n${instructionsMarkdown}`.trimEnd();
|
|
186
|
+
return `${before}\n\n${instructionsMarkdown}\n\n${after}`.trimEnd();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function findFirstSectionIndexAfterTitle(lines: string[]): number {
|
|
190
|
+
for (let i = 1; i < lines.length; i++) {
|
|
191
|
+
if (lines[i].startsWith("## ")) return i;
|
|
192
|
+
}
|
|
193
|
+
return lines.length;
|
|
194
|
+
}
|
|
@@ -64,7 +64,7 @@ export function isStructuredPatternKind(kind: string | undefined): kind is Struc
|
|
|
64
64
|
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: enumeration-interrupted, cap, timeout, and error branches are each necessary
|
|
65
65
|
export async function getStructuredPatternMatches(
|
|
66
66
|
params: StructuredPatternParams,
|
|
67
|
-
scopePath: string,
|
|
67
|
+
scopePath: string | readonly string[],
|
|
68
68
|
cwd: string,
|
|
69
69
|
relScope: string,
|
|
70
70
|
structural: StructuralSubstrate,
|
|
@@ -143,7 +143,10 @@ interface FileEnumeration {
|
|
|
143
143
|
* Enumerate all tree-sitter-supported source files in scopePath using rg --files.
|
|
144
144
|
* Returns null if ripgrep is not available.
|
|
145
145
|
*/
|
|
146
|
-
function enumerateSourceFiles(
|
|
146
|
+
function enumerateSourceFiles(
|
|
147
|
+
scopePath: string | readonly string[],
|
|
148
|
+
cwd: string,
|
|
149
|
+
): FileEnumeration | null {
|
|
147
150
|
const extensions = getSupportedExtensions();
|
|
148
151
|
// Strip leading dots — ripgrep -g expects ".ext" without the dot prefix
|
|
149
152
|
const globPattern = `*.{${Array.from(extensions)
|
|
@@ -151,18 +154,14 @@ function enumerateSourceFiles(scopePath: string, cwd: string): FileEnumeration |
|
|
|
151
154
|
.join(",")}}`;
|
|
152
155
|
|
|
153
156
|
try {
|
|
154
|
-
const output = execFileSync("rg", ["--files", "-g", globPattern, scopePath], {
|
|
157
|
+
const output = execFileSync("rg", ["--files", "-g", globPattern, ...scopePathArgs(scopePath)], {
|
|
155
158
|
encoding: "utf-8",
|
|
156
159
|
cwd,
|
|
157
160
|
timeout: 5000,
|
|
158
161
|
stdio: ["pipe", "pipe", "pipe"],
|
|
159
162
|
});
|
|
160
163
|
return {
|
|
161
|
-
files: output
|
|
162
|
-
.split("\n")
|
|
163
|
-
.map((line) => line.trim())
|
|
164
|
-
.filter((line) => line.length > 0)
|
|
165
|
-
.sort((a, b) => a.localeCompare(b)),
|
|
164
|
+
files: normalizeEnumeratedFiles(output),
|
|
166
165
|
interrupted: false,
|
|
167
166
|
};
|
|
168
167
|
} catch (err: unknown) {
|
|
@@ -174,11 +173,7 @@ function enumerateSourceFiles(scopePath: string, cwd: string): FileEnumeration |
|
|
|
174
173
|
const stdout = typeof err.stdout === "string" ? err.stdout : "";
|
|
175
174
|
const wasKilled = (err as { killed?: boolean }).killed === true;
|
|
176
175
|
return {
|
|
177
|
-
files: stdout
|
|
178
|
-
.split("\n")
|
|
179
|
-
.map((line) => line.trim())
|
|
180
|
-
.filter((line) => line.length > 0)
|
|
181
|
-
.sort((a, b) => a.localeCompare(b)),
|
|
176
|
+
files: normalizeEnumeratedFiles(stdout),
|
|
182
177
|
interrupted: wasKilled,
|
|
183
178
|
};
|
|
184
179
|
}
|
|
@@ -186,6 +181,22 @@ function enumerateSourceFiles(scopePath: string, cwd: string): FileEnumeration |
|
|
|
186
181
|
}
|
|
187
182
|
}
|
|
188
183
|
|
|
184
|
+
function scopePathArgs(scopePath: string | readonly string[]): string[] {
|
|
185
|
+
const paths = Array.isArray(scopePath) ? scopePath : [scopePath];
|
|
186
|
+
return paths.length > 0 ? [...paths] : ["."];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function normalizeEnumeratedFiles(output: string): string[] {
|
|
190
|
+
return [
|
|
191
|
+
...new Set(
|
|
192
|
+
output
|
|
193
|
+
.split("\n")
|
|
194
|
+
.map((line) => line.trim())
|
|
195
|
+
.filter((line) => line.length > 0),
|
|
196
|
+
),
|
|
197
|
+
].sort((a, b) => a.localeCompare(b));
|
|
198
|
+
}
|
|
199
|
+
|
|
189
200
|
// biome-ignore lint/complexity/useMaxParams: helper takes explicit collection inputs to avoid intermediate objects in the hot path
|
|
190
201
|
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: kind-specific tree-sitter matching is clearest as one helper
|
|
191
202
|
async function collectMatchesForFile(
|
|
@@ -47,6 +47,11 @@ export function isInProjectPath(filePath: string, cwd: string): boolean {
|
|
|
47
47
|
/** Result of resolving a user-provided `scope` value to an absolute path. */
|
|
48
48
|
export type ScopeResolution = { kind: "ok"; path: string } | { kind: "error"; reason: string };
|
|
49
49
|
|
|
50
|
+
/** Result of resolving a code_find `scope` value to one or more absolute paths. */
|
|
51
|
+
export type ScopeSetResolution =
|
|
52
|
+
| { kind: "ok"; paths: string[]; display: string | null }
|
|
53
|
+
| { kind: "error"; reason: string };
|
|
54
|
+
|
|
50
55
|
/**
|
|
51
56
|
* Resolve a `scope` value to an absolute path using pi scope semantics:
|
|
52
57
|
* - strip leading `@`
|
|
@@ -61,6 +66,55 @@ export function resolveScope(scope: string | undefined, cwd: string): ScopeResol
|
|
|
61
66
|
reason: `Scope accepts a single directory or file path, not multiple: \`${scope}\``,
|
|
62
67
|
};
|
|
63
68
|
}
|
|
69
|
+
return resolveSingleScope(scope, cwd);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Resolve a code_find scope input to one or more absolute paths.
|
|
74
|
+
*
|
|
75
|
+
* `code_find` is intentionally more flexible than other code-intelligence tools:
|
|
76
|
+
* it accepts `scope: ["docs", "packages"]` and also splits delimiter-separated
|
|
77
|
+
* strings such as `"docs packages"` only when no exact path by that name exists.
|
|
78
|
+
*/
|
|
79
|
+
export function resolveScopeSet(
|
|
80
|
+
scope: string | readonly string[] | undefined,
|
|
81
|
+
cwd: string,
|
|
82
|
+
): ScopeSetResolution {
|
|
83
|
+
if (scope === undefined) {
|
|
84
|
+
return { kind: "ok", paths: [cwd], display: null };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const labels = typeof scope === "string" ? splitScopeString(scope, cwd) : [...scope];
|
|
88
|
+
if (labels.length === 0) {
|
|
89
|
+
return { kind: "error", reason: "Scope must include at least one directory or file path." };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const resolved: Array<{ label: string; path: string }> = [];
|
|
93
|
+
for (const label of labels) {
|
|
94
|
+
const trimmed = label.trim();
|
|
95
|
+
if (!trimmed) {
|
|
96
|
+
return { kind: "error", reason: "Scope must not include empty path entries." };
|
|
97
|
+
}
|
|
98
|
+
const single = resolveSingleScope(trimmed, cwd);
|
|
99
|
+
if (single.kind === "error") return single;
|
|
100
|
+
resolved.push({ label: trimmed, path: single.path });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const byPath = new Map<string, string>();
|
|
104
|
+
for (const entry of resolved) {
|
|
105
|
+
if (!byPath.has(entry.path)) byPath.set(entry.path, entry.label);
|
|
106
|
+
}
|
|
107
|
+
const paths = [...byPath.keys()];
|
|
108
|
+
const uniqueLabels = paths.map((p) => byPath.get(p) ?? p);
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
kind: "ok",
|
|
112
|
+
paths,
|
|
113
|
+
display: uniqueLabels.length > 0 ? uniqueLabels.join(", ") : null,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function resolveSingleScope(scope: string, cwd: string): ScopeResolution {
|
|
64
118
|
const resolved = normalizePath(scope, cwd);
|
|
65
119
|
if (!existsSync(resolved)) {
|
|
66
120
|
return { kind: "error", reason: `Scope path not found: \`${scope}\`` };
|
|
@@ -68,6 +122,20 @@ export function resolveScope(scope: string | undefined, cwd: string): ScopeResol
|
|
|
68
122
|
return { kind: "ok", path: resolved };
|
|
69
123
|
}
|
|
70
124
|
|
|
125
|
+
function splitScopeString(scope: string, cwd: string): string[] {
|
|
126
|
+
const trimmed = scope.trim();
|
|
127
|
+
if (!trimmed) return [];
|
|
128
|
+
|
|
129
|
+
const exact = resolveSingleScope(trimmed, cwd);
|
|
130
|
+
if (exact.kind === "ok") return [trimmed];
|
|
131
|
+
|
|
132
|
+
const parts = trimmed
|
|
133
|
+
.split(/[,;\s]+/)
|
|
134
|
+
.map((part) => part.trim())
|
|
135
|
+
.filter((part) => part.length > 0);
|
|
136
|
+
return parts.length > 1 ? parts : [trimmed];
|
|
137
|
+
}
|
|
138
|
+
|
|
71
139
|
/** Escape regex special characters. */
|
|
72
140
|
export function escapeRegex(s: string): string {
|
|
73
141
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -152,7 +220,7 @@ export class RipgrepAbortedError extends Error {
|
|
|
152
220
|
*/
|
|
153
221
|
export async function runRipgrep(
|
|
154
222
|
pattern: string,
|
|
155
|
-
scopePath: string,
|
|
223
|
+
scopePath: string | readonly string[],
|
|
156
224
|
cwd: string,
|
|
157
225
|
opts?: RipgrepOptions,
|
|
158
226
|
): Promise<RgMatch[]> {
|
|
@@ -166,7 +234,7 @@ export async function runRipgrep(
|
|
|
166
234
|
*/
|
|
167
235
|
export async function runRipgrepDetailed(
|
|
168
236
|
pattern: string,
|
|
169
|
-
scopePath: string,
|
|
237
|
+
scopePath: string | readonly string[],
|
|
170
238
|
cwd: string,
|
|
171
239
|
opts?: RipgrepOptions,
|
|
172
240
|
): Promise<RipgrepRunResult> {
|
|
@@ -195,16 +263,16 @@ export async function runRipgrepDetailed(
|
|
|
195
263
|
};
|
|
196
264
|
case "ok":
|
|
197
265
|
case "nomatch":
|
|
198
|
-
return { matches: parseRgJson(proc.stdout, filter) };
|
|
266
|
+
return { matches: dedupeMatches(parseRgJson(proc.stdout, filter)) };
|
|
199
267
|
case "timeout":
|
|
200
268
|
// Timeout: yield any partial stdout matches with no error surfaced — an
|
|
201
269
|
// improvement over the prior execFileSync path, which discarded partial
|
|
202
270
|
// output on timeout (the timeout error lacked a `status`, so the old
|
|
203
271
|
// handleRipgrepError returned an empty match set).
|
|
204
|
-
return { matches: proc.stdout ? parseRgJson(proc.stdout, filter) : [] };
|
|
272
|
+
return { matches: proc.stdout ? dedupeMatches(parseRgJson(proc.stdout, filter)) : [] };
|
|
205
273
|
case "error":
|
|
206
274
|
return {
|
|
207
|
-
matches: proc.stdout ? parseRgJson(proc.stdout, filter) : [],
|
|
275
|
+
matches: proc.stdout ? dedupeMatches(parseRgJson(proc.stdout, filter)) : [],
|
|
208
276
|
...(proc.stderr.trim() ? { error: proc.stderr.trim() } : {}),
|
|
209
277
|
};
|
|
210
278
|
}
|
|
@@ -212,7 +280,7 @@ export async function runRipgrepDetailed(
|
|
|
212
280
|
|
|
213
281
|
function buildRipgrepArgs(
|
|
214
282
|
pattern: string,
|
|
215
|
-
scopePath: string,
|
|
283
|
+
scopePath: string | readonly string[],
|
|
216
284
|
opts?: { maxMatches?: number; contextLines?: number; literal?: boolean },
|
|
217
285
|
): string[] {
|
|
218
286
|
const args = ["--json", "-m", String(opts?.maxMatches ?? 30)];
|
|
@@ -222,10 +290,15 @@ function buildRipgrepArgs(
|
|
|
222
290
|
if (opts?.literal) {
|
|
223
291
|
args.push("-F");
|
|
224
292
|
}
|
|
225
|
-
args.push("-e", pattern, scopePath);
|
|
293
|
+
args.push("-e", pattern, ...normalizeScopePathArgs(scopePath));
|
|
226
294
|
return args;
|
|
227
295
|
}
|
|
228
296
|
|
|
297
|
+
function normalizeScopePathArgs(scopePath: string | readonly string[]): string[] {
|
|
298
|
+
const paths = Array.isArray(scopePath) ? scopePath : [scopePath];
|
|
299
|
+
return paths.length > 0 ? [...paths] : ["."];
|
|
300
|
+
}
|
|
301
|
+
|
|
229
302
|
/** Discriminated result of a single ripgrep process run (see {@link runRgProcess}). */
|
|
230
303
|
type RgProcessResult =
|
|
231
304
|
| { kind: "ok"; stdout: string; stderr: string; status: number }
|
|
@@ -432,6 +505,18 @@ function parseRgJson(output: string, filterLowSignal: boolean): RgMatch[] {
|
|
|
432
505
|
return matches;
|
|
433
506
|
}
|
|
434
507
|
|
|
508
|
+
function dedupeMatches(matches: RgMatch[]): RgMatch[] {
|
|
509
|
+
const seen = new Set<string>();
|
|
510
|
+
const deduped: RgMatch[] = [];
|
|
511
|
+
for (const match of matches) {
|
|
512
|
+
const key = `${match.file}\u0000${match.line}\u0000${match.text}`;
|
|
513
|
+
if (seen.has(key)) continue;
|
|
514
|
+
seen.add(key);
|
|
515
|
+
deduped.push(match);
|
|
516
|
+
}
|
|
517
|
+
return deduped;
|
|
518
|
+
}
|
|
519
|
+
|
|
435
520
|
/**
|
|
436
521
|
* Minimal interface for a reference-like object with a URI and range start.
|
|
437
522
|
* Used by {@link filterOutDeclaration} to avoid coupling to a specific LspRef type.
|
package/src/app/app.ts
CHANGED
|
@@ -77,8 +77,9 @@ export function createCodeIntelligenceApp(pi: ExtensionAPI): CodeIntelligenceApp
|
|
|
77
77
|
pi.on("session_start", (_event, ctx) => {
|
|
78
78
|
const session = manager.getOrCreateSession(ctx.cwd);
|
|
79
79
|
|
|
80
|
-
// Check if the branch already contains an overview
|
|
80
|
+
// Check if the branch already contains an overview and restore branch-local instruction state.
|
|
81
81
|
const branch = ctx.sessionManager.getBranch();
|
|
82
|
+
session.reconstructInstructionState(branch);
|
|
82
83
|
for (const entry of branch) {
|
|
83
84
|
if (
|
|
84
85
|
entry.type === "custom_message" &&
|
|
@@ -90,6 +91,10 @@ export function createCodeIntelligenceApp(pi: ExtensionAPI): CodeIntelligenceApp
|
|
|
90
91
|
}
|
|
91
92
|
});
|
|
92
93
|
|
|
94
|
+
pi.on("session_compact", (_event, ctx) => {
|
|
95
|
+
manager.getSession(ctx.cwd)?.resetSurfacedInstructionDirs();
|
|
96
|
+
});
|
|
97
|
+
|
|
93
98
|
pi.on("session_shutdown", () => {
|
|
94
99
|
// Clear per-session stores before releasing sessions
|
|
95
100
|
for (const session of manager.allSessions()) {
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Code Intelligence configuration and settings registration.
|
|
2
|
+
|
|
3
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
import { loadSupiConfig } from "@mrclrchtr/supi-core/config";
|
|
5
|
+
import { registerDeclarativeSettings } from "@mrclrchtr/supi-core/settings";
|
|
6
|
+
|
|
7
|
+
const CODE_INTELLIGENCE_SECTION = "code-intelligence";
|
|
8
|
+
|
|
9
|
+
/** User-facing configuration for the code-intelligence extension. */
|
|
10
|
+
export interface CodeIntelligenceConfig extends Record<string, unknown> {
|
|
11
|
+
/** Ordered directory-local instruction file names to surface during directory orientation. */
|
|
12
|
+
instructionFileNames: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Default code-intelligence configuration. */
|
|
16
|
+
export const CODE_INTELLIGENCE_DEFAULTS: CodeIntelligenceConfig = {
|
|
17
|
+
instructionFileNames: ["CLAUDE.md", "AGENTS.md"],
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/** Load merged code-intelligence configuration for a workspace. */
|
|
21
|
+
export function loadCodeIntelligenceConfig(cwd: string, homeDir?: string): CodeIntelligenceConfig {
|
|
22
|
+
return loadSupiConfig(CODE_INTELLIGENCE_SECTION, cwd, CODE_INTELLIGENCE_DEFAULTS, { homeDir });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Register code-intelligence settings with the shared SuPi settings registry. */
|
|
26
|
+
export function registerCodeIntelligenceSettings(pi: ExtensionAPI, homeDir?: string): void {
|
|
27
|
+
registerDeclarativeSettings(pi, {
|
|
28
|
+
id: CODE_INTELLIGENCE_SECTION,
|
|
29
|
+
label: "Code Intelligence",
|
|
30
|
+
section: CODE_INTELLIGENCE_SECTION,
|
|
31
|
+
defaults: CODE_INTELLIGENCE_DEFAULTS,
|
|
32
|
+
fields: [
|
|
33
|
+
{
|
|
34
|
+
kind: "stringList" as const,
|
|
35
|
+
key: "instructionFileNames",
|
|
36
|
+
label: "Instruction File Names",
|
|
37
|
+
description: "Directory-local instruction file names shown by directory orientation",
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
...(homeDir ? { homeDir } : {}),
|
|
41
|
+
});
|
|
42
|
+
}
|
package/src/extension.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
gatherCoverageEvalInput,
|
|
9
9
|
} from "./analysis/coverage/coverage-warnings.ts";
|
|
10
10
|
import { createCodeIntelligenceApp } from "./app/app.ts";
|
|
11
|
+
import { registerCodeIntelligenceSettings } from "./config.ts";
|
|
11
12
|
import type { WorkspaceCodeIntelligenceSession } from "./session/session.ts";
|
|
12
13
|
import { registerDiagnosticInjectionHandlers } from "./substrate/lsp/diagnostic-injection.ts";
|
|
13
14
|
import { registerLspSessionLifecycle } from "./substrate/lsp/lifecycle.ts";
|
|
@@ -38,7 +39,8 @@ export default function codeIntelligenceExtension(
|
|
|
38
39
|
const tsState = createTsAdapterState();
|
|
39
40
|
|
|
40
41
|
// ── Substrate wiring ──────────────────────────────────────────────
|
|
41
|
-
|
|
42
|
+
registerCodeIntelligenceSettings(pi);
|
|
43
|
+
registerLspSettings(pi);
|
|
42
44
|
registerLspSessionLifecycle(pi, lspState);
|
|
43
45
|
registerLspAwareToolOverrides(pi, lspState);
|
|
44
46
|
registerDiagnosticInjectionHandlers(pi, lspState);
|
|
@@ -64,6 +66,12 @@ export default function codeIntelligenceExtension(
|
|
|
64
66
|
registerCiStatusCommand(pi);
|
|
65
67
|
registerLspFooterContribution(lspState);
|
|
66
68
|
|
|
69
|
+
// ── Native context path capture for instruction-file dedup ─────────
|
|
70
|
+
pi.on("before_agent_start", (event, ctx) => {
|
|
71
|
+
const session = app.getSession(ctx.cwd) ?? app.createSession(ctx.cwd);
|
|
72
|
+
session.captureNativeInstructionPaths(event.systemPromptOptions.contextFiles ?? []);
|
|
73
|
+
});
|
|
74
|
+
|
|
67
75
|
// ── Coverage warning emission ─────────────────────────────────────
|
|
68
76
|
pi.on(
|
|
69
77
|
"before_agent_start",
|