@burdenoff/vibe-agent 2.7.4 → 2.8.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/dist/{app-hc590rye.js → app-tba5zhmy.js} +2 -2
- package/dist/cli.js +395 -9
- package/dist/cli.js.map +9 -6
- package/dist/{index-wmvkjcjj.js → index-0429nfr9.js} +2 -2
- package/dist/{index-3rjnbp97.js → index-0nt6wnb9.js} +2 -2
- package/dist/{index-npmvh1x9.js → index-7ph3496b.js} +2 -2
- package/dist/{index-4nsdre0j.js → index-9grqzmk5.js} +40 -12
- package/dist/index-9grqzmk5.js.map +13 -0
- package/dist/{index-fm6gqenc.js → index-a3q5ewrj.js} +2 -2
- package/dist/{index-10wkaqpa.js → index-cndcb55v.js} +178 -13
- package/dist/index-cndcb55v.js.map +13 -0
- package/dist/{index-6vry08rz.js → index-dhbg241c.js} +2 -2
- package/dist/{index-hefqxwht.js → index-e2dzjkmm.js} +2 -2
- package/dist/{index-t0nsa57v.js → index-et6rnq2y.js} +2 -2
- package/dist/{index-ftbphe7j.js → index-exh7dh2v.js} +141 -14
- package/dist/{index-ftbphe7j.js.map → index-exh7dh2v.js.map} +3 -3
- package/dist/{index-30p492yv.js → index-swqzafr9.js} +2 -2
- package/dist/{index-xmeskdnb.js → index-t0x810hm.js} +133 -74
- package/dist/index-t0x810hm.js.map +12 -0
- package/dist/{index-c7zy3n33.js → index-vzmmv3r7.js} +2 -2
- package/dist/{index-a9g7hbj9.js → index-w7m3p4qa.js} +2 -2
- package/dist/index.js +2 -2
- package/dist/{package-a5yw4d19.js → package-cck2kzyn.js} +3 -3
- package/dist/{package-a5yw4d19.js.map → package-cck2kzyn.js.map} +1 -1
- package/dist/{plugin-system-7hmbwvtf.js → plugin-system-75q3s1rf.js} +135 -16
- package/dist/plugin-system-75q3s1rf.js.map +10 -0
- package/package.json +1 -1
- package/dist/index-10wkaqpa.js.map +0 -13
- package/dist/index-4nsdre0j.js.map +0 -13
- package/dist/index-xmeskdnb.js.map +0 -11
- package/dist/plugin-system-7hmbwvtf.js.map +0 -10
- /package/dist/{app-hc590rye.js.map → app-tba5zhmy.js.map} +0 -0
- /package/dist/{index-wmvkjcjj.js.map → index-0429nfr9.js.map} +0 -0
- /package/dist/{index-3rjnbp97.js.map → index-0nt6wnb9.js.map} +0 -0
- /package/dist/{index-npmvh1x9.js.map → index-7ph3496b.js.map} +0 -0
- /package/dist/{index-fm6gqenc.js.map → index-a3q5ewrj.js.map} +0 -0
- /package/dist/{index-6vry08rz.js.map → index-dhbg241c.js.map} +0 -0
- /package/dist/{index-hefqxwht.js.map → index-e2dzjkmm.js.map} +0 -0
- /package/dist/{index-t0nsa57v.js.map → index-et6rnq2y.js.map} +0 -0
- /package/dist/{index-30p492yv.js.map → index-swqzafr9.js.map} +0 -0
- /package/dist/{index-c7zy3n33.js.map → index-vzmmv3r7.js.map} +0 -0
- /package/dist/{index-a9g7hbj9.js.map → index-w7m3p4qa.js.map} +0 -0
|
@@ -1,4 +1,109 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
// src/cli/utils/api-client.ts
|
|
3
|
+
import { existsSync, readFileSync } from "fs";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
var DEFAULT_AGENT_URL = "http://localhost:3005";
|
|
7
|
+
var _apiKeyCache = new Map;
|
|
8
|
+
function resolveAgentUrlByName(name) {
|
|
9
|
+
const registryPath = join(homedir(), ".vibecontrols", "agents.json");
|
|
10
|
+
if (!existsSync(registryPath))
|
|
11
|
+
return null;
|
|
12
|
+
try {
|
|
13
|
+
const registry = JSON.parse(readFileSync(registryPath, "utf-8"));
|
|
14
|
+
if (!Array.isArray(registry))
|
|
15
|
+
return null;
|
|
16
|
+
const agent = registry.find((entry) => entry.name === name);
|
|
17
|
+
if (!agent || !agent.port)
|
|
18
|
+
return null;
|
|
19
|
+
return {
|
|
20
|
+
url: `http://localhost:${agent.port}`,
|
|
21
|
+
port: agent.port
|
|
22
|
+
};
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function getAgentUrl(opts) {
|
|
28
|
+
if (opts?.agentUrl)
|
|
29
|
+
return opts.agentUrl;
|
|
30
|
+
const agentName = opts?.agent || opts?.profile;
|
|
31
|
+
if (agentName) {
|
|
32
|
+
const resolved = resolveAgentUrlByName(agentName);
|
|
33
|
+
if (resolved)
|
|
34
|
+
return resolved.url;
|
|
35
|
+
}
|
|
36
|
+
return process.env.AGENT_URL || DEFAULT_AGENT_URL;
|
|
37
|
+
}
|
|
38
|
+
async function resolveApiKey(agentUrl) {
|
|
39
|
+
if (process.env.AGENT_API_KEY)
|
|
40
|
+
return process.env.AGENT_API_KEY;
|
|
41
|
+
if (_apiKeyCache.has(agentUrl))
|
|
42
|
+
return _apiKeyCache.get(agentUrl);
|
|
43
|
+
try {
|
|
44
|
+
const res = await fetch(`${agentUrl}/api/agent/api-key`);
|
|
45
|
+
if (res.ok) {
|
|
46
|
+
const data = await res.json();
|
|
47
|
+
if (data.apiKey) {
|
|
48
|
+
_apiKeyCache.set(agentUrl, data.apiKey);
|
|
49
|
+
return data.apiKey;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
} catch {}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
async function agentFetch(agentUrl, path, options = {}) {
|
|
56
|
+
const apiKey = await resolveApiKey(agentUrl);
|
|
57
|
+
const headers = {
|
|
58
|
+
...options.body ? { "Content-Type": "application/json" } : {},
|
|
59
|
+
...apiKey ? { "x-agent-api-key": apiKey } : {},
|
|
60
|
+
...options.headers ?? {}
|
|
61
|
+
};
|
|
62
|
+
const res = await fetch(`${agentUrl}${path}`, { ...options, headers });
|
|
63
|
+
const data = await res.json().catch(() => ({}));
|
|
64
|
+
return { ok: res.ok, status: res.status, data };
|
|
65
|
+
}
|
|
66
|
+
async function apiGet(agentUrl, path) {
|
|
67
|
+
const { ok, status, data } = await agentFetch(agentUrl, path);
|
|
68
|
+
if (!ok) {
|
|
69
|
+
const errorMsg = data?.error || data?.message || `Agent returned ${status}`;
|
|
70
|
+
throw new Error(String(errorMsg));
|
|
71
|
+
}
|
|
72
|
+
return data;
|
|
73
|
+
}
|
|
74
|
+
async function apiPost(agentUrl, path, body) {
|
|
75
|
+
const { ok, status, data } = await agentFetch(agentUrl, path, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
body: body != null ? JSON.stringify(body) : undefined
|
|
78
|
+
});
|
|
79
|
+
if (!ok) {
|
|
80
|
+
const errorMsg = data?.error || data?.message || `Agent returned ${status}`;
|
|
81
|
+
throw new Error(String(errorMsg));
|
|
82
|
+
}
|
|
83
|
+
return data;
|
|
84
|
+
}
|
|
85
|
+
async function apiPut(agentUrl, path, body) {
|
|
86
|
+
const { ok, status, data } = await agentFetch(agentUrl, path, {
|
|
87
|
+
method: "PUT",
|
|
88
|
+
body: body != null ? JSON.stringify(body) : undefined
|
|
89
|
+
});
|
|
90
|
+
if (!ok) {
|
|
91
|
+
const errorMsg = data?.error || data?.message || `Agent returned ${status}`;
|
|
92
|
+
throw new Error(String(errorMsg));
|
|
93
|
+
}
|
|
94
|
+
return data;
|
|
95
|
+
}
|
|
96
|
+
async function apiDelete(agentUrl, path) {
|
|
97
|
+
const { ok, status, data } = await agentFetch(agentUrl, path, {
|
|
98
|
+
method: "DELETE"
|
|
99
|
+
});
|
|
100
|
+
if (!ok) {
|
|
101
|
+
const errorMsg = data?.error || data?.message || `Agent returned ${status}`;
|
|
102
|
+
throw new Error(String(errorMsg));
|
|
103
|
+
}
|
|
104
|
+
return data;
|
|
105
|
+
}
|
|
106
|
+
|
|
2
107
|
// src/cli/utils/format.ts
|
|
3
108
|
var colors = {
|
|
4
109
|
bold: (text) => `\x1B[1m${text}\x1B[22m`,
|
|
@@ -212,81 +317,35 @@ async function printAgentDetails(agentUrl, maxWaitMs = 15000) {
|
|
|
212
317
|
blank();
|
|
213
318
|
}
|
|
214
319
|
|
|
215
|
-
// src/cli/utils/
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
function getAgentUrl(opts) {
|
|
219
|
-
return opts?.agentUrl || process.env.AGENT_URL || DEFAULT_AGENT_URL;
|
|
220
|
-
}
|
|
221
|
-
async function resolveApiKey(agentUrl) {
|
|
222
|
-
if (process.env.AGENT_API_KEY)
|
|
223
|
-
return process.env.AGENT_API_KEY;
|
|
224
|
-
if (_apiKeyCache.has(agentUrl))
|
|
225
|
-
return _apiKeyCache.get(agentUrl);
|
|
226
|
-
try {
|
|
227
|
-
const res = await fetch(`${agentUrl}/api/agent/api-key`);
|
|
228
|
-
if (res.ok) {
|
|
229
|
-
const data = await res.json();
|
|
230
|
-
if (data.apiKey) {
|
|
231
|
-
_apiKeyCache.set(agentUrl, data.apiKey);
|
|
232
|
-
return data.apiKey;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
} catch {}
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
async function agentFetch(agentUrl, path, options = {}) {
|
|
239
|
-
const apiKey = await resolveApiKey(agentUrl);
|
|
240
|
-
const headers = {
|
|
241
|
-
...options.body ? { "Content-Type": "application/json" } : {},
|
|
242
|
-
...apiKey ? { "x-agent-api-key": apiKey } : {},
|
|
243
|
-
...options.headers ?? {}
|
|
244
|
-
};
|
|
245
|
-
const res = await fetch(`${agentUrl}${path}`, { ...options, headers });
|
|
246
|
-
const data = await res.json().catch(() => ({}));
|
|
247
|
-
return { ok: res.ok, status: res.status, data };
|
|
248
|
-
}
|
|
249
|
-
async function apiGet(agentUrl, path) {
|
|
250
|
-
const { ok, status, data } = await agentFetch(agentUrl, path);
|
|
251
|
-
if (!ok) {
|
|
252
|
-
const errorMsg = data?.error || data?.message || `Agent returned ${status}`;
|
|
253
|
-
throw new Error(String(errorMsg));
|
|
254
|
-
}
|
|
255
|
-
return data;
|
|
320
|
+
// src/cli/utils/renderer.ts
|
|
321
|
+
function isInteractive() {
|
|
322
|
+
return !!process.stdout.isTTY && !!process.stdin.isTTY;
|
|
256
323
|
}
|
|
257
|
-
async function
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
324
|
+
async function promptConfirm(message, defaultValue = false) {
|
|
325
|
+
if (!isInteractive())
|
|
326
|
+
return defaultValue;
|
|
327
|
+
const hint = defaultValue ? "[Y/n]" : "[y/N]";
|
|
328
|
+
process.stdout.write(` ${message} ${hint} `);
|
|
329
|
+
return new Promise((resolve) => {
|
|
330
|
+
const stdin = process.stdin;
|
|
331
|
+
stdin.setRawMode?.(true);
|
|
332
|
+
stdin.resume();
|
|
333
|
+
stdin.setEncoding("utf8");
|
|
334
|
+
const onData = (key) => {
|
|
335
|
+
stdin.removeListener("data", onData);
|
|
336
|
+
stdin.setRawMode?.(false);
|
|
337
|
+
stdin.pause();
|
|
338
|
+
const answer = key.trim().toLowerCase();
|
|
339
|
+
console.log(answer || (defaultValue ? "y" : "n"));
|
|
340
|
+
if (answer === "")
|
|
341
|
+
resolve(defaultValue);
|
|
342
|
+
else
|
|
343
|
+
resolve(answer === "y");
|
|
344
|
+
};
|
|
345
|
+
stdin.on("data", onData);
|
|
261
346
|
});
|
|
262
|
-
if (!ok) {
|
|
263
|
-
const errorMsg = data?.error || data?.message || `Agent returned ${status}`;
|
|
264
|
-
throw new Error(String(errorMsg));
|
|
265
|
-
}
|
|
266
|
-
return data;
|
|
267
|
-
}
|
|
268
|
-
async function apiPut(agentUrl, path, body) {
|
|
269
|
-
const { ok, status, data } = await agentFetch(agentUrl, path, {
|
|
270
|
-
method: "PUT",
|
|
271
|
-
body: body != null ? JSON.stringify(body) : undefined
|
|
272
|
-
});
|
|
273
|
-
if (!ok) {
|
|
274
|
-
const errorMsg = data?.error || data?.message || `Agent returned ${status}`;
|
|
275
|
-
throw new Error(String(errorMsg));
|
|
276
|
-
}
|
|
277
|
-
return data;
|
|
278
|
-
}
|
|
279
|
-
async function apiDelete(agentUrl, path) {
|
|
280
|
-
const { ok, status, data } = await agentFetch(agentUrl, path, {
|
|
281
|
-
method: "DELETE"
|
|
282
|
-
});
|
|
283
|
-
if (!ok) {
|
|
284
|
-
const errorMsg = data?.error || data?.message || `Agent returned ${status}`;
|
|
285
|
-
throw new Error(String(errorMsg));
|
|
286
|
-
}
|
|
287
|
-
return data;
|
|
288
347
|
}
|
|
289
|
-
export { getAgentUrl, apiGet, apiPost, apiPut, apiDelete, colors, icons, fail, success, warn, info, header, kv, blank, formatTable, timeAgo, formatDuration, formatBytes, formatStatus, formatNotificationType, shortId, printAgentDetails };
|
|
348
|
+
export { getAgentUrl, apiGet, apiPost, apiPut, apiDelete, colors, icons, fail, success, warn, info, header, kv, blank, formatTable, timeAgo, formatDuration, formatBytes, formatStatus, formatNotificationType, shortId, printAgentDetails, promptConfirm };
|
|
290
349
|
|
|
291
|
-
//# debugId=
|
|
292
|
-
//# sourceMappingURL=index-
|
|
350
|
+
//# debugId=25F2128FF1C6AFEB64756E2164756E21
|
|
351
|
+
//# sourceMappingURL=index-t0x810hm.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/cli/utils/api-client.ts", "../src/cli/utils/format.ts", "../src/cli/utils/renderer.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * API Client\n *\n * Typed fetch wrapper for communicating with the VibeControls Agent HTTP API.\n * Handles API key resolution with 3-tier fallback:\n * 1. AGENT_API_KEY environment variable\n * 2. In-memory per-URL cache\n * 3. Auto-fetch from agent's auth-exempt /api/agent/api-key endpoint\n *\n * Supports --agent / --profile flags for multi-agent targeting:\n * Resolves agent name → port from ~/.vibecontrols/agents.json registry.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst DEFAULT_AGENT_URL = \"http://localhost:3005\";\n\n/** In-memory cache for auto-fetched API keys (per agent URL) */\nconst _apiKeyCache = new Map<string, string>();\n\n/**\n * Resolve an agent URL from an agent/profile name.\n * Looks up the name in ~/.vibecontrols/agents.json and returns the URL.\n * Returns null if the agent is not found.\n */\nexport function resolveAgentUrlByName(\n name: string,\n): { url: string; port: number } | null {\n const registryPath = join(homedir(), \".vibecontrols\", \"agents.json\");\n if (!existsSync(registryPath)) return null;\n\n try {\n const registry = JSON.parse(readFileSync(registryPath, \"utf-8\"));\n if (!Array.isArray(registry)) return null;\n\n const agent = registry.find(\n (entry: { name: string; port: number }) => entry.name === name,\n );\n if (!agent || !agent.port) return null;\n\n return {\n url: `http://localhost:${agent.port}`,\n port: agent.port,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Get the agent URL from options with priority:\n * 1. --agent-url (explicit URL override)\n * 2. --agent / --profile (resolve name from agents.json)\n * 3. AGENT_URL env var\n * 4. Default (http://localhost:3005)\n */\nexport function getAgentUrl(opts?: {\n agentUrl?: string;\n agent?: string;\n profile?: string;\n}): string {\n // Explicit URL always wins\n if (opts?.agentUrl) return opts.agentUrl;\n\n // Resolve from --agent or --profile name\n const agentName = opts?.agent || opts?.profile;\n if (agentName) {\n const resolved = resolveAgentUrlByName(agentName);\n if (resolved) return resolved.url;\n // If agent name doesn't resolve, fall through to defaults\n }\n\n return process.env.AGENT_URL || DEFAULT_AGENT_URL;\n}\n\n/**\n * Resolve the agent API key.\n *\n * 1. AGENT_API_KEY env var\n * 2. In-memory cache (per URL)\n * 3. Auto-fetch from auth-exempt endpoint\n */\nexport async function resolveApiKey(\n agentUrl: string,\n): Promise<string | undefined> {\n if (process.env.AGENT_API_KEY) return process.env.AGENT_API_KEY;\n\n if (_apiKeyCache.has(agentUrl)) return _apiKeyCache.get(agentUrl);\n\n try {\n const res = await fetch(`${agentUrl}/api/agent/api-key`);\n if (res.ok) {\n const data = (await res.json()) as { apiKey: string };\n if (data.apiKey) {\n _apiKeyCache.set(agentUrl, data.apiKey);\n return data.apiKey;\n }\n }\n } catch {\n // Agent not reachable\n }\n return undefined;\n}\n\n/**\n * API response wrapper (returned by agentFetch).\n */\nexport interface ApiResponse<T = unknown> {\n ok: boolean;\n status: number;\n data: T;\n}\n\n/**\n * Generic typed fetch wrapper for the agent API.\n *\n * Returns the full { ok, status, data } response. Use this when you need\n * to inspect the HTTP status or handle errors manually.\n *\n * Automatically adds API key header and Content-Type for JSON bodies.\n */\nexport async function agentFetch<T = unknown>(\n agentUrl: string,\n path: string,\n options: RequestInit = {},\n): Promise<ApiResponse<T>> {\n const apiKey = await resolveApiKey(agentUrl);\n const headers: Record<string, string> = {\n ...(options.body ? { \"Content-Type\": \"application/json\" } : {}),\n ...(apiKey ? { \"x-agent-api-key\": apiKey } : {}),\n ...((options.headers as Record<string, string>) ?? {}),\n };\n\n const res = await fetch(`${agentUrl}${path}`, { ...options, headers });\n const data = (await res.json().catch(() => ({}))) as T;\n return { ok: res.ok, status: res.status, data };\n}\n\n// ── Convenience Functions ───────────────────────────────────────────────\n//\n// These throw on non-OK responses and return just the data.\n// This allows CLI commands to use simple try/catch with fail().\n\n/**\n * GET request — throws on non-OK, returns data directly.\n */\nexport async function apiGet<T = unknown>(\n agentUrl: string,\n path: string,\n): Promise<T> {\n const { ok, status, data } = await agentFetch<T>(agentUrl, path);\n if (!ok) {\n const errorMsg =\n (data as Record<string, unknown>)?.error ||\n (data as Record<string, unknown>)?.message ||\n `Agent returned ${status}`;\n throw new Error(String(errorMsg));\n }\n return data;\n}\n\n/**\n * POST request with JSON body — throws on non-OK, returns data directly.\n */\nexport async function apiPost<T = unknown>(\n agentUrl: string,\n path: string,\n body?: unknown,\n): Promise<T> {\n const { ok, status, data } = await agentFetch<T>(agentUrl, path, {\n method: \"POST\",\n body: body != null ? JSON.stringify(body) : undefined,\n });\n if (!ok) {\n const errorMsg =\n (data as Record<string, unknown>)?.error ||\n (data as Record<string, unknown>)?.message ||\n `Agent returned ${status}`;\n throw new Error(String(errorMsg));\n }\n return data;\n}\n\n/**\n * PUT request with JSON body — throws on non-OK, returns data directly.\n */\nexport async function apiPut<T = unknown>(\n agentUrl: string,\n path: string,\n body?: unknown,\n): Promise<T> {\n const { ok, status, data } = await agentFetch<T>(agentUrl, path, {\n method: \"PUT\",\n body: body != null ? JSON.stringify(body) : undefined,\n });\n if (!ok) {\n const errorMsg =\n (data as Record<string, unknown>)?.error ||\n (data as Record<string, unknown>)?.message ||\n `Agent returned ${status}`;\n throw new Error(String(errorMsg));\n }\n return data;\n}\n\n/**\n * DELETE request — throws on non-OK, returns data directly.\n */\nexport async function apiDelete<T = unknown>(\n agentUrl: string,\n path: string,\n): Promise<T> {\n const { ok, status, data } = await agentFetch<T>(agentUrl, path, {\n method: \"DELETE\",\n });\n if (!ok) {\n const errorMsg =\n (data as Record<string, unknown>)?.error ||\n (data as Record<string, unknown>)?.message ||\n `Agent returned ${status}`;\n throw new Error(String(errorMsg));\n }\n return data;\n}\n",
|
|
6
|
+
"/**\n * CLI Formatting Utilities\n *\n * ANSI color helpers, table formatting, time formatting, and output helpers.\n * Uses raw ANSI escape codes (no external color library).\n */\n\n// ── ANSI Color Helpers ──────────────────────────────────────────────────\n\nexport const colors = {\n // Modifiers\n bold: (text: string) => `\\x1b[1m${text}\\x1b[22m`,\n dim: (text: string) => `\\x1b[2m${text}\\x1b[22m`,\n italic: (text: string) => `\\x1b[3m${text}\\x1b[23m`,\n underline: (text: string) => `\\x1b[4m${text}\\x1b[24m`,\n\n // Colors\n red: (text: string) => `\\x1b[31m${text}\\x1b[39m`,\n green: (text: string) => `\\x1b[32m${text}\\x1b[39m`,\n yellow: (text: string) => `\\x1b[33m${text}\\x1b[39m`,\n blue: (text: string) => `\\x1b[34m${text}\\x1b[39m`,\n magenta: (text: string) => `\\x1b[35m${text}\\x1b[39m`,\n cyan: (text: string) => `\\x1b[36m${text}\\x1b[39m`,\n white: (text: string) => `\\x1b[37m${text}\\x1b[39m`,\n gray: (text: string) => `\\x1b[90m${text}\\x1b[39m`,\n\n // Bright variants\n brightRed: (text: string) => `\\x1b[91m${text}\\x1b[39m`,\n brightGreen: (text: string) => `\\x1b[92m${text}\\x1b[39m`,\n brightYellow: (text: string) => `\\x1b[93m${text}\\x1b[39m`,\n brightBlue: (text: string) => `\\x1b[94m${text}\\x1b[39m`,\n\n // Reset\n reset: \"\\x1b[0m\",\n} as const;\n\n// ── Status Icons ────────────────────────────────────────────────────────\n\nexport const icons = {\n success: colors.green(\"✓\"),\n error: colors.red(\"✗\"),\n warning: colors.yellow(\"⚠\"),\n info: colors.blue(\"●\"),\n running: colors.green(\"●\"),\n stopped: colors.red(\"○\"),\n pending: colors.yellow(\"◌\"),\n arrow: colors.gray(\"→\"),\n bullet: colors.gray(\"•\"),\n check: colors.green(\"✔\"),\n} as const;\n\n// ── Output Helpers ──────────────────────────────────────────────────────\n\n/**\n * Print an error message and exit with code 1.\n */\nexport function fail(msg: string): never {\n console.error(`${colors.red(\"Error:\")} ${msg}`);\n process.exit(1);\n}\n\n/**\n * Print a success message.\n */\nexport function success(msg: string): void {\n console.log(` ${icons.success} ${msg}`);\n}\n\n/**\n * Print a warning message.\n */\nexport function warn(msg: string): void {\n console.log(` ${icons.warning} ${msg}`);\n}\n\n/**\n * Print an info message.\n */\nexport function info(msg: string): void {\n console.log(` ${icons.info} ${msg}`);\n}\n\n/**\n * Print a header / title.\n */\nexport function header(title: string): void {\n console.log(`\\n ${colors.bold(`── ${title} ──`)}\\n`);\n}\n\n/**\n * Print a key-value pair.\n */\nexport function kv(\n key: string,\n value: string | number | boolean | null | undefined,\n): void {\n const display =\n value === null || value === undefined\n ? colors.gray(\"(none)\")\n : String(value);\n console.log(` ${colors.bold(key.padEnd(14))} ${display}`);\n}\n\n/**\n * Print a blank line.\n */\nexport function blank(): void {\n console.log();\n}\n\n// ── Table Formatting ────────────────────────────────────────────────────\n\n/**\n * Format and display a table of records using console.table.\n * Shows \"(none)\" for empty arrays.\n */\nexport function formatTable(rows: Record<string, unknown>[]): void {\n if (rows.length === 0) {\n console.log(\" (none)\");\n return;\n }\n console.table(rows);\n}\n\n/**\n * Format a simple aligned key-value table.\n */\nexport function formatKeyValue(\n entries: Record<string, string | number | boolean | null | undefined>,\n): void {\n const maxKeyLen = Math.max(...Object.keys(entries).map((k) => k.length));\n for (const [key, value] of Object.entries(entries)) {\n const display =\n value === null || value === undefined\n ? colors.gray(\"(none)\")\n : String(value);\n console.log(` ${colors.bold(key.padEnd(maxKeyLen + 2))} ${display}`);\n }\n}\n\n// ── Time Formatting ─────────────────────────────────────────────────────\n\n/**\n * Format a date string or timestamp as relative time (e.g. \"2m ago\", \"3h ago\").\n */\nexport function timeAgo(dateStr: string | number): string {\n const diff = Date.now() - new Date(dateStr).getTime();\n const s = Math.floor(diff / 1000);\n if (s < 0) return \"just now\";\n if (s < 60) return `${s}s ago`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m ago`;\n const h = Math.floor(m / 60);\n if (h < 24) return `${h}h ago`;\n const d = Math.floor(h / 24);\n if (d < 30) return `${d}d ago`;\n return `${Math.floor(d / 30)}mo ago`;\n}\n\n/**\n * Format seconds as human-readable duration (e.g. \"2h 15m 30s\").\n */\nexport function formatDuration(seconds: number): string {\n if (seconds < 60) return `${Math.floor(seconds)}s`;\n const m = Math.floor(seconds / 60);\n const s = Math.floor(seconds % 60);\n if (m < 60) return `${m}m ${s}s`;\n const h = Math.floor(m / 60);\n const rm = m % 60;\n return `${h}h ${rm}m`;\n}\n\n/**\n * Format bytes as human-readable (e.g. \"1.5 GB\").\n */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n}\n\n// ── Status Formatting ───────────────────────────────────────────────────\n\n/**\n * Format a status string with appropriate color.\n */\nexport function formatStatus(status: string): string {\n switch (status) {\n case \"running\":\n case \"active\":\n case \"healthy\":\n case \"success\":\n case \"completed\":\n return colors.green(status);\n case \"stopped\":\n case \"inactive\":\n case \"terminated\":\n case \"failed\":\n return colors.red(status);\n case \"starting\":\n case \"stopping\":\n case \"pending\":\n case \"warning\":\n return colors.yellow(status);\n case \"error\":\n return colors.red(status);\n default:\n return status;\n }\n}\n\n/**\n * Format a notification type icon with appropriate color.\n */\nexport function formatNotificationType(type: string): string {\n switch (type) {\n case \"error\":\n return colors.red(\"●\");\n case \"warning\":\n return colors.yellow(\"●\");\n case \"success\":\n return colors.green(\"●\");\n case \"info\":\n default:\n return colors.blue(\"●\");\n }\n}\n\n// ── ID Formatting ───────────────────────────────────────────────────────\n\n/**\n * Truncate a long ID for display (e.g., \"abc123def456\" → \"abc123de...\").\n */\nexport function shortId(id: string, len = 10): string {\n if (id.length <= len) return id;\n return id.substring(0, len) + \"...\";\n}\n\n// ── Agent Details ───────────────────────────────────────────────────────\n\n/**\n * After the agent starts, poll until healthy and print connection details\n * (agent URL, API key, tunnel URL). Used by both foreground and daemon start.\n */\nexport async function printAgentDetails(\n agentUrl: string,\n maxWaitMs = 15000,\n): Promise<void> {\n const startTime = Date.now();\n let healthy = false;\n\n // Poll until the agent is healthy\n while (Date.now() - startTime < maxWaitMs) {\n try {\n const res = await fetch(`${agentUrl}/health`);\n if (res.ok) {\n healthy = true;\n break;\n }\n } catch {\n // Not ready yet\n }\n await new Promise((r) => setTimeout(r, 500));\n }\n\n if (!healthy) {\n console.log(\n `\\n ${icons.warning} Agent not yet responding at ${agentUrl}. Check ${colors.bold(\"vibe logs\")} for details.\\n`,\n );\n return;\n }\n\n // Fetch API key (auth-exempt endpoint)\n let apiKey = \"(unavailable)\";\n try {\n const res = await fetch(`${agentUrl}/api/agent/api-key`);\n if (res.ok) {\n const data = (await res.json()) as { apiKey: string };\n apiKey = data.apiKey;\n }\n } catch {\n /* ignore */\n }\n\n // Fetch tunnel URL (auth-exempt endpoint)\n let tunnelUrl = \"(not running)\";\n let tunnelWaiting = false;\n try {\n const res = await fetch(`${agentUrl}/api/agent/tunnel`);\n if (res.ok) {\n const data = (await res.json()) as {\n tunnelUrl: string | null;\n status: string;\n };\n if (data.tunnelUrl) {\n tunnelUrl = data.tunnelUrl;\n } else if (data.status !== \"inactive\") {\n tunnelWaiting = true;\n }\n }\n } catch {\n /* ignore */\n }\n\n // If tunnel is still starting, wait a bit longer\n if (tunnelWaiting || tunnelUrl === \"(not running)\") {\n const tunnelWaitMs = 20000;\n const tunnelStart = Date.now();\n while (Date.now() - tunnelStart < tunnelWaitMs) {\n try {\n const res = await fetch(`${agentUrl}/api/agent/tunnel`);\n if (res.ok) {\n const data = (await res.json()) as {\n tunnelUrl: string | null;\n status: string;\n };\n if (data.tunnelUrl) {\n tunnelUrl = data.tunnelUrl;\n break;\n }\n }\n } catch {\n /* ignore */\n }\n await new Promise((r) => setTimeout(r, 1000));\n }\n }\n\n header(\"Agent Connection Details\");\n kv(\"Agent URL:\", agentUrl);\n kv(\"API Key:\", apiKey);\n kv(\n \"Tunnel URL:\",\n tunnelUrl === \"(not running)\"\n ? colors.yellow(tunnelUrl)\n : colors.green(tunnelUrl),\n );\n blank();\n console.log(\n \" Copy the API Key and Tunnel URL into the VibeControls UI agent configuration.\",\n );\n if (tunnelUrl === \"(not running)\") {\n console.log(\n ` Start a tunnel manually: ${colors.bold(`vibe tunnel agent --start --agent-url ${agentUrl}`)}`,\n );\n }\n blank();\n}\n",
|
|
7
|
+
"/**\n * OpenTUI Renderer Factory\n *\n * Provides helpers for creating OpenTUI renderers in two modes:\n *\n * 1. One-shot: Render content and exit (for simple command output).\n * Uses `useAlternateScreen: false`, `useMouse: false`, renders once,\n * then destroys the renderer and exits.\n *\n * 2. Interactive: Render content that stays alive for user interaction\n * (dashboard, log streaming, setup wizard, etc.).\n *\n * Both modes use the OpenTUI React bindings.\n *\n * NOTE: OpenTUI requires Bun runtime (Zig FFI rendering backend).\n * If OpenTUI is not available (e.g., not installed), we gracefully\n * fall back to plain console output.\n */\n\nimport type { ReactNode } from \"react\";\n\nexport interface RendererOptions {\n /** Use alternate screen buffer (default: true for interactive, false for one-shot) */\n alternateScreen?: boolean;\n /** Enable mouse input (default: true for interactive, false for one-shot) */\n mouse?: boolean;\n /** Exit delay in ms for one-shot mode (default: 100) */\n exitDelay?: number;\n}\n\n/**\n * Attempt to render a React element using OpenTUI.\n *\n * If OpenTUI is not installed, logs a warning and returns false.\n * This allows CLI commands to gracefully degrade to console.log output.\n */\nexport async function renderOnce(\n element: ReactNode,\n options?: RendererOptions,\n): Promise<boolean> {\n try {\n const opentuiCore = await import(\"@opentui/core\");\n const { createRoot } = await import(\"@opentui/react\");\n\n const RendererClass = (opentuiCore as Record<string, unknown>).Renderer as\n | (new (opts: Record<string, unknown>) => { destroy(): void })\n | undefined;\n\n if (!RendererClass) return false;\n\n const renderer = new RendererClass({\n useAlternateScreen: options?.alternateScreen ?? false,\n useMouse: options?.mouse ?? false,\n });\n\n const root = createRoot(renderer as never);\n root.render(element);\n\n await new Promise((resolve) =>\n setTimeout(resolve, options?.exitDelay ?? 100),\n );\n renderer.destroy();\n return true;\n } catch {\n // OpenTUI not available — caller should fall back to console output\n return false;\n }\n}\n\n/**\n * Create an interactive OpenTUI renderer.\n *\n * Returns a destroy function to clean up. The renderer stays alive until\n * explicitly destroyed or the process exits.\n */\nexport async function renderInteractive(\n element: ReactNode,\n options?: RendererOptions,\n): Promise<{ destroy: () => void } | null> {\n try {\n const opentuiCore = await import(\"@opentui/core\");\n const { createRoot } = await import(\"@opentui/react\");\n\n const RendererClass = (opentuiCore as Record<string, unknown>).Renderer as\n | (new (opts: Record<string, unknown>) => { destroy(): void })\n | undefined;\n\n if (!RendererClass) return null;\n\n const renderer = new RendererClass({\n useAlternateScreen: options?.alternateScreen ?? true,\n useMouse: options?.mouse ?? true,\n });\n\n const root = createRoot(renderer as never);\n root.render(element);\n\n return {\n destroy: () => {\n renderer.destroy();\n },\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Check if OpenTUI is available in the current environment.\n */\nexport async function isOpenTuiAvailable(): Promise<boolean> {\n try {\n await import(\"@opentui/core\");\n return true;\n } catch {\n return false;\n }\n}\n\n// ── Interactive Prompt Utilities ─────────────────────────────────────────\n//\n// These provide TTY-aware prompts that gracefully degrade to simple stdin\n// when OpenTUI is not available. Commands should use these instead of raw\n// stdin operations for consistency.\n\n/**\n * Check if the current environment supports interactive prompts.\n * Returns true when running in a TTY (not piped/redirected).\n */\nexport function isInteractive(): boolean {\n return !!process.stdout.isTTY && !!process.stdin.isTTY;\n}\n\n/**\n * Prompt the user for a yes/no confirmation.\n *\n * Uses raw TTY single-keypress mode for fast response.\n * In non-interactive environments, returns the defaultValue.\n *\n * @param message - The question to display\n * @param defaultValue - Returned when stdin is not a TTY (default: false)\n */\nexport async function promptConfirm(\n message: string,\n defaultValue = false,\n): Promise<boolean> {\n if (!isInteractive()) return defaultValue;\n\n const hint = defaultValue ? \"[Y/n]\" : \"[y/N]\";\n process.stdout.write(` ${message} ${hint} `);\n\n return new Promise<boolean>((resolve) => {\n const stdin = process.stdin;\n stdin.setRawMode?.(true);\n stdin.resume();\n stdin.setEncoding(\"utf8\");\n\n const onData = (key: string) => {\n stdin.removeListener(\"data\", onData);\n stdin.setRawMode?.(false);\n stdin.pause();\n const answer = key.trim().toLowerCase();\n console.log(answer || (defaultValue ? \"y\" : \"n\"));\n\n if (answer === \"\") resolve(defaultValue);\n else resolve(answer === \"y\");\n };\n\n stdin.on(\"data\", onData);\n });\n}\n\n/**\n * Prompt the user to select from a list of options.\n *\n * Uses arrow keys + Enter for selection in TTY mode.\n * In non-interactive environments, returns the defaultIndex.\n *\n * @param message - The prompt header\n * @param options - Array of { label, value } options\n * @param defaultIndex - Default selection index (default: 0)\n */\nexport async function promptSelect<T>(\n message: string,\n options: Array<{ label: string; value: T }>,\n defaultIndex = 0,\n): Promise<T> {\n if (!isInteractive() || options.length === 0) {\n return options[defaultIndex]?.value ?? options[0].value;\n }\n\n console.log(`\\n ${message}\\n`);\n\n let selected = defaultIndex;\n\n return new Promise<T>((resolve) => {\n const stdin = process.stdin;\n stdin.setRawMode?.(true);\n stdin.resume();\n stdin.setEncoding(\"utf8\");\n\n const render = () => {\n // Move cursor up to re-render options\n if (selected >= 0) {\n process.stdout.write(`\\x1b[${options.length}A`);\n }\n for (let i = 0; i < options.length; i++) {\n const prefix = i === selected ? \"\\x1b[36m❯\\x1b[39m\" : \" \";\n const label =\n i === selected\n ? `\\x1b[1m${options[i].label}\\x1b[22m`\n : options[i].label;\n process.stdout.write(` ${prefix} ${label}\\x1b[K\\n`);\n }\n };\n\n // Initial render\n for (let i = 0; i < options.length; i++) {\n const prefix = i === selected ? \"\\x1b[36m❯\\x1b[39m\" : \" \";\n const label =\n i === selected\n ? `\\x1b[1m${options[i].label}\\x1b[22m`\n : options[i].label;\n console.log(` ${prefix} ${label}`);\n }\n\n const onData = (key: string) => {\n // ESC or Ctrl+C\n if (key === \"\\x1b\" || key === \"\\x03\") {\n stdin.removeListener(\"data\", onData);\n stdin.setRawMode?.(false);\n stdin.pause();\n process.exit(0);\n }\n\n // Enter\n if (key === \"\\r\" || key === \"\\n\") {\n stdin.removeListener(\"data\", onData);\n stdin.setRawMode?.(false);\n stdin.pause();\n console.log();\n resolve(options[selected].value);\n return;\n }\n\n // Arrow up / k\n if (key === \"\\x1b[A\" || key === \"k\") {\n selected = (selected - 1 + options.length) % options.length;\n render();\n return;\n }\n\n // Arrow down / j\n if (key === \"\\x1b[B\" || key === \"j\") {\n selected = (selected + 1) % options.length;\n render();\n return;\n }\n };\n\n stdin.on(\"data\", onData);\n });\n}\n"
|
|
8
|
+
],
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "25F2128FF1C6AFEB64756E2164756E21",
|
|
11
|
+
"names": []
|
|
12
|
+
}
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
info,
|
|
19
19
|
kv,
|
|
20
20
|
success
|
|
21
|
-
} from "./index-
|
|
21
|
+
} from "./index-t0x810hm.js";
|
|
22
22
|
import"./index-g8dczzvv.js";
|
|
23
23
|
|
|
24
24
|
// src/plugins/config/routes.ts
|
|
@@ -164,4 +164,4 @@ export {
|
|
|
164
164
|
};
|
|
165
165
|
|
|
166
166
|
//# debugId=9ACD369BD3C87E6764756E2164756E21
|
|
167
|
-
//# sourceMappingURL=index-
|
|
167
|
+
//# sourceMappingURL=index-vzmmv3r7.js.map
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
header,
|
|
15
15
|
info,
|
|
16
16
|
timeAgo
|
|
17
|
-
} from "./index-
|
|
17
|
+
} from "./index-t0x810hm.js";
|
|
18
18
|
import"./index-g8dczzvv.js";
|
|
19
19
|
|
|
20
20
|
// src/plugins/log/routes.ts
|
|
@@ -226,4 +226,4 @@ export {
|
|
|
226
226
|
};
|
|
227
227
|
|
|
228
228
|
//# debugId=04448E46225BA29664756E2164756E21
|
|
229
|
-
//# sourceMappingURL=index-
|
|
229
|
+
//# sourceMappingURL=index-w7m3p4qa.js.map
|
package/dist/index.js
CHANGED
|
@@ -9,8 +9,8 @@ import"./index-wr0mkm57.js";
|
|
|
9
9
|
import"./index-g8dczzvv.js";
|
|
10
10
|
import {
|
|
11
11
|
createApp
|
|
12
|
-
} from "./app-
|
|
13
|
-
import"./plugin-system-
|
|
12
|
+
} from "./app-tba5zhmy.js";
|
|
13
|
+
import"./plugin-system-75q3s1rf.js";
|
|
14
14
|
|
|
15
15
|
// src/index.ts
|
|
16
16
|
if (typeof Bun === "undefined") {
|
|
@@ -3,7 +3,7 @@ import"./index-g8dczzvv.js";
|
|
|
3
3
|
|
|
4
4
|
// package.json
|
|
5
5
|
var name = "@burdenoff/vibe-agent";
|
|
6
|
-
var version = "2.
|
|
6
|
+
var version = "2.8.0";
|
|
7
7
|
var main = "./dist/index.js";
|
|
8
8
|
var type = "module";
|
|
9
9
|
var bin = {
|
|
@@ -134,5 +134,5 @@ export {
|
|
|
134
134
|
author
|
|
135
135
|
};
|
|
136
136
|
|
|
137
|
-
//# debugId=
|
|
138
|
-
//# sourceMappingURL=package-
|
|
137
|
+
//# debugId=0056B34BC81F953D64756E2164756E21
|
|
138
|
+
//# sourceMappingURL=package-cck2kzyn.js.map
|
|
@@ -29,6 +29,20 @@ var CORE_PLUGIN_NAMES = [
|
|
|
29
29
|
var VIBECONTROLS_DIR = join(os.homedir(), ".vibecontrols");
|
|
30
30
|
var REGISTRY_FILE = join(VIBECONTROLS_DIR, "plugins.json");
|
|
31
31
|
var PROVIDER_DEFAULT_PREFIX = "provider:default:";
|
|
32
|
+
var DEFAULT_PLUGINS = [
|
|
33
|
+
{
|
|
34
|
+
packageName: "@burdenoff/vibe-plugin-session-tmux",
|
|
35
|
+
label: "tmux session provider",
|
|
36
|
+
category: "session",
|
|
37
|
+
pluginName: "session-tmux"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
packageName: "@burdenoff/vibe-plugin-tunnel-cloudflare",
|
|
41
|
+
label: "Cloudflare tunnel provider",
|
|
42
|
+
category: "tunnel",
|
|
43
|
+
pluginName: "tunnel-cloudflare"
|
|
44
|
+
}
|
|
45
|
+
];
|
|
32
46
|
|
|
33
47
|
class PluginManager {
|
|
34
48
|
registry = [];
|
|
@@ -64,19 +78,19 @@ class PluginManager {
|
|
|
64
78
|
}
|
|
65
79
|
async loadCorePlugins() {
|
|
66
80
|
const coreModules = await Promise.allSettled([
|
|
67
|
-
import("./index-
|
|
68
|
-
import("./index-
|
|
69
|
-
import("./index-
|
|
70
|
-
import("./index-
|
|
71
|
-
import("./index-
|
|
72
|
-
import("./index-
|
|
73
|
-
import("./index-
|
|
74
|
-
import("./index-
|
|
75
|
-
import("./index-
|
|
76
|
-
import("./index-
|
|
77
|
-
import("./index-
|
|
78
|
-
import("./index-
|
|
79
|
-
import("./index-
|
|
81
|
+
import("./index-exh7dh2v.js"),
|
|
82
|
+
import("./index-et6rnq2y.js"),
|
|
83
|
+
import("./index-9grqzmk5.js"),
|
|
84
|
+
import("./index-0nt6wnb9.js"),
|
|
85
|
+
import("./index-vzmmv3r7.js"),
|
|
86
|
+
import("./index-a3q5ewrj.js"),
|
|
87
|
+
import("./index-7ph3496b.js"),
|
|
88
|
+
import("./index-dhbg241c.js"),
|
|
89
|
+
import("./index-0429nfr9.js"),
|
|
90
|
+
import("./index-swqzafr9.js"),
|
|
91
|
+
import("./index-cndcb55v.js"),
|
|
92
|
+
import("./index-e2dzjkmm.js"),
|
|
93
|
+
import("./index-w7m3p4qa.js")
|
|
80
94
|
]);
|
|
81
95
|
for (let i = 0;i < coreModules.length; i++) {
|
|
82
96
|
const result = coreModules[i];
|
|
@@ -129,6 +143,39 @@ class PluginManager {
|
|
|
129
143
|
logger.info("plugin-manager", `Installed ${packageName}@${plugin.version} (${plugin.name})`);
|
|
130
144
|
return entry;
|
|
131
145
|
}
|
|
146
|
+
async ensureDefaultPlugins(onStatus) {
|
|
147
|
+
const installed = [];
|
|
148
|
+
const categoryMap = new Map;
|
|
149
|
+
for (const entry of DEFAULT_PLUGINS) {
|
|
150
|
+
const list = categoryMap.get(entry.category) || [];
|
|
151
|
+
list.push(entry);
|
|
152
|
+
categoryMap.set(entry.category, list);
|
|
153
|
+
}
|
|
154
|
+
for (const [category, defaults] of categoryMap) {
|
|
155
|
+
const hasPlugin = this.registry.some((r) => {
|
|
156
|
+
return defaults.some((d) => d.packageName === r.packageName);
|
|
157
|
+
});
|
|
158
|
+
if (hasPlugin) {
|
|
159
|
+
logger.info("plugin-manager", `${category} plugin already installed, skipping auto-install`);
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const defaultPlugin = defaults[0];
|
|
163
|
+
onStatus?.(`No ${category} plugin found. Installing ${defaultPlugin.label} (${defaultPlugin.packageName})...`);
|
|
164
|
+
try {
|
|
165
|
+
await this.install(defaultPlugin.packageName);
|
|
166
|
+
installed.push(defaultPlugin);
|
|
167
|
+
onStatus?.(`Installed ${defaultPlugin.label} (${defaultPlugin.packageName})`);
|
|
168
|
+
} catch (err) {
|
|
169
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
170
|
+
logger.error("plugin-manager", `Failed to auto-install ${defaultPlugin.packageName}: ${message}`);
|
|
171
|
+
onStatus?.(`Failed to install ${defaultPlugin.label}: ${message}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (installed.length > 0) {
|
|
175
|
+
this.loadRegistry();
|
|
176
|
+
}
|
|
177
|
+
return installed;
|
|
178
|
+
}
|
|
132
179
|
async installAndLoad(packageName, app, hostServices) {
|
|
133
180
|
const entry = await this.install(packageName);
|
|
134
181
|
const plugin = this.loaded.get(entry.packageName);
|
|
@@ -140,6 +187,78 @@ class PluginManager {
|
|
|
140
187
|
}
|
|
141
188
|
return entry;
|
|
142
189
|
}
|
|
190
|
+
async update(packageName) {
|
|
191
|
+
logger.info("plugin-manager", `Updating ${packageName}...`);
|
|
192
|
+
const existing = this.registry.find((e) => e.packageName === packageName);
|
|
193
|
+
if (!existing) {
|
|
194
|
+
throw new Error(`Plugin ${packageName} is not installed. Use 'install' first.`);
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
const result = Bun.spawnSync(["npm", "install", "-g", `${packageName}@latest`], {
|
|
198
|
+
timeout: 120000,
|
|
199
|
+
stdout: "pipe",
|
|
200
|
+
stderr: "pipe"
|
|
201
|
+
});
|
|
202
|
+
if (result.exitCode !== 0) {
|
|
203
|
+
throw new Error(result.stderr.toString().trim());
|
|
204
|
+
}
|
|
205
|
+
} catch (err) {
|
|
206
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
207
|
+
throw new Error(`Failed to update ${packageName}: ${message}`, {
|
|
208
|
+
cause: err
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
this.loaded.delete(packageName);
|
|
212
|
+
const plugin = await this.importPlugin(packageName);
|
|
213
|
+
const entry = {
|
|
214
|
+
packageName,
|
|
215
|
+
version: plugin.version,
|
|
216
|
+
pluginName: plugin.name,
|
|
217
|
+
installedAt: existing.installedAt
|
|
218
|
+
};
|
|
219
|
+
this.registry = this.registry.filter((e) => e.packageName !== packageName);
|
|
220
|
+
this.registry.push(entry);
|
|
221
|
+
this.saveRegistry();
|
|
222
|
+
logger.info("plugin-manager", `Updated ${packageName} to v${plugin.version}`);
|
|
223
|
+
return entry;
|
|
224
|
+
}
|
|
225
|
+
async updateAll() {
|
|
226
|
+
const results = [];
|
|
227
|
+
for (const entry of [...this.registry]) {
|
|
228
|
+
try {
|
|
229
|
+
const updated = await this.update(entry.packageName);
|
|
230
|
+
results.push({
|
|
231
|
+
packageName: entry.packageName,
|
|
232
|
+
success: true,
|
|
233
|
+
version: updated.version
|
|
234
|
+
});
|
|
235
|
+
} catch (err) {
|
|
236
|
+
results.push({
|
|
237
|
+
packageName: entry.packageName,
|
|
238
|
+
success: false,
|
|
239
|
+
error: err instanceof Error ? err.message : String(err)
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return results;
|
|
244
|
+
}
|
|
245
|
+
async removeAll() {
|
|
246
|
+
const results = [];
|
|
247
|
+
const toRemove = [...this.registry];
|
|
248
|
+
for (const entry of toRemove) {
|
|
249
|
+
try {
|
|
250
|
+
await this.remove(entry.packageName);
|
|
251
|
+
results.push({ packageName: entry.packageName, success: true });
|
|
252
|
+
} catch (err) {
|
|
253
|
+
results.push({
|
|
254
|
+
packageName: entry.packageName,
|
|
255
|
+
success: false,
|
|
256
|
+
error: err instanceof Error ? err.message : String(err)
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return results;
|
|
261
|
+
}
|
|
143
262
|
async remove(packageName) {
|
|
144
263
|
logger.info("plugin-manager", `Removing ${packageName}...`);
|
|
145
264
|
const plugin = this.loaded.get(packageName);
|
|
@@ -502,7 +621,7 @@ class PluginManager {
|
|
|
502
621
|
}
|
|
503
622
|
}
|
|
504
623
|
|
|
505
|
-
export { PluginManager };
|
|
624
|
+
export { PluginManager, DEFAULT_PLUGINS };
|
|
506
625
|
|
|
507
|
-
//# debugId=
|
|
508
|
-
//# sourceMappingURL=plugin-system-
|
|
626
|
+
//# debugId=D696C85BB158D43F64756E2164756E21
|
|
627
|
+
//# sourceMappingURL=plugin-system-75q3s1rf.js.map
|