aglio-worker 0.13.0 → 0.22.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 +219 -49
- 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;
|
|
@@ -27378,6 +27378,20 @@ var autoClaimScheduleSchema = external_exports.object({
|
|
|
27378
27378
|
start: autoClaimTimeSchema.default("00:00"),
|
|
27379
27379
|
end: autoClaimTimeSchema.default("00:00")
|
|
27380
27380
|
}).default({ enabled: false, timezone: "UTC", days: [0, 1, 2, 3, 4, 5, 6], start: "00:00", end: "00:00" });
|
|
27381
|
+
var routingLabelsSchema = external_exports.array(external_exports.string()).max(16).superRefine((labels, ctx) => {
|
|
27382
|
+
try {
|
|
27383
|
+
validateRoutingLabels(labels);
|
|
27384
|
+
} catch (error62) {
|
|
27385
|
+
ctx.addIssue({
|
|
27386
|
+
code: "custom",
|
|
27387
|
+
message: error62 instanceof Error ? error62.message : "Invalid worker labels."
|
|
27388
|
+
});
|
|
27389
|
+
}
|
|
27390
|
+
});
|
|
27391
|
+
var cardRoutingOverrideSchema = external_exports.object({
|
|
27392
|
+
requiredWorkerLabels: routingLabelsSchema.nullable().optional(),
|
|
27393
|
+
planningRequiredWorkerLabels: routingLabelsSchema.nullable().optional()
|
|
27394
|
+
});
|
|
27381
27395
|
var projectSettingsSchema = external_exports.object({
|
|
27382
27396
|
/** Demo projects are sandbox rows: the worker never claims them and no model runs. */
|
|
27383
27397
|
demoMode: external_exports.boolean().default(false),
|
|
@@ -27402,23 +27416,20 @@ var projectSettingsSchema = external_exports.object({
|
|
|
27402
27416
|
runRetryBackoffSeconds: external_exports.number().int().min(10).max(600).default(60),
|
|
27403
27417
|
runRetryMaxBackoffSeconds: external_exports.number().int().min(60).max(3600).default(600),
|
|
27404
27418
|
notificationSound: external_exports.boolean().default(true),
|
|
27419
|
+
/** Null inherits the workspace default. True or false overrides it for this project. */
|
|
27420
|
+
requireVerificationEvidence: external_exports.boolean().nullable().default(null),
|
|
27405
27421
|
/** Slack incoming webhook for question, failure and PR-ready alerts. Null disables Slack. */
|
|
27406
27422
|
slackWebhookUrl: external_exports.string().trim().max(500).refine(isSlackWebhookUrl, "Slack webhook must be an https URL").nullable().default(null),
|
|
27407
27423
|
/** Rendered column strip: built-in columns and custom list ids. */
|
|
27408
27424
|
boardColumnOrder: external_exports.array(external_exports.string()).optional(),
|
|
27409
27425
|
/** Last repository connectivity check from Project settings or the worker gate. */
|
|
27410
27426
|
repoConnection: repoConnectionReportSchema.nullish(),
|
|
27411
|
-
/**
|
|
27412
|
-
requiredWorkerLabels:
|
|
27413
|
-
|
|
27414
|
-
|
|
27415
|
-
|
|
27416
|
-
|
|
27417
|
-
code: "custom",
|
|
27418
|
-
message: error62 instanceof Error ? error62.message : "Invalid worker labels."
|
|
27419
|
-
});
|
|
27420
|
-
}
|
|
27421
|
-
})
|
|
27427
|
+
/** Build, consult and review job labels. Empty means any worker. */
|
|
27428
|
+
requiredWorkerLabels: routingLabelsSchema.default([]),
|
|
27429
|
+
/** Planning job labels. Empty means any online worker, so planning never waits on a build machine. */
|
|
27430
|
+
planningRequiredWorkerLabels: routingLabelsSchema.default([]),
|
|
27431
|
+
/** Undefined inherits the workspace switch. True or false overrides it. */
|
|
27432
|
+
postBuildReply: external_exports.boolean().optional()
|
|
27422
27433
|
});
|
|
27423
27434
|
var repoConfigSchema = external_exports.object({
|
|
27424
27435
|
id: external_exports.string(),
|
|
@@ -27671,6 +27682,18 @@ function artifactFileName(id, label) {
|
|
|
27671
27682
|
return `${id}-${sanitizeFileName(label)}`;
|
|
27672
27683
|
}
|
|
27673
27684
|
|
|
27685
|
+
// ../../packages/shared/src/feedback.ts
|
|
27686
|
+
var FEEDBACK_TYPES = ["bug", "feature"];
|
|
27687
|
+
var FEEDBACK_MAX_ATTACHMENT_BYTES = 10 * 1024 * 1024;
|
|
27688
|
+
var FEEDBACK_RATE_WINDOW_MS = 60 * 60 * 1e3;
|
|
27689
|
+
var feedbackTypeSchema = external_exports.enum(FEEDBACK_TYPES);
|
|
27690
|
+
var feedbackInputSchema = external_exports.object({
|
|
27691
|
+
type: feedbackTypeSchema,
|
|
27692
|
+
title: external_exports.string().trim().min(5, "Title must be at least 5 characters").max(140, "Title must be 140 characters or fewer"),
|
|
27693
|
+
description: external_exports.string().trim().min(10, "Description must be at least 10 characters").max(5e3, "Description must be 5000 characters or fewer"),
|
|
27694
|
+
pageUrl: external_exports.string().trim().max(500, "Page URL must be 500 characters or fewer").refine((value) => value === "" || URL.canParse(value), "Page URL must be a valid URL").optional().default("")
|
|
27695
|
+
});
|
|
27696
|
+
|
|
27674
27697
|
// ../../packages/shared/src/providers.ts
|
|
27675
27698
|
var apiKey = (env, drivers, label = "API key") => ({
|
|
27676
27699
|
type: "api_key",
|
|
@@ -28152,10 +28175,6 @@ var cardLabelInputSchema = external_exports.object({
|
|
|
28152
28175
|
var INVITE_TTL_DAYS = 7;
|
|
28153
28176
|
var INVITE_TTL_MS = INVITE_TTL_DAYS * 24 * 60 * 60 * 1e3;
|
|
28154
28177
|
|
|
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
28178
|
// ../../packages/shared/src/workspace-settings.ts
|
|
28160
28179
|
var WORKSPACE_SETTINGS_DEFAULTS = {
|
|
28161
28180
|
allowMemberInvites: true,
|
|
@@ -28166,10 +28185,8 @@ var WORKSPACE_SETTINGS_DEFAULTS = {
|
|
|
28166
28185
|
defaultGitProvider: "github",
|
|
28167
28186
|
/** The shared workspace consultant is opt-out. Disabled hides every entry point. */
|
|
28168
28187
|
consultantEnabled: true,
|
|
28169
|
-
/**
|
|
28170
|
-
|
|
28171
|
-
/** Workspace-wide text scale. Same for every member so boards stay aligned. */
|
|
28172
|
-
themeScale: "default"
|
|
28188
|
+
/** Post the agent's exact final build message as a card comment. */
|
|
28189
|
+
postBuildReply: true
|
|
28173
28190
|
};
|
|
28174
28191
|
var workspaceSettingsSchema = external_exports.object({
|
|
28175
28192
|
allowMemberInvites: external_exports.boolean().catch(WORKSPACE_SETTINGS_DEFAULTS.allowMemberInvites),
|
|
@@ -28178,10 +28195,21 @@ var workspaceSettingsSchema = external_exports.object({
|
|
|
28178
28195
|
artifactRetentionDays: external_exports.number().int().min(0).max(3650).catch(WORKSPACE_SETTINGS_DEFAULTS.artifactRetentionDays),
|
|
28179
28196
|
defaultGitProvider: external_exports.string().optional().transform((value) => normalizeGitProvider(value)).catch(WORKSPACE_SETTINGS_DEFAULTS.defaultGitProvider),
|
|
28180
28197
|
consultantEnabled: external_exports.boolean().catch(WORKSPACE_SETTINGS_DEFAULTS.consultantEnabled),
|
|
28181
|
-
|
|
28182
|
-
themeScale: external_exports.enum(WORKSPACE_THEME_SCALES).catch(WORKSPACE_SETTINGS_DEFAULTS.themeScale)
|
|
28198
|
+
postBuildReply: external_exports.boolean().catch(WORKSPACE_SETTINGS_DEFAULTS.postBuildReply)
|
|
28183
28199
|
}).passthrough();
|
|
28184
28200
|
|
|
28201
|
+
// ../../packages/shared/src/theme.ts
|
|
28202
|
+
var THEME_ACCENT_IDS = ["default", "violet", "emerald", "amber", "rose"];
|
|
28203
|
+
var THEME_SCALES = ["compact", "default", "large"];
|
|
28204
|
+
var DEFAULT_THEME_PREFERENCES = {
|
|
28205
|
+
themeAccent: "default",
|
|
28206
|
+
themeScale: "default"
|
|
28207
|
+
};
|
|
28208
|
+
var themePreferencesSchema = external_exports.object({
|
|
28209
|
+
themeAccent: external_exports.enum(THEME_ACCENT_IDS).catch(DEFAULT_THEME_PREFERENCES.themeAccent),
|
|
28210
|
+
themeScale: external_exports.enum(THEME_SCALES).catch(DEFAULT_THEME_PREFERENCES.themeScale)
|
|
28211
|
+
});
|
|
28212
|
+
|
|
28185
28213
|
// ../../packages/shared/src/plans.ts
|
|
28186
28214
|
var PLAN_IDS = ["free", "team", "enterprise"];
|
|
28187
28215
|
var MEGABYTE = 1024 * 1024;
|
|
@@ -28250,7 +28278,7 @@ var CARD_OPEN_SIZES = ["default", "large", "fullscreen"];
|
|
|
28250
28278
|
var cardOpenSizeSchema = external_exports.enum(CARD_OPEN_SIZES);
|
|
28251
28279
|
|
|
28252
28280
|
// src/remote-docker.ts
|
|
28253
|
-
import { existsSync } from "node:fs";
|
|
28281
|
+
import { existsSync, readFileSync as readFileSync2 } from "node:fs";
|
|
28254
28282
|
import { PassThrough } from "node:stream";
|
|
28255
28283
|
import { join as join2, posix, relative, resolve } from "node:path";
|
|
28256
28284
|
import Dockerode from "dockerode";
|
|
@@ -28355,15 +28383,137 @@ async function ensureDockerImage(input2) {
|
|
|
28355
28383
|
return "pulled";
|
|
28356
28384
|
}
|
|
28357
28385
|
|
|
28386
|
+
// src/resources.ts
|
|
28387
|
+
var GIB = 1024 * 1024 * 1024;
|
|
28388
|
+
var AUTO_MEMORY_RATIO = 0.8;
|
|
28389
|
+
var MEMORY_UNITS = {
|
|
28390
|
+
"": 1,
|
|
28391
|
+
b: 1,
|
|
28392
|
+
k: 1024,
|
|
28393
|
+
kb: 1024,
|
|
28394
|
+
m: 1024 ** 2,
|
|
28395
|
+
mb: 1024 ** 2,
|
|
28396
|
+
g: 1024 ** 3,
|
|
28397
|
+
gb: 1024 ** 3,
|
|
28398
|
+
t: 1024 ** 4,
|
|
28399
|
+
tb: 1024 ** 4
|
|
28400
|
+
};
|
|
28401
|
+
var AGENT_RESOURCE_FALLBACK = {
|
|
28402
|
+
cpu: 2,
|
|
28403
|
+
memoryBytes: 4 * GIB
|
|
28404
|
+
};
|
|
28405
|
+
function invalid(variable, value, expected) {
|
|
28406
|
+
return new Error(`Invalid ${variable} value "${value}": expected ${expected}`);
|
|
28407
|
+
}
|
|
28408
|
+
function parseCpuLimit(value, variable = "AGENT_CPU_LIMIT") {
|
|
28409
|
+
const trimmed = value.trim();
|
|
28410
|
+
if (!/^\d+(?:\.\d+)?$/.test(trimmed)) {
|
|
28411
|
+
throw invalid(variable, value, "positive CPU cores such as 2 or 2.5");
|
|
28412
|
+
}
|
|
28413
|
+
const cores = Number(trimmed);
|
|
28414
|
+
if (!Number.isFinite(cores) || cores <= 0) {
|
|
28415
|
+
throw invalid(variable, value, "positive CPU cores such as 2 or 2.5");
|
|
28416
|
+
}
|
|
28417
|
+
return cores;
|
|
28418
|
+
}
|
|
28419
|
+
function parseMemoryLimit(value, variable = "AGENT_MEMORY_LIMIT") {
|
|
28420
|
+
const trimmed = value.trim().toLowerCase();
|
|
28421
|
+
const match = /^(\d+(?:\.\d+)?)\s*([bkmgt]?b?)$/.exec(trimmed);
|
|
28422
|
+
const multiplier = match ? MEMORY_UNITS[match[2] ?? ""] : void 0;
|
|
28423
|
+
const amount = match ? Number(match[1]) : Number.NaN;
|
|
28424
|
+
if (!match || multiplier === void 0 || !Number.isFinite(amount)) {
|
|
28425
|
+
throw invalid(variable, value, "bytes or a Docker-style size such as 512m, 8g, 1073741824");
|
|
28426
|
+
}
|
|
28427
|
+
const bytes = Math.round(amount * multiplier);
|
|
28428
|
+
if (bytes <= 0) {
|
|
28429
|
+
throw invalid(variable, value, "bytes or a Docker-style size such as 512m, 8g, 1073741824");
|
|
28430
|
+
}
|
|
28431
|
+
return bytes;
|
|
28432
|
+
}
|
|
28433
|
+
function cpuToNanoCpus(cpu) {
|
|
28434
|
+
return Math.round(cpu * 1e9);
|
|
28435
|
+
}
|
|
28436
|
+
function readAgentResourceOverrides(source = process.env) {
|
|
28437
|
+
const cpu = source.AGENT_CPU_LIMIT?.trim();
|
|
28438
|
+
const memory = source.AGENT_MEMORY_LIMIT?.trim();
|
|
28439
|
+
return {
|
|
28440
|
+
cpu: cpu ? parseCpuLimit(cpu) : null,
|
|
28441
|
+
memory: memory ? parseMemoryLimit(memory) : null
|
|
28442
|
+
};
|
|
28443
|
+
}
|
|
28444
|
+
function resolveAgentResources(input2) {
|
|
28445
|
+
const fallback = input2.fallback ?? AGENT_RESOURCE_FALLBACK;
|
|
28446
|
+
const hostCpu = input2.host?.cpuCount;
|
|
28447
|
+
const hostMemory = input2.host?.totalMemoryBytes;
|
|
28448
|
+
let cpu;
|
|
28449
|
+
let cpuSource;
|
|
28450
|
+
if (input2.cpu != null) {
|
|
28451
|
+
cpu = input2.cpu;
|
|
28452
|
+
cpuSource = "env";
|
|
28453
|
+
} else if (typeof hostCpu === "number" && Number.isFinite(hostCpu) && hostCpu > 0) {
|
|
28454
|
+
cpu = hostCpu;
|
|
28455
|
+
cpuSource = "auto";
|
|
28456
|
+
} else {
|
|
28457
|
+
cpu = fallback.cpu;
|
|
28458
|
+
cpuSource = "fallback";
|
|
28459
|
+
}
|
|
28460
|
+
let memoryBytes;
|
|
28461
|
+
let memorySource;
|
|
28462
|
+
if (input2.memory != null) {
|
|
28463
|
+
memoryBytes = input2.memory;
|
|
28464
|
+
memorySource = "env";
|
|
28465
|
+
} else {
|
|
28466
|
+
const detected = typeof hostMemory === "number" && Number.isFinite(hostMemory) && hostMemory > 0 ? Math.floor(hostMemory * AUTO_MEMORY_RATIO) : 0;
|
|
28467
|
+
if (detected > 0) {
|
|
28468
|
+
memoryBytes = detected;
|
|
28469
|
+
memorySource = "auto";
|
|
28470
|
+
} else {
|
|
28471
|
+
memoryBytes = fallback.memoryBytes;
|
|
28472
|
+
memorySource = "fallback";
|
|
28473
|
+
}
|
|
28474
|
+
}
|
|
28475
|
+
return { cpu, memoryBytes, nanoCpus: cpuToNanoCpus(cpu), cpuSource, memorySource };
|
|
28476
|
+
}
|
|
28477
|
+
function agentHostResources(resources) {
|
|
28478
|
+
return { Memory: resources.memoryBytes, NanoCpus: resources.nanoCpus };
|
|
28479
|
+
}
|
|
28480
|
+
|
|
28358
28481
|
// src/remote-docker.ts
|
|
28359
|
-
async function
|
|
28482
|
+
async function resolveRemoteAgentResources(client, log, overrides = readAgentResourceOverrides()) {
|
|
28483
|
+
const needsDetection = overrides.cpu == null || overrides.memory == null;
|
|
28484
|
+
const info = needsDetection ? await client.info().catch(() => null) : null;
|
|
28485
|
+
const resources = resolveAgentResources({
|
|
28486
|
+
cpu: overrides.cpu,
|
|
28487
|
+
memory: overrides.memory,
|
|
28488
|
+
host: { cpuCount: info?.NCPU, totalMemoryBytes: info?.MemTotal }
|
|
28489
|
+
});
|
|
28490
|
+
if (resources.cpuSource === "fallback" || resources.memorySource === "fallback") {
|
|
28491
|
+
log?.("remote daemon resources unavailable, using fallback 2 CPU / 4 GB", {
|
|
28492
|
+
cpuSource: resources.cpuSource,
|
|
28493
|
+
memorySource: resources.memorySource
|
|
28494
|
+
});
|
|
28495
|
+
}
|
|
28496
|
+
return resources;
|
|
28497
|
+
}
|
|
28498
|
+
async function loginCpuNanoCpus(client) {
|
|
28360
28499
|
const info = await client.info().catch(() => null);
|
|
28361
|
-
return Math.max(1, Math.min(2, Math.floor(info?.NCPU ?? 1)));
|
|
28500
|
+
return Math.max(1, Math.min(2, Math.floor(info?.NCPU ?? 1))) * 1e9;
|
|
28362
28501
|
}
|
|
28363
28502
|
var CONTAINER_WORKSPACE = "/workspace";
|
|
28364
28503
|
function isRunningInContainer() {
|
|
28365
28504
|
return existsSync("/.dockerenv") || existsSync("/run/.containerenv");
|
|
28366
28505
|
}
|
|
28506
|
+
function parseAgentContainerId(mountInfo) {
|
|
28507
|
+
const match = mountInfo.match(/containers\/([0-9a-f]{64})\/(?:hostname|hosts|resolv\.conf)/);
|
|
28508
|
+
return match?.[1] ?? null;
|
|
28509
|
+
}
|
|
28510
|
+
function readAgentContainerId() {
|
|
28511
|
+
try {
|
|
28512
|
+
return parseAgentContainerId(readFileSync2("/proc/self/mountinfo", "utf8"));
|
|
28513
|
+
} catch {
|
|
28514
|
+
return null;
|
|
28515
|
+
}
|
|
28516
|
+
}
|
|
28367
28517
|
function resolveRunnerNetworkMode(input2) {
|
|
28368
28518
|
const override = input2.override?.trim();
|
|
28369
28519
|
if (override) return override;
|
|
@@ -28405,7 +28555,7 @@ function sleep(ms) {
|
|
|
28405
28555
|
return new Promise((resolvePromise) => setTimeout(resolvePromise, ms));
|
|
28406
28556
|
}
|
|
28407
28557
|
var defaultClients = /* @__PURE__ */ new Map();
|
|
28408
|
-
function
|
|
28558
|
+
function remoteDockerClient(socketPath) {
|
|
28409
28559
|
const existing = defaultClients.get(socketPath);
|
|
28410
28560
|
if (existing) return existing;
|
|
28411
28561
|
const client = new Dockerode({ socketPath });
|
|
@@ -28413,7 +28563,7 @@ function defaultClient(socketPath) {
|
|
|
28413
28563
|
return client;
|
|
28414
28564
|
}
|
|
28415
28565
|
async function createDockerJobExecutor(input2) {
|
|
28416
|
-
const client = input2.client ??
|
|
28566
|
+
const client = input2.client ?? remoteDockerClient(input2.socketPath ?? "/var/run/docker.sock");
|
|
28417
28567
|
await ensureDockerImage({ client, image: input2.image, log: input2.log });
|
|
28418
28568
|
const { hostPath } = mapDockerWorkspace({
|
|
28419
28569
|
workspaceRoot: input2.workspaceRoot,
|
|
@@ -28437,11 +28587,11 @@ async function createDockerJobExecutor(input2) {
|
|
|
28437
28587
|
if (error62.statusCode !== 404) throw error62;
|
|
28438
28588
|
}
|
|
28439
28589
|
const networkMode = input2.networkMode?.trim() || "bridge";
|
|
28590
|
+
const resources = input2.resources ?? await resolveRemoteAgentResources(client, input2.log);
|
|
28440
28591
|
const hostConfig = {
|
|
28441
28592
|
Binds: [`${hostPath}:${CONTAINER_WORKSPACE}`],
|
|
28442
28593
|
NetworkMode: networkMode,
|
|
28443
|
-
|
|
28444
|
-
NanoCpus: await runnerCpuCount(client) * 1e9,
|
|
28594
|
+
...agentHostResources(resources),
|
|
28445
28595
|
PidsLimit: 1024,
|
|
28446
28596
|
AutoRemove: false,
|
|
28447
28597
|
Init: true,
|
|
@@ -28527,7 +28677,7 @@ async function createDockerJobExecutor(input2) {
|
|
|
28527
28677
|
};
|
|
28528
28678
|
}
|
|
28529
28679
|
async function prefetchRunnerImage(input2) {
|
|
28530
|
-
const client = input2.client ??
|
|
28680
|
+
const client = input2.client ?? remoteDockerClient(input2.socketPath ?? "/var/run/docker.sock");
|
|
28531
28681
|
try {
|
|
28532
28682
|
if (isRegistryImage(input2.image)) {
|
|
28533
28683
|
await pullDockerImage(client, input2.image);
|
|
@@ -28550,7 +28700,7 @@ async function prefetchRunnerImage(input2) {
|
|
|
28550
28700
|
}
|
|
28551
28701
|
}
|
|
28552
28702
|
async function createDockerLoginContainer(input2) {
|
|
28553
|
-
const client = new Dockerode({ socketPath: input2.socketPath ?? "/var/run/docker.sock" });
|
|
28703
|
+
const client = input2.client ?? new Dockerode({ socketPath: input2.socketPath ?? "/var/run/docker.sock" });
|
|
28554
28704
|
await ensureDockerImage({
|
|
28555
28705
|
client,
|
|
28556
28706
|
image: input2.image
|
|
@@ -28576,6 +28726,7 @@ async function createDockerLoginContainer(input2) {
|
|
|
28576
28726
|
} catch (error62) {
|
|
28577
28727
|
if (error62.statusCode !== 404) throw error62;
|
|
28578
28728
|
}
|
|
28729
|
+
const overrides = readAgentResourceOverrides();
|
|
28579
28730
|
const container = await client.createContainer({
|
|
28580
28731
|
Image: input2.image,
|
|
28581
28732
|
name,
|
|
@@ -28588,8 +28739,10 @@ async function createDockerLoginContainer(input2) {
|
|
|
28588
28739
|
Binds: [`${hostPath}:${CONTAINER_WORKSPACE}`],
|
|
28589
28740
|
NetworkMode: "bridge",
|
|
28590
28741
|
ExtraHosts: input2.extraHosts ?? [],
|
|
28591
|
-
|
|
28592
|
-
|
|
28742
|
+
// Login keeps its small legacy default and never auto-detects, but an
|
|
28743
|
+
// explicit AGENT_CPU_LIMIT / AGENT_MEMORY_LIMIT override wins.
|
|
28744
|
+
Memory: overrides.memory ?? 2 * 1024 * 1024 * 1024,
|
|
28745
|
+
NanoCpus: overrides.cpu != null ? cpuToNanoCpus(overrides.cpu) : await loginCpuNanoCpus(client),
|
|
28593
28746
|
PidsLimit: 512,
|
|
28594
28747
|
AutoRemove: false,
|
|
28595
28748
|
Init: true,
|
|
@@ -28682,11 +28835,11 @@ async function verifyHostRuntime(input2, run = defaultRunner) {
|
|
|
28682
28835
|
import { statfs } from "node:fs/promises";
|
|
28683
28836
|
import { dirname, resolve as resolve2 } from "node:path";
|
|
28684
28837
|
import Dockerode2 from "dockerode";
|
|
28685
|
-
var
|
|
28838
|
+
var GIB2 = 1024 * 1024 * 1024;
|
|
28686
28839
|
var DISK_GUARD_DEFAULTS = {
|
|
28687
28840
|
enabled: true,
|
|
28688
|
-
minFreeBytes: 10 *
|
|
28689
|
-
criticalFreeBytes: 2 *
|
|
28841
|
+
minFreeBytes: 10 * GIB2,
|
|
28842
|
+
criticalFreeBytes: 2 * GIB2,
|
|
28690
28843
|
buildCachePrune: true,
|
|
28691
28844
|
runnerImageRetentionDays: 14,
|
|
28692
28845
|
intervalMs: 60 * 60 * 1e3
|
|
@@ -28708,16 +28861,16 @@ function resolveDiskGuardPolicy(source = process.env) {
|
|
|
28708
28861
|
const minFreeBytes = numberFromEnv(
|
|
28709
28862
|
source,
|
|
28710
28863
|
"AGLIO_DISK_MIN_FREE_GB",
|
|
28711
|
-
DISK_GUARD_DEFAULTS.minFreeBytes /
|
|
28864
|
+
DISK_GUARD_DEFAULTS.minFreeBytes / GIB2,
|
|
28712
28865
|
0
|
|
28713
|
-
) *
|
|
28866
|
+
) * GIB2;
|
|
28714
28867
|
const criticalFreeBytes = Math.min(
|
|
28715
28868
|
numberFromEnv(
|
|
28716
28869
|
source,
|
|
28717
28870
|
"AGLIO_DISK_CRITICAL_FREE_GB",
|
|
28718
|
-
DISK_GUARD_DEFAULTS.criticalFreeBytes /
|
|
28871
|
+
DISK_GUARD_DEFAULTS.criticalFreeBytes / GIB2,
|
|
28719
28872
|
0
|
|
28720
|
-
) *
|
|
28873
|
+
) * GIB2,
|
|
28721
28874
|
// A critical threshold above the low threshold would make "low" unreachable.
|
|
28722
28875
|
minFreeBytes
|
|
28723
28876
|
);
|
|
@@ -28888,7 +29041,7 @@ async function cleanupDockerDisk(input2) {
|
|
|
28888
29041
|
input2.log?.("docker disk cleanup", {
|
|
28889
29042
|
status: result.status,
|
|
28890
29043
|
pressure,
|
|
28891
|
-
freeGb: input2.disk ? Number((input2.disk.freeBytes /
|
|
29044
|
+
freeGb: input2.disk ? Number((input2.disk.freeBytes / GIB2).toFixed(1)) : null,
|
|
28892
29045
|
reclaimedMb: Math.round(result.spaceReclaimedBytes / (1024 * 1024)),
|
|
28893
29046
|
danglingImages: result.danglingImagesRemoved,
|
|
28894
29047
|
runnerImages: result.runnerImagesRemoved,
|
|
@@ -30354,6 +30507,7 @@ async function runRemoteCardJob(deps) {
|
|
|
30354
30507
|
});
|
|
30355
30508
|
const exit = await runAgent(command, env);
|
|
30356
30509
|
if (deps.cancelled()) return { state: "cancelled", error: "Cancelled from the board" };
|
|
30510
|
+
await status({ finalMessage: exit.finalMessage });
|
|
30357
30511
|
if (exit.error) return { state: "failed", error: exit.error };
|
|
30358
30512
|
if (exit.sessionId) await status({ sessionId: exit.sessionId, usage: exit.usage });
|
|
30359
30513
|
if (context.card && (context.run.kind === "build" || context.run.kind === "consult")) {
|
|
@@ -30664,6 +30818,7 @@ async function runRemoteCardJob(deps) {
|
|
|
30664
30818
|
let messageSeq = 0;
|
|
30665
30819
|
let lastFlushAt = 0;
|
|
30666
30820
|
let chatMessageId = null;
|
|
30821
|
+
let finalMessage = "";
|
|
30667
30822
|
let toolCalls = 0;
|
|
30668
30823
|
let consumeQueue = Promise.resolve();
|
|
30669
30824
|
const isPlanning = context.run.kind === "planning";
|
|
@@ -30749,10 +30904,12 @@ async function runRemoteCardJob(deps) {
|
|
|
30749
30904
|
}
|
|
30750
30905
|
if (parsed.messageEnd) {
|
|
30751
30906
|
await flushAssistant(true);
|
|
30907
|
+
finalMessage = text || messageText;
|
|
30752
30908
|
messageText = "";
|
|
30753
30909
|
messageSeq += 1;
|
|
30754
30910
|
chatMessageId = null;
|
|
30755
30911
|
} else if (!parsed.assistantDelta) {
|
|
30912
|
+
finalMessage = text;
|
|
30756
30913
|
messageSeq += 1;
|
|
30757
30914
|
chatMessageId = null;
|
|
30758
30915
|
}
|
|
@@ -30807,18 +30964,20 @@ async function runRemoteCardJob(deps) {
|
|
|
30807
30964
|
});
|
|
30808
30965
|
await consumeQueue;
|
|
30809
30966
|
await flushAssistant(true);
|
|
30967
|
+
if (!finalMessage && messageText) finalMessage = messageText;
|
|
30810
30968
|
clearTimeout(timeout);
|
|
30811
30969
|
deps.signal.removeEventListener("abort", forwardAbort);
|
|
30812
|
-
if (deps.cancelled()) return { error: null, sessionId, usage: usagePatch };
|
|
30813
|
-
if (error62) return { error: error62, sessionId, usage: usagePatch };
|
|
30970
|
+
if (deps.cancelled()) return { error: null, sessionId, finalMessage, usage: usagePatch };
|
|
30971
|
+
if (error62) return { error: error62, sessionId, finalMessage, usage: usagePatch };
|
|
30814
30972
|
if (code !== 0 && !final && !timedOut) {
|
|
30815
30973
|
return {
|
|
30816
30974
|
error: stderr.trim().slice(-2e3) || `Agent exited with code ${code}`,
|
|
30817
30975
|
sessionId,
|
|
30976
|
+
finalMessage,
|
|
30818
30977
|
usage: usagePatch
|
|
30819
30978
|
};
|
|
30820
30979
|
}
|
|
30821
|
-
return { error: null, sessionId, usage: usagePatch };
|
|
30980
|
+
return { error: null, sessionId, finalMessage, usage: usagePatch };
|
|
30822
30981
|
}
|
|
30823
30982
|
}
|
|
30824
30983
|
|
|
@@ -43583,7 +43742,7 @@ function createServerForRun(run) {
|
|
|
43583
43742
|
server.registerTool(
|
|
43584
43743
|
"verification_record",
|
|
43585
43744
|
{
|
|
43586
|
-
description: "Record
|
|
43745
|
+
description: "Record verification evidence before opening a PR. Non-N/A kinds require an artifactId unless this project or its workspace made evidence optional. N/A requires a reason.",
|
|
43587
43746
|
inputSchema: {
|
|
43588
43747
|
kind: external_exports.enum(VERIFICATION_KINDS),
|
|
43589
43748
|
summary: external_exports.string().min(1).max(400),
|
|
@@ -43660,7 +43819,7 @@ function createServerForRun(run) {
|
|
|
43660
43819
|
server.registerTool(
|
|
43661
43820
|
"pr_open",
|
|
43662
43821
|
{
|
|
43663
|
-
description: "Push the branch and open a pull request for one repo. Requires verification evidence unless
|
|
43822
|
+
description: "Push the branch and open a pull request for one repo. Requires verification evidence unless this project or its workspace made evidence optional. Moves the card to review.",
|
|
43664
43823
|
inputSchema: {
|
|
43665
43824
|
repoId: external_exports.string().min(1),
|
|
43666
43825
|
branch: external_exports.string().min(1),
|
|
@@ -43786,10 +43945,11 @@ async function main() {
|
|
|
43786
43945
|
const mcpPort = Number(process.env.AGLIO_WORKER_MCP_PORT ?? 4310);
|
|
43787
43946
|
const claimTimeoutRaw = Number(process.env.AGLIO_WORKER_CLAIM_TIMEOUT_SECONDS);
|
|
43788
43947
|
const claimTimeoutSeconds = Number.isFinite(claimTimeoutRaw) && claimTimeoutRaw > 0 ? claimTimeoutRaw : void 0;
|
|
43789
|
-
const
|
|
43948
|
+
const containerized = isRunningInContainer();
|
|
43949
|
+
const agentContainerId = (containerized ? readAgentContainerId() : null) || process.env.HOSTNAME?.trim() || hostname3();
|
|
43790
43950
|
const runnerNetwork = mode === "docker" ? resolveRunnerNetworkMode({
|
|
43791
43951
|
override: process.env.AGLIO_WORKER_RUNNER_NETWORK,
|
|
43792
|
-
containerized
|
|
43952
|
+
containerized,
|
|
43793
43953
|
hostname: agentContainerId
|
|
43794
43954
|
}) : "host";
|
|
43795
43955
|
const containerMcpUrl = runnerMcpUrl({
|
|
@@ -43835,6 +43995,15 @@ async function main() {
|
|
|
43835
43995
|
);
|
|
43836
43996
|
const hostTools = await verifyHostRuntime({ mode, labels, platform: process.platform });
|
|
43837
43997
|
if (hostTools.length > 0) console.log(`[worker-agent] host tools ${hostTools.join(" | ")}`);
|
|
43998
|
+
const agentResources = mode === "docker" ? await resolveRemoteAgentResources(
|
|
43999
|
+
remoteDockerClient(dockerSocket),
|
|
44000
|
+
(message, extra) => console.log(`[worker-agent] ${message}`, extra ?? "")
|
|
44001
|
+
) : void 0;
|
|
44002
|
+
if (agentResources) {
|
|
44003
|
+
console.log(
|
|
44004
|
+
`[worker-agent] agent resources cpu=${agentResources.cpu} (${agentResources.cpuSource}) memoryBytes=${agentResources.memoryBytes} (${agentResources.memorySource})`
|
|
44005
|
+
);
|
|
44006
|
+
}
|
|
43838
44007
|
if (mode === "docker") {
|
|
43839
44008
|
void prefetchRunnerImage({
|
|
43840
44009
|
image: runnerImage,
|
|
@@ -43858,6 +44027,7 @@ async function main() {
|
|
|
43858
44027
|
// Only the bridge fallback needs a host gateway. Docker Desktop
|
|
43859
44028
|
// resolves host.docker.internal already; Linux needs the entry.
|
|
43860
44029
|
extraHosts: runnerExtraHosts,
|
|
44030
|
+
resources: agentResources,
|
|
43861
44031
|
log: (message, extra) => console.log(`[worker-agent] ${message}`, extra ?? "")
|
|
43862
44032
|
}) : void 0
|
|
43863
44033
|
});
|