@burdenoff/vibe-agent 2.1.0 → 2.2.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.
Files changed (54) hide show
  1. package/dist/app-6mmbmske.js +1166 -0
  2. package/dist/app-6mmbmske.js.map +19 -0
  3. package/dist/cli.js +152 -2036
  4. package/dist/cli.js.map +6 -28
  5. package/dist/index-05qfwz8r.js +122 -0
  6. package/dist/index-05qfwz8r.js.map +10 -0
  7. package/dist/index-30p492yv.js +294 -0
  8. package/dist/index-30p492yv.js.map +13 -0
  9. package/dist/index-3v78e2cn.js +373 -0
  10. package/dist/index-3v78e2cn.js.map +11 -0
  11. package/dist/index-41m1exz7.js +269 -0
  12. package/dist/index-41m1exz7.js.map +13 -0
  13. package/dist/index-88ym10cs.js +194 -0
  14. package/dist/index-88ym10cs.js.map +10 -0
  15. package/dist/index-9tgyd3ep.js +513 -0
  16. package/dist/index-9tgyd3ep.js.map +19 -0
  17. package/dist/index-a9g7hbj9.js +229 -0
  18. package/dist/index-a9g7hbj9.js.map +13 -0
  19. package/dist/index-atjhkm74.js +149 -0
  20. package/dist/index-atjhkm74.js.map +10 -0
  21. package/dist/index-c7zy3n33.js +167 -0
  22. package/dist/index-c7zy3n33.js.map +13 -0
  23. package/dist/index-gmz54dkc.js +2 -201
  24. package/dist/index-hefqxwht.js +270 -0
  25. package/dist/index-hefqxwht.js.map +13 -0
  26. package/dist/index-k9hb0b93.js +280 -0
  27. package/dist/index-k9hb0b93.js.map +13 -0
  28. package/dist/index-npmvh1x9.js +385 -0
  29. package/dist/index-npmvh1x9.js.map +13 -0
  30. package/dist/index-q4ytrfx7.js +286 -0
  31. package/dist/index-q4ytrfx7.js.map +13 -0
  32. package/dist/index-qthbtg9n.js +302 -0
  33. package/dist/index-qthbtg9n.js.map +13 -0
  34. package/dist/index-rdm6e3rr.js +587 -0
  35. package/dist/index-rdm6e3rr.js.map +13 -0
  36. package/dist/index-wdtxbebz.js +339 -0
  37. package/dist/index-wdtxbebz.js.map +13 -0
  38. package/dist/{app-31chs2a1.js → index-wr0mkm57.js} +8 -3204
  39. package/dist/{app-31chs2a1.js.map → index-wr0mkm57.js.map} +4 -25
  40. package/dist/index-xmeskdnb.js +292 -0
  41. package/dist/index-xmeskdnb.js.map +11 -0
  42. package/dist/index-xn4tarcd.js +287 -0
  43. package/dist/index-xn4tarcd.js.map +13 -0
  44. package/dist/index.js +9 -6
  45. package/dist/index.js.map +2 -2
  46. package/dist/{package-0158fp3w.js → package-ywexp6sg.js} +4 -4
  47. package/dist/{package-0158fp3w.js.map → package-ywexp6sg.js.map} +1 -1
  48. package/dist/plugin-system-v7a7xnhk.js +475 -0
  49. package/dist/plugin-system-v7a7xnhk.js.map +10 -0
  50. package/package.json +2 -2
  51. package/dist/index-t06ktmx9.js +0 -216
  52. package/dist/index-t06ktmx9.js.map +0 -11
  53. package/dist/plugin-system-bg1pzjj9.js +0 -453
  54. package/dist/plugin-system-bg1pzjj9.js.map +0 -11
@@ -0,0 +1,292 @@
1
+ // @bun
2
+ // src/cli/utils/format.ts
3
+ var colors = {
4
+ bold: (text) => `\x1B[1m${text}\x1B[22m`,
5
+ dim: (text) => `\x1B[2m${text}\x1B[22m`,
6
+ italic: (text) => `\x1B[3m${text}\x1B[23m`,
7
+ underline: (text) => `\x1B[4m${text}\x1B[24m`,
8
+ red: (text) => `\x1B[31m${text}\x1B[39m`,
9
+ green: (text) => `\x1B[32m${text}\x1B[39m`,
10
+ yellow: (text) => `\x1B[33m${text}\x1B[39m`,
11
+ blue: (text) => `\x1B[34m${text}\x1B[39m`,
12
+ magenta: (text) => `\x1B[35m${text}\x1B[39m`,
13
+ cyan: (text) => `\x1B[36m${text}\x1B[39m`,
14
+ white: (text) => `\x1B[37m${text}\x1B[39m`,
15
+ gray: (text) => `\x1B[90m${text}\x1B[39m`,
16
+ brightRed: (text) => `\x1B[91m${text}\x1B[39m`,
17
+ brightGreen: (text) => `\x1B[92m${text}\x1B[39m`,
18
+ brightYellow: (text) => `\x1B[93m${text}\x1B[39m`,
19
+ brightBlue: (text) => `\x1B[94m${text}\x1B[39m`,
20
+ reset: "\x1B[0m"
21
+ };
22
+ var icons = {
23
+ success: colors.green("\u2713"),
24
+ error: colors.red("\u2717"),
25
+ warning: colors.yellow("\u26A0"),
26
+ info: colors.blue("\u25CF"),
27
+ running: colors.green("\u25CF"),
28
+ stopped: colors.red("\u25CB"),
29
+ pending: colors.yellow("\u25CC"),
30
+ arrow: colors.gray("\u2192"),
31
+ bullet: colors.gray("\u2022"),
32
+ check: colors.green("\u2714")
33
+ };
34
+ function fail(msg) {
35
+ console.error(`${colors.red("Error:")} ${msg}`);
36
+ process.exit(1);
37
+ }
38
+ function success(msg) {
39
+ console.log(` ${icons.success} ${msg}`);
40
+ }
41
+ function warn(msg) {
42
+ console.log(` ${icons.warning} ${msg}`);
43
+ }
44
+ function info(msg) {
45
+ console.log(` ${icons.info} ${msg}`);
46
+ }
47
+ function header(title) {
48
+ console.log(`
49
+ ${colors.bold(`\u2500\u2500 ${title} \u2500\u2500`)}
50
+ `);
51
+ }
52
+ function kv(key, value) {
53
+ const display = value === null || value === undefined ? colors.gray("(none)") : String(value);
54
+ console.log(` ${colors.bold(key.padEnd(14))} ${display}`);
55
+ }
56
+ function blank() {
57
+ console.log();
58
+ }
59
+ function formatTable(rows) {
60
+ if (rows.length === 0) {
61
+ console.log(" (none)");
62
+ return;
63
+ }
64
+ console.table(rows);
65
+ }
66
+ function timeAgo(dateStr) {
67
+ const diff = Date.now() - new Date(dateStr).getTime();
68
+ const s = Math.floor(diff / 1000);
69
+ if (s < 0)
70
+ return "just now";
71
+ if (s < 60)
72
+ return `${s}s ago`;
73
+ const m = Math.floor(s / 60);
74
+ if (m < 60)
75
+ return `${m}m ago`;
76
+ const h = Math.floor(m / 60);
77
+ if (h < 24)
78
+ return `${h}h ago`;
79
+ const d = Math.floor(h / 24);
80
+ if (d < 30)
81
+ return `${d}d ago`;
82
+ return `${Math.floor(d / 30)}mo ago`;
83
+ }
84
+ function formatDuration(seconds) {
85
+ if (seconds < 60)
86
+ return `${Math.floor(seconds)}s`;
87
+ const m = Math.floor(seconds / 60);
88
+ const s = Math.floor(seconds % 60);
89
+ if (m < 60)
90
+ return `${m}m ${s}s`;
91
+ const h = Math.floor(m / 60);
92
+ const rm = m % 60;
93
+ return `${h}h ${rm}m`;
94
+ }
95
+ function formatBytes(bytes) {
96
+ if (bytes < 1024)
97
+ return `${bytes} B`;
98
+ if (bytes < 1024 * 1024)
99
+ return `${(bytes / 1024).toFixed(1)} KB`;
100
+ if (bytes < 1024 * 1024 * 1024)
101
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
102
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
103
+ }
104
+ function formatStatus(status) {
105
+ switch (status) {
106
+ case "running":
107
+ case "active":
108
+ case "healthy":
109
+ case "success":
110
+ case "completed":
111
+ return colors.green(status);
112
+ case "stopped":
113
+ case "inactive":
114
+ case "terminated":
115
+ case "failed":
116
+ return colors.red(status);
117
+ case "starting":
118
+ case "stopping":
119
+ case "pending":
120
+ case "warning":
121
+ return colors.yellow(status);
122
+ case "error":
123
+ return colors.red(status);
124
+ default:
125
+ return status;
126
+ }
127
+ }
128
+ function formatNotificationType(type) {
129
+ switch (type) {
130
+ case "error":
131
+ return colors.red("\u25CF");
132
+ case "warning":
133
+ return colors.yellow("\u25CF");
134
+ case "success":
135
+ return colors.green("\u25CF");
136
+ case "info":
137
+ default:
138
+ return colors.blue("\u25CF");
139
+ }
140
+ }
141
+ function shortId(id, len = 10) {
142
+ if (id.length <= len)
143
+ return id;
144
+ return id.substring(0, len) + "...";
145
+ }
146
+ async function printAgentDetails(agentUrl, maxWaitMs = 15000) {
147
+ const startTime = Date.now();
148
+ let healthy = false;
149
+ while (Date.now() - startTime < maxWaitMs) {
150
+ try {
151
+ const res = await fetch(`${agentUrl}/health`);
152
+ if (res.ok) {
153
+ healthy = true;
154
+ break;
155
+ }
156
+ } catch {}
157
+ await new Promise((r) => setTimeout(r, 500));
158
+ }
159
+ if (!healthy) {
160
+ console.log(`
161
+ ${icons.warning} Agent not yet responding at ${agentUrl}. Check ${colors.bold("vibe logs")} for details.
162
+ `);
163
+ return;
164
+ }
165
+ let apiKey = "(unavailable)";
166
+ try {
167
+ const res = await fetch(`${agentUrl}/api/agent/api-key`);
168
+ if (res.ok) {
169
+ const data = await res.json();
170
+ apiKey = data.apiKey;
171
+ }
172
+ } catch {}
173
+ let tunnelUrl = "(not running)";
174
+ let tunnelWaiting = false;
175
+ try {
176
+ const res = await fetch(`${agentUrl}/api/agent/tunnel`);
177
+ if (res.ok) {
178
+ const data = await res.json();
179
+ if (data.tunnelUrl) {
180
+ tunnelUrl = data.tunnelUrl;
181
+ } else if (data.status !== "inactive") {
182
+ tunnelWaiting = true;
183
+ }
184
+ }
185
+ } catch {}
186
+ if (tunnelWaiting || tunnelUrl === "(not running)") {
187
+ const tunnelWaitMs = 20000;
188
+ const tunnelStart = Date.now();
189
+ while (Date.now() - tunnelStart < tunnelWaitMs) {
190
+ try {
191
+ const res = await fetch(`${agentUrl}/api/agent/tunnel`);
192
+ if (res.ok) {
193
+ const data = await res.json();
194
+ if (data.tunnelUrl) {
195
+ tunnelUrl = data.tunnelUrl;
196
+ break;
197
+ }
198
+ }
199
+ } catch {}
200
+ await new Promise((r) => setTimeout(r, 1000));
201
+ }
202
+ }
203
+ header("Agent Connection Details");
204
+ kv("Agent URL:", agentUrl);
205
+ kv("API Key:", apiKey);
206
+ kv("Tunnel URL:", tunnelUrl === "(not running)" ? colors.yellow(tunnelUrl) : colors.green(tunnelUrl));
207
+ blank();
208
+ console.log(" Copy the API Key and Tunnel URL into the VibeControls UI agent configuration.");
209
+ if (tunnelUrl === "(not running)") {
210
+ console.log(` Start a tunnel manually: ${colors.bold(`vibe tunnel agent --start --agent-url ${agentUrl}`)}`);
211
+ }
212
+ blank();
213
+ }
214
+
215
+ // src/cli/utils/api-client.ts
216
+ var DEFAULT_AGENT_URL = "http://localhost:3005";
217
+ var _apiKeyCache = new Map;
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;
256
+ }
257
+ async function apiPost(agentUrl, path, body) {
258
+ const { ok, status, data } = await agentFetch(agentUrl, path, {
259
+ method: "POST",
260
+ body: body != null ? JSON.stringify(body) : undefined
261
+ });
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
+ }
289
+ export { getAgentUrl, apiGet, apiPost, apiPut, apiDelete, colors, icons, fail, success, warn, info, header, kv, blank, formatTable, timeAgo, formatDuration, formatBytes, formatStatus, formatNotificationType, shortId, printAgentDetails };
290
+
291
+ //# debugId=09BE319ACAA6468764756E2164756E21
292
+ //# sourceMappingURL=index-xmeskdnb.js.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cli/utils/format.ts", "../src/cli/utils/api-client.ts"],
4
+ "sourcesContent": [
5
+ "/**\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",
6
+ "/**\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\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 * Get the agent URL from --agent-url option or environment.\n */\nexport function getAgentUrl(opts?: { agentUrl?: string }): string {\n return opts?.agentUrl || 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"
7
+ ],
8
+ "mappings": "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",
9
+ "debugId": "09BE319ACAA6468764756E2164756E21",
10
+ "names": []
11
+ }
@@ -0,0 +1,287 @@
1
+ // @bun
2
+ import {
3
+ Elysia,
4
+ t
5
+ } from "./index-wr0mkm57.js";
6
+ import {
7
+ apiGet,
8
+ apiPost,
9
+ fail,
10
+ formatTable,
11
+ getAgentUrl,
12
+ header,
13
+ info,
14
+ kv,
15
+ success,
16
+ warn
17
+ } from "./index-xmeskdnb.js";
18
+ import {
19
+ __require,
20
+ __toESM
21
+ } from "./index-g8dczzvv.js";
22
+
23
+ // src/plugins/plugin-mgr/routes.ts
24
+ var AVAILABLE_PLUGINS = [
25
+ {
26
+ packageName: "@burdenoff/vibe-plugin-tunnel-cloudflare",
27
+ name: "tunnel-cloudflare",
28
+ description: "Cloudflare Tunnel provider for remote access",
29
+ cliCommand: "tunnel",
30
+ apiPrefix: "/api/tunnel-cloudflare",
31
+ installed: false,
32
+ category: "tunnel"
33
+ },
34
+ {
35
+ packageName: "@burdenoff/vibe-plugin-session-tmux",
36
+ name: "session-tmux",
37
+ description: "tmux session provider for terminal management",
38
+ cliCommand: "session",
39
+ apiPrefix: "/api/session-tmux",
40
+ installed: false,
41
+ category: "session"
42
+ },
43
+ {
44
+ packageName: "@burdenoff/vibe-plugin-ssh",
45
+ name: "ssh",
46
+ description: "SSH connection management and port forwarding",
47
+ cliCommand: "ssh",
48
+ apiPrefix: "/api/ssh",
49
+ installed: false,
50
+ category: "tool"
51
+ },
52
+ {
53
+ packageName: "@burdenoff/vibe-plugin-ai",
54
+ name: "ai",
55
+ description: "AI tool management and integration",
56
+ cliCommand: "ai",
57
+ apiPrefix: undefined,
58
+ installed: false,
59
+ category: "integration"
60
+ },
61
+ {
62
+ packageName: "@burdenoff/vibe-plugin-ui-ssh",
63
+ name: "ui-ssh",
64
+ description: "Web UI for SSH connection management and port forwarding",
65
+ cliCommand: undefined,
66
+ apiPrefix: undefined,
67
+ installed: false,
68
+ category: "frontend"
69
+ },
70
+ {
71
+ packageName: "@burdenoff/vibe-plugin-ui-ai",
72
+ name: "ui-ai",
73
+ description: "Web UI for AI tool catalog and detection status",
74
+ cliCommand: undefined,
75
+ apiPrefix: undefined,
76
+ installed: false,
77
+ category: "frontend"
78
+ }
79
+ ];
80
+ function createRoutes(deps) {
81
+ const { pluginManager } = deps;
82
+ return new Elysia().get("/", () => {
83
+ const plugins = pluginManager.getPluginDetails();
84
+ return { plugins, count: plugins.length };
85
+ }).get("/available", () => {
86
+ const installed = pluginManager.getPluginDetails();
87
+ const installedNames = new Set(installed.map((p) => p.packageName));
88
+ return {
89
+ plugins: AVAILABLE_PLUGINS.map((p) => ({
90
+ ...p,
91
+ installed: installedNames.has(p.packageName)
92
+ }))
93
+ };
94
+ }).post("/install", async ({ body, set }) => {
95
+ if (!body.packageName || typeof body.packageName !== "string") {
96
+ set.status = 400;
97
+ return { error: "Missing required field: packageName" };
98
+ }
99
+ try {
100
+ await pluginManager.install(body.packageName);
101
+ return {
102
+ success: true,
103
+ message: `Plugin ${body.packageName} installed and loaded successfully`
104
+ };
105
+ } catch (err) {
106
+ set.status = 500;
107
+ return { error: "Failed to install plugin", details: String(err) };
108
+ }
109
+ }, {
110
+ body: t.Object({
111
+ packageName: t.String()
112
+ })
113
+ }).post("/remove", async ({ body, set }) => {
114
+ if (!body.packageName || typeof body.packageName !== "string") {
115
+ set.status = 400;
116
+ return { error: "Missing required field: packageName" };
117
+ }
118
+ try {
119
+ await pluginManager.remove(body.packageName);
120
+ return {
121
+ success: true,
122
+ message: `Plugin ${body.packageName} removed successfully`
123
+ };
124
+ } catch (err) {
125
+ set.status = 500;
126
+ return { error: "Failed to remove plugin", details: String(err) };
127
+ }
128
+ }, {
129
+ body: t.Object({
130
+ packageName: t.String()
131
+ })
132
+ }).post("/reload", async ({ set }) => {
133
+ try {
134
+ await pluginManager.dispatchServerStop();
135
+ await pluginManager.loadAll();
136
+ const plugins = pluginManager.getPluginDetails();
137
+ return {
138
+ success: true,
139
+ plugins,
140
+ message: `Reloaded ${plugins.length} plugin(s)`
141
+ };
142
+ } catch (err) {
143
+ set.status = 500;
144
+ return { error: "Failed to reload plugins", details: String(err) };
145
+ }
146
+ });
147
+ }
148
+
149
+ // src/cli/commands/plugin.cmd.ts
150
+ var DEFAULT_AGENT_URL = "http://localhost:3005";
151
+ function register(program) {
152
+ const cmd = program.command("plugin").description("Manage plugins");
153
+ cmd.command("list").description("List installed plugins").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
154
+ try {
155
+ const url = getAgentUrl(options);
156
+ let plugins;
157
+ try {
158
+ const data = await apiGet(url, "/api/plugins");
159
+ plugins = data.plugins || [];
160
+ } catch {
161
+ warn("Agent not reachable. Attempting local plugin registry...");
162
+ try {
163
+ const { PluginManager } = await import("./plugin-system-v7a7xnhk.js");
164
+ const pm = new PluginManager;
165
+ plugins = pm.getPluginDetails() || [];
166
+ } catch {
167
+ fail("Could not list plugins from agent or local registry.");
168
+ return;
169
+ }
170
+ }
171
+ if (!plugins || plugins.length === 0) {
172
+ info("No plugins installed.");
173
+ return;
174
+ }
175
+ header("Installed Plugins");
176
+ formatTable(plugins.map((p) => ({
177
+ Name: p.name || p.package || "-",
178
+ Version: p.version || "-",
179
+ Status: p.status || p.enabled ? "enabled" : "disabled",
180
+ Description: p.description || "-"
181
+ })));
182
+ } catch (err) {
183
+ fail(err.message);
184
+ }
185
+ });
186
+ cmd.command("install").description("Install a plugin").argument("<package>", "NPM package name to install").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (packageName, options) => {
187
+ try {
188
+ const url = getAgentUrl(options);
189
+ try {
190
+ const result = await apiPost(url, "/api/plugins/install", {
191
+ package: packageName
192
+ });
193
+ success(`Plugin "${packageName}" installed.`);
194
+ if (result?.version)
195
+ kv("Version", result.version);
196
+ } catch {
197
+ warn("Agent not reachable. Attempting local install...");
198
+ try {
199
+ const { PluginManager } = await import("./plugin-system-v7a7xnhk.js");
200
+ const pm = new PluginManager;
201
+ await pm.install(packageName);
202
+ success(`Plugin "${packageName}" installed locally.`);
203
+ } catch (localErr) {
204
+ fail(`Could not install plugin via agent or locally: ${localErr.message}`);
205
+ }
206
+ }
207
+ } catch (err) {
208
+ fail(err.message);
209
+ }
210
+ });
211
+ cmd.command("remove").description("Remove a plugin").argument("<package>", "NPM package name to remove").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (packageName, options) => {
212
+ try {
213
+ const url = getAgentUrl(options);
214
+ try {
215
+ await apiPost(url, "/api/plugins/remove", {
216
+ package: packageName
217
+ });
218
+ success(`Plugin "${packageName}" removed.`);
219
+ } catch {
220
+ warn("Agent not reachable. Attempting local removal...");
221
+ try {
222
+ const { PluginManager } = await import("./plugin-system-v7a7xnhk.js");
223
+ const pm = new PluginManager;
224
+ await pm.remove(packageName);
225
+ success(`Plugin "${packageName}" removed locally.`);
226
+ } catch (localErr) {
227
+ fail(`Could not remove plugin via agent or locally: ${localErr.message}`);
228
+ }
229
+ }
230
+ } catch (err) {
231
+ fail(err.message);
232
+ }
233
+ });
234
+ cmd.command("reload").description("Reload all plugins").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
235
+ try {
236
+ const url = getAgentUrl(options);
237
+ await apiPost(url, "/api/plugins/reload", {});
238
+ success("Plugins reloaded.");
239
+ } catch (err) {
240
+ fail(err.message);
241
+ }
242
+ });
243
+ cmd.command("available").description("Show available plugins").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
244
+ try {
245
+ const url = getAgentUrl(options);
246
+ const availData = await apiGet(url, "/api/plugins/available");
247
+ const plugins = availData.plugins || [];
248
+ if (!plugins || plugins.length === 0) {
249
+ info("No available plugins found.");
250
+ return;
251
+ }
252
+ header("Available Plugins");
253
+ formatTable(plugins.map((p) => ({
254
+ Name: p.name || p.package || "-",
255
+ Version: p.version || p.latestVersion || "-",
256
+ Description: p.description || "-"
257
+ })));
258
+ } catch (err) {
259
+ fail(err.message);
260
+ }
261
+ });
262
+ }
263
+
264
+ // src/plugins/plugin-mgr/commands.ts
265
+ function registerCommands(program, _hostServices) {
266
+ register(program);
267
+ }
268
+
269
+ // src/plugins/plugin-mgr/index.ts
270
+ var vibePlugin = {
271
+ name: "plugin-mgr",
272
+ version: "2.2.0",
273
+ description: "Plugin lifecycle management \u2014 install, remove, reload, catalog",
274
+ tags: ["backend", "cli"],
275
+ cliCommand: "plugin",
276
+ apiPrefix: "/api/plugins",
277
+ createRoutes: (deps) => createRoutes(deps),
278
+ onCliSetup: async (program, hostServices) => {
279
+ registerCommands(program, hostServices);
280
+ }
281
+ };
282
+ export {
283
+ vibePlugin
284
+ };
285
+
286
+ //# debugId=6D591618982CB48A64756E2164756E21
287
+ //# sourceMappingURL=index-xn4tarcd.js.map