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