decorated-pi 0.7.1 → 0.7.3
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 +29 -8
- package/commands/dp-settings.ts +3 -3
- package/hooks/compaction.ts +115 -85
- package/hooks/externalize.ts +48 -35
- package/hooks/inject-agents-md.ts +20 -12
- package/hooks/mcp.ts +61 -64
- package/hooks/pi-tool-filter.ts +2 -1
- package/hooks/rtk.ts +24 -96
- package/hooks/skeleton.ts +86 -23
- package/hooks/smart-at.ts +59 -7
- package/hooks/wakatime.ts +16 -28
- package/index.ts +122 -4
- package/package.json +2 -4
- package/settings.ts +164 -4
- package/skills/pi-docs/SKILL.md +13 -0
- package/tools/ask/index.ts +0 -3
- package/tools/lsp/servers.ts +31 -15
- package/tools/lsp/tools.ts +0 -1
- package/tools/mcp/builtin/codegraph.ts +1 -1
- package/tools/mcp/client.ts +1 -1
- package/tools/mcp/config.ts +34 -15
- package/tools/patch/core.ts +10 -0
- package/tools/patch/index.ts +338 -226
- package/tsconfig.json +1 -0
- package/ui/ask.ts +72 -22
- package/ui/module-settings.ts +166 -16
- package/utils/which.ts +109 -0
package/tools/lsp/servers.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* LSP Server Config — language detection, server commands, workspace roots.
|
|
3
3
|
*/
|
|
4
4
|
import { existsSync, readdirSync, type Dirent } from "node:fs";
|
|
5
|
-
import { spawnSync } from "node:child_process";
|
|
6
5
|
import { dirname, extname, isAbsolute, join, resolve } from "node:path";
|
|
7
6
|
import type { DependencyStatus } from "../../hooks/skeleton.js";
|
|
7
|
+
import { getDependencyPath, resolveDependency } from "../../settings.js";
|
|
8
8
|
|
|
9
9
|
// ─── File extension → language mapping ────────────────────────────────────
|
|
10
10
|
|
|
@@ -97,6 +97,16 @@ export function listSupportedLanguages(): string[] {
|
|
|
97
97
|
return Object.keys(LANGUAGE_SERVERS).sort();
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
/** Unique binary names used by builtin LSP servers. Used by the
|
|
101
|
+
* /dp-settings Dependencies UI to know which binaries are configurable. */
|
|
102
|
+
export function listLspBinaryNames(): string[] {
|
|
103
|
+
const seen = new Set<string>();
|
|
104
|
+
for (const lang of Object.keys(LANGUAGE_SERVERS)) {
|
|
105
|
+
seen.add(LANGUAGE_SERVERS[lang].command);
|
|
106
|
+
}
|
|
107
|
+
return [...seen].sort();
|
|
108
|
+
}
|
|
109
|
+
|
|
100
110
|
export function getServerConfig(
|
|
101
111
|
language: string,
|
|
102
112
|
cwd = process.cwd(),
|
|
@@ -104,6 +114,12 @@ export function getServerConfig(
|
|
|
104
114
|
const base = LANGUAGE_SERVERS[language];
|
|
105
115
|
if (!base) return undefined;
|
|
106
116
|
|
|
117
|
+
const override = getDependencyPath(base.command);
|
|
118
|
+
if (override) {
|
|
119
|
+
const resolvedOverride = resolveDependency(base.command, { extendPath: [] });
|
|
120
|
+
return { ...base, command: resolvedOverride ?? override, is_project_local: false };
|
|
121
|
+
}
|
|
122
|
+
|
|
107
123
|
const resolved = resolveLocalBinary(base.command, cwd);
|
|
108
124
|
return { ...base, command: resolved.command, is_project_local: resolved.is_project_local };
|
|
109
125
|
}
|
|
@@ -147,14 +163,16 @@ export function collectLspDependencyStatuses(cwd: string): DependencyStatus[] {
|
|
|
147
163
|
const statuses: DependencyStatus[] = [];
|
|
148
164
|
const seen = new Set<string>();
|
|
149
165
|
for (const language of listSupportedLanguages()) {
|
|
150
|
-
const
|
|
151
|
-
if (!
|
|
152
|
-
seen.add(
|
|
166
|
+
const base = LANGUAGE_SERVERS[language];
|
|
167
|
+
if (!base || seen.has(base.command)) continue;
|
|
168
|
+
seen.add(base.command);
|
|
169
|
+
const path = resolveLspBinary(base.command, cwd);
|
|
153
170
|
statuses.push({
|
|
154
171
|
module: "lsp",
|
|
155
|
-
label:
|
|
156
|
-
state:
|
|
157
|
-
detail:
|
|
172
|
+
label: base.command,
|
|
173
|
+
state: path ? "ok" : "missing",
|
|
174
|
+
detail: base.install_hint,
|
|
175
|
+
path: path ?? undefined,
|
|
158
176
|
});
|
|
159
177
|
}
|
|
160
178
|
return statuses;
|
|
@@ -174,14 +192,12 @@ export function findWorkspaceRoot(
|
|
|
174
192
|
|
|
175
193
|
// ─── Internal helpers ─────────────────────────────────────────────────────
|
|
176
194
|
|
|
177
|
-
function
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
: spawnSync(process.env.SHELL || "sh", ["-lc", `command -v '${command.replace(/'/g, `'"'"'`)}'`], { encoding: "utf-8" });
|
|
184
|
-
return result.status === 0;
|
|
195
|
+
export function lspDependencyExtendPath(cwd = process.cwd()): string[] {
|
|
196
|
+
return [...ancestorDirs(cwd)].map((dir) => join(dir, "node_modules", ".bin"));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function resolveLspBinary(command: string, cwd = process.cwd()): string | null {
|
|
200
|
+
return resolveDependency(command, { extendPath: lspDependencyExtendPath(cwd) });
|
|
185
201
|
}
|
|
186
202
|
|
|
187
203
|
function resolveLocalBinary(
|
package/tools/lsp/tools.ts
CHANGED
|
@@ -69,7 +69,6 @@ function severityLabel(s: number): string {
|
|
|
69
69
|
// ─── Register tools ───────────────────────────────────────────────────────
|
|
70
70
|
|
|
71
71
|
export function registerLspTools(pi: ExtensionAPI, manager: LspServerManager) {
|
|
72
|
-
|
|
73
72
|
// ── lsp_diagnostics ────────────────────────────────────────────────────
|
|
74
73
|
pi.registerTool({
|
|
75
74
|
name: "lsp_diagnostics",
|
|
@@ -14,7 +14,7 @@ export const CODEGRAPH_BUILTIN: Omit<McpServerConfig, "source"> = {
|
|
|
14
14
|
name: "codegraph",
|
|
15
15
|
command: "codegraph",
|
|
16
16
|
args: ["serve", "--mcp"],
|
|
17
|
-
enabled:
|
|
17
|
+
enabled: true,
|
|
18
18
|
description:
|
|
19
19
|
"Local code knowledge graph (colbymchenry/codegraph). Enable via /mcp.",
|
|
20
20
|
canUseInProject: (cwd: string) => fs.existsSync(path.join(cwd, ".codegraph")),
|
package/tools/mcp/client.ts
CHANGED
|
@@ -16,7 +16,7 @@ export class McpConnection {
|
|
|
16
16
|
client: Client;
|
|
17
17
|
transport: StreamableHTTPClientTransport | SSEClientTransport | StdioClientTransport | undefined;
|
|
18
18
|
tools: McpToolSpec[] = [];
|
|
19
|
-
|
|
19
|
+
connected = false;
|
|
20
20
|
|
|
21
21
|
source: string = "unknown";
|
|
22
22
|
|
package/tools/mcp/config.ts
CHANGED
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
import * as fs from "node:fs";
|
|
16
16
|
import * as os from "node:os";
|
|
17
17
|
import * as path from "node:path";
|
|
18
|
-
import {
|
|
19
|
-
import { isModuleEnabled } from "../../settings.js";
|
|
18
|
+
import { isModuleEnabled, resolveDependency } from "../../settings.js";
|
|
20
19
|
import type { DependencyStatus } from "../../hooks/skeleton.js";
|
|
21
20
|
import { BUILTIN_MCP_SERVERS } from "./builtin/index.js";
|
|
22
21
|
|
|
22
|
+
|
|
23
23
|
export { BUILTIN_MCP_SERVERS } from "./builtin/index.js";
|
|
24
24
|
|
|
25
25
|
export interface McpServerConfig {
|
|
@@ -33,6 +33,8 @@ export interface McpServerConfig {
|
|
|
33
33
|
source: "builtin" | "global" | "project";
|
|
34
34
|
/** Optional predicate: return false if this server cannot be used in the given project. */
|
|
35
35
|
canUseInProject?: (cwd: string) => boolean;
|
|
36
|
+
/** Binary/config key before dependency path resolution. */
|
|
37
|
+
dependencyName?: string;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
function globalMcpJsonPath(): string {
|
|
@@ -217,33 +219,50 @@ export function resolveMcpConfigs(cwd: string): McpServerConfig[] {
|
|
|
217
219
|
}
|
|
218
220
|
}
|
|
219
221
|
|
|
220
|
-
return [...byName.values()]
|
|
222
|
+
return [...byName.values()]
|
|
223
|
+
.filter((s) => s.url || s.command)
|
|
224
|
+
.map((s) => {
|
|
225
|
+
// Apply user-configured binary path override (dependencies[cmd].path)
|
|
226
|
+
// last, so it wins over builtin/global/project configs. Only applies
|
|
227
|
+
// to servers that use a command (not URL-based servers).
|
|
228
|
+
if (!s.command) return s;
|
|
229
|
+
const dependencyName = s.command;
|
|
230
|
+
const resolved = resolveMcpBinary(dependencyName);
|
|
231
|
+
return { ...s, dependencyName, command: resolved ?? s.command };
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** Unique binary names used by builtin MCP servers that have a `command`
|
|
236
|
+
* (URL-based servers are excluded — they don't need a binary). */
|
|
237
|
+
export function listMcpBinaryNames(): string[] {
|
|
238
|
+
const seen = new Set<string>();
|
|
239
|
+
for (const s of BUILTIN_MCP_SERVERS) {
|
|
240
|
+
if (s.command) seen.add(s.command);
|
|
241
|
+
}
|
|
242
|
+
return [...seen].sort();
|
|
221
243
|
}
|
|
222
244
|
|
|
223
245
|
export function collectMcpDependencyStatuses(cwd: string): DependencyStatus[] {
|
|
224
246
|
const seen = new Set<string>();
|
|
225
247
|
const statuses: DependencyStatus[] = [];
|
|
226
248
|
for (const cfg of resolveMcpConfigs(cwd)) {
|
|
227
|
-
|
|
228
|
-
|
|
249
|
+
const depName = cfg.dependencyName ?? cfg.command;
|
|
250
|
+
if (!cfg.enabled || !cfg.command || !depName || seen.has(depName)) continue;
|
|
251
|
+
seen.add(depName);
|
|
252
|
+
const resolved = resolveMcpBinary(depName);
|
|
229
253
|
statuses.push({
|
|
230
254
|
module: `mcp:${cfg.name}`,
|
|
231
|
-
label:
|
|
232
|
-
state:
|
|
255
|
+
label: depName,
|
|
256
|
+
state: resolved ? "ok" : "missing",
|
|
233
257
|
detail: `Install the MCP server command for \"${cfg.name}\" or update its config.`,
|
|
258
|
+
path: resolved ?? undefined,
|
|
234
259
|
});
|
|
235
260
|
}
|
|
236
261
|
return statuses;
|
|
237
262
|
}
|
|
238
263
|
|
|
239
|
-
function
|
|
240
|
-
|
|
241
|
-
return fs.existsSync(command);
|
|
242
|
-
}
|
|
243
|
-
const result = process.platform === "win32"
|
|
244
|
-
? spawnSync("where", [command], { encoding: "utf-8" })
|
|
245
|
-
: spawnSync(process.env.SHELL || "sh", ["-lc", `command -v '${command.replace(/'/g, `'"'"'`)}'`], { encoding: "utf-8" });
|
|
246
|
-
return result.status === 0;
|
|
264
|
+
export function resolveMcpBinary(command: string): string | null {
|
|
265
|
+
return resolveDependency(command);
|
|
247
266
|
}
|
|
248
267
|
|
|
249
268
|
function readMcpJsonSafe(filePath: string): Record<string, any> | null {
|
package/tools/patch/core.ts
CHANGED
|
@@ -1521,3 +1521,13 @@ function truncate(s: string, maxLen = 60): string {
|
|
|
1521
1521
|
if (firstLine.length <= maxLen) return firstLine;
|
|
1522
1522
|
return firstLine.slice(0, maxLen - 3) + "...";
|
|
1523
1523
|
}
|
|
1524
|
+
|
|
1525
|
+
// Test exports
|
|
1526
|
+
export const __patchCoreTest = {
|
|
1527
|
+
charOffsetToLine,
|
|
1528
|
+
detectTabWidth,
|
|
1529
|
+
normalizeIndentForFuzzy,
|
|
1530
|
+
truncate,
|
|
1531
|
+
collapseSequentialReplacements,
|
|
1532
|
+
generateReplacementDiff,
|
|
1533
|
+
};
|