vibora 4.5.2 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.html CHANGED
@@ -5,8 +5,8 @@
5
5
  <link rel="icon" type="image/jpeg" href="/logo-dark.jpg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Vibora</title>
8
- <script type="module" crossorigin src="/assets/index-rvVpMwsP.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-DujV-tJ5.css">
8
+ <script type="module" crossorigin src="/assets/index-D9hu2Hyr.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-CVgbBi7w.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibora",
3
- "version": "4.5.2",
3
+ "version": "4.6.0",
4
4
  "description": "The Vibe Engineer's Cockpit",
5
5
  "license": "PolyForm-Shield-1.0.0",
6
6
  "repository": {
package/server/index.js CHANGED
@@ -152493,6 +152493,212 @@ app13.get("/dependencies", (c) => {
152493
152493
  });
152494
152494
  var system_default = app13;
152495
152495
 
152496
+ // server/routes/exec.ts
152497
+ import { spawn as spawn3 } from "child_process";
152498
+ import { randomUUID } from "crypto";
152499
+ import * as os6 from "os";
152500
+ var DEFAULT_TIMEOUT = 30000;
152501
+ var START_MARKER = `<<VIBORA_CMD_START_${randomUUID().slice(0, 8)}>>`;
152502
+ var END_MARKER_PREFIX = `<<VIBORA_CMD_END_${randomUUID().slice(0, 8)}:`;
152503
+ var sessions = new Map;
152504
+ function createSession(cwd, name) {
152505
+ const id = randomUUID();
152506
+ const initialCwd = cwd || os6.homedir();
152507
+ const proc2 = spawn3("/bin/bash", ["--norc", "--noprofile"], {
152508
+ cwd: initialCwd,
152509
+ env: { ...process.env, TERM: "dumb" },
152510
+ stdio: ["pipe", "pipe", "pipe"]
152511
+ });
152512
+ const session = {
152513
+ id,
152514
+ name,
152515
+ process: proc2,
152516
+ cwd: initialCwd,
152517
+ outputBuffer: "",
152518
+ stderrBuffer: "",
152519
+ pendingResolve: null,
152520
+ pendingReject: null,
152521
+ createdAt: new Date,
152522
+ lastUsedAt: new Date
152523
+ };
152524
+ proc2.stdout?.on("data", (data) => {
152525
+ session.outputBuffer += data.toString();
152526
+ checkForCompletion(session);
152527
+ });
152528
+ proc2.stderr?.on("data", (data) => {
152529
+ session.stderrBuffer += data.toString();
152530
+ });
152531
+ proc2.on("error", (err) => {
152532
+ if (session.pendingReject) {
152533
+ session.pendingReject(err);
152534
+ session.pendingResolve = null;
152535
+ session.pendingReject = null;
152536
+ }
152537
+ });
152538
+ proc2.on("exit", () => {
152539
+ sessions.delete(id);
152540
+ if (session.pendingReject) {
152541
+ session.pendingReject(new Error("Shell process exited unexpectedly"));
152542
+ session.pendingResolve = null;
152543
+ session.pendingReject = null;
152544
+ }
152545
+ });
152546
+ sessions.set(id, session);
152547
+ return session;
152548
+ }
152549
+ function checkForCompletion(session) {
152550
+ if (!session.pendingResolve)
152551
+ return;
152552
+ const endMarkerRegex = new RegExp(`${END_MARKER_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(\\d+)>>`);
152553
+ const match3 = session.outputBuffer.match(endMarkerRegex);
152554
+ if (match3) {
152555
+ const exitCode = parseInt(match3[1], 10);
152556
+ const startIdx = session.outputBuffer.indexOf(START_MARKER);
152557
+ const endIdx = session.outputBuffer.indexOf(match3[0]);
152558
+ let stdout = "";
152559
+ if (startIdx !== -1 && endIdx > startIdx) {
152560
+ stdout = session.outputBuffer.slice(startIdx + START_MARKER.length + 1, endIdx);
152561
+ if (stdout.endsWith(`
152562
+ `)) {
152563
+ stdout = stdout.slice(0, -1);
152564
+ }
152565
+ }
152566
+ const stderr = session.stderrBuffer;
152567
+ session.outputBuffer = "";
152568
+ session.stderrBuffer = "";
152569
+ const resolve4 = session.pendingResolve;
152570
+ session.pendingResolve = null;
152571
+ session.pendingReject = null;
152572
+ resolve4({ stdout, stderr, exitCode });
152573
+ }
152574
+ }
152575
+ function destroySession(id) {
152576
+ const session = sessions.get(id);
152577
+ if (!session)
152578
+ return false;
152579
+ try {
152580
+ session.process.kill();
152581
+ } catch {}
152582
+ sessions.delete(id);
152583
+ return true;
152584
+ }
152585
+ async function executeCommand(session, command, timeout) {
152586
+ return new Promise((resolve4, reject) => {
152587
+ session.lastUsedAt = new Date;
152588
+ session.outputBuffer = "";
152589
+ session.stderrBuffer = "";
152590
+ session.pendingResolve = resolve4;
152591
+ session.pendingReject = reject;
152592
+ const wrappedCommand = `echo "${START_MARKER}"; ${command}; echo "${END_MARKER_PREFIX}$?>>"
152593
+ `;
152594
+ const timeoutId = setTimeout(() => {
152595
+ session.pendingResolve = null;
152596
+ session.pendingReject = null;
152597
+ reject(new Error("Command timed out"));
152598
+ }, timeout);
152599
+ const originalResolve = resolve4;
152600
+ session.pendingResolve = (result) => {
152601
+ clearTimeout(timeoutId);
152602
+ originalResolve(result);
152603
+ };
152604
+ session.process.stdin?.write(wrappedCommand);
152605
+ });
152606
+ }
152607
+ async function updateSessionCwd(session) {
152608
+ try {
152609
+ const result = await executeCommand(session, "pwd", 5000);
152610
+ if (result.exitCode === 0 && result.stdout.trim()) {
152611
+ session.cwd = result.stdout.trim();
152612
+ }
152613
+ } catch {}
152614
+ }
152615
+ var app14 = new Hono2;
152616
+ app14.post("/", async (c) => {
152617
+ try {
152618
+ const body = await c.req.json();
152619
+ const { command, sessionId, cwd, timeout = DEFAULT_TIMEOUT, name } = body;
152620
+ if (!command) {
152621
+ return c.json({ error: "command is required" }, 400);
152622
+ }
152623
+ let session;
152624
+ if (sessionId) {
152625
+ const existing = sessions.get(sessionId);
152626
+ if (!existing) {
152627
+ return c.json({ error: `Session ${sessionId} not found` }, 404);
152628
+ }
152629
+ session = existing;
152630
+ } else {
152631
+ session = createSession(cwd, name);
152632
+ }
152633
+ try {
152634
+ const result = await executeCommand(session, command, timeout);
152635
+ await updateSessionCwd(session);
152636
+ const response = {
152637
+ sessionId: session.id,
152638
+ stdout: result.stdout,
152639
+ stderr: result.stderr,
152640
+ exitCode: result.exitCode,
152641
+ timedOut: false
152642
+ };
152643
+ return c.json(response);
152644
+ } catch (err) {
152645
+ if (err instanceof Error && err.message === "Command timed out") {
152646
+ const response = {
152647
+ sessionId: session.id,
152648
+ stdout: session.outputBuffer,
152649
+ stderr: session.stderrBuffer,
152650
+ exitCode: null,
152651
+ timedOut: true
152652
+ };
152653
+ return c.json(response);
152654
+ }
152655
+ throw err;
152656
+ }
152657
+ } catch (err) {
152658
+ return c.json({ error: err instanceof Error ? err.message : "Failed to execute command" }, 500);
152659
+ }
152660
+ });
152661
+ app14.get("/sessions", (c) => {
152662
+ const sessionList = [];
152663
+ for (const [id, session] of sessions) {
152664
+ sessionList.push({
152665
+ id,
152666
+ name: session.name,
152667
+ cwd: session.cwd,
152668
+ createdAt: session.createdAt.toISOString(),
152669
+ lastUsedAt: session.lastUsedAt.toISOString()
152670
+ });
152671
+ }
152672
+ return c.json(sessionList);
152673
+ });
152674
+ app14.patch("/sessions/:id", async (c) => {
152675
+ const id = c.req.param("id");
152676
+ const session = sessions.get(id);
152677
+ if (!session) {
152678
+ return c.json({ error: `Session ${id} not found` }, 404);
152679
+ }
152680
+ const body = await c.req.json();
152681
+ if (body.name !== undefined) {
152682
+ session.name = body.name;
152683
+ }
152684
+ return c.json({
152685
+ id: session.id,
152686
+ name: session.name,
152687
+ cwd: session.cwd,
152688
+ createdAt: session.createdAt.toISOString(),
152689
+ lastUsedAt: session.lastUsedAt.toISOString()
152690
+ });
152691
+ });
152692
+ app14.delete("/sessions/:id", (c) => {
152693
+ const id = c.req.param("id");
152694
+ const destroyed = destroySession(id);
152695
+ if (!destroyed) {
152696
+ return c.json({ error: `Session ${id} not found` }, 404);
152697
+ }
152698
+ return c.json({ success: true });
152699
+ });
152700
+ var exec_default = app14;
152701
+
152496
152702
  // server/app.ts
152497
152703
  function getDistPath() {
152498
152704
  if (process.env.VIBORA_PACKAGE_ROOT) {
@@ -152501,35 +152707,36 @@ function getDistPath() {
152501
152707
  return join15(process.cwd(), "dist");
152502
152708
  }
152503
152709
  function createApp() {
152504
- const app14 = new Hono2;
152505
- app14.use("*", logger());
152506
- app14.use("*", cors({
152710
+ const app15 = new Hono2;
152711
+ app15.use("*", logger());
152712
+ app15.use("*", cors({
152507
152713
  origin: "*",
152508
152714
  allowMethods: ["GET", "POST", "PATCH", "PUT", "DELETE", "OPTIONS"],
152509
152715
  allowHeaders: ["Content-Type"]
152510
152716
  }));
152511
- app14.route("/health", health_default);
152512
- app14.route("/api/tasks", tasks_default);
152513
- app14.route("/api/git", git_default);
152514
- app14.route("/api/fs", filesystem_default);
152515
- app14.route("/api/config", config_default);
152516
- app14.route("/api/uploads", uploads_default);
152517
- app14.route("/api/worktrees", worktrees_default);
152518
- app14.route("/api/terminal-view-state", terminal_view_state_default);
152519
- app14.route("/api/repositories", repositories_default);
152520
- app14.route("/api/copier", copier_default);
152521
- app14.route("/api/linear", linear_default);
152522
- app14.route("/api/github", github_default);
152523
- app14.route("/api/monitoring", monitoringRoutes);
152524
- app14.route("/api/system", system_default);
152525
- app14.post("/api/logs", async (c) => {
152717
+ app15.route("/health", health_default);
152718
+ app15.route("/api/tasks", tasks_default);
152719
+ app15.route("/api/git", git_default);
152720
+ app15.route("/api/fs", filesystem_default);
152721
+ app15.route("/api/config", config_default);
152722
+ app15.route("/api/uploads", uploads_default);
152723
+ app15.route("/api/worktrees", worktrees_default);
152724
+ app15.route("/api/terminal-view-state", terminal_view_state_default);
152725
+ app15.route("/api/repositories", repositories_default);
152726
+ app15.route("/api/copier", copier_default);
152727
+ app15.route("/api/linear", linear_default);
152728
+ app15.route("/api/github", github_default);
152729
+ app15.route("/api/monitoring", monitoringRoutes);
152730
+ app15.route("/api/system", system_default);
152731
+ app15.route("/api/exec", exec_default);
152732
+ app15.post("/api/logs", async (c) => {
152526
152733
  const { entries } = await c.req.json();
152527
152734
  for (const entry of entries) {
152528
152735
  writeEntry(entry);
152529
152736
  }
152530
152737
  return c.json({ ok: true });
152531
152738
  });
152532
- app14.post("/api/debug", async (c) => {
152739
+ app15.post("/api/debug", async (c) => {
152533
152740
  const body = await c.req.json();
152534
152741
  const entry = {
152535
152742
  ts: new Date().toISOString(),
@@ -152566,14 +152773,14 @@ function createApp() {
152566
152773
  headers: { "Content-Type": mimeTypes2[ext2 || ""] || "application/octet-stream" }
152567
152774
  });
152568
152775
  };
152569
- app14.get("/assets/*", async (c) => {
152776
+ app15.get("/assets/*", async (c) => {
152570
152777
  const assetPath = join15(distPath, c.req.path);
152571
152778
  if (existsSync13(assetPath)) {
152572
152779
  return serveFile(assetPath);
152573
152780
  }
152574
152781
  return c.notFound();
152575
152782
  });
152576
- app14.get("/sounds/*", async (c) => {
152783
+ app15.get("/sounds/*", async (c) => {
152577
152784
  const soundPath = join15(distPath, c.req.path);
152578
152785
  if (existsSync13(soundPath)) {
152579
152786
  return serveFile(soundPath);
@@ -152582,7 +152789,7 @@ function createApp() {
152582
152789
  });
152583
152790
  const staticFiles = ["vibora-icon.png", "vibora-logo.jpeg", "vite.svg", "logo-dark.jpg", "logo-light.jpg", "goat.jpeg"];
152584
152791
  for (const file of staticFiles) {
152585
- app14.get(`/${file}`, async () => {
152792
+ app15.get(`/${file}`, async () => {
152586
152793
  const filePath = join15(distPath, file);
152587
152794
  if (existsSync13(filePath)) {
152588
152795
  return serveFile(filePath);
@@ -152590,7 +152797,7 @@ function createApp() {
152590
152797
  return new Response("Not Found", { status: 404 });
152591
152798
  });
152592
152799
  }
152593
- app14.get("*", async (c, next) => {
152800
+ app15.get("*", async (c, next) => {
152594
152801
  const path9 = c.req.path;
152595
152802
  if (path9.startsWith("/api/") || path9.startsWith("/ws/") || path9 === "/health") {
152596
152803
  return next();
@@ -152599,7 +152806,7 @@ function createApp() {
152599
152806
  return c.html(html);
152600
152807
  });
152601
152808
  }
152602
- return app14;
152809
+ return app15;
152603
152810
  }
152604
152811
 
152605
152812
  // server/services/pr-monitor.ts
@@ -152702,11 +152909,11 @@ setBroadcastDestroyed((terminalId) => {
152702
152909
  payload: { terminalId }
152703
152910
  });
152704
152911
  });
152705
- var app14 = createApp();
152706
- var { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app: app14 });
152707
- app14.get("/ws/terminal", upgradeWebSocket(() => terminalWebSocketHandlers));
152912
+ var app15 = createApp();
152913
+ var { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app: app15 });
152914
+ app15.get("/ws/terminal", upgradeWebSocket(() => terminalWebSocketHandlers));
152708
152915
  var server = serve({
152709
- fetch: app14.fetch,
152916
+ fetch: app15.fetch,
152710
152917
  port: PORT,
152711
152918
  hostname: HOST
152712
152919
  }, (info) => {