vibora 3.7.0 → 3.9.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-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-B-nLH4Y8.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-3kiCCuAw.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -10131,8 +10131,8 @@ var logger = (fn = console.log) => {
|
|
|
10131
10131
|
|
|
10132
10132
|
// server/app.ts
|
|
10133
10133
|
import { readFile as readFile2 } from "fs/promises";
|
|
10134
|
-
import { join as
|
|
10135
|
-
import { existsSync as
|
|
10134
|
+
import { join as join15 } from "path";
|
|
10135
|
+
import { existsSync as existsSync13 } from "fs";
|
|
10136
10136
|
|
|
10137
10137
|
// server/routes/health.ts
|
|
10138
10138
|
var app = new Hono2;
|
|
@@ -147221,6 +147221,33 @@ app8.patch("/", async (c) => {
|
|
|
147221
147221
|
});
|
|
147222
147222
|
var terminal_view_state_default = app8;
|
|
147223
147223
|
|
|
147224
|
+
// server/routes/repositories.ts
|
|
147225
|
+
import { existsSync as existsSync10, rmSync as rmSync4, readdirSync as readdirSync7 } from "fs";
|
|
147226
|
+
import { join as join12 } from "path";
|
|
147227
|
+
import { execSync as execSync4 } from "child_process";
|
|
147228
|
+
|
|
147229
|
+
// server/lib/git-utils.ts
|
|
147230
|
+
function isGitUrl(source) {
|
|
147231
|
+
return source.startsWith("git@") || source.startsWith("https://") || source.startsWith("http://") || source.startsWith("gh:") || source.startsWith("gl:") || source.startsWith("bb:");
|
|
147232
|
+
}
|
|
147233
|
+
function extractRepoNameFromUrl(url) {
|
|
147234
|
+
const cleaned = url.replace(/\.git$/, "");
|
|
147235
|
+
if (cleaned.startsWith("git@")) {
|
|
147236
|
+
const match3 = cleaned.match(/:([^/]+\/)?([^/]+)$/);
|
|
147237
|
+
if (match3)
|
|
147238
|
+
return match3[2];
|
|
147239
|
+
} else if (cleaned.startsWith("gh:") || cleaned.startsWith("gl:") || cleaned.startsWith("bb:")) {
|
|
147240
|
+
const parts = cleaned.split("/");
|
|
147241
|
+
if (parts.length > 0)
|
|
147242
|
+
return parts[parts.length - 1];
|
|
147243
|
+
} else {
|
|
147244
|
+
const parts = cleaned.split("/");
|
|
147245
|
+
if (parts.length > 0)
|
|
147246
|
+
return parts[parts.length - 1];
|
|
147247
|
+
}
|
|
147248
|
+
return cleaned;
|
|
147249
|
+
}
|
|
147250
|
+
|
|
147224
147251
|
// server/routes/repositories.ts
|
|
147225
147252
|
var app9 = new Hono2;
|
|
147226
147253
|
app9.get("/", (c) => {
|
|
@@ -147264,6 +147291,65 @@ app9.post("/", async (c) => {
|
|
|
147264
147291
|
return c.json({ error: err instanceof Error ? err.message : "Failed to create repository" }, 400);
|
|
147265
147292
|
}
|
|
147266
147293
|
});
|
|
147294
|
+
app9.post("/clone", async (c) => {
|
|
147295
|
+
try {
|
|
147296
|
+
const body = await c.req.json();
|
|
147297
|
+
if (!body.url) {
|
|
147298
|
+
return c.json({ error: "url is required" }, 400);
|
|
147299
|
+
}
|
|
147300
|
+
if (!isGitUrl(body.url)) {
|
|
147301
|
+
return c.json({ error: "Invalid git URL format" }, 400);
|
|
147302
|
+
}
|
|
147303
|
+
const settings = getSettings();
|
|
147304
|
+
const gitReposDir = settings.paths.defaultGitReposDir;
|
|
147305
|
+
const repoName = extractRepoNameFromUrl(body.url);
|
|
147306
|
+
const targetPath = join12(gitReposDir, repoName);
|
|
147307
|
+
if (existsSync10(targetPath)) {
|
|
147308
|
+
return c.json({ error: `Directory already exists: ${targetPath}` }, 400);
|
|
147309
|
+
}
|
|
147310
|
+
try {
|
|
147311
|
+
execSync4(`git clone "${body.url}" "${targetPath}"`, {
|
|
147312
|
+
encoding: "utf-8",
|
|
147313
|
+
stdio: "pipe",
|
|
147314
|
+
timeout: 120000
|
|
147315
|
+
});
|
|
147316
|
+
} catch (cloneErr) {
|
|
147317
|
+
if (existsSync10(targetPath)) {
|
|
147318
|
+
rmSync4(targetPath, { recursive: true, force: true });
|
|
147319
|
+
}
|
|
147320
|
+
const errorMessage = cloneErr instanceof Error ? cloneErr.message : "Clone failed";
|
|
147321
|
+
if (errorMessage.includes("Permission denied") || errorMessage.includes("publickey")) {
|
|
147322
|
+
return c.json({ error: "Authentication failed. Check your SSH keys or use HTTPS with credentials." }, 500);
|
|
147323
|
+
}
|
|
147324
|
+
if (errorMessage.includes("not found") || errorMessage.includes("does not exist")) {
|
|
147325
|
+
return c.json({ error: "Repository not found or access denied" }, 500);
|
|
147326
|
+
}
|
|
147327
|
+
return c.json({ error: `Failed to clone repository: ${errorMessage}` }, 500);
|
|
147328
|
+
}
|
|
147329
|
+
const existing = db.select().from(repositories).where(eq(repositories.path, targetPath)).get();
|
|
147330
|
+
if (existing) {
|
|
147331
|
+
return c.json({ error: "Repository with this path already exists in database" }, 400);
|
|
147332
|
+
}
|
|
147333
|
+
const now = new Date().toISOString();
|
|
147334
|
+
const displayName = body.displayName || repoName;
|
|
147335
|
+
const newRepo = {
|
|
147336
|
+
id: crypto.randomUUID(),
|
|
147337
|
+
path: targetPath,
|
|
147338
|
+
displayName,
|
|
147339
|
+
remoteUrl: body.url,
|
|
147340
|
+
startupScript: null,
|
|
147341
|
+
copyFiles: null,
|
|
147342
|
+
isCopierTemplate: false,
|
|
147343
|
+
createdAt: now,
|
|
147344
|
+
updatedAt: now
|
|
147345
|
+
};
|
|
147346
|
+
db.insert(repositories).values(newRepo).run();
|
|
147347
|
+
const created = db.select().from(repositories).where(eq(repositories.id, newRepo.id)).get();
|
|
147348
|
+
return c.json(created, 201);
|
|
147349
|
+
} catch (err) {
|
|
147350
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to clone repository" }, 500);
|
|
147351
|
+
}
|
|
147352
|
+
});
|
|
147267
147353
|
app9.patch("/:id", async (c) => {
|
|
147268
147354
|
const id = c.req.param("id");
|
|
147269
147355
|
try {
|
|
@@ -147295,6 +147381,80 @@ app9.delete("/:id", (c) => {
|
|
|
147295
147381
|
db.delete(repositories).where(eq(repositories.id, id)).run();
|
|
147296
147382
|
return c.json({ success: true });
|
|
147297
147383
|
});
|
|
147384
|
+
app9.post("/scan", async (c) => {
|
|
147385
|
+
try {
|
|
147386
|
+
const body = await c.req.json().catch(() => ({}));
|
|
147387
|
+
const settings = getSettings();
|
|
147388
|
+
const directory = body.directory || settings.paths.defaultGitReposDir;
|
|
147389
|
+
if (!existsSync10(directory)) {
|
|
147390
|
+
return c.json({ error: `Directory does not exist: ${directory}` }, 400);
|
|
147391
|
+
}
|
|
147392
|
+
const existingRepos = db.select({ path: repositories.path }).from(repositories).all();
|
|
147393
|
+
const existingPaths = new Set(existingRepos.map((r) => r.path));
|
|
147394
|
+
const discovered = [];
|
|
147395
|
+
const entries = readdirSync7(directory, { withFileTypes: true });
|
|
147396
|
+
for (const entry of entries) {
|
|
147397
|
+
if (!entry.isDirectory())
|
|
147398
|
+
continue;
|
|
147399
|
+
if (entry.name.startsWith("."))
|
|
147400
|
+
continue;
|
|
147401
|
+
const subPath = join12(directory, entry.name);
|
|
147402
|
+
const gitPath = join12(subPath, ".git");
|
|
147403
|
+
if (existsSync10(gitPath)) {
|
|
147404
|
+
discovered.push({
|
|
147405
|
+
path: subPath,
|
|
147406
|
+
name: entry.name,
|
|
147407
|
+
exists: existingPaths.has(subPath)
|
|
147408
|
+
});
|
|
147409
|
+
}
|
|
147410
|
+
}
|
|
147411
|
+
discovered.sort((a, b) => a.name.localeCompare(b.name));
|
|
147412
|
+
return c.json({ directory, repositories: discovered });
|
|
147413
|
+
} catch (err) {
|
|
147414
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to scan directory" }, 500);
|
|
147415
|
+
}
|
|
147416
|
+
});
|
|
147417
|
+
app9.post("/bulk", async (c) => {
|
|
147418
|
+
try {
|
|
147419
|
+
const body = await c.req.json();
|
|
147420
|
+
if (!body.repositories || !Array.isArray(body.repositories) || body.repositories.length === 0) {
|
|
147421
|
+
return c.json({ error: "repositories array is required" }, 400);
|
|
147422
|
+
}
|
|
147423
|
+
const paths = body.repositories.map((r) => r.path);
|
|
147424
|
+
const existingRepos = db.select({ path: repositories.path }).from(repositories).where(inArray(repositories.path, paths)).all();
|
|
147425
|
+
const existingPaths = new Set(existingRepos.map((r) => r.path));
|
|
147426
|
+
const now = new Date().toISOString();
|
|
147427
|
+
const toCreate = [];
|
|
147428
|
+
for (const repo of body.repositories) {
|
|
147429
|
+
if (existingPaths.has(repo.path))
|
|
147430
|
+
continue;
|
|
147431
|
+
if (!existsSync10(repo.path))
|
|
147432
|
+
continue;
|
|
147433
|
+
const displayName = repo.displayName || repo.path.split("/").pop() || "repo";
|
|
147434
|
+
toCreate.push({
|
|
147435
|
+
id: crypto.randomUUID(),
|
|
147436
|
+
path: repo.path,
|
|
147437
|
+
displayName,
|
|
147438
|
+
startupScript: null,
|
|
147439
|
+
copyFiles: null,
|
|
147440
|
+
isCopierTemplate: false,
|
|
147441
|
+
createdAt: now,
|
|
147442
|
+
updatedAt: now
|
|
147443
|
+
});
|
|
147444
|
+
}
|
|
147445
|
+
if (toCreate.length > 0) {
|
|
147446
|
+
db.insert(repositories).values(toCreate).run();
|
|
147447
|
+
}
|
|
147448
|
+
const createdIds = toCreate.map((r) => r.id);
|
|
147449
|
+
const created = createdIds.length > 0 ? db.select().from(repositories).where(inArray(repositories.id, createdIds)).all() : [];
|
|
147450
|
+
return c.json({
|
|
147451
|
+
created,
|
|
147452
|
+
skipped: body.repositories.length - toCreate.length
|
|
147453
|
+
});
|
|
147454
|
+
} catch (err) {
|
|
147455
|
+
return c.json({ error: err instanceof Error ? err.message : "Failed to bulk create repositories" }, 500);
|
|
147456
|
+
}
|
|
147457
|
+
});
|
|
147298
147458
|
var repositories_default = app9;
|
|
147299
147459
|
|
|
147300
147460
|
// node_modules/yaml/dist/index.js
|
|
@@ -147344,14 +147504,14 @@ var $visit = visit.visit;
|
|
|
147344
147504
|
var $visitAsync = visit.visitAsync;
|
|
147345
147505
|
|
|
147346
147506
|
// server/routes/copier.ts
|
|
147347
|
-
import { existsSync as
|
|
147348
|
-
import { join as
|
|
147507
|
+
import { existsSync as existsSync11, readFileSync as readFileSync6, writeFileSync as writeFileSync4, unlinkSync as unlinkSync4, mkdtempSync, rmSync as rmSync5 } from "fs";
|
|
147508
|
+
import { join as join13 } from "path";
|
|
147349
147509
|
import { tmpdir } from "os";
|
|
147350
|
-
import { execSync as
|
|
147510
|
+
import { execSync as execSync5 } from "child_process";
|
|
147351
147511
|
var app10 = new Hono2;
|
|
147352
147512
|
function isUvInstalled() {
|
|
147353
147513
|
try {
|
|
147354
|
-
|
|
147514
|
+
execSync5("uv --version", { stdio: "pipe" });
|
|
147355
147515
|
return true;
|
|
147356
147516
|
} catch {
|
|
147357
147517
|
return false;
|
|
@@ -147410,47 +147570,44 @@ function parseCopierQuestions(yamlContent) {
|
|
|
147410
147570
|
}
|
|
147411
147571
|
return questions;
|
|
147412
147572
|
}
|
|
147413
|
-
function isGitUrl(source) {
|
|
147414
|
-
return source.startsWith("git@") || source.startsWith("https://") || source.startsWith("http://") || source.startsWith("gh:") || source.startsWith("gl:") || source.startsWith("bb:");
|
|
147415
|
-
}
|
|
147416
147573
|
function fetchCopierYamlFromGit(gitUrl) {
|
|
147417
|
-
const tempDir = mkdtempSync(
|
|
147574
|
+
const tempDir = mkdtempSync(join13(tmpdir(), "copier-template-"));
|
|
147418
147575
|
try {
|
|
147419
|
-
|
|
147576
|
+
execSync5(`git clone --depth 1 "${gitUrl}" "${tempDir}"`, {
|
|
147420
147577
|
encoding: "utf-8",
|
|
147421
147578
|
stdio: "pipe"
|
|
147422
147579
|
});
|
|
147423
|
-
const yamlPath =
|
|
147424
|
-
const yamlAltPath =
|
|
147580
|
+
const yamlPath = join13(tempDir, "copier.yml");
|
|
147581
|
+
const yamlAltPath = join13(tempDir, "copier.yaml");
|
|
147425
147582
|
let content = null;
|
|
147426
|
-
if (
|
|
147583
|
+
if (existsSync11(yamlPath)) {
|
|
147427
147584
|
content = readFileSync6(yamlPath, "utf-8");
|
|
147428
|
-
} else if (
|
|
147585
|
+
} else if (existsSync11(yamlAltPath)) {
|
|
147429
147586
|
content = readFileSync6(yamlAltPath, "utf-8");
|
|
147430
147587
|
}
|
|
147431
147588
|
if (!content) {
|
|
147432
|
-
|
|
147589
|
+
rmSync5(tempDir, { recursive: true, force: true });
|
|
147433
147590
|
return null;
|
|
147434
147591
|
}
|
|
147435
147592
|
return {
|
|
147436
147593
|
content,
|
|
147437
|
-
cleanup: () =>
|
|
147594
|
+
cleanup: () => rmSync5(tempDir, { recursive: true, force: true })
|
|
147438
147595
|
};
|
|
147439
147596
|
} catch (err) {
|
|
147440
|
-
|
|
147597
|
+
rmSync5(tempDir, { recursive: true, force: true });
|
|
147441
147598
|
throw err;
|
|
147442
147599
|
}
|
|
147443
147600
|
}
|
|
147444
147601
|
async function fetchCopierYaml(source) {
|
|
147445
147602
|
const repo = db.select().from(repositories).where(eq(repositories.id, source)).get();
|
|
147446
147603
|
const templatePath = repo ? repo.path : source;
|
|
147447
|
-
if (
|
|
147448
|
-
const yamlPath =
|
|
147449
|
-
const yamlAltPath =
|
|
147450
|
-
if (
|
|
147604
|
+
if (existsSync11(templatePath)) {
|
|
147605
|
+
const yamlPath = join13(templatePath, "copier.yml");
|
|
147606
|
+
const yamlAltPath = join13(templatePath, "copier.yaml");
|
|
147607
|
+
if (existsSync11(yamlPath)) {
|
|
147451
147608
|
return { content: readFileSync6(yamlPath, "utf-8"), templatePath };
|
|
147452
147609
|
}
|
|
147453
|
-
if (
|
|
147610
|
+
if (existsSync11(yamlAltPath)) {
|
|
147454
147611
|
return { content: readFileSync6(yamlAltPath, "utf-8"), templatePath };
|
|
147455
147612
|
}
|
|
147456
147613
|
throw new Error("copier.yml not found in template directory");
|
|
@@ -147501,8 +147658,8 @@ app10.post("/create", async (c) => {
|
|
|
147501
147658
|
}
|
|
147502
147659
|
const repo = db.select().from(repositories).where(eq(repositories.id, templateSource)).get();
|
|
147503
147660
|
const templatePath = repo ? repo.path : templateSource;
|
|
147504
|
-
const fullOutputPath =
|
|
147505
|
-
if (
|
|
147661
|
+
const fullOutputPath = join13(outputPath, projectName);
|
|
147662
|
+
if (existsSync11(fullOutputPath)) {
|
|
147506
147663
|
return c.json({ error: `Output directory already exists: ${fullOutputPath}` }, 400);
|
|
147507
147664
|
}
|
|
147508
147665
|
const filteredAnswers = {};
|
|
@@ -147512,10 +147669,10 @@ app10.post("/create", async (c) => {
|
|
|
147512
147669
|
}
|
|
147513
147670
|
filteredAnswers[key] = value;
|
|
147514
147671
|
}
|
|
147515
|
-
answersFile =
|
|
147672
|
+
answersFile = join13(tmpdir(), `copier-answers-${crypto.randomUUID()}.json`);
|
|
147516
147673
|
writeFileSync4(answersFile, JSON.stringify(filteredAnswers));
|
|
147517
147674
|
try {
|
|
147518
|
-
|
|
147675
|
+
execSync5(`uvx copier copy --data-file "${answersFile}" --force --vcs-ref HEAD "${templatePath}" "${fullOutputPath}"`, {
|
|
147519
147676
|
encoding: "utf-8",
|
|
147520
147677
|
stdio: "pipe",
|
|
147521
147678
|
timeout: 120000
|
|
@@ -147551,7 +147708,7 @@ app10.post("/create", async (c) => {
|
|
|
147551
147708
|
log2.api.error("Failed to create project from template", { error: String(err) });
|
|
147552
147709
|
return c.json({ error: err instanceof Error ? err.message : "Failed to create project" }, 500);
|
|
147553
147710
|
} finally {
|
|
147554
|
-
if (answersFile &&
|
|
147711
|
+
if (answersFile && existsSync11(answersFile)) {
|
|
147555
147712
|
unlinkSync4(answersFile);
|
|
147556
147713
|
}
|
|
147557
147714
|
}
|
|
@@ -151286,15 +151443,15 @@ app12.get("/prs", async (c) => {
|
|
|
151286
151443
|
var github_default = app12;
|
|
151287
151444
|
|
|
151288
151445
|
// server/routes/monitoring.ts
|
|
151289
|
-
import { readdirSync as
|
|
151290
|
-
import { execSync as
|
|
151446
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync7, readlinkSync as readlinkSync2, existsSync as existsSync12 } from "fs";
|
|
151447
|
+
import { execSync as execSync7 } from "child_process";
|
|
151291
151448
|
import { homedir as homedir5 } from "os";
|
|
151292
|
-
import { join as
|
|
151449
|
+
import { join as join14 } from "path";
|
|
151293
151450
|
|
|
151294
151451
|
// server/services/metrics-collector.ts
|
|
151295
151452
|
import os5 from "os";
|
|
151296
151453
|
import fs7 from "fs";
|
|
151297
|
-
import { execSync as
|
|
151454
|
+
import { execSync as execSync6 } from "child_process";
|
|
151298
151455
|
var COLLECT_INTERVAL = 5000;
|
|
151299
151456
|
var RETENTION_HOURS = 24;
|
|
151300
151457
|
var isMacOS = process.platform === "darwin";
|
|
@@ -151306,13 +151463,13 @@ function getMemoryInfo() {
|
|
|
151306
151463
|
}
|
|
151307
151464
|
function getMemoryInfoMacOS() {
|
|
151308
151465
|
try {
|
|
151309
|
-
const totalStr =
|
|
151466
|
+
const totalStr = execSync6("sysctl -n hw.memsize", {
|
|
151310
151467
|
encoding: "utf-8",
|
|
151311
151468
|
timeout: 5000,
|
|
151312
151469
|
stdio: ["pipe", "pipe", "pipe"]
|
|
151313
151470
|
}).trim();
|
|
151314
151471
|
const total = parseInt(totalStr, 10);
|
|
151315
|
-
const vmstat =
|
|
151472
|
+
const vmstat = execSync6("vm_stat", {
|
|
151316
151473
|
encoding: "utf-8",
|
|
151317
151474
|
timeout: 5000,
|
|
151318
151475
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -151417,7 +151574,7 @@ function calculateCpuPercent() {
|
|
|
151417
151574
|
function getDiskUsage() {
|
|
151418
151575
|
try {
|
|
151419
151576
|
if (isMacOS) {
|
|
151420
|
-
const output =
|
|
151577
|
+
const output = execSync6("df -k /System/Volumes/Data 2>/dev/null || df -k /", {
|
|
151421
151578
|
encoding: "utf-8",
|
|
151422
151579
|
timeout: 5000,
|
|
151423
151580
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -151435,7 +151592,7 @@ function getDiskUsage() {
|
|
|
151435
151592
|
}
|
|
151436
151593
|
}
|
|
151437
151594
|
} else {
|
|
151438
|
-
const output =
|
|
151595
|
+
const output = execSync6("df -B1 / | tail -1", {
|
|
151439
151596
|
encoding: "utf-8",
|
|
151440
151597
|
timeout: 5000,
|
|
151441
151598
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -151547,7 +151704,7 @@ function parseWindow(window) {
|
|
|
151547
151704
|
function findAllClaudeProcesses() {
|
|
151548
151705
|
const claudeProcesses = [];
|
|
151549
151706
|
try {
|
|
151550
|
-
const procDirs =
|
|
151707
|
+
const procDirs = readdirSync8("/proc").filter((d) => /^\d+$/.test(d));
|
|
151551
151708
|
for (const pidStr of procDirs) {
|
|
151552
151709
|
const pid = parseInt(pidStr, 10);
|
|
151553
151710
|
try {
|
|
@@ -151559,13 +151716,13 @@ function findAllClaudeProcesses() {
|
|
|
151559
151716
|
}
|
|
151560
151717
|
} catch {
|
|
151561
151718
|
try {
|
|
151562
|
-
const result =
|
|
151719
|
+
const result = execSync7("pgrep -f claude", { encoding: "utf-8" });
|
|
151563
151720
|
for (const line of result.trim().split(`
|
|
151564
151721
|
`)) {
|
|
151565
151722
|
const pid = parseInt(line, 10);
|
|
151566
151723
|
if (!isNaN(pid)) {
|
|
151567
151724
|
try {
|
|
151568
|
-
const cmdline =
|
|
151725
|
+
const cmdline = execSync7(`ps -p ${pid} -o args=`, { encoding: "utf-8" }).trim();
|
|
151569
151726
|
claudeProcesses.push({ pid, cmdline });
|
|
151570
151727
|
} catch {
|
|
151571
151728
|
claudeProcesses.push({ pid, cmdline: "claude" });
|
|
@@ -151583,7 +151740,7 @@ function getProcessCwd(pid) {
|
|
|
151583
151740
|
} catch {}
|
|
151584
151741
|
}
|
|
151585
151742
|
try {
|
|
151586
|
-
const result =
|
|
151743
|
+
const result = execSync7(`lsof -a -p ${pid} -d cwd -F n 2>/dev/null`, {
|
|
151587
151744
|
encoding: "utf-8",
|
|
151588
151745
|
timeout: 5000
|
|
151589
151746
|
});
|
|
@@ -151603,7 +151760,7 @@ function getProcessMemoryMB(pid) {
|
|
|
151603
151760
|
return match3 ? parseInt(match3[1], 10) / 1024 : 0;
|
|
151604
151761
|
} catch {
|
|
151605
151762
|
try {
|
|
151606
|
-
const result =
|
|
151763
|
+
const result = execSync7(`ps -o rss= -p ${pid}`, { encoding: "utf-8" });
|
|
151607
151764
|
return parseInt(result.trim(), 10) / 1024;
|
|
151608
151765
|
} catch {
|
|
151609
151766
|
return 0;
|
|
@@ -151623,7 +151780,7 @@ function getProcessStartTime(pid) {
|
|
|
151623
151780
|
} catch {}
|
|
151624
151781
|
}
|
|
151625
151782
|
try {
|
|
151626
|
-
const result =
|
|
151783
|
+
const result = execSync7(`ps -o lstart= -p ${pid}`, {
|
|
151627
151784
|
encoding: "utf-8",
|
|
151628
151785
|
timeout: 5000
|
|
151629
151786
|
}).trim();
|
|
@@ -151641,9 +151798,9 @@ function getDescendantPids2(pid) {
|
|
|
151641
151798
|
try {
|
|
151642
151799
|
let result;
|
|
151643
151800
|
if (isMacOS2) {
|
|
151644
|
-
result =
|
|
151801
|
+
result = execSync7(`pgrep -P ${pid} 2>/dev/null || true`, { encoding: "utf-8" });
|
|
151645
151802
|
} else {
|
|
151646
|
-
result =
|
|
151803
|
+
result = execSync7(`ps --ppid ${pid} -o pid= 2>/dev/null || true`, { encoding: "utf-8" });
|
|
151647
151804
|
}
|
|
151648
151805
|
for (const line of result.trim().split(`
|
|
151649
151806
|
`)) {
|
|
@@ -151671,7 +151828,7 @@ monitoringRoutes.get("/claude-instances", (c) => {
|
|
|
151671
151828
|
const foundPids = [];
|
|
151672
151829
|
if (isMacOS2) {
|
|
151673
151830
|
try {
|
|
151674
|
-
const psResult =
|
|
151831
|
+
const psResult = execSync7("ps -Axo pid,args", {
|
|
151675
151832
|
encoding: "utf-8",
|
|
151676
151833
|
timeout: 5000,
|
|
151677
151834
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -151687,7 +151844,7 @@ monitoringRoutes.get("/claude-instances", (c) => {
|
|
|
151687
151844
|
}
|
|
151688
151845
|
} catch {}
|
|
151689
151846
|
} else {
|
|
151690
|
-
const procDirs =
|
|
151847
|
+
const procDirs = readdirSync8("/proc").filter((d) => /^\d+$/.test(d));
|
|
151691
151848
|
for (const pidStr of procDirs) {
|
|
151692
151849
|
const pid = parseInt(pidStr, 10);
|
|
151693
151850
|
try {
|
|
@@ -151798,7 +151955,7 @@ monitoringRoutes.post("/claude-instances/:pid/kill-pid", (c) => {
|
|
|
151798
151955
|
function getTotalMemory() {
|
|
151799
151956
|
if (isMacOS2) {
|
|
151800
151957
|
try {
|
|
151801
|
-
const result =
|
|
151958
|
+
const result = execSync7("sysctl -n hw.memsize", {
|
|
151802
151959
|
encoding: "utf-8",
|
|
151803
151960
|
timeout: 5000,
|
|
151804
151961
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -151823,13 +151980,13 @@ monitoringRoutes.get("/top-processes", (c) => {
|
|
|
151823
151980
|
const memTotal = getTotalMemory();
|
|
151824
151981
|
let psResult;
|
|
151825
151982
|
if (isMacOS2) {
|
|
151826
|
-
psResult =
|
|
151983
|
+
psResult = execSync7("ps -Axo pid,comm,%cpu,rss,args", {
|
|
151827
151984
|
encoding: "utf-8",
|
|
151828
151985
|
timeout: 5000,
|
|
151829
151986
|
stdio: ["pipe", "pipe", "pipe"]
|
|
151830
151987
|
});
|
|
151831
151988
|
} else {
|
|
151832
|
-
psResult =
|
|
151989
|
+
psResult = execSync7("ps -eo pid,comm,%cpu,rss,args --no-headers", {
|
|
151833
151990
|
encoding: "utf-8",
|
|
151834
151991
|
timeout: 5000,
|
|
151835
151992
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -151876,14 +152033,14 @@ monitoringRoutes.get("/docker-stats", (c) => {
|
|
|
151876
152033
|
let result;
|
|
151877
152034
|
let runtime = "docker";
|
|
151878
152035
|
try {
|
|
151879
|
-
result =
|
|
152036
|
+
result = execSync7('docker stats --no-stream --format "{{json .}}"', {
|
|
151880
152037
|
encoding: "utf-8",
|
|
151881
152038
|
timeout: 1e4,
|
|
151882
152039
|
stdio: ["pipe", "pipe", "pipe"]
|
|
151883
152040
|
});
|
|
151884
152041
|
} catch {
|
|
151885
152042
|
try {
|
|
151886
|
-
result =
|
|
152043
|
+
result = execSync7('podman stats --no-stream --format "{{json .}}"', {
|
|
151887
152044
|
encoding: "utf-8",
|
|
151888
152045
|
timeout: 1e4,
|
|
151889
152046
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -151977,7 +152134,7 @@ function findViboraInstances() {
|
|
|
151977
152134
|
const backends = [];
|
|
151978
152135
|
const frontends = [];
|
|
151979
152136
|
try {
|
|
151980
|
-
const procDirs =
|
|
152137
|
+
const procDirs = readdirSync8("/proc").filter((d) => /^\d+$/.test(d));
|
|
151981
152138
|
for (const pidStr of procDirs) {
|
|
151982
152139
|
const pid = parseInt(pidStr, 10);
|
|
151983
152140
|
try {
|
|
@@ -152094,9 +152251,9 @@ var cachedUsage = null;
|
|
|
152094
152251
|
var usageCacheTimestamp = 0;
|
|
152095
152252
|
var USAGE_CACHE_MS = 15 * 1000;
|
|
152096
152253
|
async function getClaudeOAuthToken() {
|
|
152097
|
-
const primaryPath =
|
|
152254
|
+
const primaryPath = join14(homedir5(), ".claude", ".credentials.json");
|
|
152098
152255
|
try {
|
|
152099
|
-
if (
|
|
152256
|
+
if (existsSync12(primaryPath)) {
|
|
152100
152257
|
const content = readFileSync7(primaryPath, "utf-8");
|
|
152101
152258
|
const config = JSON.parse(content);
|
|
152102
152259
|
if (config.claudeAiOauth && typeof config.claudeAiOauth === "object") {
|
|
@@ -152109,7 +152266,7 @@ async function getClaudeOAuthToken() {
|
|
|
152109
152266
|
} catch {}
|
|
152110
152267
|
if (isMacOS2) {
|
|
152111
152268
|
try {
|
|
152112
|
-
const result =
|
|
152269
|
+
const result = execSync7('security find-generic-password -s "Claude Code-credentials" -w', {
|
|
152113
152270
|
encoding: "utf-8",
|
|
152114
152271
|
timeout: 5000,
|
|
152115
152272
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -152123,7 +152280,7 @@ async function getClaudeOAuthToken() {
|
|
|
152123
152280
|
}
|
|
152124
152281
|
if (!isMacOS2) {
|
|
152125
152282
|
try {
|
|
152126
|
-
const result =
|
|
152283
|
+
const result = execSync7('secret-tool lookup service "Claude Code"', {
|
|
152127
152284
|
encoding: "utf-8",
|
|
152128
152285
|
timeout: 5000,
|
|
152129
152286
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -152241,9 +152398,9 @@ monitoringRoutes.get("/claude-usage", async (c) => {
|
|
|
152241
152398
|
// server/app.ts
|
|
152242
152399
|
function getDistPath() {
|
|
152243
152400
|
if (process.env.VIBORA_PACKAGE_ROOT) {
|
|
152244
|
-
return
|
|
152401
|
+
return join15(process.env.VIBORA_PACKAGE_ROOT, "dist");
|
|
152245
152402
|
}
|
|
152246
|
-
return
|
|
152403
|
+
return join15(process.cwd(), "dist");
|
|
152247
152404
|
}
|
|
152248
152405
|
function createApp() {
|
|
152249
152406
|
const app13 = new Hono2;
|
|
@@ -152311,15 +152468,15 @@ function createApp() {
|
|
|
152311
152468
|
});
|
|
152312
152469
|
};
|
|
152313
152470
|
app13.get("/assets/*", async (c) => {
|
|
152314
|
-
const assetPath =
|
|
152315
|
-
if (
|
|
152471
|
+
const assetPath = join15(distPath, c.req.path);
|
|
152472
|
+
if (existsSync13(assetPath)) {
|
|
152316
152473
|
return serveFile(assetPath);
|
|
152317
152474
|
}
|
|
152318
152475
|
return c.notFound();
|
|
152319
152476
|
});
|
|
152320
152477
|
app13.get("/sounds/*", async (c) => {
|
|
152321
|
-
const soundPath =
|
|
152322
|
-
if (
|
|
152478
|
+
const soundPath = join15(distPath, c.req.path);
|
|
152479
|
+
if (existsSync13(soundPath)) {
|
|
152323
152480
|
return serveFile(soundPath);
|
|
152324
152481
|
}
|
|
152325
152482
|
return c.notFound();
|
|
@@ -152327,8 +152484,8 @@ function createApp() {
|
|
|
152327
152484
|
const staticFiles = ["vibora-icon.png", "vibora-logo.jpeg", "vite.svg", "logo-dark.jpg", "logo-light.jpg", "goat.jpeg"];
|
|
152328
152485
|
for (const file of staticFiles) {
|
|
152329
152486
|
app13.get(`/${file}`, async () => {
|
|
152330
|
-
const filePath =
|
|
152331
|
-
if (
|
|
152487
|
+
const filePath = join15(distPath, file);
|
|
152488
|
+
if (existsSync13(filePath)) {
|
|
152332
152489
|
return serveFile(filePath);
|
|
152333
152490
|
}
|
|
152334
152491
|
return new Response("Not Found", { status: 404 });
|
|
@@ -152339,7 +152496,7 @@ function createApp() {
|
|
|
152339
152496
|
if (path9.startsWith("/api/") || path9.startsWith("/ws/") || path9 === "/health") {
|
|
152340
152497
|
return next();
|
|
152341
152498
|
}
|
|
152342
|
-
const html = await readFile2(
|
|
152499
|
+
const html = await readFile2(join15(distPath, "index.html"), "utf-8");
|
|
152343
152500
|
return c.html(html);
|
|
152344
152501
|
});
|
|
152345
152502
|
}
|
|
@@ -152347,7 +152504,7 @@ function createApp() {
|
|
|
152347
152504
|
}
|
|
152348
152505
|
|
|
152349
152506
|
// server/services/pr-monitor.ts
|
|
152350
|
-
import { execSync as
|
|
152507
|
+
import { execSync as execSync8 } from "child_process";
|
|
152351
152508
|
var POLL_INTERVAL = 60000;
|
|
152352
152509
|
function parsePrUrl(url) {
|
|
152353
152510
|
const match3 = url.match(/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/);
|
|
@@ -152362,7 +152519,7 @@ function checkPrStatus(prUrl) {
|
|
|
152362
152519
|
return null;
|
|
152363
152520
|
}
|
|
152364
152521
|
try {
|
|
152365
|
-
const output =
|
|
152522
|
+
const output = execSync8(`gh pr view ${parsed.number} --repo ${parsed.owner}/${parsed.repo} --json state,mergedAt`, { encoding: "utf-8", timeout: 1e4, stdio: ["pipe", "pipe", "pipe"] });
|
|
152366
152523
|
const data = JSON.parse(output);
|
|
152367
152524
|
return {
|
|
152368
152525
|
state: data.state,
|