@polterware/polter 0.4.2 → 0.5.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 +0 -70
- package/dist/api.js +62 -30
- package/dist/app-HGIGWI7F.js +393 -0
- package/dist/appPanel-EZOHLTBX.js +1365 -0
- package/dist/applier-OEXIUYYO.js +10 -0
- package/dist/chunk-3RG5ZIWI.js +10 -0
- package/dist/chunk-45CQFZU7.js +262 -0
- package/dist/chunk-57CZSEY5.js +5398 -0
- package/dist/chunk-6IBRTRLX.js +257 -0
- package/dist/chunk-AK3NTS3Y.js +220 -0
- package/dist/chunk-BGT5TT2A.js +32 -0
- package/dist/chunk-BIN7BDA2.js +77 -0
- package/dist/chunk-E2B5FFBU.js +81 -0
- package/dist/chunk-EAMHFQKU.js +222 -0
- package/dist/chunk-ELSIHPJL.js +455 -0
- package/dist/{chunk-XCCKD3RZ.js → chunk-GCS7JEYU.js} +7 -3
- package/dist/chunk-GKROVUDG.js +15 -0
- package/dist/chunk-GVIKF6UI.js +738 -0
- package/dist/chunk-JQB2A3CA.js +72 -0
- package/dist/chunk-KEGROLGX.js +50 -0
- package/dist/chunk-OKHPN6X7.js +49 -0
- package/dist/chunk-RVMOIUSL.js +22 -0
- package/dist/chunk-TD6YNU6L.js +22 -0
- package/dist/chunk-U64WZOJ3.js +101 -0
- package/dist/chunk-U6725U7K.js +138 -0
- package/dist/chunk-XNRIN3VM.js +125 -0
- package/dist/chunk-ZU5VZHYD.js +28 -0
- package/dist/commands-BIIWGCVS.js +15 -0
- package/dist/editor-AUFJZ4PE.js +11 -0
- package/dist/engine-EZQ26HDJ.js +11 -0
- package/dist/globalConf-AGMMIKSL.js +7 -0
- package/dist/index.js +49 -7601
- package/dist/ipcServer-HXOPKNBP.js +10 -0
- package/dist/mcp.js +182 -13892
- package/dist/mcpInstaller-J2AGFNWR.js +19 -0
- package/dist/parser-4ZBGSI2U.js +10 -0
- package/dist/planner-ZVBA66V6.js +9 -0
- package/dist/processManager-6T5DBURV.js +37 -0
- package/dist/projectConfig-TRCJS3VI.js +21 -0
- package/dist/skillSetup-ZQEHJ5ZG.js +14 -0
- package/dist/status-QMRCV4XJ.js +8 -0
- package/dist/storage-C3D7TLJW.js +17 -0
- package/dist/toolResolver-A2BUT3NK.js +17 -0
- package/package.json +20 -2
- package/dist/chunk-CWBIXRZP.js +0 -2607
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findProcessesByCwd,
|
|
3
|
+
findRunningByCommand,
|
|
4
|
+
generateProcessId,
|
|
5
|
+
getProcessOutput,
|
|
6
|
+
listProcesses,
|
|
7
|
+
removeProcess,
|
|
8
|
+
startProcess,
|
|
9
|
+
stopProcess
|
|
10
|
+
} from "./chunk-6IBRTRLX.js";
|
|
11
|
+
import {
|
|
12
|
+
existsSync,
|
|
13
|
+
mkdirSync,
|
|
14
|
+
unlinkSync
|
|
15
|
+
} from "./chunk-TD6YNU6L.js";
|
|
16
|
+
|
|
17
|
+
// src/lib/ipcServer.ts
|
|
18
|
+
import net from "net";
|
|
19
|
+
import { dirname } from "path";
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
|
|
22
|
+
// src/lib/ipcProtocol.ts
|
|
23
|
+
var DELIMITER = "\n";
|
|
24
|
+
function serializeMessage(msg) {
|
|
25
|
+
return JSON.stringify(msg) + DELIMITER;
|
|
26
|
+
}
|
|
27
|
+
function parseMessages(buffer) {
|
|
28
|
+
const messages = [];
|
|
29
|
+
let remainder = buffer;
|
|
30
|
+
let idx;
|
|
31
|
+
while ((idx = remainder.indexOf(DELIMITER)) !== -1) {
|
|
32
|
+
const line = remainder.slice(0, idx);
|
|
33
|
+
remainder = remainder.slice(idx + 1);
|
|
34
|
+
if (line.length === 0) continue;
|
|
35
|
+
try {
|
|
36
|
+
messages.push(JSON.parse(line));
|
|
37
|
+
} catch {
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { messages, remainder };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/lib/ipcServer.ts
|
|
44
|
+
var PsStartParams = z.object({
|
|
45
|
+
command: z.string(),
|
|
46
|
+
args: z.array(z.string()).default([]),
|
|
47
|
+
cwd: z.string().default(process.cwd()),
|
|
48
|
+
id: z.string().optional()
|
|
49
|
+
});
|
|
50
|
+
var PsIdParams = z.object({
|
|
51
|
+
id: z.string()
|
|
52
|
+
});
|
|
53
|
+
var PsLogsParams = z.object({
|
|
54
|
+
id: z.string(),
|
|
55
|
+
tail: z.number().optional(),
|
|
56
|
+
stream: z.enum(["stdout", "stderr", "both"]).optional()
|
|
57
|
+
});
|
|
58
|
+
var PsFindByCwdParams = z.object({
|
|
59
|
+
cwd: z.string(),
|
|
60
|
+
filter: z.string().optional()
|
|
61
|
+
});
|
|
62
|
+
var PsFindRunningParams = z.object({
|
|
63
|
+
cwd: z.string(),
|
|
64
|
+
command: z.string(),
|
|
65
|
+
args: z.array(z.string())
|
|
66
|
+
});
|
|
67
|
+
var PsGenerateIdParams = z.object({
|
|
68
|
+
command: z.string(),
|
|
69
|
+
args: z.array(z.string())
|
|
70
|
+
});
|
|
71
|
+
var handlers = {
|
|
72
|
+
"ps.list": () => listProcesses(),
|
|
73
|
+
"ps.start": (params) => {
|
|
74
|
+
const { command, args, cwd, id } = PsStartParams.parse(params);
|
|
75
|
+
return startProcess(id ?? generateProcessId(command, args), command, args, cwd);
|
|
76
|
+
},
|
|
77
|
+
"ps.stop": async (params) => {
|
|
78
|
+
const { id } = PsIdParams.parse(params);
|
|
79
|
+
return stopProcess(id);
|
|
80
|
+
},
|
|
81
|
+
"ps.logs": (params) => {
|
|
82
|
+
const { id, tail, stream } = PsLogsParams.parse(params);
|
|
83
|
+
return getProcessOutput(id, tail, stream);
|
|
84
|
+
},
|
|
85
|
+
"ps.remove": (params) => {
|
|
86
|
+
const { id } = PsIdParams.parse(params);
|
|
87
|
+
removeProcess(id);
|
|
88
|
+
return null;
|
|
89
|
+
},
|
|
90
|
+
"ps.find_by_cwd": (params) => {
|
|
91
|
+
const { cwd, filter } = PsFindByCwdParams.parse(params);
|
|
92
|
+
let processes = findProcessesByCwd(cwd);
|
|
93
|
+
if (filter) {
|
|
94
|
+
const f = filter.toLowerCase();
|
|
95
|
+
processes = processes.filter(
|
|
96
|
+
(p) => (p.command + " " + p.args.join(" ")).toLowerCase().includes(f)
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
return processes;
|
|
100
|
+
},
|
|
101
|
+
"ps.find_running": (params) => {
|
|
102
|
+
const { cwd, command, args } = PsFindRunningParams.parse(params);
|
|
103
|
+
return findRunningByCommand(cwd, command, args) ?? null;
|
|
104
|
+
},
|
|
105
|
+
"ps.generate_id": (params) => {
|
|
106
|
+
const { command, args } = PsGenerateIdParams.parse(params);
|
|
107
|
+
return generateProcessId(command, args);
|
|
108
|
+
},
|
|
109
|
+
status: () => ({ tui: true, pid: process.pid })
|
|
110
|
+
};
|
|
111
|
+
async function handleRequest(req) {
|
|
112
|
+
const handler = handlers[req.method];
|
|
113
|
+
if (!handler) {
|
|
114
|
+
return {
|
|
115
|
+
jsonrpc: "2.0",
|
|
116
|
+
id: req.id,
|
|
117
|
+
error: { code: -32601, message: `Method not found: ${req.method}` }
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
const result = await handler(req.params ?? {});
|
|
122
|
+
return { jsonrpc: "2.0", id: req.id, result };
|
|
123
|
+
} catch (err) {
|
|
124
|
+
return {
|
|
125
|
+
jsonrpc: "2.0",
|
|
126
|
+
id: req.id,
|
|
127
|
+
error: { code: -32e3, message: err.message }
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function createIpcServer(socketPath) {
|
|
132
|
+
let server = null;
|
|
133
|
+
const connections = /* @__PURE__ */ new Set();
|
|
134
|
+
function handleConnection(socket) {
|
|
135
|
+
connections.add(socket);
|
|
136
|
+
let buffer = "";
|
|
137
|
+
socket.on("data", async (data) => {
|
|
138
|
+
buffer += data.toString();
|
|
139
|
+
const { messages, remainder } = parseMessages(buffer);
|
|
140
|
+
buffer = remainder;
|
|
141
|
+
for (const msg of messages) {
|
|
142
|
+
if ("method" in msg) {
|
|
143
|
+
const response = await handleRequest(msg);
|
|
144
|
+
try {
|
|
145
|
+
socket.write(serializeMessage(response));
|
|
146
|
+
} catch {
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
socket.on("close", () => {
|
|
152
|
+
connections.delete(socket);
|
|
153
|
+
});
|
|
154
|
+
socket.on("error", () => {
|
|
155
|
+
connections.delete(socket);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
async function cleanStaleSocket() {
|
|
159
|
+
if (!existsSync(socketPath)) return;
|
|
160
|
+
return new Promise((resolve) => {
|
|
161
|
+
const probe = net.createConnection(socketPath);
|
|
162
|
+
probe.on("connect", () => {
|
|
163
|
+
probe.destroy();
|
|
164
|
+
resolve();
|
|
165
|
+
});
|
|
166
|
+
probe.on("error", () => {
|
|
167
|
+
try {
|
|
168
|
+
unlinkSync(socketPath);
|
|
169
|
+
} catch {
|
|
170
|
+
}
|
|
171
|
+
resolve();
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
async start() {
|
|
177
|
+
mkdirSync(dirname(socketPath), { recursive: true });
|
|
178
|
+
await cleanStaleSocket();
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
server = net.createServer(handleConnection);
|
|
181
|
+
server.on("error", (err) => {
|
|
182
|
+
if (err.code === "EADDRINUSE") {
|
|
183
|
+
try {
|
|
184
|
+
unlinkSync(socketPath);
|
|
185
|
+
} catch {
|
|
186
|
+
}
|
|
187
|
+
server.listen(socketPath, () => resolve());
|
|
188
|
+
} else {
|
|
189
|
+
reject(err);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
server.listen(socketPath, () => resolve());
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
async stop() {
|
|
196
|
+
for (const conn of connections) {
|
|
197
|
+
conn.destroy();
|
|
198
|
+
}
|
|
199
|
+
connections.clear();
|
|
200
|
+
return new Promise((resolve) => {
|
|
201
|
+
if (!server) {
|
|
202
|
+
resolve();
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
server.close(() => {
|
|
206
|
+
try {
|
|
207
|
+
unlinkSync(socketPath);
|
|
208
|
+
} catch {
|
|
209
|
+
}
|
|
210
|
+
server = null;
|
|
211
|
+
resolve();
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export {
|
|
219
|
+
serializeMessage,
|
|
220
|
+
parseMessages,
|
|
221
|
+
createIpcServer
|
|
222
|
+
};
|
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
import {
|
|
2
|
+
commandExists,
|
|
3
|
+
execCapture
|
|
4
|
+
} from "./chunk-RVMOIUSL.js";
|
|
5
|
+
import {
|
|
6
|
+
existsSync,
|
|
7
|
+
readFileSync
|
|
8
|
+
} from "./chunk-TD6YNU6L.js";
|
|
9
|
+
|
|
10
|
+
// src/lib/toolResolver.ts
|
|
11
|
+
import { join as join3 } from "path";
|
|
12
|
+
|
|
13
|
+
// src/lib/runner.ts
|
|
14
|
+
import { execa, execaSync } from "execa";
|
|
15
|
+
import { delimiter, dirname, join, resolve } from "path";
|
|
16
|
+
import pRetry from "p-retry";
|
|
17
|
+
function getSupabaseBinaryCandidates() {
|
|
18
|
+
if (process.platform === "win32") {
|
|
19
|
+
return ["supabase.cmd", "supabase.exe", "supabase"];
|
|
20
|
+
}
|
|
21
|
+
return ["supabase"];
|
|
22
|
+
}
|
|
23
|
+
function hasLocalSupabaseBinary(binDir) {
|
|
24
|
+
return getSupabaseBinaryCandidates().some(
|
|
25
|
+
(candidate) => existsSync(join(binDir, candidate))
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
function getPathEnvKey(env) {
|
|
29
|
+
return Object.keys(env).find((key) => key.toLowerCase() === "path") ?? "PATH";
|
|
30
|
+
}
|
|
31
|
+
function findLocalSupabaseBinDir(startDir = process.cwd()) {
|
|
32
|
+
let currentDir = resolve(startDir);
|
|
33
|
+
while (true) {
|
|
34
|
+
const binDir = join(currentDir, "node_modules", ".bin");
|
|
35
|
+
if (hasLocalSupabaseBinary(binDir)) {
|
|
36
|
+
return binDir;
|
|
37
|
+
}
|
|
38
|
+
const parentDir = dirname(currentDir);
|
|
39
|
+
if (parentDir === currentDir) {
|
|
40
|
+
return void 0;
|
|
41
|
+
}
|
|
42
|
+
currentDir = parentDir;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function resolveSupabaseCommand(startDir = process.cwd(), env = process.env) {
|
|
46
|
+
const localBinDir = findLocalSupabaseBinDir(startDir);
|
|
47
|
+
if (!localBinDir) {
|
|
48
|
+
return {
|
|
49
|
+
command: "supabase",
|
|
50
|
+
env: { ...env },
|
|
51
|
+
source: "path"
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const pathKey = getPathEnvKey(env);
|
|
55
|
+
const currentPath = env[pathKey];
|
|
56
|
+
return {
|
|
57
|
+
command: "supabase",
|
|
58
|
+
env: {
|
|
59
|
+
...env,
|
|
60
|
+
[pathKey]: currentPath ? `${localBinDir}${delimiter}${currentPath}` : localBinDir
|
|
61
|
+
},
|
|
62
|
+
source: "repository",
|
|
63
|
+
localBinDir
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function runCommand(execution, args, cwd = process.cwd(), options) {
|
|
67
|
+
let stdoutBuf = "";
|
|
68
|
+
let stderrBuf = "";
|
|
69
|
+
const resolvedExecution = typeof execution === "string" ? { command: execution } : execution;
|
|
70
|
+
const subprocess = execa(resolvedExecution.command, args, {
|
|
71
|
+
cwd,
|
|
72
|
+
env: resolvedExecution.env,
|
|
73
|
+
shell: true,
|
|
74
|
+
detached: true,
|
|
75
|
+
stdin: options?.quiet ? "pipe" : "inherit",
|
|
76
|
+
stdout: "pipe",
|
|
77
|
+
stderr: "pipe",
|
|
78
|
+
reject: false
|
|
79
|
+
});
|
|
80
|
+
if (options?.quiet) {
|
|
81
|
+
subprocess.stdin?.end();
|
|
82
|
+
}
|
|
83
|
+
subprocess.stdout?.on("data", (data) => {
|
|
84
|
+
const text = data.toString();
|
|
85
|
+
stdoutBuf += text;
|
|
86
|
+
if (!options?.quiet) process.stdout.write(text);
|
|
87
|
+
options?.onData?.(stdoutBuf, stderrBuf);
|
|
88
|
+
});
|
|
89
|
+
subprocess.stderr?.on("data", (data) => {
|
|
90
|
+
const text = data.toString();
|
|
91
|
+
stderrBuf += text;
|
|
92
|
+
if (!options?.quiet) process.stderr.write(text);
|
|
93
|
+
options?.onData?.(stdoutBuf, stderrBuf);
|
|
94
|
+
});
|
|
95
|
+
const promise = subprocess.then(
|
|
96
|
+
(result) => ({
|
|
97
|
+
exitCode: result.exitCode ?? null,
|
|
98
|
+
signal: result.signal ?? null,
|
|
99
|
+
stdout: stdoutBuf,
|
|
100
|
+
stderr: stderrBuf
|
|
101
|
+
}),
|
|
102
|
+
(err) => ({
|
|
103
|
+
exitCode: null,
|
|
104
|
+
signal: null,
|
|
105
|
+
stdout: stdoutBuf,
|
|
106
|
+
stderr: stderrBuf,
|
|
107
|
+
spawnError: err.message
|
|
108
|
+
})
|
|
109
|
+
);
|
|
110
|
+
return {
|
|
111
|
+
promise,
|
|
112
|
+
abort: () => {
|
|
113
|
+
if (subprocess.pid) {
|
|
114
|
+
try {
|
|
115
|
+
process.kill(-subprocess.pid, "SIGTERM");
|
|
116
|
+
} catch {
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
pid: subprocess.pid,
|
|
121
|
+
subprocess
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function runInteractiveCommand(execution, args, cwd = process.cwd()) {
|
|
125
|
+
const resolved = typeof execution === "string" ? { command: execution } : execution;
|
|
126
|
+
try {
|
|
127
|
+
const result = execaSync(resolved.command, args, {
|
|
128
|
+
cwd,
|
|
129
|
+
env: resolved.env,
|
|
130
|
+
shell: true,
|
|
131
|
+
stdio: "inherit"
|
|
132
|
+
});
|
|
133
|
+
return {
|
|
134
|
+
exitCode: result.exitCode ?? null,
|
|
135
|
+
signal: null,
|
|
136
|
+
stdout: "",
|
|
137
|
+
stderr: ""
|
|
138
|
+
};
|
|
139
|
+
} catch (err) {
|
|
140
|
+
if (err && typeof err === "object" && "exitCode" in err) {
|
|
141
|
+
const execaErr = err;
|
|
142
|
+
return {
|
|
143
|
+
exitCode: execaErr.exitCode,
|
|
144
|
+
signal: execaErr.signal ?? null,
|
|
145
|
+
stdout: "",
|
|
146
|
+
stderr: ""
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
exitCode: null,
|
|
151
|
+
signal: null,
|
|
152
|
+
stdout: "",
|
|
153
|
+
stderr: "",
|
|
154
|
+
spawnError: err.message
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async function runCommandWithRetry(execution, args, cwd = process.cwd(), options) {
|
|
159
|
+
return pRetry(
|
|
160
|
+
async () => {
|
|
161
|
+
const result = await runCommand(execution, args, cwd, options).promise;
|
|
162
|
+
if (result.spawnError && !result.spawnError.includes("ENOENT")) {
|
|
163
|
+
throw new Error(result.spawnError);
|
|
164
|
+
}
|
|
165
|
+
return result;
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
retries: 2,
|
|
169
|
+
shouldRetry: ({ error }) => !error.message.includes("ENOENT")
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/lib/pkgManager.ts
|
|
175
|
+
import { join as join2, dirname as dirname2 } from "path";
|
|
176
|
+
var LOCK_FILES = [
|
|
177
|
+
{ file: "bun.lockb", id: "bun" },
|
|
178
|
+
{ file: "bun.lock", id: "bun" },
|
|
179
|
+
{ file: "pnpm-lock.yaml", id: "pnpm" },
|
|
180
|
+
{ file: "yarn.lock", id: "yarn" },
|
|
181
|
+
{ file: "package-lock.json", id: "npm" }
|
|
182
|
+
];
|
|
183
|
+
var MANAGER_META = {
|
|
184
|
+
npm: { lockFile: "package-lock.json", command: "npm" },
|
|
185
|
+
pnpm: { lockFile: "pnpm-lock.yaml", command: "pnpm" },
|
|
186
|
+
yarn: { lockFile: "yarn.lock", command: "yarn" },
|
|
187
|
+
bun: { lockFile: "bun.lockb", command: "bun" }
|
|
188
|
+
};
|
|
189
|
+
function detectPkgManager(cwd = process.cwd()) {
|
|
190
|
+
let dir = cwd;
|
|
191
|
+
const root = dirname2(dir) === dir ? dir : void 0;
|
|
192
|
+
while (true) {
|
|
193
|
+
for (const { file, id } of LOCK_FILES) {
|
|
194
|
+
if (existsSync(join2(dir, file))) {
|
|
195
|
+
const meta = MANAGER_META[id];
|
|
196
|
+
return { id, lockFile: meta.lockFile, command: meta.command };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const parent = dirname2(dir);
|
|
200
|
+
if (parent === dir || parent === root) break;
|
|
201
|
+
dir = parent;
|
|
202
|
+
}
|
|
203
|
+
return { id: "npm", lockFile: "package-lock.json", command: "npm" };
|
|
204
|
+
}
|
|
205
|
+
var TRANSLATIONS = {
|
|
206
|
+
"install": {},
|
|
207
|
+
// same for all
|
|
208
|
+
"add": {
|
|
209
|
+
npm: ["install"]
|
|
210
|
+
},
|
|
211
|
+
"remove": {
|
|
212
|
+
npm: ["uninstall"]
|
|
213
|
+
},
|
|
214
|
+
"run": {},
|
|
215
|
+
// same for all
|
|
216
|
+
"publish": {
|
|
217
|
+
bun: null
|
|
218
|
+
},
|
|
219
|
+
"audit": {
|
|
220
|
+
bun: null
|
|
221
|
+
},
|
|
222
|
+
"outdated": {
|
|
223
|
+
bun: null
|
|
224
|
+
},
|
|
225
|
+
"ls": {
|
|
226
|
+
yarn: ["list"],
|
|
227
|
+
bun: null
|
|
228
|
+
},
|
|
229
|
+
"pack": {
|
|
230
|
+
bun: null
|
|
231
|
+
},
|
|
232
|
+
"version": {},
|
|
233
|
+
// same for all
|
|
234
|
+
"login": {
|
|
235
|
+
bun: null
|
|
236
|
+
},
|
|
237
|
+
"logout": {
|
|
238
|
+
bun: null
|
|
239
|
+
},
|
|
240
|
+
"config": {},
|
|
241
|
+
// same for all
|
|
242
|
+
"whoami": {
|
|
243
|
+
bun: null
|
|
244
|
+
},
|
|
245
|
+
"info": {
|
|
246
|
+
npm: ["info"],
|
|
247
|
+
pnpm: ["info"],
|
|
248
|
+
yarn: ["info"],
|
|
249
|
+
bun: null
|
|
250
|
+
},
|
|
251
|
+
"search": {
|
|
252
|
+
pnpm: null,
|
|
253
|
+
yarn: null,
|
|
254
|
+
bun: null
|
|
255
|
+
},
|
|
256
|
+
"init": {}
|
|
257
|
+
// same for all
|
|
258
|
+
};
|
|
259
|
+
var UnsupportedCommandError = class extends Error {
|
|
260
|
+
constructor(command, manager) {
|
|
261
|
+
super(`"${command}" is not supported by ${manager}`);
|
|
262
|
+
this.name = "UnsupportedCommandError";
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
function translateCommand(base, manager) {
|
|
266
|
+
const [subcommand, ...rest] = base;
|
|
267
|
+
if (!subcommand) {
|
|
268
|
+
return { command: manager, args: [] };
|
|
269
|
+
}
|
|
270
|
+
const translation = TRANSLATIONS[subcommand];
|
|
271
|
+
if (translation) {
|
|
272
|
+
const managerEntry = translation[manager];
|
|
273
|
+
if (managerEntry === null) {
|
|
274
|
+
throw new UnsupportedCommandError(subcommand, manager);
|
|
275
|
+
}
|
|
276
|
+
if (managerEntry !== void 0) {
|
|
277
|
+
return { command: manager, args: [...managerEntry, ...rest] };
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return { command: manager, args: [subcommand, ...rest] };
|
|
281
|
+
}
|
|
282
|
+
function resolvePkgArgs(base, cwd = process.cwd()) {
|
|
283
|
+
const mgr = detectPkgManager(cwd);
|
|
284
|
+
return translateCommand(base, mgr.id);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// src/lib/toolResolver.ts
|
|
288
|
+
function getToolDisplayName(toolId, cwd = process.cwd()) {
|
|
289
|
+
if (toolId === "pkg") {
|
|
290
|
+
const mgr = detectPkgManager(cwd);
|
|
291
|
+
return mgr.id;
|
|
292
|
+
}
|
|
293
|
+
const names = {
|
|
294
|
+
supabase: "supabase",
|
|
295
|
+
gh: "github",
|
|
296
|
+
vercel: "vercel",
|
|
297
|
+
git: "git",
|
|
298
|
+
pkg: "npm"
|
|
299
|
+
};
|
|
300
|
+
return names[toolId];
|
|
301
|
+
}
|
|
302
|
+
function resolveToolCommand(toolId, cwd = process.cwd()) {
|
|
303
|
+
if (toolId === "supabase") {
|
|
304
|
+
const resolved = resolveSupabaseCommand(cwd);
|
|
305
|
+
return {
|
|
306
|
+
command: resolved.command,
|
|
307
|
+
env: resolved.env,
|
|
308
|
+
source: resolved.source
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
if (toolId === "pkg") {
|
|
312
|
+
const mgr = detectPkgManager(cwd);
|
|
313
|
+
if (!commandExists(mgr.command)) {
|
|
314
|
+
return { command: mgr.command, source: "not-found" };
|
|
315
|
+
}
|
|
316
|
+
return { command: mgr.command, env: { ...process.env }, source: "path" };
|
|
317
|
+
}
|
|
318
|
+
const command = toolId;
|
|
319
|
+
if (!commandExists(command)) {
|
|
320
|
+
return { command, source: "not-found" };
|
|
321
|
+
}
|
|
322
|
+
return { command, env: { ...process.env }, source: "path" };
|
|
323
|
+
}
|
|
324
|
+
function getToolVersion(toolId) {
|
|
325
|
+
try {
|
|
326
|
+
switch (toolId) {
|
|
327
|
+
case "supabase":
|
|
328
|
+
return execCapture("supabase --version").replace(/^supabase\s+/i, "");
|
|
329
|
+
case "gh":
|
|
330
|
+
return execCapture("gh --version").split("\n")[0]?.replace(/^gh\s+version\s+/i, "").split(" ")[0];
|
|
331
|
+
case "vercel":
|
|
332
|
+
return execCapture("vercel --version").split("\n")[0]?.trim();
|
|
333
|
+
case "git":
|
|
334
|
+
return execCapture("git --version").replace(/^git version\s+/i, "").trim();
|
|
335
|
+
case "pkg": {
|
|
336
|
+
const mgr = detectPkgManager();
|
|
337
|
+
return execCapture(`${mgr.command} --version`).split("\n")[0]?.trim();
|
|
338
|
+
}
|
|
339
|
+
default:
|
|
340
|
+
return void 0;
|
|
341
|
+
}
|
|
342
|
+
} catch {
|
|
343
|
+
return void 0;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
var toolInfoCache = /* @__PURE__ */ new Map();
|
|
347
|
+
function getToolInfo(toolId) {
|
|
348
|
+
const cached = toolInfoCache.get(toolId);
|
|
349
|
+
if (cached) return cached;
|
|
350
|
+
const labels = {
|
|
351
|
+
supabase: "Supabase CLI",
|
|
352
|
+
gh: "GitHub CLI",
|
|
353
|
+
vercel: "Vercel CLI",
|
|
354
|
+
git: "Git",
|
|
355
|
+
pkg: "Package Manager"
|
|
356
|
+
};
|
|
357
|
+
const commandName = toolId === "supabase" ? "supabase" : toolId === "pkg" ? detectPkgManager().command : toolId;
|
|
358
|
+
const installed = commandExists(commandName);
|
|
359
|
+
const version = installed ? getToolVersion(toolId) : void 0;
|
|
360
|
+
const info = {
|
|
361
|
+
id: toolId,
|
|
362
|
+
label: labels[toolId],
|
|
363
|
+
installed,
|
|
364
|
+
version
|
|
365
|
+
};
|
|
366
|
+
toolInfoCache.set(toolId, info);
|
|
367
|
+
return info;
|
|
368
|
+
}
|
|
369
|
+
function detectSupabaseLink(cwd) {
|
|
370
|
+
try {
|
|
371
|
+
const configPath = join3(cwd, ".supabase", "config.toml");
|
|
372
|
+
if (existsSync(configPath)) {
|
|
373
|
+
const content = readFileSync(configPath, "utf-8");
|
|
374
|
+
const match = content.match(/project_id\s*=\s*"([^"]+)"/);
|
|
375
|
+
return { linked: true, project: match?.[1] };
|
|
376
|
+
}
|
|
377
|
+
} catch {
|
|
378
|
+
}
|
|
379
|
+
return { linked: false };
|
|
380
|
+
}
|
|
381
|
+
function detectVercelLink(cwd) {
|
|
382
|
+
try {
|
|
383
|
+
const projectPath = join3(cwd, ".vercel", "project.json");
|
|
384
|
+
if (existsSync(projectPath)) {
|
|
385
|
+
const data = JSON.parse(readFileSync(projectPath, "utf-8"));
|
|
386
|
+
return { linked: true, project: data.projectId };
|
|
387
|
+
}
|
|
388
|
+
} catch {
|
|
389
|
+
}
|
|
390
|
+
return { linked: false };
|
|
391
|
+
}
|
|
392
|
+
function detectPkgLink(cwd) {
|
|
393
|
+
try {
|
|
394
|
+
const pkgPath = join3(cwd, "package.json");
|
|
395
|
+
if (existsSync(pkgPath)) {
|
|
396
|
+
const data = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
397
|
+
const mgr = detectPkgManager(cwd);
|
|
398
|
+
return { linked: true, project: data.name ? `${data.name} (${mgr.id})` : mgr.id };
|
|
399
|
+
}
|
|
400
|
+
} catch {
|
|
401
|
+
}
|
|
402
|
+
return { linked: false };
|
|
403
|
+
}
|
|
404
|
+
function detectGhLink(cwd) {
|
|
405
|
+
try {
|
|
406
|
+
const remote = execCapture(`git -C "${cwd}" remote get-url origin 2>/dev/null`);
|
|
407
|
+
if (remote) {
|
|
408
|
+
const match = remote.match(/[/:]([\w.-]+\/[\w.-]+?)(?:\.git)?$/);
|
|
409
|
+
return { linked: true, project: match?.[1] ?? remote };
|
|
410
|
+
}
|
|
411
|
+
} catch {
|
|
412
|
+
}
|
|
413
|
+
return { linked: false };
|
|
414
|
+
}
|
|
415
|
+
var toolLinkCache = /* @__PURE__ */ new Map();
|
|
416
|
+
function getToolLinkInfo(toolId, cwd = process.cwd()) {
|
|
417
|
+
const cacheKey = `${toolId}:${cwd}`;
|
|
418
|
+
const cached = toolLinkCache.get(cacheKey);
|
|
419
|
+
if (cached) return cached;
|
|
420
|
+
const base = getToolInfo(toolId);
|
|
421
|
+
let linkStatus = { linked: false };
|
|
422
|
+
if (base.installed) {
|
|
423
|
+
switch (toolId) {
|
|
424
|
+
case "supabase":
|
|
425
|
+
linkStatus = detectSupabaseLink(cwd);
|
|
426
|
+
break;
|
|
427
|
+
case "vercel":
|
|
428
|
+
linkStatus = detectVercelLink(cwd);
|
|
429
|
+
break;
|
|
430
|
+
case "gh":
|
|
431
|
+
linkStatus = detectGhLink(cwd);
|
|
432
|
+
break;
|
|
433
|
+
case "pkg":
|
|
434
|
+
linkStatus = detectPkgLink(cwd);
|
|
435
|
+
break;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
const info = { ...base, ...linkStatus };
|
|
439
|
+
toolLinkCache.set(cacheKey, info);
|
|
440
|
+
return info;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export {
|
|
444
|
+
runCommand,
|
|
445
|
+
runInteractiveCommand,
|
|
446
|
+
runCommandWithRetry,
|
|
447
|
+
detectPkgManager,
|
|
448
|
+
translateCommand,
|
|
449
|
+
resolvePkgArgs,
|
|
450
|
+
getToolDisplayName,
|
|
451
|
+
resolveToolCommand,
|
|
452
|
+
getToolVersion,
|
|
453
|
+
getToolInfo,
|
|
454
|
+
getToolLinkInfo
|
|
455
|
+
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseMessages,
|
|
3
3
|
serializeMessage
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EAMHFQKU.js";
|
|
5
5
|
|
|
6
6
|
// src/lib/ipcClient.ts
|
|
7
7
|
import net from "net";
|
|
8
|
-
|
|
8
|
+
import ms from "ms";
|
|
9
|
+
var DEFAULT_TIMEOUT = ms("5s");
|
|
9
10
|
function createIpcClient(socketPath) {
|
|
10
11
|
let socket = null;
|
|
11
12
|
let connected = false;
|
|
@@ -34,9 +35,11 @@ function createIpcClient(socketPath) {
|
|
|
34
35
|
return {
|
|
35
36
|
connect() {
|
|
36
37
|
return new Promise((resolve, reject) => {
|
|
38
|
+
let settled = false;
|
|
37
39
|
socket = net.createConnection(socketPath);
|
|
38
40
|
socket.on("connect", () => {
|
|
39
41
|
connected = true;
|
|
42
|
+
settled = true;
|
|
40
43
|
resolve();
|
|
41
44
|
});
|
|
42
45
|
socket.on("data", handleData);
|
|
@@ -49,7 +52,8 @@ function createIpcClient(socketPath) {
|
|
|
49
52
|
});
|
|
50
53
|
socket.on("error", (err) => {
|
|
51
54
|
connected = false;
|
|
52
|
-
if (!
|
|
55
|
+
if (!settled) {
|
|
56
|
+
settled = true;
|
|
53
57
|
reject(err);
|
|
54
58
|
}
|
|
55
59
|
});
|