vibora 7.1.2 → 7.1.3
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 +108 -23
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: "7.1.
|
|
32632
|
+
version: "7.1.3",
|
|
32633
32633
|
description: "Harness Attention. Orchestrate Agents. Ship.",
|
|
32634
32634
|
license: "PolyForm-Shield-1.0.0",
|
|
32635
32635
|
type: "module",
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -176605,17 +176605,15 @@ async function fetchDockerApiStats() {
|
|
|
176605
176605
|
if (!listResponse.ok)
|
|
176606
176606
|
return null;
|
|
176607
176607
|
const containerList = await listResponse.json();
|
|
176608
|
-
const
|
|
176609
|
-
|
|
176610
|
-
if (container.State !== "running")
|
|
176611
|
-
continue;
|
|
176608
|
+
const runningContainers = containerList.filter((c) => c.State === "running");
|
|
176609
|
+
const statsPromises = runningContainers.map(async (container) => {
|
|
176612
176610
|
try {
|
|
176613
176611
|
const statsUrl = `http://localhost/containers/${container.Id}/stats?stream=false`;
|
|
176614
176612
|
const statsResponse = await fetch(statsUrl, {
|
|
176615
176613
|
unix: socketPath
|
|
176616
176614
|
});
|
|
176617
176615
|
if (!statsResponse.ok)
|
|
176618
|
-
|
|
176616
|
+
return null;
|
|
176619
176617
|
const stats = await statsResponse.json();
|
|
176620
176618
|
const cpuDelta = stats.cpu_stats.cpu_usage.total_usage - stats.precpu_stats.cpu_usage.total_usage;
|
|
176621
176619
|
const systemDelta = stats.cpu_stats.system_cpu_usage - stats.precpu_stats.system_cpu_usage;
|
|
@@ -176625,18 +176623,20 @@ async function fetchDockerApiStats() {
|
|
|
176625
176623
|
const memoryMB = memoryBytes / (1024 * 1024);
|
|
176626
176624
|
const memoryLimitMB = memoryLimit / (1024 * 1024);
|
|
176627
176625
|
const memoryPercent = memoryLimit > 0 ? memoryBytes / memoryLimit * 100 : 0;
|
|
176628
|
-
|
|
176626
|
+
return {
|
|
176629
176627
|
id: container.Id.slice(0, 12),
|
|
176630
176628
|
name: (container.Names[0] || "unknown").replace(/^\//, ""),
|
|
176631
176629
|
cpuPercent: Math.round(cpuPercent * 10) / 10,
|
|
176632
176630
|
memoryMB: Math.round(memoryMB * 10) / 10,
|
|
176633
176631
|
memoryLimit: Math.round(memoryLimitMB * 10) / 10,
|
|
176634
176632
|
memoryPercent: Math.round(memoryPercent * 10) / 10
|
|
176635
|
-
}
|
|
176633
|
+
};
|
|
176636
176634
|
} catch {
|
|
176637
|
-
|
|
176635
|
+
return null;
|
|
176638
176636
|
}
|
|
176639
|
-
}
|
|
176637
|
+
});
|
|
176638
|
+
const results = await Promise.all(statsPromises);
|
|
176639
|
+
const containers = results.filter((c) => c !== null);
|
|
176640
176640
|
return containers;
|
|
176641
176641
|
} catch {
|
|
176642
176642
|
return null;
|
|
@@ -177308,6 +177308,60 @@ var nanoid = (size = 21) => {
|
|
|
177308
177308
|
import { readFile as readFile2, access } from "fs/promises";
|
|
177309
177309
|
import { join as join16 } from "path";
|
|
177310
177310
|
init_logger2();
|
|
177311
|
+
|
|
177312
|
+
// server/lib/env-expand.ts
|
|
177313
|
+
function expandEnvVar(str, env) {
|
|
177314
|
+
const braceMatch = str.match(/^\$\{([A-Za-z_][A-Za-z0-9_]*)(?:(:?[-=])(.+))?\}$/);
|
|
177315
|
+
if (braceMatch) {
|
|
177316
|
+
const varName = braceMatch[1];
|
|
177317
|
+
const operator = braceMatch[2];
|
|
177318
|
+
const defaultValue = braceMatch[3];
|
|
177319
|
+
if (env && varName in env) {
|
|
177320
|
+
const value = env[varName];
|
|
177321
|
+
if (operator?.startsWith(":") && value === "") {
|
|
177322
|
+
return defaultValue ?? null;
|
|
177323
|
+
}
|
|
177324
|
+
return value;
|
|
177325
|
+
}
|
|
177326
|
+
if (defaultValue !== undefined) {
|
|
177327
|
+
return defaultValue;
|
|
177328
|
+
}
|
|
177329
|
+
return null;
|
|
177330
|
+
}
|
|
177331
|
+
const simpleMatch = str.match(/^\$([A-Za-z_][A-Za-z0-9_]*)$/);
|
|
177332
|
+
if (simpleMatch) {
|
|
177333
|
+
const varName = simpleMatch[1];
|
|
177334
|
+
if (env && varName in env) {
|
|
177335
|
+
return env[varName];
|
|
177336
|
+
}
|
|
177337
|
+
return null;
|
|
177338
|
+
}
|
|
177339
|
+
return str;
|
|
177340
|
+
}
|
|
177341
|
+
function splitRespectingEnvVars(str, delimiter = ":") {
|
|
177342
|
+
const parts = [];
|
|
177343
|
+
let current = "";
|
|
177344
|
+
let braceDepth = 0;
|
|
177345
|
+
for (let i = 0;i < str.length; i++) {
|
|
177346
|
+
const char = str[i];
|
|
177347
|
+
if (char === "{" && i > 0 && str[i - 1] === "$") {
|
|
177348
|
+
braceDepth++;
|
|
177349
|
+
current += char;
|
|
177350
|
+
} else if (char === "}" && braceDepth > 0) {
|
|
177351
|
+
braceDepth--;
|
|
177352
|
+
current += char;
|
|
177353
|
+
} else if (char === delimiter && braceDepth === 0) {
|
|
177354
|
+
parts.push(current);
|
|
177355
|
+
current = "";
|
|
177356
|
+
} else {
|
|
177357
|
+
current += char;
|
|
177358
|
+
}
|
|
177359
|
+
}
|
|
177360
|
+
parts.push(current);
|
|
177361
|
+
return parts;
|
|
177362
|
+
}
|
|
177363
|
+
|
|
177364
|
+
// server/services/compose-parser.ts
|
|
177311
177365
|
var COMPOSE_FILE_NAMES = ["compose.yml", "compose.yaml", "docker-compose.yml", "docker-compose.yaml"];
|
|
177312
177366
|
async function findComposeFile(repoPath) {
|
|
177313
177367
|
for (const fileName of COMPOSE_FILE_NAMES) {
|
|
@@ -177319,8 +177373,23 @@ async function findComposeFile(repoPath) {
|
|
|
177319
177373
|
}
|
|
177320
177374
|
return null;
|
|
177321
177375
|
}
|
|
177376
|
+
function parsePortValue(value) {
|
|
177377
|
+
const expanded = expandEnvVar(value);
|
|
177378
|
+
if (expanded === null) {
|
|
177379
|
+
return null;
|
|
177380
|
+
}
|
|
177381
|
+
const port = parseInt(expanded, 10);
|
|
177382
|
+
if (isNaN(port) || port <= 0 || port > 65535) {
|
|
177383
|
+
return null;
|
|
177384
|
+
}
|
|
177385
|
+
return port;
|
|
177386
|
+
}
|
|
177322
177387
|
function parsePort(port) {
|
|
177323
177388
|
if (typeof port === "number") {
|
|
177389
|
+
if (port <= 0 || port > 65535) {
|
|
177390
|
+
log2.deploy.warn("Invalid port number", { port });
|
|
177391
|
+
return null;
|
|
177392
|
+
}
|
|
177324
177393
|
return { container: port };
|
|
177325
177394
|
}
|
|
177326
177395
|
if (typeof port === "string") {
|
|
@@ -177333,28 +177402,34 @@ function parsePort(port) {
|
|
|
177333
177402
|
protocol = "udp";
|
|
177334
177403
|
portStr = port.slice(0, -4);
|
|
177335
177404
|
}
|
|
177336
|
-
|
|
177337
|
-
|
|
177338
|
-
const containerPort =
|
|
177339
|
-
const hostPort =
|
|
177340
|
-
if (
|
|
177405
|
+
const parts = splitRespectingEnvVars(portStr);
|
|
177406
|
+
if (parts.length >= 2) {
|
|
177407
|
+
const containerPort = parsePortValue(parts[parts.length - 1]);
|
|
177408
|
+
const hostPort = parsePortValue(parts[parts.length - 2]);
|
|
177409
|
+
if (containerPort !== null) {
|
|
177341
177410
|
return {
|
|
177342
177411
|
container: containerPort,
|
|
177343
|
-
host:
|
|
177412
|
+
host: hostPort ?? undefined,
|
|
177344
177413
|
protocol
|
|
177345
177414
|
};
|
|
177346
177415
|
}
|
|
177416
|
+
log2.deploy.warn("Could not parse port with env var reference", { port: portStr });
|
|
177347
177417
|
} else {
|
|
177348
|
-
const containerPort =
|
|
177349
|
-
if (
|
|
177418
|
+
const containerPort = parsePortValue(portStr);
|
|
177419
|
+
if (containerPort !== null) {
|
|
177350
177420
|
return { container: containerPort, protocol };
|
|
177351
177421
|
}
|
|
177422
|
+
log2.deploy.warn("Could not parse port value", { port: portStr });
|
|
177352
177423
|
}
|
|
177353
177424
|
}
|
|
177354
177425
|
if (typeof port === "object" && port !== null) {
|
|
177355
177426
|
const portObj = port;
|
|
177356
177427
|
const target = portObj.target ?? portObj.container_port;
|
|
177357
177428
|
if (typeof target === "number") {
|
|
177429
|
+
if (target <= 0 || target > 65535) {
|
|
177430
|
+
log2.deploy.warn("Invalid port number in long syntax", { target });
|
|
177431
|
+
return null;
|
|
177432
|
+
}
|
|
177358
177433
|
return {
|
|
177359
177434
|
container: target,
|
|
177360
177435
|
host: typeof portObj.published === "number" ? portObj.published : undefined,
|
|
@@ -177978,17 +178053,22 @@ function sleep(ms) {
|
|
|
177978
178053
|
return new Promise((r) => setTimeout(r, ms));
|
|
177979
178054
|
}
|
|
177980
178055
|
function resolveVolumePath(volumePath, basePath) {
|
|
177981
|
-
|
|
178056
|
+
const expanded = expandEnvVar(volumePath);
|
|
178057
|
+
const pathToCheck = expanded ?? volumePath;
|
|
178058
|
+
if (!pathToCheck.includes("/") && !pathToCheck.startsWith(".")) {
|
|
177982
178059
|
return volumePath;
|
|
177983
178060
|
}
|
|
177984
|
-
if (
|
|
178061
|
+
if (expanded === null && volumePath.includes("${")) {
|
|
177985
178062
|
return volumePath;
|
|
177986
178063
|
}
|
|
177987
|
-
|
|
178064
|
+
if (isAbsolute2(pathToCheck)) {
|
|
178065
|
+
return expanded ?? volumePath;
|
|
178066
|
+
}
|
|
178067
|
+
return resolve5(basePath, pathToCheck);
|
|
177988
178068
|
}
|
|
177989
178069
|
function resolveVolumeEntry(volume, basePath) {
|
|
177990
178070
|
if (typeof volume === "string") {
|
|
177991
|
-
const parts = volume
|
|
178071
|
+
const parts = splitRespectingEnvVars(volume);
|
|
177992
178072
|
if (parts.length >= 2) {
|
|
177993
178073
|
const hostPath = parts[0];
|
|
177994
178074
|
const containerPath = parts[1];
|
|
@@ -178802,8 +178882,13 @@ async function deployApp(appId, options = {}, onProgress) {
|
|
|
178802
178882
|
where: eq(appServices.appId, appId)
|
|
178803
178883
|
});
|
|
178804
178884
|
for (const service of services) {
|
|
178805
|
-
if (service.exposed && service.domain
|
|
178806
|
-
|
|
178885
|
+
if (service.exposed && service.domain) {
|
|
178886
|
+
if (!service.containerPort) {
|
|
178887
|
+
throw new Error(`Service "${service.serviceName}" is exposed with domain "${service.domain}" but has no container port configured. ` + `Add a port mapping to your compose file or configure the container port in the service settings.`);
|
|
178888
|
+
}
|
|
178889
|
+
if (service.containerPort <= 0 || service.containerPort > 65535) {
|
|
178890
|
+
throw new Error(`Service "${service.serviceName}" has invalid container port ${service.containerPort}. ` + `Port must be between 1 and 65535. Check your compose file port configuration.`);
|
|
178891
|
+
}
|
|
178807
178892
|
}
|
|
178808
178893
|
}
|
|
178809
178894
|
const serviceStatuses = await stackServices(projectName);
|