aglio-worker 0.13.0 → 0.14.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/agent.js +158 -32
- package/package.json +1 -1
package/agent.js
CHANGED
|
@@ -5052,8 +5052,8 @@ var require_multipleOf = __commonJS({
|
|
|
5052
5052
|
const { gen, data, schemaCode, it } = cxt;
|
|
5053
5053
|
const prec = it.opts.multipleOfPrecision;
|
|
5054
5054
|
const res = gen.let("res");
|
|
5055
|
-
const
|
|
5056
|
-
cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${
|
|
5055
|
+
const invalid2 = prec ? (0, codegen_1._)`Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}` : (0, codegen_1._)`${res} !== parseInt(${res})`;
|
|
5056
|
+
cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid2}))`);
|
|
5057
5057
|
}
|
|
5058
5058
|
};
|
|
5059
5059
|
exports.default = def;
|
|
@@ -28152,10 +28152,6 @@ var cardLabelInputSchema = external_exports.object({
|
|
|
28152
28152
|
var INVITE_TTL_DAYS = 7;
|
|
28153
28153
|
var INVITE_TTL_MS = INVITE_TTL_DAYS * 24 * 60 * 60 * 1e3;
|
|
28154
28154
|
|
|
28155
|
-
// ../../packages/shared/src/workspace-theme.ts
|
|
28156
|
-
var WORKSPACE_THEME_ACCENT_IDS = ["default", "violet", "emerald", "amber", "rose"];
|
|
28157
|
-
var WORKSPACE_THEME_SCALES = ["compact", "default", "large"];
|
|
28158
|
-
|
|
28159
28155
|
// ../../packages/shared/src/workspace-settings.ts
|
|
28160
28156
|
var WORKSPACE_SETTINGS_DEFAULTS = {
|
|
28161
28157
|
allowMemberInvites: true,
|
|
@@ -28165,11 +28161,7 @@ var WORKSPACE_SETTINGS_DEFAULTS = {
|
|
|
28165
28161
|
artifactRetentionDays: 0,
|
|
28166
28162
|
defaultGitProvider: "github",
|
|
28167
28163
|
/** The shared workspace consultant is opt-out. Disabled hides every entry point. */
|
|
28168
|
-
consultantEnabled: true
|
|
28169
|
-
/** Workspace-wide accent preset. Applied to every member, light and dark. */
|
|
28170
|
-
themeAccent: "default",
|
|
28171
|
-
/** Workspace-wide text scale. Same for every member so boards stay aligned. */
|
|
28172
|
-
themeScale: "default"
|
|
28164
|
+
consultantEnabled: true
|
|
28173
28165
|
};
|
|
28174
28166
|
var workspaceSettingsSchema = external_exports.object({
|
|
28175
28167
|
allowMemberInvites: external_exports.boolean().catch(WORKSPACE_SETTINGS_DEFAULTS.allowMemberInvites),
|
|
@@ -28177,11 +28169,21 @@ var workspaceSettingsSchema = external_exports.object({
|
|
|
28177
28169
|
requireVerificationEvidence: external_exports.boolean().catch(WORKSPACE_SETTINGS_DEFAULTS.requireVerificationEvidence),
|
|
28178
28170
|
artifactRetentionDays: external_exports.number().int().min(0).max(3650).catch(WORKSPACE_SETTINGS_DEFAULTS.artifactRetentionDays),
|
|
28179
28171
|
defaultGitProvider: external_exports.string().optional().transform((value) => normalizeGitProvider(value)).catch(WORKSPACE_SETTINGS_DEFAULTS.defaultGitProvider),
|
|
28180
|
-
consultantEnabled: external_exports.boolean().catch(WORKSPACE_SETTINGS_DEFAULTS.consultantEnabled)
|
|
28181
|
-
themeAccent: external_exports.enum(WORKSPACE_THEME_ACCENT_IDS).catch(WORKSPACE_SETTINGS_DEFAULTS.themeAccent),
|
|
28182
|
-
themeScale: external_exports.enum(WORKSPACE_THEME_SCALES).catch(WORKSPACE_SETTINGS_DEFAULTS.themeScale)
|
|
28172
|
+
consultantEnabled: external_exports.boolean().catch(WORKSPACE_SETTINGS_DEFAULTS.consultantEnabled)
|
|
28183
28173
|
}).passthrough();
|
|
28184
28174
|
|
|
28175
|
+
// ../../packages/shared/src/theme.ts
|
|
28176
|
+
var THEME_ACCENT_IDS = ["default", "violet", "emerald", "amber", "rose"];
|
|
28177
|
+
var THEME_SCALES = ["compact", "default", "large"];
|
|
28178
|
+
var DEFAULT_THEME_PREFERENCES = {
|
|
28179
|
+
themeAccent: "default",
|
|
28180
|
+
themeScale: "default"
|
|
28181
|
+
};
|
|
28182
|
+
var themePreferencesSchema = external_exports.object({
|
|
28183
|
+
themeAccent: external_exports.enum(THEME_ACCENT_IDS).catch(DEFAULT_THEME_PREFERENCES.themeAccent),
|
|
28184
|
+
themeScale: external_exports.enum(THEME_SCALES).catch(DEFAULT_THEME_PREFERENCES.themeScale)
|
|
28185
|
+
});
|
|
28186
|
+
|
|
28185
28187
|
// ../../packages/shared/src/plans.ts
|
|
28186
28188
|
var PLAN_IDS = ["free", "team", "enterprise"];
|
|
28187
28189
|
var MEGABYTE = 1024 * 1024;
|
|
@@ -28355,10 +28357,121 @@ async function ensureDockerImage(input2) {
|
|
|
28355
28357
|
return "pulled";
|
|
28356
28358
|
}
|
|
28357
28359
|
|
|
28360
|
+
// src/resources.ts
|
|
28361
|
+
var GIB = 1024 * 1024 * 1024;
|
|
28362
|
+
var AUTO_MEMORY_RATIO = 0.8;
|
|
28363
|
+
var MEMORY_UNITS = {
|
|
28364
|
+
"": 1,
|
|
28365
|
+
b: 1,
|
|
28366
|
+
k: 1024,
|
|
28367
|
+
kb: 1024,
|
|
28368
|
+
m: 1024 ** 2,
|
|
28369
|
+
mb: 1024 ** 2,
|
|
28370
|
+
g: 1024 ** 3,
|
|
28371
|
+
gb: 1024 ** 3,
|
|
28372
|
+
t: 1024 ** 4,
|
|
28373
|
+
tb: 1024 ** 4
|
|
28374
|
+
};
|
|
28375
|
+
var AGENT_RESOURCE_FALLBACK = {
|
|
28376
|
+
cpu: 2,
|
|
28377
|
+
memoryBytes: 4 * GIB
|
|
28378
|
+
};
|
|
28379
|
+
function invalid(variable, value, expected) {
|
|
28380
|
+
return new Error(`Invalid ${variable} value "${value}": expected ${expected}`);
|
|
28381
|
+
}
|
|
28382
|
+
function parseCpuLimit(value, variable = "AGENT_CPU_LIMIT") {
|
|
28383
|
+
const trimmed = value.trim();
|
|
28384
|
+
if (!/^\d+(?:\.\d+)?$/.test(trimmed)) {
|
|
28385
|
+
throw invalid(variable, value, "positive CPU cores such as 2 or 2.5");
|
|
28386
|
+
}
|
|
28387
|
+
const cores = Number(trimmed);
|
|
28388
|
+
if (!Number.isFinite(cores) || cores <= 0) {
|
|
28389
|
+
throw invalid(variable, value, "positive CPU cores such as 2 or 2.5");
|
|
28390
|
+
}
|
|
28391
|
+
return cores;
|
|
28392
|
+
}
|
|
28393
|
+
function parseMemoryLimit(value, variable = "AGENT_MEMORY_LIMIT") {
|
|
28394
|
+
const trimmed = value.trim().toLowerCase();
|
|
28395
|
+
const match = /^(\d+(?:\.\d+)?)\s*([bkmgt]?b?)$/.exec(trimmed);
|
|
28396
|
+
const multiplier = match ? MEMORY_UNITS[match[2] ?? ""] : void 0;
|
|
28397
|
+
const amount = match ? Number(match[1]) : Number.NaN;
|
|
28398
|
+
if (!match || multiplier === void 0 || !Number.isFinite(amount)) {
|
|
28399
|
+
throw invalid(variable, value, "bytes or a Docker-style size such as 512m, 8g, 1073741824");
|
|
28400
|
+
}
|
|
28401
|
+
const bytes = Math.round(amount * multiplier);
|
|
28402
|
+
if (bytes <= 0) {
|
|
28403
|
+
throw invalid(variable, value, "bytes or a Docker-style size such as 512m, 8g, 1073741824");
|
|
28404
|
+
}
|
|
28405
|
+
return bytes;
|
|
28406
|
+
}
|
|
28407
|
+
function cpuToNanoCpus(cpu) {
|
|
28408
|
+
return Math.round(cpu * 1e9);
|
|
28409
|
+
}
|
|
28410
|
+
function readAgentResourceOverrides(source = process.env) {
|
|
28411
|
+
const cpu = source.AGENT_CPU_LIMIT?.trim();
|
|
28412
|
+
const memory = source.AGENT_MEMORY_LIMIT?.trim();
|
|
28413
|
+
return {
|
|
28414
|
+
cpu: cpu ? parseCpuLimit(cpu) : null,
|
|
28415
|
+
memory: memory ? parseMemoryLimit(memory) : null
|
|
28416
|
+
};
|
|
28417
|
+
}
|
|
28418
|
+
function resolveAgentResources(input2) {
|
|
28419
|
+
const fallback = input2.fallback ?? AGENT_RESOURCE_FALLBACK;
|
|
28420
|
+
const hostCpu = input2.host?.cpuCount;
|
|
28421
|
+
const hostMemory = input2.host?.totalMemoryBytes;
|
|
28422
|
+
let cpu;
|
|
28423
|
+
let cpuSource;
|
|
28424
|
+
if (input2.cpu != null) {
|
|
28425
|
+
cpu = input2.cpu;
|
|
28426
|
+
cpuSource = "env";
|
|
28427
|
+
} else if (typeof hostCpu === "number" && Number.isFinite(hostCpu) && hostCpu > 0) {
|
|
28428
|
+
cpu = hostCpu;
|
|
28429
|
+
cpuSource = "auto";
|
|
28430
|
+
} else {
|
|
28431
|
+
cpu = fallback.cpu;
|
|
28432
|
+
cpuSource = "fallback";
|
|
28433
|
+
}
|
|
28434
|
+
let memoryBytes;
|
|
28435
|
+
let memorySource;
|
|
28436
|
+
if (input2.memory != null) {
|
|
28437
|
+
memoryBytes = input2.memory;
|
|
28438
|
+
memorySource = "env";
|
|
28439
|
+
} else {
|
|
28440
|
+
const detected = typeof hostMemory === "number" && Number.isFinite(hostMemory) && hostMemory > 0 ? Math.floor(hostMemory * AUTO_MEMORY_RATIO) : 0;
|
|
28441
|
+
if (detected > 0) {
|
|
28442
|
+
memoryBytes = detected;
|
|
28443
|
+
memorySource = "auto";
|
|
28444
|
+
} else {
|
|
28445
|
+
memoryBytes = fallback.memoryBytes;
|
|
28446
|
+
memorySource = "fallback";
|
|
28447
|
+
}
|
|
28448
|
+
}
|
|
28449
|
+
return { cpu, memoryBytes, nanoCpus: cpuToNanoCpus(cpu), cpuSource, memorySource };
|
|
28450
|
+
}
|
|
28451
|
+
function agentHostResources(resources) {
|
|
28452
|
+
return { Memory: resources.memoryBytes, NanoCpus: resources.nanoCpus };
|
|
28453
|
+
}
|
|
28454
|
+
|
|
28358
28455
|
// src/remote-docker.ts
|
|
28359
|
-
async function
|
|
28456
|
+
async function resolveRemoteAgentResources(client, log, overrides = readAgentResourceOverrides()) {
|
|
28457
|
+
const needsDetection = overrides.cpu == null || overrides.memory == null;
|
|
28458
|
+
const info = needsDetection ? await client.info().catch(() => null) : null;
|
|
28459
|
+
const resources = resolveAgentResources({
|
|
28460
|
+
cpu: overrides.cpu,
|
|
28461
|
+
memory: overrides.memory,
|
|
28462
|
+
host: { cpuCount: info?.NCPU, totalMemoryBytes: info?.MemTotal }
|
|
28463
|
+
});
|
|
28464
|
+
if (resources.cpuSource === "fallback" || resources.memorySource === "fallback") {
|
|
28465
|
+
log?.("remote daemon resources unavailable, using fallback 2 CPU / 4 GB", {
|
|
28466
|
+
cpuSource: resources.cpuSource,
|
|
28467
|
+
memorySource: resources.memorySource
|
|
28468
|
+
});
|
|
28469
|
+
}
|
|
28470
|
+
return resources;
|
|
28471
|
+
}
|
|
28472
|
+
async function loginCpuNanoCpus(client) {
|
|
28360
28473
|
const info = await client.info().catch(() => null);
|
|
28361
|
-
return Math.max(1, Math.min(2, Math.floor(info?.NCPU ?? 1)));
|
|
28474
|
+
return Math.max(1, Math.min(2, Math.floor(info?.NCPU ?? 1))) * 1e9;
|
|
28362
28475
|
}
|
|
28363
28476
|
var CONTAINER_WORKSPACE = "/workspace";
|
|
28364
28477
|
function isRunningInContainer() {
|
|
@@ -28405,7 +28518,7 @@ function sleep(ms) {
|
|
|
28405
28518
|
return new Promise((resolvePromise) => setTimeout(resolvePromise, ms));
|
|
28406
28519
|
}
|
|
28407
28520
|
var defaultClients = /* @__PURE__ */ new Map();
|
|
28408
|
-
function
|
|
28521
|
+
function remoteDockerClient(socketPath) {
|
|
28409
28522
|
const existing = defaultClients.get(socketPath);
|
|
28410
28523
|
if (existing) return existing;
|
|
28411
28524
|
const client = new Dockerode({ socketPath });
|
|
@@ -28413,7 +28526,7 @@ function defaultClient(socketPath) {
|
|
|
28413
28526
|
return client;
|
|
28414
28527
|
}
|
|
28415
28528
|
async function createDockerJobExecutor(input2) {
|
|
28416
|
-
const client = input2.client ??
|
|
28529
|
+
const client = input2.client ?? remoteDockerClient(input2.socketPath ?? "/var/run/docker.sock");
|
|
28417
28530
|
await ensureDockerImage({ client, image: input2.image, log: input2.log });
|
|
28418
28531
|
const { hostPath } = mapDockerWorkspace({
|
|
28419
28532
|
workspaceRoot: input2.workspaceRoot,
|
|
@@ -28437,11 +28550,11 @@ async function createDockerJobExecutor(input2) {
|
|
|
28437
28550
|
if (error62.statusCode !== 404) throw error62;
|
|
28438
28551
|
}
|
|
28439
28552
|
const networkMode = input2.networkMode?.trim() || "bridge";
|
|
28553
|
+
const resources = input2.resources ?? await resolveRemoteAgentResources(client, input2.log);
|
|
28440
28554
|
const hostConfig = {
|
|
28441
28555
|
Binds: [`${hostPath}:${CONTAINER_WORKSPACE}`],
|
|
28442
28556
|
NetworkMode: networkMode,
|
|
28443
|
-
|
|
28444
|
-
NanoCpus: await runnerCpuCount(client) * 1e9,
|
|
28557
|
+
...agentHostResources(resources),
|
|
28445
28558
|
PidsLimit: 1024,
|
|
28446
28559
|
AutoRemove: false,
|
|
28447
28560
|
Init: true,
|
|
@@ -28527,7 +28640,7 @@ async function createDockerJobExecutor(input2) {
|
|
|
28527
28640
|
};
|
|
28528
28641
|
}
|
|
28529
28642
|
async function prefetchRunnerImage(input2) {
|
|
28530
|
-
const client = input2.client ??
|
|
28643
|
+
const client = input2.client ?? remoteDockerClient(input2.socketPath ?? "/var/run/docker.sock");
|
|
28531
28644
|
try {
|
|
28532
28645
|
if (isRegistryImage(input2.image)) {
|
|
28533
28646
|
await pullDockerImage(client, input2.image);
|
|
@@ -28550,7 +28663,7 @@ async function prefetchRunnerImage(input2) {
|
|
|
28550
28663
|
}
|
|
28551
28664
|
}
|
|
28552
28665
|
async function createDockerLoginContainer(input2) {
|
|
28553
|
-
const client = new Dockerode({ socketPath: input2.socketPath ?? "/var/run/docker.sock" });
|
|
28666
|
+
const client = input2.client ?? new Dockerode({ socketPath: input2.socketPath ?? "/var/run/docker.sock" });
|
|
28554
28667
|
await ensureDockerImage({
|
|
28555
28668
|
client,
|
|
28556
28669
|
image: input2.image
|
|
@@ -28576,6 +28689,7 @@ async function createDockerLoginContainer(input2) {
|
|
|
28576
28689
|
} catch (error62) {
|
|
28577
28690
|
if (error62.statusCode !== 404) throw error62;
|
|
28578
28691
|
}
|
|
28692
|
+
const overrides = readAgentResourceOverrides();
|
|
28579
28693
|
const container = await client.createContainer({
|
|
28580
28694
|
Image: input2.image,
|
|
28581
28695
|
name,
|
|
@@ -28588,8 +28702,10 @@ async function createDockerLoginContainer(input2) {
|
|
|
28588
28702
|
Binds: [`${hostPath}:${CONTAINER_WORKSPACE}`],
|
|
28589
28703
|
NetworkMode: "bridge",
|
|
28590
28704
|
ExtraHosts: input2.extraHosts ?? [],
|
|
28591
|
-
|
|
28592
|
-
|
|
28705
|
+
// Login keeps its small legacy default and never auto-detects, but an
|
|
28706
|
+
// explicit AGENT_CPU_LIMIT / AGENT_MEMORY_LIMIT override wins.
|
|
28707
|
+
Memory: overrides.memory ?? 2 * 1024 * 1024 * 1024,
|
|
28708
|
+
NanoCpus: overrides.cpu != null ? cpuToNanoCpus(overrides.cpu) : await loginCpuNanoCpus(client),
|
|
28593
28709
|
PidsLimit: 512,
|
|
28594
28710
|
AutoRemove: false,
|
|
28595
28711
|
Init: true,
|
|
@@ -28682,11 +28798,11 @@ async function verifyHostRuntime(input2, run = defaultRunner) {
|
|
|
28682
28798
|
import { statfs } from "node:fs/promises";
|
|
28683
28799
|
import { dirname, resolve as resolve2 } from "node:path";
|
|
28684
28800
|
import Dockerode2 from "dockerode";
|
|
28685
|
-
var
|
|
28801
|
+
var GIB2 = 1024 * 1024 * 1024;
|
|
28686
28802
|
var DISK_GUARD_DEFAULTS = {
|
|
28687
28803
|
enabled: true,
|
|
28688
|
-
minFreeBytes: 10 *
|
|
28689
|
-
criticalFreeBytes: 2 *
|
|
28804
|
+
minFreeBytes: 10 * GIB2,
|
|
28805
|
+
criticalFreeBytes: 2 * GIB2,
|
|
28690
28806
|
buildCachePrune: true,
|
|
28691
28807
|
runnerImageRetentionDays: 14,
|
|
28692
28808
|
intervalMs: 60 * 60 * 1e3
|
|
@@ -28708,16 +28824,16 @@ function resolveDiskGuardPolicy(source = process.env) {
|
|
|
28708
28824
|
const minFreeBytes = numberFromEnv(
|
|
28709
28825
|
source,
|
|
28710
28826
|
"AGLIO_DISK_MIN_FREE_GB",
|
|
28711
|
-
DISK_GUARD_DEFAULTS.minFreeBytes /
|
|
28827
|
+
DISK_GUARD_DEFAULTS.minFreeBytes / GIB2,
|
|
28712
28828
|
0
|
|
28713
|
-
) *
|
|
28829
|
+
) * GIB2;
|
|
28714
28830
|
const criticalFreeBytes = Math.min(
|
|
28715
28831
|
numberFromEnv(
|
|
28716
28832
|
source,
|
|
28717
28833
|
"AGLIO_DISK_CRITICAL_FREE_GB",
|
|
28718
|
-
DISK_GUARD_DEFAULTS.criticalFreeBytes /
|
|
28834
|
+
DISK_GUARD_DEFAULTS.criticalFreeBytes / GIB2,
|
|
28719
28835
|
0
|
|
28720
|
-
) *
|
|
28836
|
+
) * GIB2,
|
|
28721
28837
|
// A critical threshold above the low threshold would make "low" unreachable.
|
|
28722
28838
|
minFreeBytes
|
|
28723
28839
|
);
|
|
@@ -28888,7 +29004,7 @@ async function cleanupDockerDisk(input2) {
|
|
|
28888
29004
|
input2.log?.("docker disk cleanup", {
|
|
28889
29005
|
status: result.status,
|
|
28890
29006
|
pressure,
|
|
28891
|
-
freeGb: input2.disk ? Number((input2.disk.freeBytes /
|
|
29007
|
+
freeGb: input2.disk ? Number((input2.disk.freeBytes / GIB2).toFixed(1)) : null,
|
|
28892
29008
|
reclaimedMb: Math.round(result.spaceReclaimedBytes / (1024 * 1024)),
|
|
28893
29009
|
danglingImages: result.danglingImagesRemoved,
|
|
28894
29010
|
runnerImages: result.runnerImagesRemoved,
|
|
@@ -43835,6 +43951,15 @@ async function main() {
|
|
|
43835
43951
|
);
|
|
43836
43952
|
const hostTools = await verifyHostRuntime({ mode, labels, platform: process.platform });
|
|
43837
43953
|
if (hostTools.length > 0) console.log(`[worker-agent] host tools ${hostTools.join(" | ")}`);
|
|
43954
|
+
const agentResources = mode === "docker" ? await resolveRemoteAgentResources(
|
|
43955
|
+
remoteDockerClient(dockerSocket),
|
|
43956
|
+
(message, extra) => console.log(`[worker-agent] ${message}`, extra ?? "")
|
|
43957
|
+
) : void 0;
|
|
43958
|
+
if (agentResources) {
|
|
43959
|
+
console.log(
|
|
43960
|
+
`[worker-agent] agent resources cpu=${agentResources.cpu} (${agentResources.cpuSource}) memoryBytes=${agentResources.memoryBytes} (${agentResources.memorySource})`
|
|
43961
|
+
);
|
|
43962
|
+
}
|
|
43838
43963
|
if (mode === "docker") {
|
|
43839
43964
|
void prefetchRunnerImage({
|
|
43840
43965
|
image: runnerImage,
|
|
@@ -43858,6 +43983,7 @@ async function main() {
|
|
|
43858
43983
|
// Only the bridge fallback needs a host gateway. Docker Desktop
|
|
43859
43984
|
// resolves host.docker.internal already; Linux needs the entry.
|
|
43860
43985
|
extraHosts: runnerExtraHosts,
|
|
43986
|
+
resources: agentResources,
|
|
43861
43987
|
log: (message, extra) => console.log(`[worker-agent] ${message}`, extra ?? "")
|
|
43862
43988
|
}) : void 0
|
|
43863
43989
|
});
|