decorated-pi 0.3.0 → 0.4.1
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 +58 -34
- package/extensions/file-times.ts +60 -2
- package/extensions/guidance.ts +5 -3
- package/extensions/index.ts +2 -0
- package/extensions/io.ts +210 -29
- package/extensions/lsp/client.ts +181 -428
- package/extensions/lsp/env.ts +45 -12
- package/extensions/lsp/format.ts +102 -237
- package/extensions/lsp/index.ts +8 -11
- package/extensions/lsp/manager.ts +249 -0
- package/extensions/lsp/prompt.ts +3 -42
- package/extensions/lsp/protocol.ts +219 -0
- package/extensions/lsp/servers.ts +80 -160
- package/extensions/lsp/tools.ts +160 -553
- package/extensions/lsp/types.ts +42 -0
- package/extensions/mcp/builtin.ts +126 -0
- package/extensions/mcp/client.ts +106 -0
- package/extensions/mcp/index.ts +123 -0
- package/extensions/patch.ts +475 -77
- package/extensions/providers/ark-coding.ts +2 -0
- package/extensions/safety/detect.ts +20 -744
- package/extensions/safety/entropy.ts +226 -0
- package/extensions/safety/index.ts +1 -93
- package/extensions/safety/patterns.ts +155 -0
- package/extensions/safety/types.ts +50 -0
- package/extensions/settings.ts +8 -0
- package/extensions/slash.ts +161 -7
- package/extensions/smart-at.ts +5 -5
- package/extensions/subdir-agents.ts +43 -13
- package/package.json +2 -3
- package/tsconfig.json +16 -0
- package/extensions/lsp/server-manager.ts +0 -309
- package/extensions/lsp/trust.ts +0 -45
|
@@ -1,237 +1,157 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* LSP Server Config — language detection, server commands, workspace roots
|
|
3
|
-
*
|
|
4
|
-
* Based on @spences10/pi-lsp by Scott Spence
|
|
5
|
-
* https://github.com/spences10/my-pi/tree/main/packages/pi-lsp (MIT License)
|
|
6
|
-
*
|
|
7
|
-
* Modifications: added C/C++ (clangd) and Lua support
|
|
2
|
+
* LSP Server Config — language detection, server commands, workspace roots.
|
|
8
3
|
*/
|
|
9
4
|
import { existsSync } from "node:fs";
|
|
10
5
|
import { dirname, extname, isAbsolute, join, resolve } from "node:path";
|
|
11
6
|
|
|
7
|
+
// ─── File extension → language mapping ────────────────────────────────────
|
|
8
|
+
|
|
12
9
|
const EXTENSION_LANGUAGES: Record<string, string> = {
|
|
13
|
-
".ts": "typescript",
|
|
14
|
-
".
|
|
15
|
-
".
|
|
16
|
-
".
|
|
17
|
-
".
|
|
18
|
-
".
|
|
19
|
-
".
|
|
20
|
-
".cjs": "typescript",
|
|
21
|
-
".c": "c",
|
|
22
|
-
".h": "cpp",
|
|
23
|
-
".cc": "cpp",
|
|
24
|
-
".cp": "cpp",
|
|
25
|
-
".cpp": "cpp",
|
|
26
|
-
".cxx": "cpp",
|
|
27
|
-
".hh": "cpp",
|
|
28
|
-
".hpp": "cpp",
|
|
29
|
-
".hxx": "cpp",
|
|
30
|
-
".ipp": "cpp",
|
|
31
|
-
".ixx": "cpp",
|
|
32
|
-
".tpp": "cpp",
|
|
33
|
-
".py": "python",
|
|
34
|
-
".rs": "rust",
|
|
35
|
-
".go": "go",
|
|
36
|
-
".rb": "ruby",
|
|
37
|
-
".java": "java",
|
|
38
|
-
".lua": "lua",
|
|
39
|
-
".svelte": "svelte",
|
|
10
|
+
".ts": "typescript", ".tsx": "typescript", ".mts": "typescript", ".cts": "typescript",
|
|
11
|
+
".js": "typescript", ".jsx": "typescript", ".mjs": "typescript", ".cjs": "typescript",
|
|
12
|
+
".c": "c", ".h": "cpp", ".cc": "cpp", ".cp": "cpp", ".cpp": "cpp",
|
|
13
|
+
".cxx": "cpp", ".hh": "cpp", ".hpp": "cpp", ".hxx": "cpp",
|
|
14
|
+
".py": "python", ".rs": "rust", ".go": "go", ".rb": "ruby",
|
|
15
|
+
".java": "java", ".lua": "lua", ".svelte": "svelte",
|
|
16
|
+
".json": "json",
|
|
40
17
|
};
|
|
41
18
|
|
|
42
|
-
export
|
|
19
|
+
export interface LanguageConfig {
|
|
43
20
|
language: string;
|
|
44
21
|
command: string;
|
|
45
22
|
args: string[];
|
|
46
23
|
install_hint: string;
|
|
47
24
|
is_project_local?: boolean;
|
|
48
|
-
}
|
|
25
|
+
}
|
|
49
26
|
|
|
50
27
|
const LANGUAGE_SERVERS: Record<string, Omit<LanguageConfig, "is_project_local">> = {
|
|
51
28
|
typescript: {
|
|
52
|
-
language: "typescript",
|
|
53
|
-
command: "typescript-language-server",
|
|
29
|
+
language: "typescript", command: "typescript-language-server",
|
|
54
30
|
args: ["--stdio"],
|
|
55
|
-
install_hint:
|
|
56
|
-
"Install TypeScript LSP with: pnpm add -D typescript typescript-language-server",
|
|
31
|
+
install_hint: "Install TypeScript LSP with: pnpm add -D typescript typescript-language-server",
|
|
57
32
|
},
|
|
58
33
|
c: {
|
|
59
|
-
language: "c",
|
|
60
|
-
command: "clangd",
|
|
61
|
-
args: ["--background-index"],
|
|
34
|
+
language: "c", command: "clangd", args: ["--background-index"],
|
|
62
35
|
install_hint: "Install clangd and ensure the clangd binary is on PATH.",
|
|
63
36
|
},
|
|
64
37
|
cpp: {
|
|
65
|
-
language: "cpp",
|
|
66
|
-
command: "clangd",
|
|
67
|
-
args: ["--background-index"],
|
|
38
|
+
language: "cpp", command: "clangd", args: ["--background-index"],
|
|
68
39
|
install_hint: "Install clangd and ensure the clangd binary is on PATH.",
|
|
69
40
|
},
|
|
70
41
|
python: {
|
|
71
|
-
language: "python",
|
|
72
|
-
command: "pylsp",
|
|
73
|
-
args: [],
|
|
42
|
+
language: "python", command: "pylsp", args: [],
|
|
74
43
|
install_hint: "Install Python LSP with: pip install python-lsp-server",
|
|
75
44
|
},
|
|
76
45
|
rust: {
|
|
77
|
-
language: "rust",
|
|
78
|
-
|
|
79
|
-
args: [],
|
|
80
|
-
install_hint:
|
|
81
|
-
"Install Rust Analyzer and ensure the rust-analyzer binary is on PATH.",
|
|
46
|
+
language: "rust", command: "rust-analyzer", args: [],
|
|
47
|
+
install_hint: "Install Rust Analyzer and ensure the rust-analyzer binary is on PATH.",
|
|
82
48
|
},
|
|
83
49
|
go: {
|
|
84
|
-
language: "go",
|
|
85
|
-
|
|
86
|
-
args: ["serve"],
|
|
87
|
-
install_hint:
|
|
88
|
-
"Install Go LSP with: go install golang.org/x/tools/gopls@latest",
|
|
50
|
+
language: "go", command: "gopls", args: ["serve"],
|
|
51
|
+
install_hint: "Install Go LSP with: go install golang.org/x/tools/gopls@latest",
|
|
89
52
|
},
|
|
90
53
|
ruby: {
|
|
91
|
-
language: "ruby",
|
|
92
|
-
command: "solargraph",
|
|
93
|
-
args: ["stdio"],
|
|
54
|
+
language: "ruby", command: "solargraph", args: ["stdio"],
|
|
94
55
|
install_hint: "Install Ruby LSP with: gem install solargraph",
|
|
95
56
|
},
|
|
96
57
|
java: {
|
|
97
|
-
language: "java",
|
|
98
|
-
|
|
99
|
-
args: [],
|
|
100
|
-
install_hint:
|
|
101
|
-
"Install Eclipse JDT Language Server and ensure the jdtls binary is on PATH.",
|
|
58
|
+
language: "java", command: "jdtls", args: [],
|
|
59
|
+
install_hint: "Install Eclipse JDT Language Server and ensure the jdtls binary is on PATH.",
|
|
102
60
|
},
|
|
103
61
|
lua: {
|
|
104
|
-
language: "lua",
|
|
105
|
-
|
|
106
|
-
args: [],
|
|
107
|
-
install_hint:
|
|
108
|
-
"Install Lua LSP and ensure the lua-language-server binary is on PATH.",
|
|
62
|
+
language: "lua", command: "lua-language-server", args: [],
|
|
63
|
+
install_hint: "Install Lua LSP and ensure the lua-language-server binary is on PATH.",
|
|
109
64
|
},
|
|
110
65
|
svelte: {
|
|
111
|
-
language: "svelte",
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
66
|
+
language: "svelte", command: "svelteserver", args: ["--stdio"],
|
|
67
|
+
install_hint: "Install Svelte LSP with: pnpm add -D svelte-language-server",
|
|
68
|
+
},
|
|
69
|
+
json: {
|
|
70
|
+
language: "json", command: "biome", args: ["lsp-proxy"],
|
|
71
|
+
install_hint: "Install Biome with: pnpm add -D @biomejs/biome",
|
|
116
72
|
},
|
|
117
73
|
};
|
|
118
74
|
|
|
119
75
|
const WORKSPACE_MARKERS = [
|
|
120
|
-
"svelte.config.js",
|
|
121
|
-
"
|
|
122
|
-
"
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
"pyproject.toml",
|
|
126
|
-
"Cargo.toml",
|
|
127
|
-
"go.mod",
|
|
128
|
-
"Gemfile",
|
|
129
|
-
"pom.xml",
|
|
130
|
-
"build.gradle",
|
|
131
|
-
"build.gradle.kts",
|
|
132
|
-
".clangd",
|
|
133
|
-
"compile_commands.json",
|
|
134
|
-
"compile_flags.txt",
|
|
135
|
-
"CMakeLists.txt",
|
|
136
|
-
"meson.build",
|
|
137
|
-
"Makefile",
|
|
76
|
+
"svelte.config.js", "svelte.config.ts", "tsconfig.json", "jsconfig.json",
|
|
77
|
+
"package.json", "pyproject.toml", "Cargo.toml", "go.mod",
|
|
78
|
+
"Gemfile", "pom.xml", "build.gradle", "build.gradle.kts",
|
|
79
|
+
".clangd", "compile_commands.json", "compile_flags.txt",
|
|
80
|
+
"CMakeLists.txt", "meson.build", "Makefile",
|
|
138
81
|
];
|
|
139
82
|
|
|
140
83
|
const REPOSITORY_MARKERS = [
|
|
141
|
-
"pnpm-workspace.yaml",
|
|
142
|
-
"
|
|
143
|
-
"yarn.lock",
|
|
144
|
-
"bun.lockb",
|
|
145
|
-
"bun.lock",
|
|
146
|
-
".git",
|
|
84
|
+
"pnpm-workspace.yaml", "package-lock.json", "yarn.lock",
|
|
85
|
+
"bun.lockb", "bun.lock", ".git",
|
|
147
86
|
];
|
|
148
87
|
|
|
149
|
-
|
|
150
|
-
return EXTENSION_LANGUAGES[extname(file_path).toLowerCase()];
|
|
151
|
-
}
|
|
88
|
+
// ─── Public API ───────────────────────────────────────────────────────────
|
|
152
89
|
|
|
153
|
-
export function
|
|
154
|
-
return
|
|
90
|
+
export function detectLanguage(filePath: string): string | undefined {
|
|
91
|
+
return EXTENSION_LANGUAGES[extname(filePath).toLowerCase()];
|
|
155
92
|
}
|
|
156
93
|
|
|
157
|
-
function
|
|
158
|
-
|
|
159
|
-
cwd: string = process.cwd()
|
|
160
|
-
): { command: string; is_project_local: boolean } {
|
|
161
|
-
if (
|
|
162
|
-
!command ||
|
|
163
|
-
isAbsolute(command) ||
|
|
164
|
-
command.includes("/") ||
|
|
165
|
-
command.includes("\\")
|
|
166
|
-
) {
|
|
167
|
-
return { command, is_project_local: false };
|
|
168
|
-
}
|
|
169
|
-
for (const dir of ancestor_directories(cwd)) {
|
|
170
|
-
const local_bin = resolve_local_binary(dir, command);
|
|
171
|
-
if (local_bin) {
|
|
172
|
-
return { command: local_bin, is_project_local: true };
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return { command, is_project_local: false };
|
|
94
|
+
export function listSupportedLanguages(): string[] {
|
|
95
|
+
return Object.keys(LANGUAGE_SERVERS).sort();
|
|
176
96
|
}
|
|
177
97
|
|
|
178
|
-
export function
|
|
98
|
+
export function getServerConfig(
|
|
179
99
|
language: string,
|
|
180
|
-
cwd
|
|
100
|
+
cwd = process.cwd(),
|
|
181
101
|
): LanguageConfig | undefined {
|
|
182
102
|
const base = LANGUAGE_SERVERS[language];
|
|
183
103
|
if (!base) return undefined;
|
|
184
|
-
|
|
104
|
+
|
|
105
|
+
const resolved = resolveLocalBinary(base.command, cwd);
|
|
185
106
|
return { ...base, command: resolved.command, is_project_local: resolved.is_project_local };
|
|
186
107
|
}
|
|
187
108
|
|
|
188
|
-
export function
|
|
189
|
-
return
|
|
109
|
+
export function languageIdForFile(filePath: string): string | undefined {
|
|
110
|
+
return detectLanguage(filePath);
|
|
190
111
|
}
|
|
191
112
|
|
|
192
|
-
export function
|
|
193
|
-
|
|
194
|
-
fallback
|
|
113
|
+
export function findWorkspaceRoot(
|
|
114
|
+
filePath: string,
|
|
115
|
+
fallback = process.cwd(),
|
|
195
116
|
): string {
|
|
196
|
-
const start = resolve(dirname(
|
|
197
|
-
const
|
|
198
|
-
if (
|
|
199
|
-
const
|
|
200
|
-
if (
|
|
117
|
+
const start = resolve(dirname(filePath));
|
|
118
|
+
const projectRoot = findNearestMarker(start, WORKSPACE_MARKERS);
|
|
119
|
+
if (projectRoot) return projectRoot;
|
|
120
|
+
const repoRoot = findNearestMarker(start, REPOSITORY_MARKERS);
|
|
121
|
+
if (repoRoot) return repoRoot;
|
|
201
122
|
return resolve(fallback);
|
|
202
123
|
}
|
|
203
124
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
125
|
+
// ─── Internal helpers ─────────────────────────────────────────────────────
|
|
126
|
+
|
|
127
|
+
function resolveLocalBinary(
|
|
128
|
+
command: string,
|
|
129
|
+
cwd: string,
|
|
130
|
+
): { command: string; is_project_local: boolean } {
|
|
131
|
+
if (isAbsolute(command) || command.includes("/") || command.includes("\\")) {
|
|
132
|
+
return { command, is_project_local: false };
|
|
133
|
+
}
|
|
134
|
+
for (const dir of ancestorDirs(cwd)) {
|
|
135
|
+
const localBin = join(dir, "node_modules", ".bin", command);
|
|
136
|
+
if (existsSync(localBin)) return { command: localBin, is_project_local: true };
|
|
137
|
+
if (existsSync(localBin + ".cmd")) return { command: localBin + ".cmd", is_project_local: true };
|
|
138
|
+
}
|
|
139
|
+
return { command, is_project_local: false };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function findNearestMarker(start: string, markers: string[]): string | undefined {
|
|
143
|
+
for (const dir of ancestorDirs(start)) {
|
|
144
|
+
if (markers.some((m) => existsSync(join(dir, m)))) return dir;
|
|
212
145
|
}
|
|
213
146
|
return undefined;
|
|
214
147
|
}
|
|
215
148
|
|
|
216
|
-
function
|
|
217
|
-
const dirs: string[] = [];
|
|
149
|
+
function* ancestorDirs(start: string): Generator<string> {
|
|
218
150
|
let current = resolve(start);
|
|
219
151
|
while (true) {
|
|
220
|
-
|
|
152
|
+
yield current;
|
|
221
153
|
const parent = dirname(current);
|
|
222
154
|
if (parent === current) break;
|
|
223
155
|
current = parent;
|
|
224
156
|
}
|
|
225
|
-
return dirs;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function resolve_local_binary(
|
|
229
|
-
directory: string,
|
|
230
|
-
command: string
|
|
231
|
-
): string | undefined {
|
|
232
|
-
const candidates = [
|
|
233
|
-
join(directory, "node_modules", ".bin", command),
|
|
234
|
-
join(directory, "node_modules", ".bin", `${command}.cmd`),
|
|
235
|
-
];
|
|
236
|
-
return candidates.find((candidate) => existsSync(candidate));
|
|
237
157
|
}
|