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/README.md +10 -1
- package/bin/vibora.js +69 -1
- package/dist/assets/index-CVgbBi7w.css +1 -0
- package/dist/assets/{index-rvVpMwsP.js → index-D9hu2Hyr.js} +89 -89
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/server/index.js +235 -28
- package/dist/assets/index-DujV-tJ5.css +0 -1
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-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
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
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
|
|
152505
|
-
|
|
152506
|
-
|
|
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
|
-
|
|
152512
|
-
|
|
152513
|
-
|
|
152514
|
-
|
|
152515
|
-
|
|
152516
|
-
|
|
152517
|
-
|
|
152518
|
-
|
|
152519
|
-
|
|
152520
|
-
|
|
152521
|
-
|
|
152522
|
-
|
|
152523
|
-
|
|
152524
|
-
|
|
152525
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
152706
|
-
var { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app:
|
|
152707
|
-
|
|
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:
|
|
152916
|
+
fetch: app15.fetch,
|
|
152710
152917
|
port: PORT,
|
|
152711
152918
|
hostname: HOST
|
|
152712
152919
|
}, (info) => {
|