vibora 6.2.3 → 6.2.5
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/bin/vibora.js +2 -1
- package/package.json +1 -1
- package/server/index.js +79 -50
package/bin/vibora.js
CHANGED
|
@@ -32629,7 +32629,7 @@ function installUv() {
|
|
|
32629
32629
|
var package_default = {
|
|
32630
32630
|
name: "vibora",
|
|
32631
32631
|
private: true,
|
|
32632
|
-
version: "6.2.
|
|
32632
|
+
version: "6.2.5",
|
|
32633
32633
|
description: "The Vibe Engineer's Cockpit",
|
|
32634
32634
|
license: "PolyForm-Shield-1.0.0",
|
|
32635
32635
|
type: "module",
|
|
@@ -32847,6 +32847,7 @@ async function handleUpCommand(flags) {
|
|
|
32847
32847
|
VIBORA_PACKAGE_ROOT: packageRoot,
|
|
32848
32848
|
VIBORA_VERSION: package_default.version,
|
|
32849
32849
|
BUN_PTY_LIB: ptyLibPath,
|
|
32850
|
+
VIBORA_CLAUDE_INSTALLED: "1",
|
|
32850
32851
|
...debug && { LOG_LEVEL: "debug", DEBUG: "1" }
|
|
32851
32852
|
}
|
|
32852
32853
|
});
|
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 readFile5 } from "fs/promises";
|
|
10134
|
-
import { join as
|
|
10135
|
-
import { existsSync as
|
|
10134
|
+
import { join as join22 } from "path";
|
|
10135
|
+
import { existsSync as existsSync17 } from "fs";
|
|
10136
10136
|
|
|
10137
10137
|
// server/routes/health.ts
|
|
10138
10138
|
var app = new Hono2;
|
|
@@ -152866,6 +152866,9 @@ monitoringRoutes.get("/claude-usage", async (c) => {
|
|
|
152866
152866
|
|
|
152867
152867
|
// server/routes/system.ts
|
|
152868
152868
|
import { execSync as execSync8 } from "child_process";
|
|
152869
|
+
import { existsSync as existsSync14 } from "fs";
|
|
152870
|
+
import { join as join15 } from "path";
|
|
152871
|
+
import { homedir as homedir7 } from "os";
|
|
152869
152872
|
var app13 = new Hono2;
|
|
152870
152873
|
function isCommandAvailable(command) {
|
|
152871
152874
|
try {
|
|
@@ -152875,9 +152878,27 @@ function isCommandAvailable(command) {
|
|
|
152875
152878
|
return { installed: false };
|
|
152876
152879
|
}
|
|
152877
152880
|
}
|
|
152881
|
+
function isClaudeCodeInstalled() {
|
|
152882
|
+
const pathCheck = isCommandAvailable("claude");
|
|
152883
|
+
if (pathCheck.installed) {
|
|
152884
|
+
return pathCheck;
|
|
152885
|
+
}
|
|
152886
|
+
const commonPaths = [
|
|
152887
|
+
join15(homedir7(), ".claude", "local", "claude"),
|
|
152888
|
+
"/usr/local/bin/claude",
|
|
152889
|
+
"/opt/homebrew/bin/claude"
|
|
152890
|
+
];
|
|
152891
|
+
for (const path9 of commonPaths) {
|
|
152892
|
+
if (existsSync14(path9)) {
|
|
152893
|
+
return { installed: true, path: path9 };
|
|
152894
|
+
}
|
|
152895
|
+
}
|
|
152896
|
+
return { installed: false };
|
|
152897
|
+
}
|
|
152878
152898
|
app13.get("/dependencies", (c) => {
|
|
152899
|
+
const claudeInstalledFromEnv = process.env.VIBORA_CLAUDE_INSTALLED === "1";
|
|
152879
152900
|
const claudeMissingFromEnv = process.env.VIBORA_CLAUDE_MISSING === "1";
|
|
152880
|
-
const claudeCheck = claudeMissingFromEnv ? { installed: false } :
|
|
152901
|
+
const claudeCheck = claudeInstalledFromEnv ? { installed: true } : claudeMissingFromEnv ? { installed: false } : isClaudeCodeInstalled();
|
|
152881
152902
|
const dtachCheck = isCommandAvailable("dtach");
|
|
152882
152903
|
return c.json({
|
|
152883
152904
|
claudeCode: claudeCheck,
|
|
@@ -153124,11 +153145,11 @@ var nanoid = (size = 21) => {
|
|
|
153124
153145
|
|
|
153125
153146
|
// server/services/compose-parser.ts
|
|
153126
153147
|
import { readFile as readFile2, access } from "fs/promises";
|
|
153127
|
-
import { join as
|
|
153148
|
+
import { join as join16 } from "path";
|
|
153128
153149
|
var COMPOSE_FILE_NAMES = ["compose.yml", "compose.yaml", "docker-compose.yml", "docker-compose.yaml"];
|
|
153129
153150
|
async function findComposeFile(repoPath) {
|
|
153130
153151
|
for (const fileName of COMPOSE_FILE_NAMES) {
|
|
153131
|
-
const filePath =
|
|
153152
|
+
const filePath = join16(repoPath, fileName);
|
|
153132
153153
|
try {
|
|
153133
153154
|
await access(filePath);
|
|
153134
153155
|
return fileName;
|
|
@@ -153206,7 +153227,7 @@ async function parseComposeFile(repoPath, composeFileName) {
|
|
|
153206
153227
|
if (!fileName) {
|
|
153207
153228
|
throw new Error(`No compose file found in ${repoPath}`);
|
|
153208
153229
|
}
|
|
153209
|
-
const filePath =
|
|
153230
|
+
const filePath = join16(repoPath, fileName);
|
|
153210
153231
|
const content = await readFile2(filePath, "utf-8");
|
|
153211
153232
|
const parsed = $parse(content);
|
|
153212
153233
|
if (!parsed || typeof parsed !== "object") {
|
|
@@ -153408,7 +153429,7 @@ async function runDocker(args, options = {}) {
|
|
|
153408
153429
|
// server/services/docker-swarm.ts
|
|
153409
153430
|
import { spawn as spawn5 } from "child_process";
|
|
153410
153431
|
import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
153411
|
-
import { join as
|
|
153432
|
+
import { join as join17 } from "path";
|
|
153412
153433
|
async function runDocker2(args, options = {}, onOutput) {
|
|
153413
153434
|
if (options.signal?.aborted) {
|
|
153414
153435
|
return { stdout: "", stderr: "Aborted", exitCode: -1, aborted: true };
|
|
@@ -153498,8 +153519,8 @@ async function ensureSwarmMode() {
|
|
|
153498
153519
|
}
|
|
153499
153520
|
async function generateSwarmComposeFile(cwd, composeFile, projectName, externalNetwork) {
|
|
153500
153521
|
const swarmFile = ".swarm-compose.yml";
|
|
153501
|
-
const originalPath =
|
|
153502
|
-
const swarmPath =
|
|
153522
|
+
const originalPath = join17(cwd, composeFile);
|
|
153523
|
+
const swarmPath = join17(cwd, swarmFile);
|
|
153503
153524
|
try {
|
|
153504
153525
|
const content = await readFile3(originalPath, "utf-8");
|
|
153505
153526
|
const parsed = $parse(content);
|
|
@@ -173235,7 +173256,7 @@ var cloudflare_default = Cloudflare;
|
|
|
173235
173256
|
// server/services/cloudflare.ts
|
|
173236
173257
|
import { generateKeyPairSync, createSign } from "crypto";
|
|
173237
173258
|
import { mkdir as mkdir2, writeFile as writeFile3, readFile as readFile4, access as access2 } from "fs/promises";
|
|
173238
|
-
import { join as
|
|
173259
|
+
import { join as join18 } from "path";
|
|
173239
173260
|
var ORIGIN_CA_PERMISSION_ERROR = `Your Cloudflare API token needs additional permissions to generate SSL certificates.
|
|
173240
173261
|
|
|
173241
173262
|
To fix this:
|
|
@@ -173343,12 +173364,12 @@ async function deleteDnsRecord(subdomain, domain) {
|
|
|
173343
173364
|
}
|
|
173344
173365
|
}
|
|
173345
173366
|
function getCertDir(domain) {
|
|
173346
|
-
return
|
|
173367
|
+
return join18(getViboraDir(), "certs", domain);
|
|
173347
173368
|
}
|
|
173348
173369
|
async function hasCertificate(domain) {
|
|
173349
173370
|
const certDir = getCertDir(domain);
|
|
173350
|
-
const certPath =
|
|
173351
|
-
const keyPath =
|
|
173371
|
+
const certPath = join18(certDir, "cert.pem");
|
|
173372
|
+
const keyPath = join18(certDir, "key.pem");
|
|
173352
173373
|
try {
|
|
173353
173374
|
await access2(certPath);
|
|
173354
173375
|
await access2(keyPath);
|
|
@@ -173363,8 +173384,8 @@ async function getCertificatePaths(domain) {
|
|
|
173363
173384
|
}
|
|
173364
173385
|
const certDir = getCertDir(domain);
|
|
173365
173386
|
return {
|
|
173366
|
-
certPath:
|
|
173367
|
-
keyPath:
|
|
173387
|
+
certPath: join18(certDir, "cert.pem"),
|
|
173388
|
+
keyPath: join18(certDir, "key.pem")
|
|
173368
173389
|
};
|
|
173369
173390
|
}
|
|
173370
173391
|
function generateKeyAndCSR(hostnames) {
|
|
@@ -173478,8 +173499,8 @@ async function createOriginCACertificate(domain) {
|
|
|
173478
173499
|
}
|
|
173479
173500
|
const certDir = getCertDir(domain);
|
|
173480
173501
|
await mkdir2(certDir, { recursive: true });
|
|
173481
|
-
const certPath =
|
|
173482
|
-
const keyPath =
|
|
173502
|
+
const certPath = join18(certDir, "cert.pem");
|
|
173503
|
+
const keyPath = join18(certDir, "key.pem");
|
|
173483
173504
|
await writeFile3(certPath, cert.certificate, "utf-8");
|
|
173484
173505
|
await writeFile3(keyPath, privateKey, { mode: 384 });
|
|
173485
173506
|
log2.deploy.info("Origin CA certificate created and saved", {
|
|
@@ -173505,7 +173526,7 @@ async function createOriginCACertificate(domain) {
|
|
|
173505
173526
|
|
|
173506
173527
|
// server/services/traefik.ts
|
|
173507
173528
|
import { writeFile as writeFile4, unlink as unlink2, access as access3, constants } from "fs/promises";
|
|
173508
|
-
import { join as
|
|
173529
|
+
import { join as join19 } from "path";
|
|
173509
173530
|
async function detectTraefik() {
|
|
173510
173531
|
try {
|
|
173511
173532
|
const dokployResult = await runDocker([
|
|
@@ -173585,9 +173606,9 @@ function parseTraefikContainer(container, type) {
|
|
|
173585
173606
|
if (type === "dokploy") {
|
|
173586
173607
|
configDir = "/etc/dokploy/traefik/dynamic";
|
|
173587
173608
|
} else if (dynamicMount) {
|
|
173588
|
-
configDir = dynamicMount.Source.includes("dynamic") ? dynamicMount.Source :
|
|
173609
|
+
configDir = dynamicMount.Source.includes("dynamic") ? dynamicMount.Source : join19(dynamicMount.Source, "dynamic");
|
|
173589
173610
|
} else {
|
|
173590
|
-
configDir =
|
|
173611
|
+
configDir = "/etc/traefik/dynamic";
|
|
173591
173612
|
}
|
|
173592
173613
|
const networks = Object.keys(container.NetworkSettings?.Networks || {});
|
|
173593
173614
|
const network = networks.find((n) => n === "dokploy-network") || networks.find((n) => n === "vibora-network") || networks.find((n) => !n.includes("bridge") && !n.includes("host")) || "dokploy-network";
|
|
@@ -173620,7 +173641,7 @@ function getConfigFilename(appId) {
|
|
|
173620
173641
|
async function addRoute(config, appId, domain, upstreamUrl, options) {
|
|
173621
173642
|
const routerId = `vibora-${appId}`;
|
|
173622
173643
|
const filename = getConfigFilename(appId);
|
|
173623
|
-
const filepath =
|
|
173644
|
+
const filepath = join19(config.configDir, filename);
|
|
173624
173645
|
let tlsConfig;
|
|
173625
173646
|
let tlsStores;
|
|
173626
173647
|
if (options?.tlsCert) {
|
|
@@ -173691,7 +173712,7 @@ async function addRoute(config, appId, domain, upstreamUrl, options) {
|
|
|
173691
173712
|
}
|
|
173692
173713
|
async function removeRoute(config, appId) {
|
|
173693
173714
|
const filename = getConfigFilename(appId);
|
|
173694
|
-
const filepath =
|
|
173715
|
+
const filepath = join19(config.configDir, filename);
|
|
173695
173716
|
try {
|
|
173696
173717
|
await unlink2(filepath);
|
|
173697
173718
|
log2.deploy.info("Removed Traefik route", { appId, filepath });
|
|
@@ -173709,14 +173730,18 @@ async function removeRoute(config, appId) {
|
|
|
173709
173730
|
|
|
173710
173731
|
// server/services/traefik-docker.ts
|
|
173711
173732
|
import { mkdir as mkdir3, writeFile as writeFile5, chmod } from "fs/promises";
|
|
173712
|
-
import { existsSync as
|
|
173713
|
-
import { join as
|
|
173733
|
+
import { existsSync as existsSync15 } from "fs";
|
|
173734
|
+
import { join as join20 } from "path";
|
|
173714
173735
|
var TRAEFIK_CONTAINER_NAME = "vibora-traefik";
|
|
173715
173736
|
var TRAEFIK_IMAGE = "traefik:v3";
|
|
173716
173737
|
var TRAEFIK_NETWORK = "vibora-network";
|
|
173717
|
-
var TRAEFIK_CONFIG_DIR = "/etc/vibora/traefik";
|
|
173718
|
-
var TRAEFIK_DYNAMIC_DIR = "/etc/vibora/traefik/dynamic";
|
|
173719
173738
|
var TRAEFIK_CERTS_MOUNT = "/certs";
|
|
173739
|
+
function getTraefikConfigDir() {
|
|
173740
|
+
return join20(getViboraDir(), "traefik");
|
|
173741
|
+
}
|
|
173742
|
+
function getTraefikDynamicDir() {
|
|
173743
|
+
return join20(getViboraDir(), "traefik", "dynamic");
|
|
173744
|
+
}
|
|
173720
173745
|
async function getTraefikContainerStatus() {
|
|
173721
173746
|
const result = await runDocker([
|
|
173722
173747
|
"inspect",
|
|
@@ -173755,17 +173780,19 @@ async function ensureNetwork() {
|
|
|
173755
173780
|
return { success: true };
|
|
173756
173781
|
}
|
|
173757
173782
|
function getCertsDir() {
|
|
173758
|
-
return
|
|
173783
|
+
return join20(getViboraDir(), "certs");
|
|
173759
173784
|
}
|
|
173760
173785
|
async function ensureConfigDirs() {
|
|
173761
|
-
|
|
173762
|
-
|
|
173786
|
+
const configDir = getTraefikConfigDir();
|
|
173787
|
+
const dynamicDir = getTraefikDynamicDir();
|
|
173788
|
+
if (!existsSync15(configDir)) {
|
|
173789
|
+
await mkdir3(configDir, { recursive: true });
|
|
173763
173790
|
}
|
|
173764
|
-
if (!
|
|
173765
|
-
await mkdir3(
|
|
173791
|
+
if (!existsSync15(dynamicDir)) {
|
|
173792
|
+
await mkdir3(dynamicDir, { recursive: true });
|
|
173766
173793
|
}
|
|
173767
173794
|
const certsDir = getCertsDir();
|
|
173768
|
-
if (!
|
|
173795
|
+
if (!existsSync15(certsDir)) {
|
|
173769
173796
|
await mkdir3(certsDir, { recursive: true });
|
|
173770
173797
|
}
|
|
173771
173798
|
}
|
|
@@ -173845,12 +173872,14 @@ async function startTraefikContainer(acmeEmail) {
|
|
|
173845
173872
|
return networkResult;
|
|
173846
173873
|
}
|
|
173847
173874
|
await ensureConfigDirs();
|
|
173848
|
-
const
|
|
173875
|
+
const configDir = getTraefikConfigDir();
|
|
173876
|
+
const dynamicDir = getTraefikDynamicDir();
|
|
173877
|
+
const traefikConfigPath = join20(configDir, "traefik.yml");
|
|
173849
173878
|
await writeFile5(traefikConfigPath, generateTraefikConfig(acmeEmail), "utf-8");
|
|
173850
|
-
const middlewaresPath =
|
|
173879
|
+
const middlewaresPath = join20(dynamicDir, "middlewares.yml");
|
|
173851
173880
|
await writeFile5(middlewaresPath, generateMiddlewaresConfig(), "utf-8");
|
|
173852
|
-
const acmePath =
|
|
173853
|
-
if (!
|
|
173881
|
+
const acmePath = join20(configDir, "acme.json");
|
|
173882
|
+
if (!existsSync15(acmePath)) {
|
|
173854
173883
|
await writeFile5(acmePath, "{}", "utf-8");
|
|
173855
173884
|
await chmod(acmePath, 384);
|
|
173856
173885
|
}
|
|
@@ -173866,11 +173895,11 @@ async function startTraefikContainer(acmeEmail) {
|
|
|
173866
173895
|
"-v",
|
|
173867
173896
|
"/var/run/docker.sock:/var/run/docker.sock:ro",
|
|
173868
173897
|
"-v",
|
|
173869
|
-
`${
|
|
173898
|
+
`${configDir}/traefik.yml:/etc/traefik/traefik.yml:ro`,
|
|
173870
173899
|
"-v",
|
|
173871
|
-
`${
|
|
173900
|
+
`${configDir}/acme.json:/etc/traefik/acme.json`,
|
|
173872
173901
|
"-v",
|
|
173873
|
-
`${
|
|
173902
|
+
`${dynamicDir}:/etc/traefik/dynamic:ro`,
|
|
173874
173903
|
"-v",
|
|
173875
173904
|
`${certsDir}:${TRAEFIK_CERTS_MOUNT}:ro`,
|
|
173876
173905
|
"--network",
|
|
@@ -173947,7 +173976,7 @@ async function getTraefikLogs(tail = 100) {
|
|
|
173947
173976
|
}
|
|
173948
173977
|
function getViboraTraefikConfig() {
|
|
173949
173978
|
return {
|
|
173950
|
-
configDir:
|
|
173979
|
+
configDir: getTraefikDynamicDir(),
|
|
173951
173980
|
network: TRAEFIK_NETWORK,
|
|
173952
173981
|
certResolver: "letsencrypt",
|
|
173953
173982
|
containerName: TRAEFIK_CONTAINER_NAME,
|
|
@@ -175238,7 +175267,7 @@ app17.post("/traefik/start", async (c) => {
|
|
|
175238
175267
|
status,
|
|
175239
175268
|
containerName: TRAEFIK_CONTAINER_NAME,
|
|
175240
175269
|
network: TRAEFIK_NETWORK,
|
|
175241
|
-
configDir:
|
|
175270
|
+
configDir: getTraefikDynamicDir()
|
|
175242
175271
|
});
|
|
175243
175272
|
});
|
|
175244
175273
|
app17.post("/traefik/stop", async (c) => {
|
|
@@ -175326,9 +175355,9 @@ var deployment_default = app17;
|
|
|
175326
175355
|
// server/app.ts
|
|
175327
175356
|
function getDistPath() {
|
|
175328
175357
|
if (process.env.VIBORA_PACKAGE_ROOT) {
|
|
175329
|
-
return
|
|
175358
|
+
return join22(process.env.VIBORA_PACKAGE_ROOT, "dist");
|
|
175330
175359
|
}
|
|
175331
|
-
return
|
|
175360
|
+
return join22(process.cwd(), "dist");
|
|
175332
175361
|
}
|
|
175333
175362
|
function createApp() {
|
|
175334
175363
|
const app18 = new Hono2;
|
|
@@ -175401,15 +175430,15 @@ function createApp() {
|
|
|
175401
175430
|
});
|
|
175402
175431
|
};
|
|
175403
175432
|
app18.get("/assets/*", async (c) => {
|
|
175404
|
-
const assetPath =
|
|
175405
|
-
if (
|
|
175433
|
+
const assetPath = join22(distPath, c.req.path);
|
|
175434
|
+
if (existsSync17(assetPath)) {
|
|
175406
175435
|
return serveFile(assetPath);
|
|
175407
175436
|
}
|
|
175408
175437
|
return c.notFound();
|
|
175409
175438
|
});
|
|
175410
175439
|
app18.get("/sounds/*", async (c) => {
|
|
175411
|
-
const soundPath =
|
|
175412
|
-
if (
|
|
175440
|
+
const soundPath = join22(distPath, c.req.path);
|
|
175441
|
+
if (existsSync17(soundPath)) {
|
|
175413
175442
|
return serveFile(soundPath);
|
|
175414
175443
|
}
|
|
175415
175444
|
return c.notFound();
|
|
@@ -175417,8 +175446,8 @@ function createApp() {
|
|
|
175417
175446
|
const staticFiles = ["vibora-icon.png", "vibora-logo.jpeg", "vite.svg", "logo.png", "goat.jpeg"];
|
|
175418
175447
|
for (const file of staticFiles) {
|
|
175419
175448
|
app18.get(`/${file}`, async () => {
|
|
175420
|
-
const filePath =
|
|
175421
|
-
if (
|
|
175449
|
+
const filePath = join22(distPath, file);
|
|
175450
|
+
if (existsSync17(filePath)) {
|
|
175422
175451
|
return serveFile(filePath);
|
|
175423
175452
|
}
|
|
175424
175453
|
return new Response("Not Found", { status: 404 });
|
|
@@ -175429,7 +175458,7 @@ function createApp() {
|
|
|
175429
175458
|
if (path10.startsWith("/api/") || path10.startsWith("/ws/") || path10 === "/health") {
|
|
175430
175459
|
return next();
|
|
175431
175460
|
}
|
|
175432
|
-
const html = await readFile5(
|
|
175461
|
+
const html = await readFile5(join22(distPath, "index.html"), "utf-8");
|
|
175433
175462
|
return c.html(html);
|
|
175434
175463
|
});
|
|
175435
175464
|
}
|