supipowers 0.1.0 → 0.1.4
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/bin/install.mjs +41 -56
- package/package.json +1 -1
- package/src/commands/config.ts +1 -1
- package/src/config/defaults.ts +0 -1
- package/src/config/schema.ts +0 -1
- package/src/lsp/detector.ts +17 -22
- package/src/lsp/setup-guide.ts +10 -41
- package/src/types.ts +0 -1
package/bin/install.mjs
CHANGED
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
note,
|
|
13
13
|
} from "@clack/prompts";
|
|
14
14
|
import { spawnSync } from "node:child_process";
|
|
15
|
-
import {
|
|
16
|
-
import { resolve,
|
|
15
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
16
|
+
import { resolve, dirname, join } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
18
18
|
import { homedir } from "node:os";
|
|
19
19
|
|
|
@@ -59,53 +59,29 @@ function findOmpBinary() {
|
|
|
59
59
|
const LSP_SERVERS = [
|
|
60
60
|
{
|
|
61
61
|
language: "TypeScript / JavaScript",
|
|
62
|
-
extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"],
|
|
63
62
|
server: "typescript-language-server",
|
|
64
63
|
installCmd: "bun add -g typescript-language-server typescript",
|
|
65
64
|
},
|
|
66
65
|
{
|
|
67
66
|
language: "Python",
|
|
68
|
-
extensions: [".py"],
|
|
69
67
|
server: "pyright",
|
|
70
68
|
installCmd: "pip install pyright",
|
|
71
69
|
},
|
|
72
70
|
{
|
|
73
71
|
language: "Rust",
|
|
74
|
-
extensions: [".rs"],
|
|
75
72
|
server: "rust-analyzer",
|
|
76
73
|
installCmd: "rustup component add rust-analyzer",
|
|
77
74
|
},
|
|
78
75
|
{
|
|
79
76
|
language: "Go",
|
|
80
|
-
extensions: [".go"],
|
|
81
77
|
server: "gopls",
|
|
82
78
|
installCmd: "go install golang.org/x/tools/gopls@latest",
|
|
83
79
|
},
|
|
84
80
|
];
|
|
85
81
|
|
|
86
|
-
function
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
90
|
-
for (const entry of entries) {
|
|
91
|
-
if (entry.isFile()) {
|
|
92
|
-
detected.add(extname(entry.name));
|
|
93
|
-
} else if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
94
|
-
// One level deep
|
|
95
|
-
try {
|
|
96
|
-
const subEntries = readdirSync(join(dir, entry.name), { withFileTypes: true });
|
|
97
|
-
for (const sub of subEntries) {
|
|
98
|
-
if (sub.isFile()) detected.add(extname(sub.name));
|
|
99
|
-
}
|
|
100
|
-
} catch {
|
|
101
|
-
// skip unreadable dirs
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
} catch {
|
|
106
|
-
// skip
|
|
107
|
-
}
|
|
108
|
-
return detected;
|
|
82
|
+
function isInstalled(binary) {
|
|
83
|
+
const result = run("which", [binary]);
|
|
84
|
+
return result.status === 0;
|
|
109
85
|
}
|
|
110
86
|
|
|
111
87
|
// ── Main ─────────────────────────────────────────────────────
|
|
@@ -115,9 +91,12 @@ async function main() {
|
|
|
115
91
|
|
|
116
92
|
// ── Step 1: OMP check ──────────────────────────────────────
|
|
117
93
|
|
|
94
|
+
const ompSpinner = spinner();
|
|
95
|
+
ompSpinner.start("Looking for OMP...");
|
|
118
96
|
let omp = findOmpBinary();
|
|
119
97
|
|
|
120
98
|
if (!omp) {
|
|
99
|
+
ompSpinner.stop("OMP not found");
|
|
121
100
|
note(
|
|
122
101
|
"OMP (oh-my-pi) is an AI coding agent that supipowers extends.\n" +
|
|
123
102
|
"It adds sub-agents, LSP integration, and plugin support to pi.\n" +
|
|
@@ -149,7 +128,7 @@ async function main() {
|
|
|
149
128
|
} else {
|
|
150
129
|
const version = run(omp, ["--version"]);
|
|
151
130
|
const ver = version.stdout?.trim() || "unknown";
|
|
152
|
-
|
|
131
|
+
ompSpinner.stop(`OMP ${ver} detected`);
|
|
153
132
|
}
|
|
154
133
|
|
|
155
134
|
// ── Step 2: Install supipowers ─────────────────────────────
|
|
@@ -178,33 +157,39 @@ async function main() {
|
|
|
178
157
|
|
|
179
158
|
// ── Step 3: LSP setup (optional) ──────────────────────────
|
|
180
159
|
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
160
|
+
const lspSpinner = spinner();
|
|
161
|
+
lspSpinner.start("Checking installed LSP servers...");
|
|
162
|
+
const lspOptions = LSP_SERVERS.map((srv) => {
|
|
163
|
+
const installed = isInstalled(srv.server);
|
|
164
|
+
return {
|
|
165
|
+
value: srv,
|
|
166
|
+
label: srv.language,
|
|
167
|
+
hint: installed ? `${srv.server} (installed)` : srv.server,
|
|
168
|
+
};
|
|
169
|
+
});
|
|
170
|
+
const installedCount = lspOptions.filter((o) => o.hint.includes("(installed)")).length;
|
|
171
|
+
lspSpinner.stop(`Found ${installedCount}/${LSP_SERVERS.length} LSP servers installed`);
|
|
172
|
+
|
|
173
|
+
const selected = await multiselect({
|
|
174
|
+
message: "Install LSP servers for better code intelligence?",
|
|
175
|
+
options: lspOptions,
|
|
176
|
+
required: false,
|
|
177
|
+
});
|
|
196
178
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
179
|
+
if (!isCancel(selected) && selected.length > 0) {
|
|
180
|
+
for (const srv of selected) {
|
|
181
|
+
if (isInstalled(srv.server)) {
|
|
182
|
+
note(`${srv.server} is already installed, skipping.`, srv.language);
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
const ls = spinner();
|
|
186
|
+
ls.start(`Installing ${srv.server}...`);
|
|
187
|
+
const [cmd, ...args] = srv.installCmd.split(" ");
|
|
188
|
+
const r = run(cmd, args);
|
|
189
|
+
if (r.status !== 0) {
|
|
190
|
+
ls.stop(`Failed to install ${srv.server} — you can install manually: ${srv.installCmd}`);
|
|
191
|
+
} else {
|
|
192
|
+
ls.stop(`${srv.server} installed`);
|
|
208
193
|
}
|
|
209
194
|
}
|
|
210
195
|
}
|
package/package.json
CHANGED
package/src/commands/config.ts
CHANGED
|
@@ -21,7 +21,7 @@ export function registerConfigCommand(pi: ExtensionAPI): void {
|
|
|
21
21
|
`Max fix retries: ${config.orchestration.maxFixRetries}`,
|
|
22
22
|
`Max nesting depth: ${config.orchestration.maxNestingDepth}`,
|
|
23
23
|
`Model preference: ${config.orchestration.modelPreference}`,
|
|
24
|
-
`LSP
|
|
24
|
+
`LSP setup guide: ${config.lsp.setupGuide}`,
|
|
25
25
|
`Notification verbosity: ${config.notifications.verbosity}`,
|
|
26
26
|
`QA framework: ${config.qa.framework ?? "not detected"}`,
|
|
27
27
|
`Release pipeline: ${config.release.pipeline ?? "not configured"}`,
|
package/src/config/defaults.ts
CHANGED
package/src/config/schema.ts
CHANGED
package/src/lsp/detector.ts
CHANGED
|
@@ -1,36 +1,31 @@
|
|
|
1
1
|
// src/lsp/detector.ts
|
|
2
|
-
import type
|
|
2
|
+
import { LSP_SERVERS, type LspServerEntry } from "./setup-guide.js";
|
|
3
3
|
|
|
4
|
-
export interface
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface LspServerInfo {
|
|
10
|
-
name: string;
|
|
11
|
-
status: "running" | "stopped" | "error";
|
|
12
|
-
fileTypes: string[];
|
|
13
|
-
error?: string;
|
|
4
|
+
export interface LspServerStatus {
|
|
5
|
+
server: LspServerEntry;
|
|
6
|
+
installed: boolean;
|
|
14
7
|
}
|
|
15
8
|
|
|
16
9
|
/**
|
|
17
|
-
* Check LSP
|
|
18
|
-
* Uses pi.exec to call the lsp tool programmatically.
|
|
10
|
+
* Check which LSP servers are installed by looking for their binaries.
|
|
19
11
|
*/
|
|
20
|
-
export async function
|
|
12
|
+
export async function checkInstalledServers(
|
|
21
13
|
exec: (cmd: string, args: string[]) => Promise<{ stdout: string; exitCode: number }>
|
|
22
|
-
): Promise<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
14
|
+
): Promise<LspServerStatus[]> {
|
|
15
|
+
const results: LspServerStatus[] = [];
|
|
16
|
+
for (const server of LSP_SERVERS) {
|
|
17
|
+
try {
|
|
18
|
+
const result = await exec("which", [server.server]);
|
|
19
|
+
results.push({ server, installed: result.exitCode === 0 });
|
|
20
|
+
} catch {
|
|
21
|
+
results.push({ server, installed: false });
|
|
22
|
+
}
|
|
29
23
|
}
|
|
24
|
+
return results;
|
|
30
25
|
}
|
|
31
26
|
|
|
32
27
|
/**
|
|
33
|
-
* Check if LSP is available from the extension context.
|
|
28
|
+
* Check if LSP is available from the OMP extension context at runtime.
|
|
34
29
|
* Reads the active tools list to see if "lsp" is registered.
|
|
35
30
|
*/
|
|
36
31
|
export function isLspAvailable(activeTools: string[]): boolean {
|
package/src/lsp/setup-guide.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// src/lsp/setup-guide.ts
|
|
2
2
|
|
|
3
|
-
export interface
|
|
3
|
+
export interface LspServerEntry {
|
|
4
4
|
language: string;
|
|
5
5
|
server: string;
|
|
6
6
|
installCommand: string;
|
|
7
7
|
notes: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
export const LSP_SERVERS: LspServerEntry[] = [
|
|
11
11
|
{
|
|
12
12
|
language: "TypeScript/JavaScript",
|
|
13
13
|
server: "typescript-language-server",
|
|
@@ -34,47 +34,16 @@ const COMMON_LSP_SERVERS: SetupInstruction[] = [
|
|
|
34
34
|
},
|
|
35
35
|
];
|
|
36
36
|
|
|
37
|
-
/**
|
|
38
|
-
export function
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
s.language.toLowerCase().includes(lang.toLowerCase())
|
|
42
|
-
)
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** Detect project languages from file extensions */
|
|
47
|
-
export function detectProjectLanguages(files: string[]): string[] {
|
|
48
|
-
const extMap: Record<string, string> = {
|
|
49
|
-
".ts": "typescript",
|
|
50
|
-
".tsx": "typescript",
|
|
51
|
-
".js": "javascript",
|
|
52
|
-
".jsx": "javascript",
|
|
53
|
-
".py": "python",
|
|
54
|
-
".rs": "rust",
|
|
55
|
-
".go": "go",
|
|
56
|
-
".java": "java",
|
|
57
|
-
".rb": "ruby",
|
|
58
|
-
".php": "php",
|
|
59
|
-
};
|
|
60
|
-
const languages = new Set<string>();
|
|
61
|
-
for (const file of files) {
|
|
62
|
-
const ext = file.slice(file.lastIndexOf("."));
|
|
63
|
-
if (extMap[ext]) languages.add(extMap[ext]);
|
|
64
|
-
}
|
|
65
|
-
return [...languages];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** Format setup instructions as readable text */
|
|
69
|
-
export function formatSetupGuide(instructions: SetupInstruction[]): string {
|
|
70
|
-
if (instructions.length === 0) {
|
|
71
|
-
return "No LSP setup instructions available for your project languages.";
|
|
37
|
+
/** Format all LSP servers as readable text */
|
|
38
|
+
export function formatSetupGuide(servers: LspServerEntry[] = LSP_SERVERS): string {
|
|
39
|
+
if (servers.length === 0) {
|
|
40
|
+
return "No LSP servers available.";
|
|
72
41
|
}
|
|
73
42
|
const lines = ["LSP Setup Guide:", ""];
|
|
74
|
-
for (const
|
|
75
|
-
lines.push(`## ${
|
|
76
|
-
lines.push(`Install: ${
|
|
77
|
-
lines.push(`Note: ${
|
|
43
|
+
for (const srv of servers) {
|
|
44
|
+
lines.push(`## ${srv.language} — ${srv.server}`);
|
|
45
|
+
lines.push(`Install: ${srv.installCommand}`);
|
|
46
|
+
lines.push(`Note: ${srv.notes}`);
|
|
78
47
|
lines.push("");
|
|
79
48
|
}
|
|
80
49
|
return lines.join("\n");
|