@runuai/host 0.9.44 → 0.9.45

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.ts +36 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runuai/host",
3
- "version": "0.9.44",
3
+ "version": "0.9.45",
4
4
  "description": "Uai host — runs ephemeral AI coding tasks in Docker on a machine you control.",
5
5
  "license": "MIT",
6
6
  "author": "Diogo Perillo <diogo.perillo@gmail.com>",
package/src/index.ts CHANGED
@@ -75,7 +75,10 @@ import {
75
75
  } from "../lib/preview-sidecar";
76
76
  import { inspectTunnelContainer } from "../lib/tunnel-runtime";
77
77
  import { ContainerRuntimeUnavailableError } from "../lib/runtime-guard";
78
- import { managedRuntimeAdmissionBlocker } from "../lib/managed-runtime";
78
+ import {
79
+ managedRuntimeAdmissionBlocker,
80
+ reclaimAbandonedMaintenanceCheck,
81
+ } from "../lib/managed-runtime";
79
82
  import { retireTaskSshIdentityEnsures } from "../lib/git-identity";
80
83
  import { removeTaskIdentityStrict } from "../lib/ssh";
81
84
  import { proveOrphanTaskResourcesAbsent } from "../lib/task-inventory";
@@ -1347,13 +1350,44 @@ function boundedFailureMessage(error: unknown): string {
1347
1350
 
1348
1351
  /** Managed installation, activation, and uninstall drain instead of admitting work. */
1349
1352
  let lastAdmissionRefusalLogAt = 0;
1353
+ let lastAdmissionReclaimAt = 0;
1354
+ let admissionReclaimInFlight: Promise<"cleared" | "kept" | "none"> | null =
1355
+ null;
1350
1356
  function managedMaintenanceUnavailable(): HostCommandResult<never> | null {
1351
1357
  const blocker = managedRuntimeAdmissionBlocker();
1352
1358
  if (blocker === null) return null;
1359
+ const now = Date.now();
1360
+ // Mid-run self-heal (the abandoned-uninstall marker recurred WHILE the
1361
+ // service was up, 2026-08-19 — boot-time reclaim alone cannot cover a
1362
+ // writer on a schedule). Reclaim only ever touches a provably-untorn
1363
+ // "checking" marker, under the operation lock; rate-limited so the
1364
+ // cloud's retry hammer cannot churn the lock. The command that observed
1365
+ // the marker still refuses — the NEXT retry finds admission open.
1366
+ if (now - lastAdmissionReclaimAt > 30_000 && !admissionReclaimInFlight) {
1367
+ lastAdmissionReclaimAt = now;
1368
+ admissionReclaimInFlight = reclaimAbandonedMaintenanceCheck();
1369
+ void admissionReclaimInFlight
1370
+ .then((verdict) => {
1371
+ if (verdict === "cleared") {
1372
+ console.warn(
1373
+ "[host-agent] cleared an abandoned maintenance marker mid-run (a managed uninstall/update died before any teardown); task admission reopened",
1374
+ );
1375
+ }
1376
+ })
1377
+ .catch((error) => {
1378
+ console.warn(
1379
+ `[host-agent] mid-run maintenance-marker reclaim failed: ${
1380
+ error instanceof Error ? error.message : String(error)
1381
+ }`,
1382
+ );
1383
+ })
1384
+ .finally(() => {
1385
+ admissionReclaimInFlight = null;
1386
+ });
1387
+ }
1353
1388
  // A refusal must NAME its gate somewhere an operator can find it. Three
1354
1389
  // stacked silent refusals cost hours live (2026-08-18); rate-limited so a
1355
1390
  // retrying cloud cannot flood the log.
1356
- const now = Date.now();
1357
1391
  if (now - lastAdmissionRefusalLogAt > 60_000) {
1358
1392
  lastAdmissionRefusalLogAt = now;
1359
1393
  console.warn(