@runuai/host 0.9.168 → 0.9.170
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/lib/agent-cli.ts +82 -4
- package/lib/agent-errors.ts +22 -0
- package/lib/agents/codex.ts +222 -41
- package/lib/agents/machine-durable.ts +8 -2
- package/lib/agents/types.ts +16 -2
- package/lib/disk-pressure.ts +42 -0
- package/lib/orchestrator.ts +72 -33
- package/lib/standard-image-cleanup.ts +117 -0
- package/lib/standard-image.ts +31 -9
- package/lib/task-environment/types.ts +20 -15
- package/lib/task-project-ops.ts +17 -7
- package/package.json +1 -1
- package/src/main.ts +17 -0
- package/src/protocol.ts +19 -0
package/lib/task-project-ops.ts
CHANGED
|
@@ -74,6 +74,7 @@ import type {
|
|
|
74
74
|
TaskProjectStatusResult,
|
|
75
75
|
} from "../src/protocol";
|
|
76
76
|
import { RUNTIME_AUTHORITY_ENV } from "./runtime-authority";
|
|
77
|
+
import { TaskEnvironmentRequestValidationError } from "./task-environment/types";
|
|
77
78
|
import type {
|
|
78
79
|
TaskEnvironmentExecRequest,
|
|
79
80
|
TaskEnvironmentExecResult,
|
|
@@ -271,7 +272,7 @@ export class TaskProjectJournalStore {
|
|
|
271
272
|
|
|
272
273
|
/**
|
|
273
274
|
* $1 staging repo path, $2 target path, $3 repo URL, $4 task branch,
|
|
274
|
-
* $5 activation id, $6 the project's fallback `.tool-versions
|
|
275
|
+
* $5 activation id, optional $6 the project's fallback `.tool-versions`.
|
|
275
276
|
* Exit 3: the target already exists. The last stdout line is the checked-out
|
|
276
277
|
* commit, or `empty` for a repository with no commits.
|
|
277
278
|
*/
|
|
@@ -684,13 +685,13 @@ export class TaskProjectOps {
|
|
|
684
685
|
}
|
|
685
686
|
|
|
686
687
|
prepare(input: TaskProjectPrepareInput): Promise<TaskProjectPrepareResult> {
|
|
687
|
-
return this.serialized(input.taskId, async () => {
|
|
688
|
-
if (!OPERATION_ID.test(input.operationId)) throw new
|
|
689
|
-
if (!SLUG.test(input.project.slug)) throw new
|
|
688
|
+
return this.serialized<TaskProjectPrepareResult>(input.taskId, async () => {
|
|
689
|
+
if (!OPERATION_ID.test(input.operationId)) throw new TaskEnvironmentRequestValidationError("invalid operation id");
|
|
690
|
+
if (!SLUG.test(input.project.slug)) throw new TaskEnvironmentRequestValidationError("invalid project slug");
|
|
690
691
|
if (!REPO_URL.test(input.project.repoUrl)) {
|
|
691
|
-
|
|
692
|
+
throw new TaskEnvironmentRequestValidationError("the repository URL is not an HTTPS or SSH Git remote");
|
|
692
693
|
}
|
|
693
|
-
if (!BRANCH.test(input.branch)) throw new
|
|
694
|
+
if (!BRANCH.test(input.branch)) throw new TaskEnvironmentRequestValidationError("invalid task branch");
|
|
694
695
|
const fenced = this.fenceFails(input);
|
|
695
696
|
if (fenced) return refused<TaskProjectPrepareResult>(fenced.reason, fenced.message);
|
|
696
697
|
|
|
@@ -728,7 +729,9 @@ export class TaskProjectOps {
|
|
|
728
729
|
input.project.repoUrl,
|
|
729
730
|
input.branch,
|
|
730
731
|
activationId,
|
|
731
|
-
|
|
732
|
+
// The provider rejects empty argv elements. The script already
|
|
733
|
+
// defaults an absent final argument to no fallback (${6:-}).
|
|
734
|
+
...(input.project.toolVersions ? [input.project.toolVersions] : []),
|
|
732
735
|
],
|
|
733
736
|
{ cwd: environment.descriptor.workspacePath, timeoutMs: TASK_PROJECT_CLONE_TIMEOUT_MS },
|
|
734
737
|
),
|
|
@@ -780,6 +783,13 @@ export class TaskProjectOps {
|
|
|
780
783
|
updatedAt: Date.now(),
|
|
781
784
|
});
|
|
782
785
|
return { outcome: "prepared", head, envSchema };
|
|
786
|
+
}).catch((error: unknown) => {
|
|
787
|
+
if (error instanceof TaskEnvironmentRequestValidationError) {
|
|
788
|
+
return refused<TaskProjectPrepareResult>("invalid_request", error.message);
|
|
789
|
+
}
|
|
790
|
+
// Provider availability, rebuilds and journal I/O remain INTERNAL so
|
|
791
|
+
// the cloud can retry them; never classify an error by its message.
|
|
792
|
+
throw error;
|
|
783
793
|
});
|
|
784
794
|
}
|
|
785
795
|
|
package/package.json
CHANGED
package/src/main.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { AssignmentDelivery, DeliveryOrigin } from "./protocol";
|
|
3
3
|
|
|
4
4
|
import "./load-env";
|
|
5
|
+
import { sampleDiskPressure } from "../lib/disk-pressure";
|
|
5
6
|
import { TASK_SECRETS_FEATURE, isTaskSecretStagingPut } from "./task-secrets";
|
|
6
7
|
import { writeTaskSecretStaging } from "../lib/task-secret-staging";
|
|
7
8
|
|
|
@@ -1473,12 +1474,28 @@ async function startLocalUi(): Promise<void> {
|
|
|
1473
1474
|
}
|
|
1474
1475
|
}
|
|
1475
1476
|
|
|
1477
|
+
// Capacity fits the existing capability/status snapshot; no new messages.
|
|
1478
|
+
let diskSnapshot: HostCapabilities["disk"];
|
|
1479
|
+
let diskSampling = false;
|
|
1480
|
+
async function refreshDiskSnapshot(): Promise<void> {
|
|
1481
|
+
if (diskSampling || sidecarMode()) return;
|
|
1482
|
+
diskSampling = true;
|
|
1483
|
+
try {
|
|
1484
|
+
diskSnapshot = await sampleDiskPressure();
|
|
1485
|
+
sendCapabilities();
|
|
1486
|
+
} finally { diskSampling = false; }
|
|
1487
|
+
}
|
|
1488
|
+
void refreshDiskSnapshot();
|
|
1489
|
+
const diskTimer = setInterval(() => void refreshDiskSnapshot(), 60_000);
|
|
1490
|
+
diskTimer.unref?.();
|
|
1491
|
+
|
|
1476
1492
|
/** Build the current host capability advertisement (ADR-021). */
|
|
1477
1493
|
function buildCapabilities(): HostCapabilities {
|
|
1478
1494
|
const runtime = containerRuntimeCapabilityState();
|
|
1479
1495
|
const projectEnvBindings = projectEnvBindingCapability();
|
|
1480
1496
|
return {
|
|
1481
1497
|
version: packageVersion(),
|
|
1498
|
+
...(diskSnapshot ? { disk: diskSnapshot } : {}),
|
|
1482
1499
|
protocolFeatures: [
|
|
1483
1500
|
"host-workspace-file-read-v1",
|
|
1484
1501
|
ASSIGNMENT_EVIDENCE_PROTOCOL_FEATURE,
|
package/src/protocol.ts
CHANGED
|
@@ -4068,6 +4068,15 @@ export function isHostConfigAckFrame(
|
|
|
4068
4068
|
* changes. The cloud caches it per hostId to drive the task-creation pickers.
|
|
4069
4069
|
*/
|
|
4070
4070
|
export interface HostCapabilities {
|
|
4071
|
+
/** Filesystem capacity, refreshed each minute. Null means unmeasurable
|
|
4072
|
+
* (for example Docker in a VM); available excludes root-reserved blocks. */
|
|
4073
|
+
disk?: {
|
|
4074
|
+
sampledAt: number;
|
|
4075
|
+
/** Cloud-only: overwritten on authenticated receipt, never trusted from the host. */
|
|
4076
|
+
receivedAt?: number;
|
|
4077
|
+
home: { totalBytes: number; availableBytes: number } | null;
|
|
4078
|
+
docker: { totalBytes: number; availableBytes: number } | null;
|
|
4079
|
+
};
|
|
4071
4080
|
/** The host-agent package version — the cloud UI shows it on the host page
|
|
4072
4081
|
* and flags when npm has a newer release. Optional (older hosts omit it). */
|
|
4073
4082
|
version?: string;
|
|
@@ -4337,6 +4346,15 @@ export interface TaskDiffInput {
|
|
|
4337
4346
|
projects: Array<{ id: string; slug: string }>;
|
|
4338
4347
|
}
|
|
4339
4348
|
|
|
4349
|
+
/** Cloud Prepare retry timing. */
|
|
4350
|
+
export const TASK_PROJECT_PREPARE_MAX_ATTEMPTS = 12;
|
|
4351
|
+
export const TASK_PROJECT_PREPARE_TIMEOUT_MS = 11 * 60_000;
|
|
4352
|
+
export function taskProjectRetryDelayMs(attempts: number): number {
|
|
4353
|
+
return Math.min(5 * 60_000, 2_000 * 2 ** Math.min(attempts, 7));
|
|
4354
|
+
}
|
|
4355
|
+
/** Bound the CLI tool call; the durable cloud operation may outlast it. */
|
|
4356
|
+
export const TASK_PROJECT_ADD_WAIT_MS = 40 * 60_000;
|
|
4357
|
+
|
|
4340
4358
|
/**
|
|
4341
4359
|
* ADR-161 §2.3: every live-project command names the task's run, the
|
|
4342
4360
|
* operation, and the project-set revision the operation commits. The runner
|
|
@@ -4362,6 +4380,7 @@ export interface TaskProjectPrepareInput extends TaskProjectOpFence {
|
|
|
4362
4380
|
/** Why a live-project command did nothing. `grant_not_installed` and
|
|
4363
4381
|
* `busy` are retryable; the rest are final for that operation. */
|
|
4364
4382
|
export type TaskProjectRefusal =
|
|
4383
|
+
| "invalid_request"
|
|
4365
4384
|
| "repo_access_denied"
|
|
4366
4385
|
| "clone_failed"
|
|
4367
4386
|
| "workspace_path_taken"
|