@burdenoff/vibe-agent 2.1.1 → 2.3.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 (53) hide show
  1. package/dist/app-sm6n9xst.js +1165 -0
  2. package/dist/app-sm6n9xst.js.map +19 -0
  3. package/dist/cli.js +167 -2050
  4. package/dist/cli.js.map +8 -30
  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-3rjnbp97.js +268 -0
  10. package/dist/index-3rjnbp97.js.map +13 -0
  11. package/dist/index-6vry08rz.js +285 -0
  12. package/dist/index-6vry08rz.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-a9g7hbj9.js +229 -0
  16. package/dist/index-a9g7hbj9.js.map +13 -0
  17. package/dist/index-atjhkm74.js +149 -0
  18. package/dist/index-atjhkm74.js.map +10 -0
  19. package/dist/index-b1eq3qvs.js +515 -0
  20. package/dist/index-b1eq3qvs.js.map +19 -0
  21. package/dist/index-c7zy3n33.js +167 -0
  22. package/dist/index-c7zy3n33.js.map +13 -0
  23. package/dist/index-fm6gqenc.js +338 -0
  24. package/dist/index-fm6gqenc.js.map +13 -0
  25. package/dist/index-hefqxwht.js +270 -0
  26. package/dist/index-hefqxwht.js.map +13 -0
  27. package/dist/index-k9hb0b93.js +280 -0
  28. package/dist/index-k9hb0b93.js.map +13 -0
  29. package/dist/index-npmvh1x9.js +385 -0
  30. package/dist/index-npmvh1x9.js.map +13 -0
  31. package/dist/index-rdm6e3rr.js +587 -0
  32. package/dist/index-rdm6e3rr.js.map +13 -0
  33. package/dist/index-s7ff1fj1.js +415 -0
  34. package/dist/index-s7ff1fj1.js.map +11 -0
  35. package/dist/index-t4qgjy5w.js +287 -0
  36. package/dist/index-t4qgjy5w.js.map +13 -0
  37. package/dist/index-wmvkjcjj.js +301 -0
  38. package/dist/index-wmvkjcjj.js.map +13 -0
  39. package/dist/{app-31chs2a1.js → index-wr0mkm57.js} +8 -3201
  40. package/dist/{app-31chs2a1.js.map → index-wr0mkm57.js.map} +4 -25
  41. package/dist/index-xmeskdnb.js +292 -0
  42. package/dist/index-xmeskdnb.js.map +11 -0
  43. package/dist/index.js +9 -6
  44. package/dist/index.js.map +2 -2
  45. package/dist/{package-hb6db316.js → package-04nkt49b.js} +5 -3
  46. package/dist/{package-hb6db316.js.map → package-04nkt49b.js.map} +1 -1
  47. package/dist/plugin-system-7r9mb1tb.js +479 -0
  48. package/dist/plugin-system-7r9mb1tb.js.map +10 -0
  49. package/package.json +3 -1
  50. package/dist/index-t06ktmx9.js +0 -216
  51. package/dist/index-t06ktmx9.js.map +0 -11
  52. package/dist/plugin-system-bg1pzjj9.js +0 -450
  53. package/dist/plugin-system-bg1pzjj9.js.map +0 -11
package/dist/cli.js CHANGED
@@ -1,19 +1,39 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
3
  import {
4
- ServiceRegistry,
4
+ ServiceRegistry
5
+ } from "./index-atjhkm74.js";
6
+ import {
7
+ ServiceManager,
5
8
  checkDependencies,
6
9
  installDependencies
7
- } from "./index-t06ktmx9.js";
10
+ } from "./index-s7ff1fj1.js";
11
+ import {
12
+ logger
13
+ } from "./index-88ym10cs.js";
14
+ import {
15
+ blank,
16
+ colors,
17
+ fail,
18
+ formatStatus,
19
+ formatTable,
20
+ header,
21
+ icons,
22
+ info,
23
+ kv,
24
+ printAgentDetails,
25
+ success,
26
+ timeAgo,
27
+ warn
28
+ } from "./index-xmeskdnb.js";
8
29
  import {
9
30
  __commonJS,
10
31
  __require,
11
32
  __toESM
12
33
  } from "./index-g8dczzvv.js";
13
34
  import {
14
- PluginManager,
15
- logger
16
- } from "./plugin-system-bg1pzjj9.js";
35
+ PluginManager
36
+ } from "./plugin-system-7r9mb1tb.js";
17
37
 
18
38
  // node_modules/commander/lib/error.js
19
39
  var require_error = __commonJS((exports) => {
@@ -2125,548 +2145,29 @@ var {
2125
2145
  } = import__.default;
2126
2146
 
2127
2147
  // src/cli.ts
2128
- import { readFileSync as readFileSync3 } from "fs";
2129
- import { join as join4, dirname as dirname2 } from "path";
2130
- import { fileURLToPath as fileURLToPath2 } from "url";
2148
+ import { join as join3 } from "path";
2131
2149
 
2132
2150
  // src/cli/commands/start.cmd.ts
2133
- import { existsSync as existsSync2 } from "fs";
2134
- import { join as join2 } from "path";
2135
- import { homedir as homedir2 } from "os";
2136
-
2137
- // src/cli/utils/api-client.ts
2138
- var DEFAULT_AGENT_URL = "http://localhost:3005";
2139
- var _apiKeyCache = new Map;
2140
- function getAgentUrl(opts) {
2141
- return opts?.agentUrl || process.env.AGENT_URL || DEFAULT_AGENT_URL;
2142
- }
2143
- async function resolveApiKey(agentUrl) {
2144
- if (process.env.AGENT_API_KEY)
2145
- return process.env.AGENT_API_KEY;
2146
- if (_apiKeyCache.has(agentUrl))
2147
- return _apiKeyCache.get(agentUrl);
2148
- try {
2149
- const res = await fetch(`${agentUrl}/api/agent/api-key`);
2150
- if (res.ok) {
2151
- const data = await res.json();
2152
- if (data.apiKey) {
2153
- _apiKeyCache.set(agentUrl, data.apiKey);
2154
- return data.apiKey;
2155
- }
2156
- }
2157
- } catch {}
2158
- return;
2159
- }
2160
- async function agentFetch(agentUrl, path, options = {}) {
2161
- const apiKey = await resolveApiKey(agentUrl);
2162
- const headers = {
2163
- ...options.body ? { "Content-Type": "application/json" } : {},
2164
- ...apiKey ? { "x-agent-api-key": apiKey } : {},
2165
- ...options.headers ?? {}
2166
- };
2167
- const res = await fetch(`${agentUrl}${path}`, { ...options, headers });
2168
- const data = await res.json().catch(() => ({}));
2169
- return { ok: res.ok, status: res.status, data };
2170
- }
2171
- async function apiGet(agentUrl, path) {
2172
- const { ok, status, data } = await agentFetch(agentUrl, path);
2173
- if (!ok) {
2174
- const errorMsg = data?.error || data?.message || `Agent returned ${status}`;
2175
- throw new Error(String(errorMsg));
2176
- }
2177
- return data;
2178
- }
2179
- async function apiPost(agentUrl, path, body) {
2180
- const { ok, status, data } = await agentFetch(agentUrl, path, {
2181
- method: "POST",
2182
- body: body != null ? JSON.stringify(body) : undefined
2183
- });
2184
- if (!ok) {
2185
- const errorMsg = data?.error || data?.message || `Agent returned ${status}`;
2186
- throw new Error(String(errorMsg));
2187
- }
2188
- return data;
2189
- }
2190
- async function apiPut(agentUrl, path, body) {
2191
- const { ok, status, data } = await agentFetch(agentUrl, path, {
2192
- method: "PUT",
2193
- body: body != null ? JSON.stringify(body) : undefined
2194
- });
2195
- if (!ok) {
2196
- const errorMsg = data?.error || data?.message || `Agent returned ${status}`;
2197
- throw new Error(String(errorMsg));
2198
- }
2199
- return data;
2200
- }
2201
- async function apiDelete(agentUrl, path) {
2202
- const { ok, status, data } = await agentFetch(agentUrl, path, {
2203
- method: "DELETE"
2204
- });
2205
- if (!ok) {
2206
- const errorMsg = data?.error || data?.message || `Agent returned ${status}`;
2207
- throw new Error(String(errorMsg));
2208
- }
2209
- return data;
2210
- }
2211
- // src/cli/utils/format.ts
2212
- var colors = {
2213
- bold: (text) => `\x1B[1m${text}\x1B[22m`,
2214
- dim: (text) => `\x1B[2m${text}\x1B[22m`,
2215
- italic: (text) => `\x1B[3m${text}\x1B[23m`,
2216
- underline: (text) => `\x1B[4m${text}\x1B[24m`,
2217
- red: (text) => `\x1B[31m${text}\x1B[39m`,
2218
- green: (text) => `\x1B[32m${text}\x1B[39m`,
2219
- yellow: (text) => `\x1B[33m${text}\x1B[39m`,
2220
- blue: (text) => `\x1B[34m${text}\x1B[39m`,
2221
- magenta: (text) => `\x1B[35m${text}\x1B[39m`,
2222
- cyan: (text) => `\x1B[36m${text}\x1B[39m`,
2223
- white: (text) => `\x1B[37m${text}\x1B[39m`,
2224
- gray: (text) => `\x1B[90m${text}\x1B[39m`,
2225
- brightRed: (text) => `\x1B[91m${text}\x1B[39m`,
2226
- brightGreen: (text) => `\x1B[92m${text}\x1B[39m`,
2227
- brightYellow: (text) => `\x1B[93m${text}\x1B[39m`,
2228
- brightBlue: (text) => `\x1B[94m${text}\x1B[39m`,
2229
- reset: "\x1B[0m"
2230
- };
2231
- var icons = {
2232
- success: colors.green("\u2713"),
2233
- error: colors.red("\u2717"),
2234
- warning: colors.yellow("\u26A0"),
2235
- info: colors.blue("\u25CF"),
2236
- running: colors.green("\u25CF"),
2237
- stopped: colors.red("\u25CB"),
2238
- pending: colors.yellow("\u25CC"),
2239
- arrow: colors.gray("\u2192"),
2240
- bullet: colors.gray("\u2022"),
2241
- check: colors.green("\u2714")
2242
- };
2243
- function fail(msg) {
2244
- console.error(`${colors.red("Error:")} ${msg}`);
2245
- process.exit(1);
2246
- }
2247
- function success(msg) {
2248
- console.log(` ${icons.success} ${msg}`);
2249
- }
2250
- function warn(msg) {
2251
- console.log(` ${icons.warning} ${msg}`);
2252
- }
2253
- function info(msg) {
2254
- console.log(` ${icons.info} ${msg}`);
2255
- }
2256
- function header(title) {
2257
- console.log(`
2258
- ${colors.bold(`\u2500\u2500 ${title} \u2500\u2500`)}
2259
- `);
2260
- }
2261
- function kv(key, value) {
2262
- const display = value === null || value === undefined ? colors.gray("(none)") : String(value);
2263
- console.log(` ${colors.bold(key.padEnd(14))} ${display}`);
2264
- }
2265
- function blank() {
2266
- console.log();
2267
- }
2268
- function formatTable(rows) {
2269
- if (rows.length === 0) {
2270
- console.log(" (none)");
2271
- return;
2272
- }
2273
- console.table(rows);
2274
- }
2275
- function timeAgo(dateStr) {
2276
- const diff = Date.now() - new Date(dateStr).getTime();
2277
- const s = Math.floor(diff / 1000);
2278
- if (s < 0)
2279
- return "just now";
2280
- if (s < 60)
2281
- return `${s}s ago`;
2282
- const m = Math.floor(s / 60);
2283
- if (m < 60)
2284
- return `${m}m ago`;
2285
- const h = Math.floor(m / 60);
2286
- if (h < 24)
2287
- return `${h}h ago`;
2288
- const d = Math.floor(h / 24);
2289
- if (d < 30)
2290
- return `${d}d ago`;
2291
- return `${Math.floor(d / 30)}mo ago`;
2292
- }
2293
- function formatDuration(seconds) {
2294
- if (seconds < 60)
2295
- return `${Math.floor(seconds)}s`;
2296
- const m = Math.floor(seconds / 60);
2297
- const s = Math.floor(seconds % 60);
2298
- if (m < 60)
2299
- return `${m}m ${s}s`;
2300
- const h = Math.floor(m / 60);
2301
- const rm = m % 60;
2302
- return `${h}h ${rm}m`;
2303
- }
2304
- function formatBytes(bytes) {
2305
- if (bytes < 1024)
2306
- return `${bytes} B`;
2307
- if (bytes < 1024 * 1024)
2308
- return `${(bytes / 1024).toFixed(1)} KB`;
2309
- if (bytes < 1024 * 1024 * 1024)
2310
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
2311
- return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
2312
- }
2313
- function formatStatus(status) {
2314
- switch (status) {
2315
- case "running":
2316
- case "active":
2317
- case "healthy":
2318
- case "success":
2319
- case "completed":
2320
- return colors.green(status);
2321
- case "stopped":
2322
- case "inactive":
2323
- case "terminated":
2324
- case "failed":
2325
- return colors.red(status);
2326
- case "starting":
2327
- case "stopping":
2328
- case "pending":
2329
- case "warning":
2330
- return colors.yellow(status);
2331
- case "error":
2332
- return colors.red(status);
2333
- default:
2334
- return status;
2335
- }
2336
- }
2337
- function formatNotificationType(type) {
2338
- switch (type) {
2339
- case "error":
2340
- return colors.red("\u25CF");
2341
- case "warning":
2342
- return colors.yellow("\u25CF");
2343
- case "success":
2344
- return colors.green("\u25CF");
2345
- case "info":
2346
- default:
2347
- return colors.blue("\u25CF");
2348
- }
2349
- }
2350
- function shortId(id, len = 10) {
2351
- if (id.length <= len)
2352
- return id;
2353
- return id.substring(0, len) + "...";
2354
- }
2355
- async function printAgentDetails(agentUrl, maxWaitMs = 15000) {
2356
- const startTime = Date.now();
2357
- let healthy = false;
2358
- while (Date.now() - startTime < maxWaitMs) {
2359
- try {
2360
- const res = await fetch(`${agentUrl}/health`);
2361
- if (res.ok) {
2362
- healthy = true;
2363
- break;
2364
- }
2365
- } catch {}
2366
- await new Promise((r) => setTimeout(r, 500));
2367
- }
2368
- if (!healthy) {
2369
- console.log(`
2370
- ${icons.warning} Agent not yet responding at ${agentUrl}. Check ${colors.bold("vibe logs")} for details.
2371
- `);
2372
- return;
2373
- }
2374
- let apiKey = "(unavailable)";
2375
- try {
2376
- const res = await fetch(`${agentUrl}/api/agent/api-key`);
2377
- if (res.ok) {
2378
- const data = await res.json();
2379
- apiKey = data.apiKey;
2380
- }
2381
- } catch {}
2382
- let tunnelUrl = "(not running)";
2383
- let tunnelWaiting = false;
2384
- try {
2385
- const res = await fetch(`${agentUrl}/api/agent/tunnel`);
2386
- if (res.ok) {
2387
- const data = await res.json();
2388
- if (data.tunnelUrl) {
2389
- tunnelUrl = data.tunnelUrl;
2390
- } else if (data.status !== "inactive") {
2391
- tunnelWaiting = true;
2392
- }
2393
- }
2394
- } catch {}
2395
- if (tunnelWaiting || tunnelUrl === "(not running)") {
2396
- const tunnelWaitMs = 20000;
2397
- const tunnelStart = Date.now();
2398
- while (Date.now() - tunnelStart < tunnelWaitMs) {
2399
- try {
2400
- const res = await fetch(`${agentUrl}/api/agent/tunnel`);
2401
- if (res.ok) {
2402
- const data = await res.json();
2403
- if (data.tunnelUrl) {
2404
- tunnelUrl = data.tunnelUrl;
2405
- break;
2406
- }
2407
- }
2408
- } catch {}
2409
- await new Promise((r) => setTimeout(r, 1000));
2410
- }
2411
- }
2412
- header("Agent Connection Details");
2413
- kv("Agent URL:", agentUrl);
2414
- kv("API Key:", apiKey);
2415
- kv("Tunnel URL:", tunnelUrl === "(not running)" ? colors.yellow(tunnelUrl) : colors.green(tunnelUrl));
2416
- blank();
2417
- console.log(" Copy the API Key and Tunnel URL into the VibeControls UI agent configuration.");
2418
- if (tunnelUrl === "(not running)") {
2419
- console.log(` Start a tunnel manually: ${colors.bold(`vibe tunnel agent --start --agent-url ${agentUrl}`)}`);
2420
- }
2421
- blank();
2422
- }
2423
- // src/services/service-manager.ts
2424
- import { spawn } from "child_process";
2425
- import { promisify } from "util";
2426
- import {
2427
- existsSync,
2428
- readFileSync,
2429
- writeFileSync,
2430
- mkdirSync,
2431
- openSync,
2432
- closeSync
2433
- } from "fs";
2434
- import { join, dirname } from "path";
2435
- import { fileURLToPath } from "url";
2151
+ import { existsSync } from "fs";
2152
+ import { join } from "path";
2436
2153
  import { homedir } from "os";
2437
- import { exec } from "child_process";
2438
- var execAsync = promisify(exec);
2439
- var __filename2 = fileURLToPath(import.meta.url);
2440
- var __dirname2 = dirname(__filename2);
2441
2154
 
2442
- class ServiceManager {
2443
- registryPath;
2444
- logsDir;
2445
- constructor() {
2446
- const configDir = join(homedir(), ".vibecontrols");
2447
- this.registryPath = join(configDir, "agents.json");
2448
- this.logsDir = join(configDir, "logs");
2449
- mkdirSync(configDir, { recursive: true });
2450
- mkdirSync(this.logsDir, { recursive: true });
2451
- }
2452
- async startDaemon(config) {
2453
- const existing = await this.findProcessByName(config.name);
2454
- if (existing && existing.status === "running") {
2455
- console.log(`\u26A0\uFE0F Agent '${config.name}' is already running on port ${existing.port}`);
2456
- return;
2457
- }
2458
- const logFile = join(this.logsDir, `${config.name}.log`);
2459
- const logFd = openSync(logFile, "a");
2460
- const indexPath = join(__dirname2, "..", "index.js");
2461
- const child = spawn("bun", ["run", indexPath], {
2462
- detached: true,
2463
- stdio: ["ignore", logFd, logFd],
2464
- env: {
2465
- ...process.env,
2466
- PORT: config.port.toString(),
2467
- DB_PATH: config.dbPath,
2468
- NODE_ENV: "production"
2469
- }
2470
- });
2471
- closeSync(logFd);
2472
- child.unref();
2473
- await new Promise((resolve) => setTimeout(resolve, 2000));
2474
- const isRunning = await this.isProcessRunning(child.pid);
2475
- if (!isRunning) {
2476
- throw new Error(`Failed to start agent '${config.name}'`);
2477
- }
2478
- await this.saveProcessInfo(config.name, child.pid, config);
2479
- console.log(`\uD83D\uDE80 Agent '${config.name}' started (PID: ${child.pid}, Port: ${config.port})`);
2480
- }
2481
- async stop(name) {
2482
- const agentProcess = await this.findProcessByName(name);
2483
- if (!agentProcess || agentProcess.status !== "running") {
2484
- console.log(`\u26A0\uFE0F Agent '${name}' is not running`);
2485
- return;
2486
- }
2487
- try {
2488
- process.kill(agentProcess.pid, "SIGTERM");
2489
- await new Promise((resolve) => setTimeout(resolve, 3000));
2490
- const stillRunning = await this.isProcessRunning(agentProcess.pid);
2491
- if (stillRunning) {
2492
- process.kill(agentProcess.pid, "SIGKILL");
2493
- }
2494
- await this.updateProcessStatus(name, "stopped");
2495
- console.log(`\u2705 Agent '${name}' stopped`);
2496
- } catch (err) {
2497
- throw new Error(`Failed to stop agent '${name}': ${err}`, { cause: err });
2498
- }
2499
- }
2500
- async restart(name, config) {
2501
- const existing = await this.findProcessByName(name);
2502
- if (existing && existing.status === "running") {
2503
- await this.stop(name);
2504
- }
2505
- await this.startDaemon(config);
2506
- console.log(`\uD83D\uDD04 Agent '${name}' restarted`);
2507
- }
2508
- async kill(name) {
2509
- const agentProcess = await this.findProcessByName(name);
2510
- if (!agentProcess || agentProcess.status !== "running") {
2511
- console.log(`\u26A0\uFE0F Agent '${name}' is not running`);
2512
- return;
2513
- }
2514
- await this.killProcessTree(agentProcess.pid);
2515
- await this.updateProcessStatus(name, "stopped");
2516
- console.log(`\uD83D\uDC80 Agent '${name}' killed`);
2517
- }
2518
- async getStatus(name) {
2519
- return this.findProcessByName(name);
2520
- }
2521
- async getStatusAll() {
2522
- const registry = this.loadRegistry();
2523
- const processes = [];
2524
- for (const processInfo of registry) {
2525
- const isRunning = await this.isProcessRunning(processInfo.pid);
2526
- processes.push({
2527
- ...processInfo,
2528
- status: isRunning ? "running" : "stopped"
2529
- });
2530
- }
2531
- return processes;
2532
- }
2533
- async listInstances() {
2534
- return this.getStatusAll();
2535
- }
2536
- async showLogs(name, options) {
2537
- const logFile = join(this.logsDir, `${name}.log`);
2538
- if (!existsSync(logFile)) {
2539
- console.log(`No logs found for agent '${name}'`);
2540
- return;
2541
- }
2542
- if (options.follow) {
2543
- const tail = spawn("tail", [
2544
- "-f",
2545
- "-n",
2546
- options.tail.toString(),
2547
- logFile
2548
- ]);
2549
- tail.stdout?.on("data", (data) => process.stdout.write(data));
2550
- tail.stderr?.on("data", (data) => process.stderr.write(data));
2551
- process.on("SIGINT", () => {
2552
- tail.kill();
2553
- process.exit(0);
2554
- });
2555
- } else {
2556
- try {
2557
- const { stdout } = await execAsync(`tail -n ${options.tail} "${logFile}"`);
2558
- console.log(stdout);
2559
- } catch (err) {
2560
- console.error("Failed to read logs:", err);
2561
- }
2562
- }
2563
- }
2564
- async checkHealth(name) {
2565
- const proc = await this.findProcessByName(name);
2566
- if (!proc || proc.status !== "running") {
2567
- return { healthy: false, details: { error: "Process not running" } };
2568
- }
2155
+ // src/services/port-utils.ts
2156
+ function isPortAvailable(port, host = "0.0.0.0") {
2157
+ return new Promise((resolve) => {
2569
2158
  try {
2570
- const response = await fetch(`http://localhost:${proc.port}/health`);
2571
- const data = await response.json();
2572
- return { healthy: response.ok, details: data };
2573
- } catch (err) {
2574
- return {
2575
- healthy: false,
2576
- details: {
2577
- error: "Health check failed",
2578
- message: err.message
2159
+ const server = Bun.listen({
2160
+ hostname: host,
2161
+ port,
2162
+ socket: {
2163
+ data() {}
2579
2164
  }
2580
- };
2581
- }
2582
- }
2583
- async setConfig(key, value) {
2584
- const configFile = join(homedir(), ".vibecontrols", "config.json");
2585
- let config = {};
2586
- if (existsSync(configFile)) {
2587
- config = JSON.parse(readFileSync(configFile, "utf8"));
2588
- }
2589
- config[key] = value;
2590
- writeFileSync(configFile, JSON.stringify(config, null, 2));
2591
- }
2592
- async getConfig(key) {
2593
- const configFile = join(homedir(), ".vibecontrols", "config.json");
2594
- if (!existsSync(configFile))
2595
- return key ? undefined : {};
2596
- const config = JSON.parse(readFileSync(configFile, "utf8"));
2597
- return key ? config[key] : config;
2598
- }
2599
- loadRegistry() {
2600
- if (!existsSync(this.registryPath))
2601
- return [];
2602
- try {
2603
- return JSON.parse(readFileSync(this.registryPath, "utf8"));
2604
- } catch {
2605
- return [];
2606
- }
2607
- }
2608
- saveRegistry(processes) {
2609
- writeFileSync(this.registryPath, JSON.stringify(processes, null, 2));
2610
- }
2611
- async saveProcessInfo(name, pid, config) {
2612
- const registry = this.loadRegistry();
2613
- const filtered = registry.filter((p) => p.name !== name);
2614
- filtered.push({
2615
- name,
2616
- pid,
2617
- port: config.port,
2618
- config,
2619
- startTime: new Date().toISOString(),
2620
- status: "running"
2621
- });
2622
- this.saveRegistry(filtered);
2623
- }
2624
- async updateProcessStatus(name, status) {
2625
- const registry = this.loadRegistry();
2626
- const proc = registry.find((p) => p.name === name);
2627
- if (proc) {
2628
- proc.status = status;
2629
- this.saveRegistry(registry);
2630
- }
2631
- }
2632
- async findProcessByName(name) {
2633
- const registry = this.loadRegistry();
2634
- const proc = registry.find((p) => p.name === name);
2635
- if (!proc)
2636
- return null;
2637
- const isRunning = await this.isProcessRunning(proc.pid);
2638
- proc.status = isRunning ? "running" : "stopped";
2639
- return proc;
2640
- }
2641
- async isProcessRunning(pid) {
2642
- try {
2643
- process.kill(pid, 0);
2644
- return true;
2645
- } catch {
2646
- return false;
2647
- }
2648
- }
2649
- async killProcessTree(pid) {
2650
- try {
2651
- process.kill(-pid, "SIGKILL");
2165
+ });
2166
+ server.stop(true);
2167
+ resolve(true);
2652
2168
  } catch {
2653
- try {
2654
- process.kill(pid, "SIGKILL");
2655
- } catch {}
2169
+ resolve(false);
2656
2170
  }
2657
- }
2658
- }
2659
-
2660
- // src/services/port-utils.ts
2661
- import { createServer } from "net";
2662
- function isPortAvailable(port, host = "0.0.0.0") {
2663
- return new Promise((resolve) => {
2664
- const server = createServer();
2665
- server.once("error", () => resolve(false));
2666
- server.once("listening", () => {
2667
- server.close(() => resolve(true));
2668
- });
2669
- server.listen(port, host);
2670
2171
  });
2671
2172
  }
2672
2173
  async function findFreePortFrom(startPort, host = "0.0.0.0") {
@@ -2682,12 +2183,12 @@ async function findFreePortFrom(startPort, host = "0.0.0.0") {
2682
2183
 
2683
2184
  // src/cli/commands/start.cmd.ts
2684
2185
  function register(program2) {
2685
- program2.command("start").description("Start a VibeControls agent instance").option("-p, --port <port>", "Port to listen on", "3005").option("-n, --name <name>", "Agent instance name", "default").option("-d, --daemon", "Run as a background daemon", false).option("--db-path <path>", "Path to the SQLite database", "./vibecontrols-agent.db").option("--host <host>", "Host to bind to", "0.0.0.0").action(async (opts) => {
2186
+ program2.command("start").description("Start a VibeControls agent instance").option("-p, --port <port>", "Port to listen on", "3005").option("-n, --name <name>", "Agent instance name", "default").option("-f, --foreground", "Run in foreground mode (default: daemon)", false).option("--db-path <path>", "Path to the SQLite database", "./vibecontrols-agent.db").option("--host <host>", "Host to bind to", "0.0.0.0").action(async (opts) => {
2686
2187
  try {
2687
2188
  const serviceManager = new ServiceManager;
2688
2189
  const dbPath = opts.dbPath;
2689
- const configDir = join2(homedir2(), ".vibecontrols");
2690
- const firstRun = !existsSync2(dbPath) && !existsSync2(join2(configDir, "agents.json"));
2190
+ const configDir = join(homedir(), ".vibecontrols");
2191
+ const firstRun = !existsSync(dbPath) && !existsSync(join(configDir, "agents.json"));
2691
2192
  if (firstRun) {
2692
2193
  info("First run detected \u2014 running setup...");
2693
2194
  blank();
@@ -2720,47 +2221,49 @@ function register(program2) {
2720
2221
  }
2721
2222
  const host = opts.host;
2722
2223
  const agentUrl = `http://${host === "0.0.0.0" ? "localhost" : host}:${port}`;
2723
- if (opts.daemon) {
2724
- header("Starting agent in daemon mode");
2725
- kv("Name", opts.name);
2726
- kv("Port", String(port));
2727
- kv("Host", host);
2728
- kv("Database", dbPath);
2729
- blank();
2730
- await serviceManager.startDaemon({
2731
- port,
2732
- name: opts.name,
2733
- daemon: true,
2734
- dbPath,
2735
- host
2736
- });
2737
- await printAgentDetails(agentUrl);
2738
- } else {
2224
+ if (opts.foreground) {
2739
2225
  header("Starting agent in foreground");
2740
2226
  kv("Name", opts.name);
2741
2227
  kv("Port", String(port));
2742
2228
  kv("Host", host);
2743
2229
  kv("Database", dbPath);
2744
2230
  blank();
2745
- const { createApp } = await import("./app-31chs2a1.js");
2231
+ const { createApp } = await import("./app-sm6n9xst.js");
2746
2232
  const appInstance = await createApp({
2747
2233
  port,
2748
2234
  host,
2749
2235
  dbPath
2750
2236
  });
2751
2237
  await appInstance.start();
2238
+ await printAgentDetails(agentUrl);
2752
2239
  const shutdown = async () => {
2753
2240
  await appInstance.stop();
2754
2241
  process.exit(0);
2755
2242
  };
2756
2243
  process.on("SIGTERM", shutdown);
2757
2244
  process.on("SIGINT", shutdown);
2245
+ } else {
2246
+ header("Starting agent in daemon mode");
2247
+ kv("Name", opts.name);
2248
+ kv("Port", String(port));
2249
+ kv("Host", host);
2250
+ kv("Database", dbPath);
2251
+ blank();
2252
+ await serviceManager.startDaemon({
2253
+ port,
2254
+ name: opts.name,
2255
+ daemon: true,
2256
+ dbPath,
2257
+ host
2258
+ });
2259
+ await printAgentDetails(agentUrl);
2758
2260
  }
2759
2261
  } catch (err) {
2760
2262
  fail(`Failed to start agent: ${err instanceof Error ? err.message : err}`);
2761
2263
  }
2762
2264
  });
2763
2265
  }
2266
+
2764
2267
  // src/cli/commands/stop.cmd.ts
2765
2268
  function register2(program2) {
2766
2269
  program2.command("stop").description("Stop a running VibeControls agent instance").option("-n, --name <name>", "Agent instance name", "default").option("--all", "Stop all running agent instances", false).action(async (opts) => {
@@ -2797,6 +2300,7 @@ function register2(program2) {
2797
2300
  }
2798
2301
  });
2799
2302
  }
2303
+
2800
2304
  // src/cli/commands/restart.cmd.ts
2801
2305
  function register3(program2) {
2802
2306
  program2.command("restart").description("Restart a running VibeControls agent instance").option("-n, --name <name>", "Agent instance name", "default").option("-p, --port <port>", "Port to listen on", "3005").option("--db-path <path>", "Path to the SQLite database", "./vibecontrols-agent.db").action(async (opts) => {
@@ -2838,54 +2342,49 @@ function register3(program2) {
2838
2342
  }
2839
2343
  });
2840
2344
  }
2841
- // src/cli/commands/status.cmd.ts
2345
+
2346
+ // src/cli/commands/kill.cmd.ts
2842
2347
  function register4(program2) {
2843
- program2.command("status").description("Show status of VibeControls agent instance(s)").option("-n, --name <name>", "Agent instance name").action(async (opts) => {
2348
+ program2.command("kill").description("Force kill a VibeControls agent instance").option("-n, --name <name>", "Agent instance name", "default").option("--all", "Kill all agent instances", false).action(async (opts) => {
2844
2349
  try {
2845
2350
  const serviceManager = new ServiceManager;
2846
- if (opts.name) {
2847
- header(`Agent Status: ${opts.name}`);
2351
+ if (opts.all) {
2352
+ header("Force killing all agent instances");
2848
2353
  blank();
2849
- const instance = await serviceManager.getStatus(opts.name);
2850
- if (!instance) {
2851
- fail(`Agent instance ${colors.bold(opts.name)} not found.`);
2354
+ const instances = await serviceManager.listInstances();
2355
+ if (!instances || instances.length === 0) {
2356
+ info(`${icons.info} No agent instances found.`);
2852
2357
  return;
2853
2358
  }
2854
- kv("Name", instance.name);
2855
- kv("Status", formatStatus(instance.status));
2856
- kv("PID", instance.pid ? String(instance.pid) : colors.dim("n/a"));
2857
- kv("Port", instance.port ? String(instance.port) : colors.dim("n/a"));
2858
- kv("Host", instance.config?.host || colors.dim("n/a"));
2859
- kv("Database", instance.config?.dbPath || colors.dim("n/a"));
2860
- if (instance.startTime) {
2861
- kv("Started", timeAgo(instance.startTime));
2359
+ let killed = 0;
2360
+ for (const instance of instances) {
2361
+ try {
2362
+ await serviceManager.kill(instance.name);
2363
+ success(`${icons.success} Killed ${colors.bold(instance.name)} (PID: ${instance.pid || "unknown"})`);
2364
+ killed++;
2365
+ } catch {
2366
+ warn(`${icons.warning} Could not kill ${colors.bold(instance.name)}`);
2367
+ }
2862
2368
  }
2863
2369
  blank();
2370
+ success(`${icons.success} Killed ${killed}/${instances.length} instance(s).`);
2864
2371
  } else {
2865
- header("Agent Instances");
2372
+ header(`Force killing agent: ${opts.name}`);
2866
2373
  blank();
2867
- const instances = await serviceManager.listInstances();
2868
- if (!instances || instances.length === 0) {
2869
- info(`${icons.info} No agent instances found.`);
2870
- info(`Run ${colors.bold("vibe start")} to start an agent.`);
2374
+ const instance = await serviceManager.getStatus(opts.name);
2375
+ if (!instance) {
2376
+ fail(`Agent instance ${colors.bold(opts.name)} not found.`);
2871
2377
  return;
2872
2378
  }
2873
- const rows = instances.map((inst) => ({
2874
- Name: inst.name,
2875
- Status: formatStatus(inst.status),
2876
- PID: inst.pid || "-",
2877
- Port: inst.port || "-",
2878
- Started: inst.startTime ? timeAgo(inst.startTime) : "-"
2879
- }));
2880
- formatTable(rows);
2881
- blank();
2882
- info(`${icons.info} ${instances.length} instance(s) found. Use ${colors.bold("vibe status -n <name>")} for details.`);
2379
+ await serviceManager.kill(opts.name);
2380
+ success(`${icons.success} Agent ${colors.bold(opts.name)} killed (PID: ${instance.pid || "unknown"}).`);
2883
2381
  }
2884
2382
  } catch (err) {
2885
- fail(`Failed to get status: ${err.message}`);
2383
+ fail(`Failed to kill agent: ${err.message}`);
2886
2384
  }
2887
2385
  });
2888
2386
  }
2387
+
2889
2388
  // src/cli/commands/list.cmd.ts
2890
2389
  function register5(program2) {
2891
2390
  program2.command("list").alias("ls").description("List all VibeControls agent instances").action(async () => {
@@ -2918,49 +2417,9 @@ function register5(program2) {
2918
2417
  }
2919
2418
  });
2920
2419
  }
2921
- // src/cli/commands/kill.cmd.ts
2922
- function register6(program2) {
2923
- program2.command("kill").description("Force kill a VibeControls agent instance").option("-n, --name <name>", "Agent instance name", "default").option("--all", "Kill all agent instances", false).action(async (opts) => {
2924
- try {
2925
- const serviceManager = new ServiceManager;
2926
- if (opts.all) {
2927
- header("Force killing all agent instances");
2928
- blank();
2929
- const instances = await serviceManager.listInstances();
2930
- if (!instances || instances.length === 0) {
2931
- info(`${icons.info} No agent instances found.`);
2932
- return;
2933
- }
2934
- let killed = 0;
2935
- for (const instance of instances) {
2936
- try {
2937
- await serviceManager.kill(instance.name);
2938
- success(`${icons.success} Killed ${colors.bold(instance.name)} (PID: ${instance.pid || "unknown"})`);
2939
- killed++;
2940
- } catch {
2941
- warn(`${icons.warning} Could not kill ${colors.bold(instance.name)}`);
2942
- }
2943
- }
2944
- blank();
2945
- success(`${icons.success} Killed ${killed}/${instances.length} instance(s).`);
2946
- } else {
2947
- header(`Force killing agent: ${opts.name}`);
2948
- blank();
2949
- const instance = await serviceManager.getStatus(opts.name);
2950
- if (!instance) {
2951
- fail(`Agent instance ${colors.bold(opts.name)} not found.`);
2952
- return;
2953
- }
2954
- await serviceManager.kill(opts.name);
2955
- success(`${icons.success} Agent ${colors.bold(opts.name)} killed (PID: ${instance.pid || "unknown"}).`);
2956
- }
2957
- } catch (err) {
2958
- fail(`Failed to kill agent: ${err.message}`);
2959
- }
2960
- });
2961
- }
2420
+
2962
2421
  // src/cli/commands/logs.cmd.ts
2963
- function register7(program2) {
2422
+ function register6(program2) {
2964
2423
  program2.command("logs").description("View logs for a VibeControls agent instance").option("-n, --name <name>", "Agent instance name", "default").option("-f, --follow", "Follow log output", false).option("--tail <lines>", "Number of lines to show from the end", "100").action(async (opts) => {
2965
2424
  try {
2966
2425
  const serviceManager = new ServiceManager;
@@ -2989,134 +2448,13 @@ function register7(program2) {
2989
2448
  }
2990
2449
  });
2991
2450
  }
2992
- // src/cli/commands/key.cmd.ts
2993
- var DEFAULT_AGENT_URL2 = "http://localhost:3005";
2994
- function register8(program2) {
2995
- program2.command("key").description("Get the API key for a running VibeControls agent").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL2).action(async (opts) => {
2451
+
2452
+ // src/cli/commands/setup.cmd.ts
2453
+ function register7(program2) {
2454
+ program2.command("setup").description("Install or verify system dependencies (tmux, ttyd, cloudflared)").option("--check", "Only check without installing", false).action(async (options) => {
2996
2455
  try {
2997
- const agentUrl = getAgentUrl(opts);
2998
- header("Agent API Key");
2999
- blank();
3000
- const data = await apiGet(agentUrl, "/api/agent/api-key");
3001
- kv("API Key", colors.bold(data.apiKey));
3002
- blank();
3003
- } catch (err) {
3004
- fail(`Failed to get API key: ${err.message}`);
3005
- }
3006
- });
3007
- }
3008
- // src/cli/commands/health.cmd.ts
3009
- var DEFAULT_AGENT_URL3 = "http://localhost:3005";
3010
- function register9(program2) {
3011
- program2.command("health").description("Check health of a VibeControls agent instance").option("-n, --name <name>", "Agent instance name").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL3).action(async (opts) => {
3012
- try {
3013
- header("Agent Health");
3014
- blank();
3015
- if (opts.name) {
3016
- const serviceManager = new ServiceManager;
3017
- const result = await serviceManager.checkHealth(opts.name);
3018
- if (!result.healthy) {
3019
- fail(`Agent instance ${colors.bold(opts.name)} is not responding.`);
3020
- return;
3021
- }
3022
- const details = result.details;
3023
- kv("Instance", opts.name);
3024
- kv("Status", formatStatus(details.status ?? "healthy"));
3025
- if (details.uptime !== undefined) {
3026
- kv("Uptime", `${details.uptime}s`);
3027
- }
3028
- if (details.checks) {
3029
- blank();
3030
- info(`${icons.info} Health checks:`);
3031
- for (const [name, check] of Object.entries(details.checks)) {
3032
- const icon = check.status === "healthy" ? icons.success : icons.error;
3033
- kv(` ${icon} ${name}`, formatStatus(check.status));
3034
- }
3035
- }
3036
- } else {
3037
- const agentUrl = getAgentUrl(opts);
3038
- const data = await apiGet(agentUrl, "/health");
3039
- kv("URL", agentUrl);
3040
- kv("Status", formatStatus(data.status));
3041
- if (data.version) {
3042
- kv("Version", data.version);
3043
- }
3044
- if (data.uptime !== undefined) {
3045
- kv("Uptime", `${data.uptime}s`);
3046
- }
3047
- if (data.timestamp) {
3048
- kv("Timestamp", data.timestamp);
3049
- }
3050
- if (data.checks) {
3051
- blank();
3052
- info(`${icons.info} Health checks:`);
3053
- for (const [name, check] of Object.entries(data.checks)) {
3054
- const icon = check.status === "healthy" ? icons.success : icons.error;
3055
- kv(` ${icon} ${name}`, formatStatus(check.status));
3056
- }
3057
- }
3058
- }
3059
- blank();
3060
- success(`${icons.success} Agent is healthy.`);
3061
- } catch (err) {
3062
- fail(`Health check failed: ${err.message}`);
3063
- }
3064
- });
3065
- }
3066
- // src/cli/commands/info.cmd.ts
3067
- import { platform, arch, release, hostname, cpus, totalmem } from "os";
3068
- var DEFAULT_AGENT_URL4 = "http://localhost:3005";
3069
- function register10(program2) {
3070
- program2.command("info").description("Show local and remote VibeControls agent information").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL4).action(async (opts) => {
3071
- try {
3072
- header("VibeControls Agent Info");
3073
- blank();
3074
- info(`${icons.info} Local System`);
3075
- kv("Hostname", hostname());
3076
- kv("Platform", `${platform()} ${arch()}`);
3077
- kv("OS Release", release());
3078
- kv("CPUs", String(cpus().length));
3079
- kv("Total Memory", formatBytes(totalmem()));
3080
- kv("Node.js", process.version);
3081
- if (process.versions.bun) {
3082
- kv("Bun", process.versions.bun);
3083
- }
3084
- blank();
3085
- const agentUrl = getAgentUrl(opts);
3086
- try {
3087
- const data = await apiGet(agentUrl, "/api/agent/version");
3088
- info(`${icons.info} Remote Agent`);
3089
- kv("URL", agentUrl);
3090
- kv("Version", colors.bold(data.version));
3091
- if (data.build) {
3092
- kv("Build", data.build);
3093
- }
3094
- if (data.commit) {
3095
- kv("Commit", data.commit);
3096
- }
3097
- if (data.nodeVersion) {
3098
- kv("Node.js (remote)", data.nodeVersion);
3099
- }
3100
- if (data.bunVersion) {
3101
- kv("Bun (remote)", data.bunVersion);
3102
- }
3103
- } catch {
3104
- info(`${icons.info} Remote Agent`);
3105
- kv("URL", agentUrl);
3106
- kv("Status", colors.dim("not reachable"));
3107
- }
3108
- blank();
3109
- } catch (err) {
3110
- fail(`Failed to get info: ${err.message}`);
3111
- }
3112
- });
3113
- }
3114
- // src/cli/commands/setup.cmd.ts
3115
- function register11(program2) {
3116
- program2.command("setup").description("Install or verify system dependencies (tmux, ttyd, cloudflared)").option("--check", "Only check without installing", false).action(async (options) => {
3117
- try {
3118
- header("VibeControls Agent Setup");
3119
- info("Checking dependencies...");
2456
+ header("VibeControls Agent Setup");
2457
+ info("Checking dependencies...");
3120
2458
  blank();
3121
2459
  const deps = checkDependencies();
3122
2460
  const missing = [];
@@ -3154,17 +2492,17 @@ function register11(program2) {
3154
2492
  }
3155
2493
  });
3156
2494
  }
2495
+
3157
2496
  // src/cli/commands/update.cmd.ts
3158
- import { execSync } from "child_process";
3159
2497
  var PACKAGE_NAME = "vibecontrols-agent";
3160
- function register12(program2) {
2498
+ function register8(program2) {
3161
2499
  program2.command("update").description("Check for and install VibeControls agent updates").option("--check", "Only check for updates without installing", false).action(async (opts) => {
3162
2500
  try {
3163
2501
  header("VibeControls Agent Update");
3164
2502
  blank();
3165
2503
  let currentVersion;
3166
2504
  try {
3167
- const pkg = await import("./package-hb6db316.js", {
2505
+ const pkg = await import("./package-04nkt49b.js", {
3168
2506
  with: { type: "json" }
3169
2507
  });
3170
2508
  currentVersion = pkg.default.version || pkg.version;
@@ -3175,9 +2513,10 @@ function register12(program2) {
3175
2513
  blank();
3176
2514
  let latestVersion;
3177
2515
  try {
3178
- latestVersion = execSync(`npm view ${PACKAGE_NAME} version`, {
3179
- encoding: "utf-8"
3180
- }).trim();
2516
+ const result = Bun.spawnSync(["npm", "view", PACKAGE_NAME, "version"], { stdout: "pipe", stderr: "pipe" });
2517
+ if (result.exitCode !== 0)
2518
+ throw new Error("npm view failed");
2519
+ latestVersion = result.stdout.toString().trim();
3181
2520
  } catch {
3182
2521
  fail(`Could not check for updates. Ensure you have internet connectivity and npm is available.`);
3183
2522
  return;
@@ -3197,10 +2536,9 @@ function register12(program2) {
3197
2536
  info(`${icons.info} Updating to ${colors.bold(latestVersion)}...`);
3198
2537
  blank();
3199
2538
  try {
3200
- execSync(`npm install -g ${PACKAGE_NAME}@${latestVersion}`, {
3201
- encoding: "utf-8",
3202
- stdio: "inherit"
3203
- });
2539
+ const installResult = Bun.spawnSync(["npm", "install", "-g", `${PACKAGE_NAME}@${latestVersion}`], { stdout: "inherit", stderr: "inherit" });
2540
+ if (installResult.exitCode !== 0)
2541
+ throw new Error("install failed");
3204
2542
  } catch {
3205
2543
  fail(`Failed to install update. Try running with sudo: ${colors.bold(`sudo npm install -g ${PACKAGE_NAME}@${latestVersion}`)}`);
3206
2544
  return;
@@ -3213,1221 +2551,17 @@ function register12(program2) {
3213
2551
  }
3214
2552
  });
3215
2553
  }
3216
- // src/cli/commands/system.cmd.ts
3217
- var DEFAULT_AGENT_URL5 = "http://localhost:3005";
3218
- function register13(program2) {
3219
- program2.command("system").description("Show system information for a running VibeControls agent").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL5).action(async (opts) => {
3220
- try {
3221
- const agentUrl = getAgentUrl(opts);
3222
- header("Agent System Information");
3223
- blank();
3224
- const data = await apiGet(agentUrl, "/api/agent/system");
3225
- info(`${icons.info} Agent`);
3226
- kv("Version", colors.bold(data.agentVersion));
3227
- if (data.bunVersion) {
3228
- kv("Bun", data.bunVersion);
3229
- }
3230
- if (data.environment) {
3231
- kv("Environment", data.environment);
3232
- }
3233
- kv("Uptime", formatDuration(data.uptime));
3234
- blank();
3235
- info(`${icons.info} Platform`);
3236
- kv("OS", `${data.platform} ${data.arch}`);
3237
- kv("Hostname", data.hostname);
3238
- kv("Release", data.release);
3239
- blank();
3240
- info(`${icons.info} Resources`);
3241
- kv("CPUs", String(data.cpus));
3242
- kv("Total Memory", formatBytes(data.totalMemory));
3243
- kv("Free Memory", formatBytes(data.freeMemory));
3244
- blank();
3245
- info(`${icons.info} Paths`);
3246
- kv("Home", data.homeDir);
3247
- kv("CWD", data.cwd);
3248
- blank();
3249
- } catch (err) {
3250
- fail(`Failed to get system info: ${err.message}`);
3251
- }
3252
- });
3253
- }
3254
- // src/cli/commands/url.cmd.ts
3255
- var DEFAULT_AGENT_URL6 = "http://localhost:3005";
3256
- function register14(program2) {
3257
- program2.command("url").description("Show the active URL for a running VibeControls agent").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL6).action(async (opts) => {
3258
- try {
3259
- const agentUrl = getAgentUrl(opts);
3260
- header("Agent URL");
3261
- blank();
3262
- const data = await apiGet(agentUrl, "/api/agent/url");
3263
- kv("Active URL", colors.bold(data.url));
3264
- kv("Local URL", data.localUrl);
3265
- if (data.tunnelUrl) {
3266
- kv("Tunnel URL", colors.cyan(data.tunnelUrl));
3267
- }
3268
- kv("Mode", data.isTunnel ? `${icons.running} Tunnel active` : `${icons.info} Local only`);
3269
- blank();
3270
- if (data.isTunnel) {
3271
- info(`${icons.info} Agent is accessible via tunnel at ${colors.bold(data.tunnelUrl)}`);
3272
- } else {
3273
- info(`${icons.info} Agent is running locally at ${colors.bold(data.localUrl)}`);
3274
- }
3275
- } catch (err) {
3276
- fail(`Failed to get URL: ${err.message}`);
3277
- }
3278
- });
3279
- }
3280
- // src/cli/commands/config.cmd.ts
3281
- var DEFAULT_AGENT_URL7 = "http://localhost:3005";
3282
- function register15(program2) {
3283
- program2.command("config").description("Manage VibeControls agent configuration").option("--set <key=value>", "Set a configuration value").option("--get <key>", "Get a configuration value").option("--delete <key>", "Delete a configuration value").option("--list", "List all configuration values", false).option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL7).action(async (opts) => {
3284
- try {
3285
- const agentUrl = getAgentUrl(opts);
3286
- if (opts.set) {
3287
- const eqIndex = opts.set.indexOf("=");
3288
- if (eqIndex === -1) {
3289
- fail(`Invalid format. Use ${colors.bold("--set key=value")}`);
3290
- return;
3291
- }
3292
- const key = opts.set.slice(0, eqIndex).trim();
3293
- const value = opts.set.slice(eqIndex + 1).trim();
3294
- if (!key) {
3295
- fail("Configuration key cannot be empty.");
3296
- return;
3297
- }
3298
- try {
3299
- await apiPut(agentUrl, `/api/config/${encodeURIComponent(key)}`, {
3300
- value
3301
- });
3302
- } catch {
3303
- await apiPost(agentUrl, "/api/config/", { key, value });
3304
- }
3305
- success(`${icons.success} Set ${colors.bold(key)} = ${colors.cyan(value)}`);
3306
- } else if (opts.get) {
3307
- header("Configuration");
3308
- blank();
3309
- const data = await apiGet(agentUrl, `/api/config/${encodeURIComponent(opts.get)}`);
3310
- kv(data.key, colors.bold(data.value));
3311
- blank();
3312
- } else if (opts.delete) {
3313
- await apiDelete(agentUrl, `/api/config/${encodeURIComponent(opts.delete)}`);
3314
- success(`${icons.success} Deleted configuration key: ${colors.bold(opts.delete)}`);
3315
- } else if (opts.list) {
3316
- header("Agent Configuration");
3317
- blank();
3318
- const data = await apiGet(agentUrl, "/api/config/");
3319
- if (!data.configs || data.configs.length === 0) {
3320
- info(`${icons.info} No configuration entries found.`);
3321
- return;
3322
- }
3323
- const rows = data.configs.map((c) => ({
3324
- Key: c.key,
3325
- Value: c.value
3326
- }));
3327
- formatTable(rows);
3328
- blank();
3329
- info(`${icons.info} ${data.configs.length} configuration(s) found.`);
3330
- } else {
3331
- info(`${icons.info} Usage:`);
3332
- info(` ${colors.bold("vibe config --list")} List all config values`);
3333
- info(` ${colors.bold("vibe config --get <key>")} Get a config value`);
3334
- info(` ${colors.bold("vibe config --set <key=value>")} Set a config value`);
3335
- info(` ${colors.bold("vibe config --delete <key>")} Delete a config value`);
3336
- }
3337
- } catch (err) {
3338
- fail(`Config operation failed: ${err.message}`);
3339
- }
3340
- });
3341
- }
3342
- // src/cli/commands/gateway-auth.cmd.ts
3343
- var DEFAULT_AGENT_URL8 = "http://localhost:3005";
3344
- function register16(program2) {
3345
- const gatewayAuth = program2.command("gateway-auth").description("Manage gateway authentication for VibeControls agent");
3346
- gatewayAuth.command("configure").description("Configure gateway authentication credentials").requiredOption("--global-url <url>", "Global gateway URL").requiredOption("--workspace-url <url>", "Workspace gateway URL").requiredOption("--client-id <id>", "OAuth client ID").requiredOption("--client-secret <secret>", "OAuth client secret").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL8).action(async (opts) => {
3347
- try {
3348
- const agentUrl = getAgentUrl(opts);
3349
- header("Configure Gateway Authentication");
3350
- blank();
3351
- info(`${icons.info} Sending gateway auth configuration...`);
3352
- blank();
3353
- const data = await apiPost(agentUrl, "/api/agent/gateway-auth", {
3354
- globalUrl: opts.globalUrl,
3355
- workspaceUrl: opts.workspaceUrl,
3356
- clientId: opts.clientId,
3357
- clientSecret: opts.clientSecret
3358
- });
3359
- if (data.success) {
3360
- success(`${icons.success} Gateway authentication configured successfully.`);
3361
- blank();
3362
- kv("Global URL", opts.globalUrl);
3363
- kv("Workspace URL", opts.workspaceUrl);
3364
- kv("Client ID", opts.clientId);
3365
- kv("Client Secret", colors.dim("********"));
3366
- } else {
3367
- fail(data.message || "Failed to configure gateway authentication.");
3368
- }
3369
- blank();
3370
- } catch (err) {
3371
- fail(`Failed to configure gateway auth: ${err.message}`);
3372
- }
3373
- });
3374
- gatewayAuth.command("status").description("Check gateway authentication status").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL8).action(async (opts) => {
3375
- try {
3376
- const agentUrl = getAgentUrl(opts);
3377
- header("Gateway Authentication Status");
3378
- blank();
3379
- const data = await apiGet(agentUrl, "/api/agent/gateway-auth");
3380
- kv("Configured", data.configured ? `${icons.success} ${colors.green("Yes")}` : `${icons.error} ${colors.red("No")}`);
3381
- if (data.configured) {
3382
- kv("Global URL", data.globalUrl || colors.dim("n/a"));
3383
- kv("Workspace URL", data.workspaceUrl || colors.dim("n/a"));
3384
- kv("Client ID", data.clientId || colors.dim("n/a"));
3385
- kv("Authenticated", data.authenticated ? `${icons.success} ${colors.green("Yes")}` : `${icons.error} ${colors.red("No")}`);
3386
- if (data.tokenExpiresAt) {
3387
- kv("Token Expires", data.tokenExpiresAt);
3388
- }
3389
- } else {
3390
- blank();
3391
- info(`${icons.info} Run ${colors.bold("vibe gateway-auth configure")} to set up gateway authentication.`);
3392
- }
3393
- blank();
3394
- } catch (err) {
3395
- fail(`Failed to get gateway auth status: ${err.message}`);
3396
- }
3397
- });
3398
- }
3399
- // src/cli/commands/session.cmd.ts
3400
- var DEFAULT_AGENT_URL9 = "http://localhost:3005";
3401
- function register17(program2) {
3402
- const cmd = program2.command("session").description("Manage terminal sessions");
3403
- cmd.command("list").description("List all sessions").option("--system", "Show system sessions instead of user sessions").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL9).action(async (options) => {
3404
- try {
3405
- const url = getAgentUrl(options);
3406
- const endpoint = options.system ? "/api/sessions?system=true" : "/api/sessions";
3407
- const sessions = await apiGet(url, endpoint);
3408
- if (!sessions || sessions.length === 0) {
3409
- info("No sessions found.");
3410
- return;
3411
- }
3412
- header("Sessions");
3413
- formatTable(sessions.map((s) => ({
3414
- ID: shortId(s.id),
3415
- Name: s.name || "-",
3416
- Status: formatStatus(s.status),
3417
- Port: s.port ?? "-",
3418
- Project: s.project || s.projectId || "-"
3419
- })));
3420
- } catch (err) {
3421
- fail(err.message);
3422
- }
3423
- });
3424
- cmd.command("create").description("Create a new session").requiredOption("--name <name>", "Session name").option("--project <id>", "Project ID", "default").option("--command <cmd>", "Initial command to run").option("--cwd <dir>", "Working directory").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL9).action(async (options) => {
3425
- try {
3426
- const url = getAgentUrl(options);
3427
- const body = {
3428
- name: options.name,
3429
- project: options.project
3430
- };
3431
- if (options.command)
3432
- body.command = options.command;
3433
- if (options.cwd)
3434
- body.cwd = options.cwd;
3435
- const result = await apiPost(url, "/api/sessions/create", body);
3436
- success(`Session created: ${shortId(result.id || result.sessionId)}`);
3437
- kv("Name", options.name);
3438
- kv("Project", options.project);
3439
- } catch (err) {
3440
- fail(err.message);
3441
- }
3442
- });
3443
- cmd.command("kill").description("Kill a session").requiredOption("-i, --id <id>", "Session ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL9).action(async (options) => {
3444
- try {
3445
- const url = getAgentUrl(options);
3446
- await apiDelete(url, `/api/sessions/${options.id}`);
3447
- success(`Session ${shortId(options.id)} killed.`);
3448
- } catch (err) {
3449
- fail(err.message);
3450
- }
3451
- });
3452
- cmd.command("exec").description("Execute a command in a session").requiredOption("-i, --id <id>", "Session ID").requiredOption("-c, --command <cmd>", "Command to execute").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL9).action(async (options) => {
3453
- try {
3454
- const url = getAgentUrl(options);
3455
- const result = await apiPost(url, `/api/sessions/${options.id}/command`, { command: options.command });
3456
- success("Command executed.");
3457
- if (result?.output) {
3458
- blank();
3459
- console.log(result.output);
3460
- }
3461
- } catch (err) {
3462
- fail(err.message);
3463
- }
3464
- });
3465
- cmd.command("capture").description("Capture session terminal output").requiredOption("-i, --id <id>", "Session ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL9).action(async (options) => {
3466
- try {
3467
- const url = getAgentUrl(options);
3468
- const result = await apiGet(url, `/api/sessions/${options.id}/capture`);
3469
- if (result?.content || result?.output) {
3470
- console.log(result.content || result.output);
3471
- } else {
3472
- info("No capture data available.");
3473
- }
3474
- } catch (err) {
3475
- fail(err.message);
3476
- }
3477
- });
3478
- cmd.command("keys").description("Send keys to a session").requiredOption("-i, --id <id>", "Session ID").requiredOption("-k, --keys <keys>", "Keys to send").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL9).action(async (options) => {
3479
- try {
3480
- const url = getAgentUrl(options);
3481
- await apiPost(url, `/api/sessions/${options.id}/keys`, {
3482
- keys: options.keys
3483
- });
3484
- success("Keys sent.");
3485
- } catch (err) {
3486
- fail(err.message);
3487
- }
3488
- });
3489
- cmd.command("interrupt").description("Send interrupt signal to a session").requiredOption("-i, --id <id>", "Session ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL9).action(async (options) => {
3490
- try {
3491
- const url = getAgentUrl(options);
3492
- await apiPost(url, `/api/sessions/${options.id}/interrupt`, {});
3493
- success(`Session ${shortId(options.id)} interrupted.`);
3494
- } catch (err) {
3495
- fail(err.message);
3496
- }
3497
- });
3498
- cmd.command("rename").description("Rename a session").requiredOption("-i, --id <id>", "Session ID").requiredOption("--name <name>", "New session name").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL9).action(async (options) => {
3499
- try {
3500
- const url = getAgentUrl(options);
3501
- await apiPut(url, `/api/sessions/${options.id}/rename`, {
3502
- name: options.name
3503
- });
3504
- success(`Session ${shortId(options.id)} renamed to "${options.name}".`);
3505
- } catch (err) {
3506
- fail(err.message);
3507
- }
3508
- });
3509
- cmd.command("toggle-mouse").description("Toggle mouse support in a session").requiredOption("-i, --id <id>", "Session ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL9).action(async (options) => {
3510
- try {
3511
- const url = getAgentUrl(options);
3512
- const result = await apiPost(url, `/api/sessions/${options.id}/toggle-mouse`, {});
3513
- success(`Mouse support ${result?.mouseEnabled ? "enabled" : "toggled"} for session ${shortId(options.id)}.`);
3514
- } catch (err) {
3515
- fail(err.message);
3516
- }
3517
- });
3518
- cmd.command("terminal-start").description("Start terminal for a session").requiredOption("-i, --id <id>", "Session ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL9).action(async (options) => {
3519
- try {
3520
- const url = getAgentUrl(options);
3521
- const result = await apiPost(url, `/api/sessions/${options.id}/terminal`, {});
3522
- success(`Terminal started for session ${shortId(options.id)}.`);
3523
- if (result?.port)
3524
- kv("Port", result.port);
3525
- } catch (err) {
3526
- fail(err.message);
3527
- }
3528
- });
3529
- cmd.command("terminal-stop").description("Stop terminal for a session").requiredOption("-i, --id <id>", "Session ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL9).action(async (options) => {
3530
- try {
3531
- const url = getAgentUrl(options);
3532
- await apiPost(url, `/api/sessions/${options.id}/terminal/stop`, {});
3533
- success(`Terminal stopped for session ${shortId(options.id)}.`);
3534
- } catch (err) {
3535
- fail(err.message);
3536
- }
3537
- });
3538
- cmd.command("health-check").description("Run health check on all sessions").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL9).action(async (options) => {
3539
- try {
3540
- const url = getAgentUrl(options);
3541
- const result = await apiPost(url, "/api/sessions/health-check", {});
3542
- success("Health check completed.");
3543
- if (result?.healthy !== undefined)
3544
- kv("Healthy", result.healthy);
3545
- if (result?.checked !== undefined)
3546
- kv("Checked", result.checked);
3547
- if (result?.fixed !== undefined)
3548
- kv("Fixed", result.fixed);
3549
- } catch (err) {
3550
- fail(err.message);
3551
- }
3552
- });
3553
- }
3554
- // src/cli/commands/tunnel.cmd.ts
3555
- var DEFAULT_AGENT_URL10 = "http://localhost:3005";
3556
- function register18(program2) {
3557
- const cmd = program2.command("tunnel").description("Manage tunnels for exposing local ports");
3558
- cmd.command("list").description("List all tunnels").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL10).action(async (options) => {
3559
- try {
3560
- const url = getAgentUrl(options);
3561
- const tunnels = await apiGet(url, "/api/tunnels");
3562
- if (!tunnels || tunnels.length === 0) {
3563
- info("No tunnels found.");
3564
- return;
3565
- }
3566
- header("Tunnels");
3567
- formatTable(tunnels.map((t) => ({
3568
- ID: shortId(t.id),
3569
- Port: t.port ?? "-",
3570
- "Public URL": t.publicUrl || t.url || "-",
3571
- Status: formatStatus(t.status),
3572
- PID: t.pid ?? "-"
3573
- })));
3574
- } catch (err) {
3575
- fail(err.message);
3576
- }
3577
- });
3578
- cmd.command("start").description("Start a new tunnel").requiredOption("-p, --port <port>", "Local port to expose").option("-s, --subdomain <subdomain>", "Preferred subdomain").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL10).action(async (options) => {
3579
- try {
3580
- const url = getAgentUrl(options);
3581
- const body = {
3582
- port: parseInt(options.port, 10)
3583
- };
3584
- if (options.subdomain)
3585
- body.subdomain = options.subdomain;
3586
- const result = await apiPost(url, "/api/tunnels/start", body);
3587
- success("Tunnel started.");
3588
- if (result?.id)
3589
- kv("ID", shortId(result.id));
3590
- if (result?.publicUrl || result?.url)
3591
- kv("Public URL", result.publicUrl || result.url);
3592
- kv("Port", options.port);
3593
- } catch (err) {
3594
- fail(err.message);
3595
- }
3596
- });
3597
- cmd.command("stop").description("Stop a tunnel").requiredOption("-i, --id <id>", "Tunnel ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL10).action(async (options) => {
3598
- try {
3599
- const url = getAgentUrl(options);
3600
- await apiPost(url, `/api/tunnels/${options.id}/stop`, {});
3601
- success(`Tunnel ${shortId(options.id)} stopped.`);
3602
- } catch (err) {
3603
- fail(err.message);
3604
- }
3605
- });
3606
- cmd.command("delete").description("Delete a tunnel").requiredOption("-i, --id <id>", "Tunnel ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL10).action(async (options) => {
3607
- try {
3608
- const url = getAgentUrl(options);
3609
- await apiDelete(url, `/api/tunnels/${options.id}`);
3610
- success(`Tunnel ${shortId(options.id)} deleted.`);
3611
- } catch (err) {
3612
- fail(err.message);
3613
- }
3614
- });
3615
- cmd.command("status").description("Show tunnel status summary").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL10).action(async (options) => {
3616
- try {
3617
- const url = getAgentUrl(options);
3618
- const result = await apiGet(url, "/api/tunnels/status");
3619
- header("Tunnel Status");
3620
- kv("Total", result?.total ?? 0);
3621
- kv("Active", result?.active ?? 0);
3622
- kv("Inactive", result?.inactive ?? 0);
3623
- kv("Errored", result?.errored ?? 0);
3624
- } catch (err) {
3625
- fail(err.message);
3626
- }
3627
- });
3628
- cmd.command("agent").description("Manage agent tunnel").option("--start", "Start the agent tunnel").option("--stop", "Stop the agent tunnel").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL10).action(async (options) => {
3629
- try {
3630
- const url = getAgentUrl(options);
3631
- if (options.start) {
3632
- const result = await apiPost(url, "/api/agent/tunnel", {
3633
- action: "start"
3634
- });
3635
- success("Agent tunnel started.");
3636
- if (result?.publicUrl || result?.url)
3637
- kv("Public URL", result.publicUrl || result.url);
3638
- } else if (options.stop) {
3639
- const result = await apiPost(url, "/api/agent/tunnel", {
3640
- action: "stop"
3641
- });
3642
- success("Agent tunnel stopped.");
3643
- } else {
3644
- const result = await apiGet(url, "/api/agent/tunnel");
3645
- header("Agent Tunnel");
3646
- kv("Status", formatStatus(result?.status || "unknown"));
3647
- if (result?.publicUrl || result?.url)
3648
- kv("Public URL", result.publicUrl || result.url);
3649
- if (result?.port)
3650
- kv("Port", result.port);
3651
- }
3652
- } catch (err) {
3653
- fail(err.message);
3654
- }
3655
- });
3656
- }
3657
- // src/cli/commands/task.cmd.ts
3658
- var DEFAULT_AGENT_URL11 = "http://localhost:3005";
3659
- function register19(program2) {
3660
- const cmd = program2.command("task").description("Manage background tasks");
3661
- cmd.command("list").description("List tasks").option("--status <status>", "Filter by status").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL11).action(async (options) => {
3662
- try {
3663
- const url = getAgentUrl(options);
3664
- const query = options.status ? `/api/tasks/?status=${encodeURIComponent(options.status)}` : "/api/tasks/";
3665
- const data = await apiGet(url, query);
3666
- const tasks = data.tasks || [];
3667
- if (!tasks || tasks.length === 0) {
3668
- info("No tasks found.");
3669
- return;
3670
- }
3671
- header("Tasks");
3672
- formatTable(tasks.map((t) => ({
3673
- ID: shortId(t.id),
3674
- Type: t.type || "-",
3675
- Status: formatStatus(t.status),
3676
- Created: t.createdAt ? timeAgo(t.createdAt) : "-"
3677
- })));
3678
- } catch (err) {
3679
- fail(err.message);
3680
- }
3681
- });
3682
- cmd.command("run").description("Run a new task").requiredOption("-c, --command <cmd>", "Command to run").option("--cwd <dir>", "Working directory").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL11).action(async (options) => {
3683
- try {
3684
- const url = getAgentUrl(options);
3685
- const payload = { command: options.command };
3686
- if (options.cwd)
3687
- payload.cwd = options.cwd;
3688
- const body = {
3689
- type: "command",
3690
- payload: JSON.stringify(payload)
3691
- };
3692
- const result = await apiPost(url, "/api/tasks/", body);
3693
- success(`Task created: ${shortId(result?.id || result?.taskId)}`);
3694
- } catch (err) {
3695
- fail(err.message);
3696
- }
3697
- });
3698
- cmd.command("cancel").description("Cancel a running task").requiredOption("-i, --id <id>", "Task ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL11).action(async (options) => {
3699
- try {
3700
- const url = getAgentUrl(options);
3701
- await apiPut(url, `/api/tasks/${options.id}/cancel`, {});
3702
- success(`Task ${shortId(options.id)} cancelled.`);
3703
- } catch (err) {
3704
- fail(err.message);
3705
- }
3706
- });
3707
- }
3708
- // src/cli/commands/git.cmd.ts
3709
- var DEFAULT_AGENT_URL12 = "http://localhost:3005";
3710
- function register20(program2) {
3711
- const cmd = program2.command("git").description("Manage git repositories");
3712
- cmd.command("list").description("List discovered git repositories").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL12).action(async (options) => {
3713
- try {
3714
- const url = getAgentUrl(options);
3715
- const data = await apiGet(url, "/api/git");
3716
- const repos = data.repositories || [];
3717
- if (!repos || repos.length === 0) {
3718
- info("No git repositories found.");
3719
- return;
3720
- }
3721
- header("Git Repositories");
3722
- formatTable(repos.map((r) => ({
3723
- ID: shortId(r.id),
3724
- Name: r.name || "-",
3725
- Path: r.path || "-",
3726
- Type: r.type || r.projectType || "-",
3727
- Submodule: r.isSubmodule ? "Yes" : "No",
3728
- Scanned: r.scannedAt ? timeAgo(r.scannedAt) : "-"
3729
- })));
3730
- } catch (err) {
3731
- fail(err.message);
3732
- }
3733
- });
3734
- cmd.command("scan").description("Scan a directory for git repositories").requiredOption("--dir <directory>", "Directory to scan").option("--depth <depth>", "Scan depth", "3").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL12).action(async (options) => {
3735
- try {
3736
- const url = getAgentUrl(options);
3737
- const result = await apiPost(url, "/api/git/scan", {
3738
- directory: options.dir,
3739
- depth: parseInt(options.depth, 10)
3740
- });
3741
- success("Git scan completed.");
3742
- if (result?.found !== undefined)
3743
- kv("Repositories found", result.found);
3744
- if (result?.repositories)
3745
- kv("Repositories found", result.repositories.length);
3746
- } catch (err) {
3747
- fail(err.message);
3748
- }
3749
- });
3750
- cmd.command("update").description("Update a git repository entry").requiredOption("-i, --id <id>", "Repository ID").option("--vite-port <port>", "Vite dev server port").option("--project-type <type>", "Project type").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL12).action(async (options) => {
3751
- try {
3752
- const url = getAgentUrl(options);
3753
- const body = {};
3754
- if (options.vitePort)
3755
- body.vitePort = parseInt(options.vitePort, 10);
3756
- if (options.projectType)
3757
- body.projectType = options.projectType;
3758
- await apiPut(url, `/api/git/${options.id}`, body);
3759
- success(`Repository ${shortId(options.id)} updated.`);
3760
- } catch (err) {
3761
- fail(err.message);
3762
- }
3763
- });
3764
- cmd.command("delete").description("Delete a git repository entry").requiredOption("-i, --id <id>", "Repository ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL12).action(async (options) => {
3765
- try {
3766
- const url = getAgentUrl(options);
3767
- await apiDelete(url, `/api/git/${options.id}`);
3768
- success(`Repository ${shortId(options.id)} deleted.`);
3769
- } catch (err) {
3770
- fail(err.message);
3771
- }
3772
- });
3773
- cmd.command("fix-hierarchy").description("Fix repository parent-child hierarchy").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL12).action(async (options) => {
3774
- try {
3775
- const url = getAgentUrl(options);
3776
- const result = await apiPost(url, "/api/git/fix-hierarchy", {});
3777
- success("Hierarchy fix completed.");
3778
- if (result?.fixed !== undefined)
3779
- kv("Fixed", result.fixed);
3780
- } catch (err) {
3781
- fail(err.message);
3782
- }
3783
- });
3784
- }
3785
- // src/cli/commands/file.cmd.ts
3786
- var DEFAULT_AGENT_URL13 = "http://localhost:3005";
3787
- function register21(program2) {
3788
- const cmd = program2.command("file").description("File system operations via agent");
3789
- cmd.command("read").description("Read a file").requiredOption("--path <path>", "File path to read").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL13).action(async (options) => {
3790
- try {
3791
- const url = getAgentUrl(options);
3792
- const result = await apiPost(url, "/api/files/read", {
3793
- path: options.path
3794
- });
3795
- if (result?.content !== undefined) {
3796
- console.log(result.content);
3797
- } else {
3798
- info("File is empty or has no content.");
3799
- }
3800
- } catch (err) {
3801
- fail(err.message);
3802
- }
3803
- });
3804
- cmd.command("write").description("Write content to a file").requiredOption("--path <path>", "File path to write").requiredOption("--content <content>", "Content to write").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL13).action(async (options) => {
3805
- try {
3806
- const url = getAgentUrl(options);
3807
- await apiPost(url, "/api/files/write", {
3808
- path: options.path,
3809
- content: options.content
3810
- });
3811
- success(`File written: ${options.path}`);
3812
- } catch (err) {
3813
- fail(err.message);
3814
- }
3815
- });
3816
- cmd.command("list").description("List files in a directory").requiredOption("--path <path>", "Directory path").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL13).action(async (options) => {
3817
- try {
3818
- const url = getAgentUrl(options);
3819
- const result = await apiPost(url, "/api/files/list", {
3820
- path: options.path
3821
- });
3822
- const files = result?.files || result;
3823
- if (!files || Array.isArray(files) && files.length === 0) {
3824
- info("Directory is empty.");
3825
- return;
3826
- }
3827
- header(`Files in ${options.path}`);
3828
- formatTable((Array.isArray(files) ? files : []).map((f) => ({
3829
- Name: f.name || f.filename || "-",
3830
- Type: f.type || (f.isDirectory ? "directory" : "file"),
3831
- Size: f.size !== undefined ? formatBytes(f.size) : "-"
3832
- })));
3833
- } catch (err) {
3834
- fail(err.message);
3835
- }
3836
- });
3837
- cmd.command("exists").description("Check if a file exists").requiredOption("--path <path>", "File path to check").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL13).action(async (options) => {
3838
- try {
3839
- const url = getAgentUrl(options);
3840
- const result = await apiPost(url, "/api/files/exists", {
3841
- path: options.path
3842
- });
3843
- if (result?.exists) {
3844
- success(`File exists: ${options.path}`);
3845
- } else {
3846
- info(`File does not exist: ${options.path}`);
3847
- }
3848
- } catch (err) {
3849
- fail(err.message);
3850
- }
3851
- });
3852
- cmd.command("delete").description("Delete a file").requiredOption("--path <path>", "File path to delete").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL13).action(async (options) => {
3853
- try {
3854
- const url = getAgentUrl(options);
3855
- await apiPost(url, "/api/files/delete", {
3856
- path: options.path
3857
- });
3858
- success(`File deleted: ${options.path}`);
3859
- } catch (err) {
3860
- fail(err.message);
3861
- }
3862
- });
3863
- cmd.command("readme").description("Read the README file from a directory").requiredOption("--path <path>", "Directory path").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL13).action(async (options) => {
3864
- try {
3865
- const url = getAgentUrl(options);
3866
- const result = await apiPost(url, "/api/files/readme", {
3867
- path: options.path
3868
- });
3869
- if (result?.content) {
3870
- console.log(result.content);
3871
- } else {
3872
- info("No README found in the specified directory.");
3873
- }
3874
- } catch (err) {
3875
- fail(err.message);
3876
- }
3877
- });
3878
- }
3879
- // src/cli/commands/bookmark.cmd.ts
3880
- var DEFAULT_AGENT_URL14 = "http://localhost:3005";
3881
- function register22(program2) {
3882
- const cmd = program2.command("bookmark").description("Manage command bookmarks");
3883
- cmd.command("list").description("List bookmarks").option("--project <id>", "Filter by project ID").option("--category <cat>", "Filter by category").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL14).action(async (options) => {
3884
- try {
3885
- const url = getAgentUrl(options);
3886
- const params = new URLSearchParams;
3887
- if (options.project)
3888
- params.set("project", options.project);
3889
- if (options.category)
3890
- params.set("category", options.category);
3891
- const query = params.toString();
3892
- const endpoint = query ? `/api/bookmarks?${query}` : "/api/bookmarks";
3893
- const data = await apiGet(url, endpoint);
3894
- const bookmarks = data.bookmarks || [];
3895
- if (!bookmarks || bookmarks.length === 0) {
3896
- info("No bookmarks found.");
3897
- return;
3898
- }
3899
- header("Bookmarks");
3900
- formatTable(bookmarks.map((b) => ({
3901
- ID: shortId(b.id),
3902
- Command: b.command || "-",
3903
- Description: b.description || "-",
3904
- Category: b.category || "-",
3905
- Project: b.project || b.projectId || "-"
3906
- })));
3907
- } catch (err) {
3908
- fail(err.message);
3909
- }
3910
- });
3911
- cmd.command("create").description("Create a new bookmark").requiredOption("-c, --command <cmd>", "Command to bookmark").option("--description <desc>", "Bookmark description").option("--category <cat>", "Category").option("--project <id>", "Project ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL14).action(async (options) => {
3912
- try {
3913
- const url = getAgentUrl(options);
3914
- const body = { command: options.command };
3915
- if (options.description)
3916
- body.description = options.description;
3917
- if (options.category)
3918
- body.category = options.category;
3919
- if (options.project)
3920
- body.project = options.project;
3921
- const result = await apiPost(url, "/api/bookmarks", body);
3922
- success(`Bookmark created: ${shortId(result?.id)}`);
3923
- } catch (err) {
3924
- fail(err.message);
3925
- }
3926
- });
3927
- cmd.command("update").description("Update a bookmark").requiredOption("-i, --id <id>", "Bookmark ID").option("-c, --command <cmd>", "New command").option("--description <desc>", "New description").option("--category <cat>", "New category").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL14).action(async (options) => {
3928
- try {
3929
- const url = getAgentUrl(options);
3930
- const body = {};
3931
- if (options.command)
3932
- body.command = options.command;
3933
- if (options.description)
3934
- body.description = options.description;
3935
- if (options.category)
3936
- body.category = options.category;
3937
- if (Object.keys(body).length === 0) {
3938
- fail("No fields to update. Provide at least one of --command, --description, or --category.");
3939
- return;
3940
- }
3941
- await apiPut(url, `/api/bookmarks/${options.id}`, body);
3942
- success(`Bookmark ${shortId(options.id)} updated.`);
3943
- } catch (err) {
3944
- fail(err.message);
3945
- }
3946
- });
3947
- cmd.command("delete").description("Delete a bookmark").requiredOption("-i, --id <id>", "Bookmark ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL14).action(async (options) => {
3948
- try {
3949
- const url = getAgentUrl(options);
3950
- await apiDelete(url, `/api/bookmarks/${options.id}`);
3951
- success(`Bookmark ${shortId(options.id)} deleted.`);
3952
- } catch (err) {
3953
- fail(err.message);
3954
- }
3955
- });
3956
- cmd.command("execute").description("Execute a bookmarked command").requiredOption("-i, --id <id>", "Bookmark ID").option("--session <sessionId>", "Session ID to execute in").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL14).action(async (options) => {
3957
- try {
3958
- const url = getAgentUrl(options);
3959
- const body = {};
3960
- if (options.session)
3961
- body.sessionId = options.session;
3962
- const result = await apiPost(url, `/api/bookmarks/${options.id}/execute`, body);
3963
- success(`Bookmark ${shortId(options.id)} executed.`);
3964
- if (result?.output) {
3965
- console.log(result.output);
3966
- }
3967
- } catch (err) {
3968
- fail(err.message);
3969
- }
3970
- });
3971
- }
3972
- // src/cli/commands/notify.cmd.ts
3973
- var DEFAULT_AGENT_URL15 = "http://localhost:3005";
3974
- function register23(program2) {
3975
- const cmd = program2.command("notify").description("Manage notifications");
3976
- cmd.command("list").description("List notifications").option("--unread", "Show only unread notifications").option("--project <id>", "Filter by project ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL15).action(async (options) => {
3977
- try {
3978
- const url = getAgentUrl(options);
3979
- const params = new URLSearchParams;
3980
- if (options.unread)
3981
- params.set("unread", "true");
3982
- if (options.project)
3983
- params.set("project", options.project);
3984
- const query = params.toString();
3985
- const endpoint = query ? `/api/notifications?${query}` : "/api/notifications";
3986
- const data = await apiGet(url, endpoint);
3987
- const notifications = data.notifications || [];
3988
- if (!notifications || notifications.length === 0) {
3989
- info("No notifications found.");
3990
- return;
3991
- }
3992
- header("Notifications");
3993
- blank();
3994
- for (const n of notifications) {
3995
- const icon = formatNotificationType(n.type);
3996
- const time = n.createdAt ? colors.dim(timeAgo(n.createdAt)) : "";
3997
- const title = colors.bold(n.title || "Untitled");
3998
- const id = colors.dim(`[${shortId(n.id)}]`);
3999
- console.log(` ${icon} ${title} ${id} ${time}`);
4000
- if (n.message) {
4001
- console.log(` ${n.message}`);
4002
- }
4003
- blank();
4004
- }
4005
- } catch (err) {
4006
- fail(err.message);
4007
- }
4008
- });
4009
- cmd.command("create").description("Create a notification").requiredOption("--title <title>", "Notification title").requiredOption("--message <msg>", "Notification message").option("--type <type>", "Notification type", "info").option("--project <id>", "Project ID").option("--session <name>", "Session name").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL15).action(async (options) => {
4010
- try {
4011
- const url = getAgentUrl(options);
4012
- const body = {
4013
- title: options.title,
4014
- message: options.message,
4015
- type: options.type
4016
- };
4017
- if (options.project)
4018
- body.project = options.project;
4019
- if (options.session)
4020
- body.session = options.session;
4021
- const result = await apiPost(url, "/api/notifications", body);
4022
- success(`Notification created: ${shortId(result?.id)}`);
4023
- } catch (err) {
4024
- fail(err.message);
4025
- }
4026
- });
4027
- cmd.command("delete").description("Delete a notification").requiredOption("-i, --id <id>", "Notification ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL15).action(async (options) => {
4028
- try {
4029
- const url = getAgentUrl(options);
4030
- await apiDelete(url, `/api/notifications/${options.id}`);
4031
- success(`Notification ${shortId(options.id)} deleted.`);
4032
- } catch (err) {
4033
- fail(err.message);
4034
- }
4035
- });
4036
- cmd.command("read-all").description("Mark all notifications as read").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL15).action(async (options) => {
4037
- try {
4038
- const url = getAgentUrl(options);
4039
- await apiPut(url, "/api/notifications/read-all", {});
4040
- success("All notifications marked as read.");
4041
- } catch (err) {
4042
- fail(err.message);
4043
- }
4044
- });
4045
- cmd.command("clear-old").description("Clear old notifications").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL15).action(async (options) => {
4046
- try {
4047
- const url = getAgentUrl(options);
4048
- await apiDelete(url, "/api/notifications/clear/old");
4049
- success("Old notifications cleared.");
4050
- } catch (err) {
4051
- fail(err.message);
4052
- }
4053
- });
4054
- cmd.command("webhook").description("Send a webhook notification to a session").requiredOption("--session <sessionId>", "Target session ID").option("--title <title>", "Notification title").option("--message <msg>", "Notification message").option("--type <type>", "Notification type", "info").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL15).action(async (options) => {
4055
- try {
4056
- const url = getAgentUrl(options);
4057
- const body = {};
4058
- if (options.title)
4059
- body.title = options.title;
4060
- if (options.message)
4061
- body.message = options.message;
4062
- if (options.type)
4063
- body.type = options.type;
4064
- await apiPost(url, `/api/notifications/webhook/${options.session}`, body);
4065
- success(`Webhook notification sent to session ${shortId(options.session)}.`);
4066
- } catch (err) {
4067
- fail(err.message);
4068
- }
4069
- });
4070
- }
4071
- // src/cli/commands/project.cmd.ts
4072
- var DEFAULT_AGENT_URL16 = "http://localhost:3005";
4073
- function register24(program2) {
4074
- const cmd = program2.command("project").description("Manage projects");
4075
- cmd.command("list").description("List all projects").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL16).action(async (options) => {
4076
- try {
4077
- const url = getAgentUrl(options);
4078
- const data = await apiGet(url, "/api/projects");
4079
- const projects = data.projects || [];
4080
- if (!projects || projects.length === 0) {
4081
- info("No projects found.");
4082
- return;
4083
- }
4084
- header("Projects");
4085
- formatTable(projects.map((p) => ({
4086
- ID: shortId(p.id),
4087
- Name: p.name || "-",
4088
- Path: p.path || "-",
4089
- Type: p.type || p.projectType || "-",
4090
- Framework: p.framework || "-",
4091
- "Git Branch": p.gitBranch || p.branch || "-"
4092
- })));
4093
- } catch (err) {
4094
- fail(err.message);
4095
- }
4096
- });
4097
- cmd.command("scan").description("Scan a directory for projects").requiredOption("--dir <directory>", "Directory to scan").option("--depth <depth>", "Scan depth", "3").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL16).action(async (options) => {
4098
- try {
4099
- const url = getAgentUrl(options);
4100
- const result = await apiPost(url, "/api/projects/scan", {
4101
- directory: options.dir,
4102
- depth: parseInt(options.depth, 10)
4103
- });
4104
- success("Project scan completed.");
4105
- if (result?.found !== undefined)
4106
- kv("Projects found", result.found);
4107
- if (result?.projects)
4108
- kv("Projects found", result.projects.length);
4109
- } catch (err) {
4110
- fail(err.message);
4111
- }
4112
- });
4113
- cmd.command("scan-remote").description("Scan remote workspace for projects").requiredOption("--workspace-id <id>", "Workspace ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL16).action(async (options) => {
4114
- try {
4115
- const url = getAgentUrl(options);
4116
- const result = await apiPost(url, "/api/projects/scan-remote", {
4117
- workspaceId: options.workspaceId
4118
- });
4119
- success("Remote project scan completed.");
4120
- if (result?.found !== undefined)
4121
- kv("Projects found", result.found);
4122
- if (result?.projects)
4123
- kv("Projects found", result.projects.length);
4124
- } catch (err) {
4125
- fail(err.message);
4126
- }
4127
- });
4128
- }
4129
- // src/cli/commands/plugin.cmd.ts
4130
- var DEFAULT_AGENT_URL17 = "http://localhost:3005";
4131
- function register25(program2) {
4132
- const cmd = program2.command("plugin").description("Manage plugins");
4133
- cmd.command("list").description("List installed plugins").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL17).action(async (options) => {
4134
- try {
4135
- const url = getAgentUrl(options);
4136
- let plugins;
4137
- try {
4138
- const data = await apiGet(url, "/api/plugins");
4139
- plugins = data.plugins || [];
4140
- } catch {
4141
- warn("Agent not reachable. Attempting local plugin registry...");
4142
- try {
4143
- const { PluginManager: PluginManager2 } = await import("./plugin-system-bg1pzjj9.js");
4144
- const pm = new PluginManager2;
4145
- plugins = pm.getPluginDetails() || [];
4146
- } catch {
4147
- fail("Could not list plugins from agent or local registry.");
4148
- return;
4149
- }
4150
- }
4151
- if (!plugins || plugins.length === 0) {
4152
- info("No plugins installed.");
4153
- return;
4154
- }
4155
- header("Installed Plugins");
4156
- formatTable(plugins.map((p) => ({
4157
- Name: p.name || p.package || "-",
4158
- Version: p.version || "-",
4159
- Status: p.status || p.enabled ? "enabled" : "disabled",
4160
- Description: p.description || "-"
4161
- })));
4162
- } catch (err) {
4163
- fail(err.message);
4164
- }
4165
- });
4166
- cmd.command("install").description("Install a plugin").argument("<package>", "NPM package name to install").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL17).action(async (packageName, options) => {
4167
- try {
4168
- const url = getAgentUrl(options);
4169
- try {
4170
- const result = await apiPost(url, "/api/plugins/install", {
4171
- package: packageName
4172
- });
4173
- success(`Plugin "${packageName}" installed.`);
4174
- if (result?.version)
4175
- kv("Version", result.version);
4176
- } catch {
4177
- warn("Agent not reachable. Attempting local install...");
4178
- try {
4179
- const { PluginManager: PluginManager2 } = await import("./plugin-system-bg1pzjj9.js");
4180
- const pm = new PluginManager2;
4181
- await pm.install(packageName);
4182
- success(`Plugin "${packageName}" installed locally.`);
4183
- } catch (localErr) {
4184
- fail(`Could not install plugin via agent or locally: ${localErr.message}`);
4185
- }
4186
- }
4187
- } catch (err) {
4188
- fail(err.message);
4189
- }
4190
- });
4191
- cmd.command("remove").description("Remove a plugin").argument("<package>", "NPM package name to remove").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL17).action(async (packageName, options) => {
4192
- try {
4193
- const url = getAgentUrl(options);
4194
- try {
4195
- await apiPost(url, "/api/plugins/remove", {
4196
- package: packageName
4197
- });
4198
- success(`Plugin "${packageName}" removed.`);
4199
- } catch {
4200
- warn("Agent not reachable. Attempting local removal...");
4201
- try {
4202
- const { PluginManager: PluginManager2 } = await import("./plugin-system-bg1pzjj9.js");
4203
- const pm = new PluginManager2;
4204
- await pm.remove(packageName);
4205
- success(`Plugin "${packageName}" removed locally.`);
4206
- } catch (localErr) {
4207
- fail(`Could not remove plugin via agent or locally: ${localErr.message}`);
4208
- }
4209
- }
4210
- } catch (err) {
4211
- fail(err.message);
4212
- }
4213
- });
4214
- cmd.command("reload").description("Reload all plugins").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL17).action(async (options) => {
4215
- try {
4216
- const url = getAgentUrl(options);
4217
- await apiPost(url, "/api/plugins/reload", {});
4218
- success("Plugins reloaded.");
4219
- } catch (err) {
4220
- fail(err.message);
4221
- }
4222
- });
4223
- cmd.command("available").description("Show available plugins").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL17).action(async (options) => {
4224
- try {
4225
- const url = getAgentUrl(options);
4226
- const availData = await apiGet(url, "/api/plugins/available");
4227
- const plugins = availData.plugins || [];
4228
- if (!plugins || plugins.length === 0) {
4229
- info("No available plugins found.");
4230
- return;
4231
- }
4232
- header("Available Plugins");
4233
- formatTable(plugins.map((p) => ({
4234
- Name: p.name || p.package || "-",
4235
- Version: p.version || p.latestVersion || "-",
4236
- Description: p.description || "-"
4237
- })));
4238
- } catch (err) {
4239
- fail(err.message);
4240
- }
4241
- });
4242
- }
4243
- // src/cli/commands/state.cmd.ts
4244
- var DEFAULT_AGENT_URL18 = "http://localhost:3005";
4245
- function register26(program2) {
4246
- const cmd = program2.command("state").description("Manage plugin key-value state");
4247
- cmd.command("list").description("List all state entries for a plugin").argument("<plugin>", "Plugin name").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL18).action(async (plugin, options) => {
4248
- try {
4249
- const url = getAgentUrl(options);
4250
- const entries = await apiGet(url, `/api/plugin-state/${encodeURIComponent(plugin)}`);
4251
- if (!entries || typeof entries === "object" && Object.keys(entries).length === 0) {
4252
- info(`No state entries for plugin "${plugin}".`);
4253
- return;
4254
- }
4255
- header(`State: ${plugin}`);
4256
- blank();
4257
- if (Array.isArray(entries)) {
4258
- for (const entry of entries) {
4259
- kv(entry.key, JSON.stringify(entry.value));
4260
- }
4261
- } else if (typeof entries === "object") {
4262
- for (const [key, value] of Object.entries(entries)) {
4263
- kv(key, JSON.stringify(value));
4264
- }
4265
- }
4266
- } catch (err) {
4267
- fail(err.message);
4268
- }
4269
- });
4270
- cmd.command("get").description("Get a state value").argument("<plugin>", "Plugin name").argument("<key>", "State key").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL18).action(async (plugin, key, options) => {
4271
- try {
4272
- const url = getAgentUrl(options);
4273
- const result = await apiGet(url, `/api/plugin-state/${encodeURIComponent(plugin)}/${encodeURIComponent(key)}`);
4274
- if (result?.value !== undefined) {
4275
- header(`${plugin} / ${key}`);
4276
- console.log(typeof result.value === "string" ? result.value : JSON.stringify(result.value, null, 2));
4277
- } else {
4278
- info(`No value found for key "${key}" in plugin "${plugin}".`);
4279
- }
4280
- } catch (err) {
4281
- fail(err.message);
4282
- }
4283
- });
4284
- cmd.command("set").description("Set a state value").argument("<plugin>", "Plugin name").argument("<key>", "State key").argument("<value>", "Value to set").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL18).action(async (plugin, key, value, options) => {
4285
- try {
4286
- const url = getAgentUrl(options);
4287
- let parsedValue = value;
4288
- try {
4289
- parsedValue = JSON.parse(value);
4290
- } catch {}
4291
- await apiPut(url, `/api/plugin-state/${encodeURIComponent(plugin)}/${encodeURIComponent(key)}`, { value: parsedValue });
4292
- success(`State set: ${plugin}/${key}`);
4293
- } catch (err) {
4294
- fail(err.message);
4295
- }
4296
- });
4297
- cmd.command("unset").description("Remove a state value").argument("<plugin>", "Plugin name").argument("<key>", "State key").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL18).action(async (plugin, key, options) => {
4298
- try {
4299
- const url = getAgentUrl(options);
4300
- await apiDelete(url, `/api/plugin-state/${encodeURIComponent(plugin)}/${encodeURIComponent(key)}`);
4301
- success(`State removed: ${plugin}/${key}`);
4302
- } catch (err) {
4303
- fail(err.message);
4304
- }
4305
- });
4306
- }
4307
- // src/cli/commands/log.cmd.ts
4308
- var DEFAULT_AGENT_URL19 = "http://localhost:3005";
4309
- function register27(program2) {
4310
- const cmd = program2.command("log").description("View and stream logs");
4311
- cmd.command("list").description("List recent log entries").option("--level <level>", "Minimum log level", "info").option("--limit <n>", "Number of entries to show", "50").option("--source <source>", "Filter by source").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL19).action(async (options) => {
4312
- try {
4313
- const url = getAgentUrl(options);
4314
- const params = new URLSearchParams;
4315
- params.set("level", options.level);
4316
- params.set("limit", options.limit);
4317
- if (options.source)
4318
- params.set("source", options.source);
4319
- const logs = await apiGet(url, `/api/logs?${params.toString()}`);
4320
- if (!logs || logs.length === 0) {
4321
- info("No log entries found.");
4322
- return;
4323
- }
4324
- header("Logs");
4325
- blank();
4326
- for (const entry of logs) {
4327
- const level = formatLogLevel(entry.level);
4328
- const time = entry.timestamp ? colors.dim(timeAgo(entry.timestamp)) : "";
4329
- const source = entry.source ? colors.cyan(`[${entry.source}]`) : "";
4330
- const message = entry.message || "";
4331
- console.log(` ${level} ${source} ${message} ${time}`);
4332
- }
4333
- } catch (err) {
4334
- fail(err.message);
4335
- }
4336
- });
4337
- cmd.command("stream").description("Stream logs in real-time (SSE)").option("--level <level>", "Minimum log level", "info").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL19).action(async (options) => {
4338
- try {
4339
- const url = getAgentUrl(options);
4340
- const params = new URLSearchParams;
4341
- params.set("level", options.level);
4342
- const streamUrl = `${url}/api/logs/stream?${params.toString()}`;
4343
- info(`Streaming logs from ${url} (level: ${options.level})...`);
4344
- info(`Press Ctrl+C to stop.
4345
- `);
4346
- const response = await fetch(streamUrl, {
4347
- headers: { Accept: "text/event-stream" }
4348
- });
4349
- if (!response.ok) {
4350
- fail(`Failed to connect to log stream: ${response.status} ${response.statusText}`);
4351
- return;
4352
- }
4353
- if (!response.body) {
4354
- fail("No response body for SSE stream.");
4355
- return;
4356
- }
4357
- const decoder = new TextDecoder;
4358
- const reader = response.body.getReader();
4359
- const cleanup = () => {
4360
- reader.cancel().catch(() => {});
4361
- console.log(`
4362
- Log stream ended.`);
4363
- process.exit(0);
4364
- };
4365
- process.on("SIGINT", cleanup);
4366
- process.on("SIGTERM", cleanup);
4367
- let buffer = "";
4368
- while (true) {
4369
- const { done, value } = await reader.read();
4370
- if (done)
4371
- break;
4372
- buffer += decoder.decode(value, { stream: true });
4373
- const lines = buffer.split(`
4374
- `);
4375
- buffer = lines.pop() || "";
4376
- for (const line of lines) {
4377
- if (line.startsWith("data: ")) {
4378
- const data = line.slice(6).trim();
4379
- if (!data || data === "[DONE]")
4380
- continue;
4381
- try {
4382
- const entry = JSON.parse(data);
4383
- const level = formatLogLevel(entry.level);
4384
- const source = entry.source ? colors.cyan(`[${entry.source}]`) : "";
4385
- const message = entry.message || "";
4386
- const time = entry.timestamp ? colors.dim(new Date(entry.timestamp).toLocaleTimeString()) : "";
4387
- console.log(`${level} ${source} ${message} ${time}`);
4388
- } catch {
4389
- if (data.trim())
4390
- console.log(data);
4391
- }
4392
- }
4393
- }
4394
- }
4395
- } catch (err) {
4396
- if (err.name === "AbortError")
4397
- return;
4398
- fail(err.message);
4399
- }
4400
- });
4401
- }
4402
- function formatLogLevel(level) {
4403
- if (!level)
4404
- return colors.dim("???");
4405
- switch (level.toLowerCase()) {
4406
- case "error":
4407
- return colors.red(colors.bold("ERR"));
4408
- case "warn":
4409
- case "warning":
4410
- return colors.yellow("WRN");
4411
- case "info":
4412
- return colors.blue("INF");
4413
- case "debug":
4414
- return colors.gray("DBG");
4415
- case "trace":
4416
- return colors.dim("TRC");
4417
- default:
4418
- return colors.dim(level.toUpperCase().slice(0, 3));
4419
- }
4420
- }
2554
+
4421
2555
  // src/services/completion.service.ts
4422
2556
  import {
4423
- existsSync as existsSync3,
4424
- mkdirSync as mkdirSync2,
4425
- writeFileSync as writeFileSync2,
2557
+ existsSync as existsSync2,
2558
+ mkdirSync,
2559
+ writeFileSync,
4426
2560
  unlinkSync,
4427
- readFileSync as readFileSync2
2561
+ readFileSync
4428
2562
  } from "fs";
4429
- import { join as join3 } from "path";
4430
- import { homedir as homedir3 } from "os";
2563
+ import { join as join2 } from "path";
2564
+ import { homedir as homedir2 } from "os";
4431
2565
  function collectCommands(cmd) {
4432
2566
  return cmd.commands.map((sub) => ({
4433
2567
  name: sub.name(),
@@ -4603,7 +2737,7 @@ ${MARKER_END}`;
4603
2737
  return { shell: sh, path: rcFile };
4604
2738
  }
4605
2739
  case "zsh": {
4606
- const zshrc = join3(homedir3(), ".zshrc");
2740
+ const zshrc = join2(homedir2(), ".zshrc");
4607
2741
  const evalLine = `${MARKER_START}
4608
2742
  eval "$(vibe completion zsh)"
4609
2743
  ${MARKER_END}`;
@@ -4611,11 +2745,11 @@ ${MARKER_END}`;
4611
2745
  return { shell: sh, path: zshrc };
4612
2746
  }
4613
2747
  case "fish": {
4614
- const dir = join3(process.env.XDG_CONFIG_HOME || join3(homedir3(), ".config"), "fish", "completions");
4615
- if (!existsSync3(dir))
4616
- mkdirSync2(dir, { recursive: true });
4617
- const target = join3(dir, "vibe.fish");
4618
- writeFileSync2(target, generateFish(cmds), "utf8");
2748
+ const dir = join2(process.env.XDG_CONFIG_HOME || join2(homedir2(), ".config"), "fish", "completions");
2749
+ if (!existsSync2(dir))
2750
+ mkdirSync(dir, { recursive: true });
2751
+ const target = join2(dir, "vibe.fish");
2752
+ writeFileSync(target, generateFish(cmds), "utf8");
4619
2753
  return { shell: sh, path: target };
4620
2754
  }
4621
2755
  }
@@ -4629,52 +2763,52 @@ function uninstallCompletion(shell) {
4629
2763
  return { shell: sh, path: rcFile };
4630
2764
  }
4631
2765
  case "zsh": {
4632
- const zshrc = join3(homedir3(), ".zshrc");
2766
+ const zshrc = join2(homedir2(), ".zshrc");
4633
2767
  removeMarkedBlock(zshrc);
4634
2768
  return { shell: sh, path: zshrc };
4635
2769
  }
4636
2770
  case "fish": {
4637
- const target = join3(process.env.XDG_CONFIG_HOME || join3(homedir3(), ".config"), "fish", "completions", "vibe.fish");
4638
- if (existsSync3(target))
2771
+ const target = join2(process.env.XDG_CONFIG_HOME || join2(homedir2(), ".config"), "fish", "completions", "vibe.fish");
2772
+ if (existsSync2(target))
4639
2773
  unlinkSync(target);
4640
2774
  return { shell: sh, path: target };
4641
2775
  }
4642
2776
  }
4643
2777
  }
4644
2778
  function bashrcPath() {
4645
- const bashrc = join3(homedir3(), ".bashrc");
4646
- if (existsSync3(bashrc))
2779
+ const bashrc = join2(homedir2(), ".bashrc");
2780
+ if (existsSync2(bashrc))
4647
2781
  return bashrc;
4648
- const profile = join3(homedir3(), ".bash_profile");
4649
- if (existsSync3(profile))
2782
+ const profile = join2(homedir2(), ".bash_profile");
2783
+ if (existsSync2(profile))
4650
2784
  return profile;
4651
2785
  return bashrc;
4652
2786
  }
4653
2787
  function appendIfMissing(file, marker, block) {
4654
2788
  let content = "";
4655
- if (existsSync3(file))
4656
- content = readFileSync2(file, "utf8");
2789
+ if (existsSync2(file))
2790
+ content = readFileSync(file, "utf8");
4657
2791
  if (content.includes(marker)) {
4658
2792
  removeMarkedBlock(file);
4659
- content = existsSync3(file) ? readFileSync2(file, "utf8") : "";
2793
+ content = existsSync2(file) ? readFileSync(file, "utf8") : "";
4660
2794
  }
4661
- writeFileSync2(file, content + `
2795
+ writeFileSync(file, content + `
4662
2796
  ` + block + `
4663
2797
  `, "utf8");
4664
2798
  }
4665
2799
  function removeMarkedBlock(file) {
4666
- if (!existsSync3(file))
2800
+ if (!existsSync2(file))
4667
2801
  return;
4668
- const content = readFileSync2(file, "utf8");
2802
+ const content = readFileSync(file, "utf8");
4669
2803
  const startIdx = content.indexOf(MARKER_START);
4670
2804
  const endIdx = content.indexOf(MARKER_END);
4671
2805
  if (startIdx === -1 || endIdx === -1)
4672
2806
  return;
4673
- writeFileSync2(file, content.substring(0, startIdx) + content.substring(endIdx + MARKER_END.length), "utf8");
2807
+ writeFileSync(file, content.substring(0, startIdx) + content.substring(endIdx + MARKER_END.length), "utf8");
4674
2808
  }
4675
2809
 
4676
2810
  // src/cli/commands/completion.cmd.ts
4677
- function register28(program2) {
2811
+ function register9(program2) {
4678
2812
  const cmd = program2.command("completion").description("Generate shell completion scripts (bash, zsh, fish)");
4679
2813
  cmd.command("bash").description("Print Bash completion script").action(() => {
4680
2814
  const cmds = collectCommands(program2);
@@ -4712,6 +2846,7 @@ function register28(program2) {
4712
2846
  }
4713
2847
  });
4714
2848
  }
2849
+
4715
2850
  // src/cli.ts
4716
2851
  if (typeof Bun === "undefined") {
4717
2852
  console.error(`\x1B[31mError:\x1B[0m VibeControls Agent requires the Bun runtime.
@@ -4719,16 +2854,14 @@ if (typeof Bun === "undefined") {
4719
2854
  ` + " Then run: bun run vibe ...");
4720
2855
  process.exit(1);
4721
2856
  }
4722
- var __filename3 = fileURLToPath2(import.meta.url);
4723
- var __dirname3 = dirname2(__filename3);
4724
2857
  var packageVersion = "1.0.0";
4725
2858
  try {
4726
- const packageJsonPath = join4(__dirname3, "..", "package.json");
4727
- const packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf8"));
2859
+ const packageJsonPath = join3(import.meta.dir, "..", "package.json");
2860
+ const packageJson = await Bun.file(packageJsonPath).json();
4728
2861
  packageVersion = packageJson.version;
4729
2862
  } catch {}
4730
2863
  var program2 = new Command;
4731
- program2.name("vibe").description("VibeControls Agent CLI \u2014 Remote development environment management").version(packageVersion, "-v, --version");
2864
+ program2.name("vibe").description("VibeControls Agent CLI \u2014 Remote development environment management").version(packageVersion, "-v, --version").option("--provider <name>", "Override the default provider for tunnel/session operations");
4732
2865
  register(program2);
4733
2866
  register2(program2);
4734
2867
  register3(program2);
@@ -4738,55 +2871,39 @@ register6(program2);
4738
2871
  register7(program2);
4739
2872
  register8(program2);
4740
2873
  register9(program2);
4741
- register10(program2);
4742
- register11(program2);
4743
- register12(program2);
4744
- register13(program2);
4745
- register14(program2);
4746
- register15(program2);
4747
- register16(program2);
4748
- register17(program2);
4749
- register18(program2);
4750
- register19(program2);
4751
- register20(program2);
4752
- register21(program2);
4753
- register22(program2);
4754
- register23(program2);
4755
- register24(program2);
4756
- register25(program2);
4757
- register26(program2);
4758
- register27(program2);
4759
- register28(program2);
4760
2874
  async function main() {
4761
2875
  const pluginManager = new PluginManager;
2876
+ try {
2877
+ await pluginManager.loadCorePlugins();
2878
+ } catch {}
4762
2879
  try {
4763
2880
  await pluginManager.loadAll();
4764
2881
  } catch {}
2882
+ const serviceRegistry = new ServiceRegistry;
2883
+ const cliStorage = {
2884
+ async get() {
2885
+ return null;
2886
+ },
2887
+ async set() {},
2888
+ async delete() {
2889
+ return false;
2890
+ },
2891
+ async list() {
2892
+ return [];
2893
+ },
2894
+ async deleteAll() {
2895
+ return 0;
2896
+ }
2897
+ };
2898
+ const hostServices = {
2899
+ storage: cliStorage,
2900
+ logger,
2901
+ serviceRegistry,
2902
+ getProvider: (type) => serviceRegistry.getProvider(type),
2903
+ getAgentBaseUrl: () => process.env.AGENT_URL || "http://localhost:3005",
2904
+ getAgentVersion: () => packageVersion
2905
+ };
4765
2906
  try {
4766
- const serviceRegistry = new ServiceRegistry;
4767
- const cliStorage = {
4768
- async get() {
4769
- return null;
4770
- },
4771
- async set() {},
4772
- async delete() {
4773
- return false;
4774
- },
4775
- async list() {
4776
- return [];
4777
- },
4778
- async deleteAll() {
4779
- return 0;
4780
- }
4781
- };
4782
- const hostServices = {
4783
- storage: cliStorage,
4784
- logger,
4785
- serviceRegistry,
4786
- getProvider: (type) => serviceRegistry.getProvider(type),
4787
- getAgentBaseUrl: () => process.env.AGENT_URL || "http://localhost:3005",
4788
- getAgentVersion: () => packageVersion
4789
- };
4790
2907
  await pluginManager.dispatchCliSetup(program2, hostServices);
4791
2908
  } catch {}
4792
2909
  program2.parse();
@@ -4796,5 +2913,5 @@ main().catch((err) => {
4796
2913
  process.exit(1);
4797
2914
  });
4798
2915
 
4799
- //# debugId=7429A5527447039F64756E2164756E21
2916
+ //# debugId=B3B10A5CB7971CB864756E2164756E21
4800
2917
  //# sourceMappingURL=cli.js.map