aglio-worker 0.12.8 → 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 +162 -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;
|
|
@@ -28245,6 +28247,10 @@ var PASSWORD_RESET_TTL_SECONDS = 60 * 60;
|
|
|
28245
28247
|
var CARD_OPEN_MODES = ["popup", "page"];
|
|
28246
28248
|
var cardOpenModeSchema = external_exports.enum(CARD_OPEN_MODES);
|
|
28247
28249
|
|
|
28250
|
+
// ../../packages/shared/src/card-open-size.ts
|
|
28251
|
+
var CARD_OPEN_SIZES = ["default", "large", "fullscreen"];
|
|
28252
|
+
var cardOpenSizeSchema = external_exports.enum(CARD_OPEN_SIZES);
|
|
28253
|
+
|
|
28248
28254
|
// src/remote-docker.ts
|
|
28249
28255
|
import { existsSync } from "node:fs";
|
|
28250
28256
|
import { PassThrough } from "node:stream";
|
|
@@ -28351,10 +28357,121 @@ async function ensureDockerImage(input2) {
|
|
|
28351
28357
|
return "pulled";
|
|
28352
28358
|
}
|
|
28353
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
|
+
|
|
28354
28455
|
// src/remote-docker.ts
|
|
28355
|
-
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) {
|
|
28356
28473
|
const info = await client.info().catch(() => null);
|
|
28357
|
-
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;
|
|
28358
28475
|
}
|
|
28359
28476
|
var CONTAINER_WORKSPACE = "/workspace";
|
|
28360
28477
|
function isRunningInContainer() {
|
|
@@ -28401,7 +28518,7 @@ function sleep(ms) {
|
|
|
28401
28518
|
return new Promise((resolvePromise) => setTimeout(resolvePromise, ms));
|
|
28402
28519
|
}
|
|
28403
28520
|
var defaultClients = /* @__PURE__ */ new Map();
|
|
28404
|
-
function
|
|
28521
|
+
function remoteDockerClient(socketPath) {
|
|
28405
28522
|
const existing = defaultClients.get(socketPath);
|
|
28406
28523
|
if (existing) return existing;
|
|
28407
28524
|
const client = new Dockerode({ socketPath });
|
|
@@ -28409,7 +28526,7 @@ function defaultClient(socketPath) {
|
|
|
28409
28526
|
return client;
|
|
28410
28527
|
}
|
|
28411
28528
|
async function createDockerJobExecutor(input2) {
|
|
28412
|
-
const client = input2.client ??
|
|
28529
|
+
const client = input2.client ?? remoteDockerClient(input2.socketPath ?? "/var/run/docker.sock");
|
|
28413
28530
|
await ensureDockerImage({ client, image: input2.image, log: input2.log });
|
|
28414
28531
|
const { hostPath } = mapDockerWorkspace({
|
|
28415
28532
|
workspaceRoot: input2.workspaceRoot,
|
|
@@ -28433,11 +28550,11 @@ async function createDockerJobExecutor(input2) {
|
|
|
28433
28550
|
if (error62.statusCode !== 404) throw error62;
|
|
28434
28551
|
}
|
|
28435
28552
|
const networkMode = input2.networkMode?.trim() || "bridge";
|
|
28553
|
+
const resources = input2.resources ?? await resolveRemoteAgentResources(client, input2.log);
|
|
28436
28554
|
const hostConfig = {
|
|
28437
28555
|
Binds: [`${hostPath}:${CONTAINER_WORKSPACE}`],
|
|
28438
28556
|
NetworkMode: networkMode,
|
|
28439
|
-
|
|
28440
|
-
NanoCpus: await runnerCpuCount(client) * 1e9,
|
|
28557
|
+
...agentHostResources(resources),
|
|
28441
28558
|
PidsLimit: 1024,
|
|
28442
28559
|
AutoRemove: false,
|
|
28443
28560
|
Init: true,
|
|
@@ -28523,7 +28640,7 @@ async function createDockerJobExecutor(input2) {
|
|
|
28523
28640
|
};
|
|
28524
28641
|
}
|
|
28525
28642
|
async function prefetchRunnerImage(input2) {
|
|
28526
|
-
const client = input2.client ??
|
|
28643
|
+
const client = input2.client ?? remoteDockerClient(input2.socketPath ?? "/var/run/docker.sock");
|
|
28527
28644
|
try {
|
|
28528
28645
|
if (isRegistryImage(input2.image)) {
|
|
28529
28646
|
await pullDockerImage(client, input2.image);
|
|
@@ -28546,7 +28663,7 @@ async function prefetchRunnerImage(input2) {
|
|
|
28546
28663
|
}
|
|
28547
28664
|
}
|
|
28548
28665
|
async function createDockerLoginContainer(input2) {
|
|
28549
|
-
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" });
|
|
28550
28667
|
await ensureDockerImage({
|
|
28551
28668
|
client,
|
|
28552
28669
|
image: input2.image
|
|
@@ -28572,6 +28689,7 @@ async function createDockerLoginContainer(input2) {
|
|
|
28572
28689
|
} catch (error62) {
|
|
28573
28690
|
if (error62.statusCode !== 404) throw error62;
|
|
28574
28691
|
}
|
|
28692
|
+
const overrides = readAgentResourceOverrides();
|
|
28575
28693
|
const container = await client.createContainer({
|
|
28576
28694
|
Image: input2.image,
|
|
28577
28695
|
name,
|
|
@@ -28584,8 +28702,10 @@ async function createDockerLoginContainer(input2) {
|
|
|
28584
28702
|
Binds: [`${hostPath}:${CONTAINER_WORKSPACE}`],
|
|
28585
28703
|
NetworkMode: "bridge",
|
|
28586
28704
|
ExtraHosts: input2.extraHosts ?? [],
|
|
28587
|
-
|
|
28588
|
-
|
|
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),
|
|
28589
28709
|
PidsLimit: 512,
|
|
28590
28710
|
AutoRemove: false,
|
|
28591
28711
|
Init: true,
|
|
@@ -28678,11 +28798,11 @@ async function verifyHostRuntime(input2, run = defaultRunner) {
|
|
|
28678
28798
|
import { statfs } from "node:fs/promises";
|
|
28679
28799
|
import { dirname, resolve as resolve2 } from "node:path";
|
|
28680
28800
|
import Dockerode2 from "dockerode";
|
|
28681
|
-
var
|
|
28801
|
+
var GIB2 = 1024 * 1024 * 1024;
|
|
28682
28802
|
var DISK_GUARD_DEFAULTS = {
|
|
28683
28803
|
enabled: true,
|
|
28684
|
-
minFreeBytes: 10 *
|
|
28685
|
-
criticalFreeBytes: 2 *
|
|
28804
|
+
minFreeBytes: 10 * GIB2,
|
|
28805
|
+
criticalFreeBytes: 2 * GIB2,
|
|
28686
28806
|
buildCachePrune: true,
|
|
28687
28807
|
runnerImageRetentionDays: 14,
|
|
28688
28808
|
intervalMs: 60 * 60 * 1e3
|
|
@@ -28704,16 +28824,16 @@ function resolveDiskGuardPolicy(source = process.env) {
|
|
|
28704
28824
|
const minFreeBytes = numberFromEnv(
|
|
28705
28825
|
source,
|
|
28706
28826
|
"AGLIO_DISK_MIN_FREE_GB",
|
|
28707
|
-
DISK_GUARD_DEFAULTS.minFreeBytes /
|
|
28827
|
+
DISK_GUARD_DEFAULTS.minFreeBytes / GIB2,
|
|
28708
28828
|
0
|
|
28709
|
-
) *
|
|
28829
|
+
) * GIB2;
|
|
28710
28830
|
const criticalFreeBytes = Math.min(
|
|
28711
28831
|
numberFromEnv(
|
|
28712
28832
|
source,
|
|
28713
28833
|
"AGLIO_DISK_CRITICAL_FREE_GB",
|
|
28714
|
-
DISK_GUARD_DEFAULTS.criticalFreeBytes /
|
|
28834
|
+
DISK_GUARD_DEFAULTS.criticalFreeBytes / GIB2,
|
|
28715
28835
|
0
|
|
28716
|
-
) *
|
|
28836
|
+
) * GIB2,
|
|
28717
28837
|
// A critical threshold above the low threshold would make "low" unreachable.
|
|
28718
28838
|
minFreeBytes
|
|
28719
28839
|
);
|
|
@@ -28884,7 +29004,7 @@ async function cleanupDockerDisk(input2) {
|
|
|
28884
29004
|
input2.log?.("docker disk cleanup", {
|
|
28885
29005
|
status: result.status,
|
|
28886
29006
|
pressure,
|
|
28887
|
-
freeGb: input2.disk ? Number((input2.disk.freeBytes /
|
|
29007
|
+
freeGb: input2.disk ? Number((input2.disk.freeBytes / GIB2).toFixed(1)) : null,
|
|
28888
29008
|
reclaimedMb: Math.round(result.spaceReclaimedBytes / (1024 * 1024)),
|
|
28889
29009
|
danglingImages: result.danglingImagesRemoved,
|
|
28890
29010
|
runnerImages: result.runnerImagesRemoved,
|
|
@@ -43831,6 +43951,15 @@ async function main() {
|
|
|
43831
43951
|
);
|
|
43832
43952
|
const hostTools = await verifyHostRuntime({ mode, labels, platform: process.platform });
|
|
43833
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
|
+
}
|
|
43834
43963
|
if (mode === "docker") {
|
|
43835
43964
|
void prefetchRunnerImage({
|
|
43836
43965
|
image: runnerImage,
|
|
@@ -43854,6 +43983,7 @@ async function main() {
|
|
|
43854
43983
|
// Only the bridge fallback needs a host gateway. Docker Desktop
|
|
43855
43984
|
// resolves host.docker.internal already; Linux needs the entry.
|
|
43856
43985
|
extraHosts: runnerExtraHosts,
|
|
43986
|
+
resources: agentResources,
|
|
43857
43987
|
log: (message, extra) => console.log(`[worker-agent] ${message}`, extra ?? "")
|
|
43858
43988
|
}) : void 0
|
|
43859
43989
|
});
|