@burdenoff/vibe-agent 2.1.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/app-6mmbmske.js +1166 -0
  2. package/dist/app-6mmbmske.js.map +19 -0
  3. package/dist/cli.js +152 -2036
  4. package/dist/cli.js.map +6 -28
  5. package/dist/index-05qfwz8r.js +122 -0
  6. package/dist/index-05qfwz8r.js.map +10 -0
  7. package/dist/index-30p492yv.js +294 -0
  8. package/dist/index-30p492yv.js.map +13 -0
  9. package/dist/index-3v78e2cn.js +373 -0
  10. package/dist/index-3v78e2cn.js.map +11 -0
  11. package/dist/index-41m1exz7.js +269 -0
  12. package/dist/index-41m1exz7.js.map +13 -0
  13. package/dist/index-88ym10cs.js +194 -0
  14. package/dist/index-88ym10cs.js.map +10 -0
  15. package/dist/index-9tgyd3ep.js +513 -0
  16. package/dist/index-9tgyd3ep.js.map +19 -0
  17. package/dist/index-a9g7hbj9.js +229 -0
  18. package/dist/index-a9g7hbj9.js.map +13 -0
  19. package/dist/index-atjhkm74.js +149 -0
  20. package/dist/index-atjhkm74.js.map +10 -0
  21. package/dist/index-c7zy3n33.js +167 -0
  22. package/dist/index-c7zy3n33.js.map +13 -0
  23. package/dist/index-hefqxwht.js +270 -0
  24. package/dist/index-hefqxwht.js.map +13 -0
  25. package/dist/index-k9hb0b93.js +280 -0
  26. package/dist/index-k9hb0b93.js.map +13 -0
  27. package/dist/index-npmvh1x9.js +385 -0
  28. package/dist/index-npmvh1x9.js.map +13 -0
  29. package/dist/index-q4ytrfx7.js +286 -0
  30. package/dist/index-q4ytrfx7.js.map +13 -0
  31. package/dist/index-qthbtg9n.js +302 -0
  32. package/dist/index-qthbtg9n.js.map +13 -0
  33. package/dist/index-rdm6e3rr.js +587 -0
  34. package/dist/index-rdm6e3rr.js.map +13 -0
  35. package/dist/index-wdtxbebz.js +339 -0
  36. package/dist/index-wdtxbebz.js.map +13 -0
  37. package/dist/{app-31chs2a1.js → index-wr0mkm57.js} +8 -3201
  38. package/dist/{app-31chs2a1.js.map → index-wr0mkm57.js.map} +4 -25
  39. package/dist/index-xmeskdnb.js +292 -0
  40. package/dist/index-xmeskdnb.js.map +11 -0
  41. package/dist/index-xn4tarcd.js +287 -0
  42. package/dist/index-xn4tarcd.js.map +13 -0
  43. package/dist/index.js +9 -6
  44. package/dist/index.js.map +2 -2
  45. package/dist/{package-hb6db316.js → package-ywexp6sg.js} +3 -3
  46. package/dist/{package-hb6db316.js.map → package-ywexp6sg.js.map} +1 -1
  47. package/dist/plugin-system-v7a7xnhk.js +475 -0
  48. package/dist/plugin-system-v7a7xnhk.js.map +10 -0
  49. package/package.json +1 -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-3v78e2cn.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-v7a7xnhk.js";
17
37
 
18
38
  // node_modules/commander/lib/error.js
19
39
  var require_error = __commonJS((exports) => {
@@ -2125,537 +2145,14 @@ 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 { readFileSync as readFileSync2 } from "fs";
2149
+ import { join as join3, dirname } from "path";
2150
+ import { fileURLToPath } from "url";
2131
2151
 
2132
2152
  // 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";
2153
+ import { existsSync } from "fs";
2154
+ import { join } from "path";
2436
2155
  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
-
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
- }
2569
- 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
2579
- }
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");
2652
- } catch {
2653
- try {
2654
- process.kill(pid, "SIGKILL");
2655
- } catch {}
2656
- }
2657
- }
2658
- }
2659
2156
 
2660
2157
  // src/services/port-utils.ts
2661
2158
  import { createServer } from "net";
@@ -2682,12 +2179,12 @@ async function findFreePortFrom(startPort, host = "0.0.0.0") {
2682
2179
 
2683
2180
  // src/cli/commands/start.cmd.ts
2684
2181
  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) => {
2182
+ 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
2183
  try {
2687
2184
  const serviceManager = new ServiceManager;
2688
2185
  const dbPath = opts.dbPath;
2689
- const configDir = join2(homedir2(), ".vibecontrols");
2690
- const firstRun = !existsSync2(dbPath) && !existsSync2(join2(configDir, "agents.json"));
2186
+ const configDir = join(homedir(), ".vibecontrols");
2187
+ const firstRun = !existsSync(dbPath) && !existsSync(join(configDir, "agents.json"));
2691
2188
  if (firstRun) {
2692
2189
  info("First run detected \u2014 running setup...");
2693
2190
  blank();
@@ -2720,47 +2217,49 @@ function register(program2) {
2720
2217
  }
2721
2218
  const host = opts.host;
2722
2219
  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 {
2220
+ if (opts.foreground) {
2739
2221
  header("Starting agent in foreground");
2740
2222
  kv("Name", opts.name);
2741
2223
  kv("Port", String(port));
2742
2224
  kv("Host", host);
2743
2225
  kv("Database", dbPath);
2744
2226
  blank();
2745
- const { createApp } = await import("./app-31chs2a1.js");
2227
+ const { createApp } = await import("./app-6mmbmske.js");
2746
2228
  const appInstance = await createApp({
2747
2229
  port,
2748
2230
  host,
2749
2231
  dbPath
2750
2232
  });
2751
2233
  await appInstance.start();
2234
+ await printAgentDetails(agentUrl);
2752
2235
  const shutdown = async () => {
2753
2236
  await appInstance.stop();
2754
2237
  process.exit(0);
2755
2238
  };
2756
2239
  process.on("SIGTERM", shutdown);
2757
2240
  process.on("SIGINT", shutdown);
2241
+ } else {
2242
+ header("Starting agent in daemon mode");
2243
+ kv("Name", opts.name);
2244
+ kv("Port", String(port));
2245
+ kv("Host", host);
2246
+ kv("Database", dbPath);
2247
+ blank();
2248
+ await serviceManager.startDaemon({
2249
+ port,
2250
+ name: opts.name,
2251
+ daemon: true,
2252
+ dbPath,
2253
+ host
2254
+ });
2255
+ await printAgentDetails(agentUrl);
2758
2256
  }
2759
2257
  } catch (err) {
2760
2258
  fail(`Failed to start agent: ${err instanceof Error ? err.message : err}`);
2761
2259
  }
2762
2260
  });
2763
2261
  }
2262
+
2764
2263
  // src/cli/commands/stop.cmd.ts
2765
2264
  function register2(program2) {
2766
2265
  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 +2296,7 @@ function register2(program2) {
2797
2296
  }
2798
2297
  });
2799
2298
  }
2299
+
2800
2300
  // src/cli/commands/restart.cmd.ts
2801
2301
  function register3(program2) {
2802
2302
  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 +2338,49 @@ function register3(program2) {
2838
2338
  }
2839
2339
  });
2840
2340
  }
2841
- // src/cli/commands/status.cmd.ts
2341
+
2342
+ // src/cli/commands/kill.cmd.ts
2842
2343
  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) => {
2344
+ 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
2345
  try {
2845
2346
  const serviceManager = new ServiceManager;
2846
- if (opts.name) {
2847
- header(`Agent Status: ${opts.name}`);
2347
+ if (opts.all) {
2348
+ header("Force killing all agent instances");
2848
2349
  blank();
2849
- const instance = await serviceManager.getStatus(opts.name);
2850
- if (!instance) {
2851
- fail(`Agent instance ${colors.bold(opts.name)} not found.`);
2350
+ const instances = await serviceManager.listInstances();
2351
+ if (!instances || instances.length === 0) {
2352
+ info(`${icons.info} No agent instances found.`);
2852
2353
  return;
2853
2354
  }
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));
2355
+ let killed = 0;
2356
+ for (const instance of instances) {
2357
+ try {
2358
+ await serviceManager.kill(instance.name);
2359
+ success(`${icons.success} Killed ${colors.bold(instance.name)} (PID: ${instance.pid || "unknown"})`);
2360
+ killed++;
2361
+ } catch {
2362
+ warn(`${icons.warning} Could not kill ${colors.bold(instance.name)}`);
2363
+ }
2862
2364
  }
2863
2365
  blank();
2366
+ success(`${icons.success} Killed ${killed}/${instances.length} instance(s).`);
2864
2367
  } else {
2865
- header("Agent Instances");
2368
+ header(`Force killing agent: ${opts.name}`);
2866
2369
  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.`);
2370
+ const instance = await serviceManager.getStatus(opts.name);
2371
+ if (!instance) {
2372
+ fail(`Agent instance ${colors.bold(opts.name)} not found.`);
2871
2373
  return;
2872
2374
  }
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.`);
2375
+ await serviceManager.kill(opts.name);
2376
+ success(`${icons.success} Agent ${colors.bold(opts.name)} killed (PID: ${instance.pid || "unknown"}).`);
2883
2377
  }
2884
2378
  } catch (err) {
2885
- fail(`Failed to get status: ${err.message}`);
2379
+ fail(`Failed to kill agent: ${err.message}`);
2886
2380
  }
2887
2381
  });
2888
2382
  }
2383
+
2889
2384
  // src/cli/commands/list.cmd.ts
2890
2385
  function register5(program2) {
2891
2386
  program2.command("list").alias("ls").description("List all VibeControls agent instances").action(async () => {
@@ -2918,49 +2413,9 @@ function register5(program2) {
2918
2413
  }
2919
2414
  });
2920
2415
  }
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
- }
2416
+
2962
2417
  // src/cli/commands/logs.cmd.ts
2963
- function register7(program2) {
2418
+ function register6(program2) {
2964
2419
  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
2420
  try {
2966
2421
  const serviceManager = new ServiceManager;
@@ -2989,134 +2444,13 @@ function register7(program2) {
2989
2444
  }
2990
2445
  });
2991
2446
  }
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) => {
2447
+
2448
+ // src/cli/commands/setup.cmd.ts
2449
+ function register7(program2) {
2450
+ program2.command("setup").description("Install or verify system dependencies (tmux, ttyd, cloudflared)").option("--check", "Only check without installing", false).action(async (options) => {
2996
2451
  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...");
2452
+ header("VibeControls Agent Setup");
2453
+ info("Checking dependencies...");
3120
2454
  blank();
3121
2455
  const deps = checkDependencies();
3122
2456
  const missing = [];
@@ -3154,17 +2488,18 @@ function register11(program2) {
3154
2488
  }
3155
2489
  });
3156
2490
  }
2491
+
3157
2492
  // src/cli/commands/update.cmd.ts
3158
2493
  import { execSync } from "child_process";
3159
2494
  var PACKAGE_NAME = "vibecontrols-agent";
3160
- function register12(program2) {
2495
+ function register8(program2) {
3161
2496
  program2.command("update").description("Check for and install VibeControls agent updates").option("--check", "Only check for updates without installing", false).action(async (opts) => {
3162
2497
  try {
3163
2498
  header("VibeControls Agent Update");
3164
2499
  blank();
3165
2500
  let currentVersion;
3166
2501
  try {
3167
- const pkg = await import("./package-hb6db316.js", {
2502
+ const pkg = await import("./package-ywexp6sg.js", {
3168
2503
  with: { type: "json" }
3169
2504
  });
3170
2505
  currentVersion = pkg.default.version || pkg.version;
@@ -3213,1221 +2548,17 @@ function register12(program2) {
3213
2548
  }
3214
2549
  });
3215
2550
  }
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
- }
2551
+
4421
2552
  // src/services/completion.service.ts
4422
2553
  import {
4423
- existsSync as existsSync3,
4424
- mkdirSync as mkdirSync2,
4425
- writeFileSync as writeFileSync2,
2554
+ existsSync as existsSync2,
2555
+ mkdirSync,
2556
+ writeFileSync,
4426
2557
  unlinkSync,
4427
- readFileSync as readFileSync2
2558
+ readFileSync
4428
2559
  } from "fs";
4429
- import { join as join3 } from "path";
4430
- import { homedir as homedir3 } from "os";
2560
+ import { join as join2 } from "path";
2561
+ import { homedir as homedir2 } from "os";
4431
2562
  function collectCommands(cmd) {
4432
2563
  return cmd.commands.map((sub) => ({
4433
2564
  name: sub.name(),
@@ -4603,7 +2734,7 @@ ${MARKER_END}`;
4603
2734
  return { shell: sh, path: rcFile };
4604
2735
  }
4605
2736
  case "zsh": {
4606
- const zshrc = join3(homedir3(), ".zshrc");
2737
+ const zshrc = join2(homedir2(), ".zshrc");
4607
2738
  const evalLine = `${MARKER_START}
4608
2739
  eval "$(vibe completion zsh)"
4609
2740
  ${MARKER_END}`;
@@ -4611,11 +2742,11 @@ ${MARKER_END}`;
4611
2742
  return { shell: sh, path: zshrc };
4612
2743
  }
4613
2744
  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");
2745
+ const dir = join2(process.env.XDG_CONFIG_HOME || join2(homedir2(), ".config"), "fish", "completions");
2746
+ if (!existsSync2(dir))
2747
+ mkdirSync(dir, { recursive: true });
2748
+ const target = join2(dir, "vibe.fish");
2749
+ writeFileSync(target, generateFish(cmds), "utf8");
4619
2750
  return { shell: sh, path: target };
4620
2751
  }
4621
2752
  }
@@ -4629,52 +2760,52 @@ function uninstallCompletion(shell) {
4629
2760
  return { shell: sh, path: rcFile };
4630
2761
  }
4631
2762
  case "zsh": {
4632
- const zshrc = join3(homedir3(), ".zshrc");
2763
+ const zshrc = join2(homedir2(), ".zshrc");
4633
2764
  removeMarkedBlock(zshrc);
4634
2765
  return { shell: sh, path: zshrc };
4635
2766
  }
4636
2767
  case "fish": {
4637
- const target = join3(process.env.XDG_CONFIG_HOME || join3(homedir3(), ".config"), "fish", "completions", "vibe.fish");
4638
- if (existsSync3(target))
2768
+ const target = join2(process.env.XDG_CONFIG_HOME || join2(homedir2(), ".config"), "fish", "completions", "vibe.fish");
2769
+ if (existsSync2(target))
4639
2770
  unlinkSync(target);
4640
2771
  return { shell: sh, path: target };
4641
2772
  }
4642
2773
  }
4643
2774
  }
4644
2775
  function bashrcPath() {
4645
- const bashrc = join3(homedir3(), ".bashrc");
4646
- if (existsSync3(bashrc))
2776
+ const bashrc = join2(homedir2(), ".bashrc");
2777
+ if (existsSync2(bashrc))
4647
2778
  return bashrc;
4648
- const profile = join3(homedir3(), ".bash_profile");
4649
- if (existsSync3(profile))
2779
+ const profile = join2(homedir2(), ".bash_profile");
2780
+ if (existsSync2(profile))
4650
2781
  return profile;
4651
2782
  return bashrc;
4652
2783
  }
4653
2784
  function appendIfMissing(file, marker, block) {
4654
2785
  let content = "";
4655
- if (existsSync3(file))
4656
- content = readFileSync2(file, "utf8");
2786
+ if (existsSync2(file))
2787
+ content = readFileSync(file, "utf8");
4657
2788
  if (content.includes(marker)) {
4658
2789
  removeMarkedBlock(file);
4659
- content = existsSync3(file) ? readFileSync2(file, "utf8") : "";
2790
+ content = existsSync2(file) ? readFileSync(file, "utf8") : "";
4660
2791
  }
4661
- writeFileSync2(file, content + `
2792
+ writeFileSync(file, content + `
4662
2793
  ` + block + `
4663
2794
  `, "utf8");
4664
2795
  }
4665
2796
  function removeMarkedBlock(file) {
4666
- if (!existsSync3(file))
2797
+ if (!existsSync2(file))
4667
2798
  return;
4668
- const content = readFileSync2(file, "utf8");
2799
+ const content = readFileSync(file, "utf8");
4669
2800
  const startIdx = content.indexOf(MARKER_START);
4670
2801
  const endIdx = content.indexOf(MARKER_END);
4671
2802
  if (startIdx === -1 || endIdx === -1)
4672
2803
  return;
4673
- writeFileSync2(file, content.substring(0, startIdx) + content.substring(endIdx + MARKER_END.length), "utf8");
2804
+ writeFileSync(file, content.substring(0, startIdx) + content.substring(endIdx + MARKER_END.length), "utf8");
4674
2805
  }
4675
2806
 
4676
2807
  // src/cli/commands/completion.cmd.ts
4677
- function register28(program2) {
2808
+ function register9(program2) {
4678
2809
  const cmd = program2.command("completion").description("Generate shell completion scripts (bash, zsh, fish)");
4679
2810
  cmd.command("bash").description("Print Bash completion script").action(() => {
4680
2811
  const cmds = collectCommands(program2);
@@ -4712,6 +2843,7 @@ function register28(program2) {
4712
2843
  }
4713
2844
  });
4714
2845
  }
2846
+
4715
2847
  // src/cli.ts
4716
2848
  if (typeof Bun === "undefined") {
4717
2849
  console.error(`\x1B[31mError:\x1B[0m VibeControls Agent requires the Bun runtime.
@@ -4719,16 +2851,16 @@ if (typeof Bun === "undefined") {
4719
2851
  ` + " Then run: bun run vibe ...");
4720
2852
  process.exit(1);
4721
2853
  }
4722
- var __filename3 = fileURLToPath2(import.meta.url);
4723
- var __dirname3 = dirname2(__filename3);
2854
+ var __filename2 = fileURLToPath(import.meta.url);
2855
+ var __dirname2 = dirname(__filename2);
4724
2856
  var packageVersion = "1.0.0";
4725
2857
  try {
4726
- const packageJsonPath = join4(__dirname3, "..", "package.json");
4727
- const packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf8"));
2858
+ const packageJsonPath = join3(__dirname2, "..", "package.json");
2859
+ const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
4728
2860
  packageVersion = packageJson.version;
4729
2861
  } catch {}
4730
2862
  var program2 = new Command;
4731
- program2.name("vibe").description("VibeControls Agent CLI \u2014 Remote development environment management").version(packageVersion, "-v, --version");
2863
+ 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
2864
  register(program2);
4733
2865
  register2(program2);
4734
2866
  register3(program2);
@@ -4738,55 +2870,39 @@ register6(program2);
4738
2870
  register7(program2);
4739
2871
  register8(program2);
4740
2872
  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
2873
  async function main() {
4761
2874
  const pluginManager = new PluginManager;
2875
+ try {
2876
+ await pluginManager.loadCorePlugins();
2877
+ } catch {}
4762
2878
  try {
4763
2879
  await pluginManager.loadAll();
4764
2880
  } catch {}
2881
+ const serviceRegistry = new ServiceRegistry;
2882
+ const cliStorage = {
2883
+ async get() {
2884
+ return null;
2885
+ },
2886
+ async set() {},
2887
+ async delete() {
2888
+ return false;
2889
+ },
2890
+ async list() {
2891
+ return [];
2892
+ },
2893
+ async deleteAll() {
2894
+ return 0;
2895
+ }
2896
+ };
2897
+ const hostServices = {
2898
+ storage: cliStorage,
2899
+ logger,
2900
+ serviceRegistry,
2901
+ getProvider: (type) => serviceRegistry.getProvider(type),
2902
+ getAgentBaseUrl: () => process.env.AGENT_URL || "http://localhost:3005",
2903
+ getAgentVersion: () => packageVersion
2904
+ };
4765
2905
  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
2906
  await pluginManager.dispatchCliSetup(program2, hostServices);
4791
2907
  } catch {}
4792
2908
  program2.parse();
@@ -4796,5 +2912,5 @@ main().catch((err) => {
4796
2912
  process.exit(1);
4797
2913
  });
4798
2914
 
4799
- //# debugId=7429A5527447039F64756E2164756E21
2915
+ //# debugId=8AF41CABD49D71F564756E2164756E21
4800
2916
  //# sourceMappingURL=cli.js.map