@runuai/host 0.9.124 → 0.9.127
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/standard-image.ts +9 -0
- package/package.json +1 -1
- package/src/main.ts +42 -1
package/lib/standard-image.ts
CHANGED
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
standardImagePullCommands,
|
|
46
46
|
standardImagePullDigest,
|
|
47
47
|
} from "./standard-image-pin";
|
|
48
|
+
import { sidecarMode } from "./sidecar";
|
|
48
49
|
|
|
49
50
|
/** Pinned, host-wide constants (must match task-up.sh and the compose gen). */
|
|
50
51
|
export const STANDARD_IMAGE_TAG = "uai-standard:dev";
|
|
@@ -1138,6 +1139,14 @@ function markAgentClisReady(): void {
|
|
|
1138
1139
|
export function ensureStandardImage(
|
|
1139
1140
|
opts: { maxAgeMs?: number } = {},
|
|
1140
1141
|
): Promise<StandardImageResult> {
|
|
1142
|
+
// ADR-133 sidecar mode: a task machine has no container image to keep —
|
|
1143
|
+
// its agent CLIs are baked into the machine image. Live 2026-09-10
|
|
1144
|
+
// (hostless smoke 4): task-up refused with "could not prepare the host
|
|
1145
|
+
// base image uai-standard:dev … Docker is not available".
|
|
1146
|
+
if (sidecarMode()) {
|
|
1147
|
+
markAgentClisReady();
|
|
1148
|
+
return Promise.resolve({ ok: true });
|
|
1149
|
+
}
|
|
1141
1150
|
// A task-up passes maxAgeMs: a pass that succeeded recently for the same
|
|
1142
1151
|
// engine configuration is reused instead of spending ~15 s spinning a
|
|
1143
1152
|
// maintenance container per task (live 2026-09-09: 16 s of every task
|
package/package.json
CHANGED
package/src/main.ts
CHANGED
|
@@ -243,6 +243,7 @@ import {
|
|
|
243
243
|
type TaskDiffInput,
|
|
244
244
|
type TaskDownInput,
|
|
245
245
|
type TaskLaunchInput,
|
|
246
|
+
type TaskLease,
|
|
246
247
|
type FilesOpInput,
|
|
247
248
|
engineAccountScopeFromWire,
|
|
248
249
|
isEngineAccountLabel,
|
|
@@ -1272,7 +1273,6 @@ async function connect(): Promise<void> {
|
|
|
1272
1273
|
reconnectAttempt = 0;
|
|
1273
1274
|
markConnected();
|
|
1274
1275
|
console.log(`[host-agent] connected as ${hostId}`);
|
|
1275
|
-
leaseManager?.reconnected();
|
|
1276
1276
|
setHostObsTag(hostId);
|
|
1277
1277
|
addHostBreadcrumb("bridge", "connected");
|
|
1278
1278
|
|
|
@@ -1322,6 +1322,12 @@ async function connect(): Promise<void> {
|
|
|
1322
1322
|
case "pong":
|
|
1323
1323
|
break;
|
|
1324
1324
|
case "event.resume":
|
|
1325
|
+
// ADR-133: the cloud's first frame after a verified auth. A lease
|
|
1326
|
+
// request sent any earlier lands in the bridge's pre-verdict window,
|
|
1327
|
+
// where only auth/ping/result frames survive (live 2026-09-10,
|
|
1328
|
+
// hostless smoke 5: the first request vanished, the machine sat
|
|
1329
|
+
// three minutes without credentials).
|
|
1330
|
+
leaseManager?.reconnected();
|
|
1325
1331
|
// ADR-103: the cloud named its watermark — rewind the transmit
|
|
1326
1332
|
// cursor to it (null = no state, replay nothing) and start draining.
|
|
1327
1333
|
if (resumeFallbackTimer) {
|
|
@@ -2704,6 +2710,24 @@ function expectNumberArg(args: unknown[], index: number): number {
|
|
|
2704
2710
|
return value;
|
|
2705
2711
|
}
|
|
2706
2712
|
|
|
2713
|
+
function isTaskLease(value: unknown): value is TaskLease {
|
|
2714
|
+
if (!value || typeof value !== "object") return false;
|
|
2715
|
+
const lease = value as Record<string, unknown>;
|
|
2716
|
+
const files = lease.files as Record<string, unknown> | undefined;
|
|
2717
|
+
return (
|
|
2718
|
+
typeof lease.accessKeyId === "string" &&
|
|
2719
|
+
typeof lease.secretAccessKey === "string" &&
|
|
2720
|
+
typeof lease.sessionToken === "string" &&
|
|
2721
|
+
typeof lease.expiresAt === "number" &&
|
|
2722
|
+
typeof lease.region === "string" &&
|
|
2723
|
+
!!files &&
|
|
2724
|
+
typeof files === "object" &&
|
|
2725
|
+
typeof files.bucket === "string" &&
|
|
2726
|
+
(files.orgPrefix === null || typeof files.orgPrefix === "string") &&
|
|
2727
|
+
typeof files.userPrefix === "string"
|
|
2728
|
+
);
|
|
2729
|
+
}
|
|
2730
|
+
|
|
2707
2731
|
function parseCloudFrame(data: RawData): CloudToHost | null {
|
|
2708
2732
|
let parsed: unknown;
|
|
2709
2733
|
try {
|
|
@@ -2931,6 +2955,23 @@ function parseCloudFrame(data: RawData): CloudToHost | null {
|
|
|
2931
2955
|
) {
|
|
2932
2956
|
return { kind: "mcp.op", opId: frame.opId, op: frame.op };
|
|
2933
2957
|
}
|
|
2958
|
+
// ADR-133: the cloud's answers to a sidecar's lease request. Without these
|
|
2959
|
+
// two clauses the sidecar logs "dropping unknown frame kind=lease.grant"
|
|
2960
|
+
// and the task dies after the 3-minute credentials gate.
|
|
2961
|
+
if (
|
|
2962
|
+
frame.kind === "lease.grant" &&
|
|
2963
|
+
typeof frame.opId === "string" &&
|
|
2964
|
+
isTaskLease(frame.lease)
|
|
2965
|
+
) {
|
|
2966
|
+
return { kind: "lease.grant", opId: frame.opId, lease: frame.lease };
|
|
2967
|
+
}
|
|
2968
|
+
if (
|
|
2969
|
+
frame.kind === "lease.deny" &&
|
|
2970
|
+
typeof frame.opId === "string" &&
|
|
2971
|
+
typeof frame.error === "string"
|
|
2972
|
+
) {
|
|
2973
|
+
return { kind: "lease.deny", opId: frame.opId, error: frame.error };
|
|
2974
|
+
}
|
|
2934
2975
|
// Names only — never payloads (frames can carry tokens).
|
|
2935
2976
|
console.warn(
|
|
2936
2977
|
`[host-agent] dropping unknown frame kind=${String(frame.kind)}` +
|