@runuai/host 0.9.65 → 0.9.66

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.
@@ -883,14 +883,21 @@ export async function detectContainerRuntime(
883
883
  appleUnavailable(preference, selectedAppleRuntime(deps) === null, deps)
884
884
  );
885
885
  }
886
- // ADR-106: prefer the bundled runtime wherever it can run — ambient
887
- // Docker existing is not a reason to skip it. A failed activation falls
888
- // through to Docker rather than degrading a machine that has one.
886
+ // ADR-119 (inverting ADR-106): a present, healthy ambient Docker/OrbStack
887
+ // daemon wins it is the battle-tested path, and `auto` must never
888
+ // migrate a machine off a working daemon it already trusts. The bundled
889
+ // runtime is the zero-dependency fallback for machines with no daemon:
890
+ // an absent/remote/unanswering Docker on a machine that never chose
891
+ // Docker is not an error to surface. One probe serves both outcomes —
892
+ // its rendered state is reused if the bundled runtime also fails.
893
+ const ambient = await detectAmbientDockerCore(preference, deps);
894
+ if (ambient.usable) return ambient.state;
889
895
  const selected = await probeAndSelectApple(preference, deps);
890
896
  if (selected !== null) return selected;
897
+ return ambient.state;
891
898
  }
892
899
 
893
- return detectAmbientDocker(preference, deps);
900
+ return (await detectAmbientDockerCore(preference, deps)).state;
894
901
  }
895
902
 
896
903
  function appleUnavailable(
@@ -915,10 +922,19 @@ function appleUnavailable(
915
922
  };
916
923
  }
917
924
 
918
- async function detectAmbientDocker(
925
+ /**
926
+ * Ambient-Docker detection. `usable: false` marks the ADR-119 fall-through
927
+ * verdicts — an absent daemon, a remote endpoint, an unresolvable context —
928
+ * so `auto` can try the bundled runtime instead of surfacing Docker's
929
+ * errors on a machine that never chose Docker, while still carrying the
930
+ * rendered state for callers that need it (explicit `docker`, and auto once
931
+ * the bundled runtime also failed). A ready selection and a pin conflict
932
+ * are both `usable: true`: neither may fall through.
933
+ */
934
+ async function detectAmbientDockerCore(
919
935
  preference: "auto" | "docker",
920
936
  deps: RuntimeDetectionDeps,
921
- ): Promise<ContainerRuntimeState> {
937
+ ): Promise<{ usable: boolean; state: ContainerRuntimeState }> {
922
938
  // A successful ambient `docker info` is not a durable selection: collapse a
923
939
  // named context to its exact local endpoint before publishing DOCKER_HOST.
924
940
  const selection =
@@ -929,24 +945,30 @@ async function detectAmbientDocker(
929
945
  : null;
930
946
  if (selection && !isLocalDockerEndpoint(selection.host)) {
931
947
  return {
932
- status: "no-runtime",
933
- preference,
934
- message:
935
- "The selected Docker endpoint is remote. " +
936
- "Uai Host requires a local Unix-socket daemon for workspace mounts and loopback tunnels. " +
937
- `Select a local Docker context, then run \`${RUNTIME_RESTART_COMMAND}\`.`,
938
- action: RUNTIME_RESTART_COMMAND,
948
+ usable: false,
949
+ state: {
950
+ status: "no-runtime",
951
+ preference,
952
+ message:
953
+ "The selected Docker endpoint is remote. " +
954
+ "Uai Host requires a local Unix-socket daemon for workspace mounts and loopback tunnels. " +
955
+ `Select a local Docker context, then run \`${RUNTIME_RESTART_COMMAND}\`.`,
956
+ action: RUNTIME_RESTART_COMMAND,
957
+ },
939
958
  };
940
959
  }
941
960
 
942
961
  if (deps.dockerInfo === undefined && selection === null) {
943
962
  return {
944
- status: "no-runtime",
945
- preference,
946
- message:
947
- "Uai Host could not resolve the selected Docker context to a local endpoint. " +
948
- `Select a local Docker context and run \`${RUNTIME_RECHECK_COMMAND}\`.`,
949
- action: RUNTIME_RECHECK_COMMAND,
963
+ usable: false,
964
+ state: {
965
+ status: "no-runtime",
966
+ preference,
967
+ message:
968
+ "Uai Host could not resolve the selected Docker context to a local endpoint. " +
969
+ `Select a local Docker context and run \`${RUNTIME_RECHECK_COMMAND}\`.`,
970
+ action: RUNTIME_RECHECK_COMMAND,
971
+ },
950
972
  };
951
973
  }
952
974
 
@@ -954,20 +976,26 @@ async function detectAmbientDocker(
954
976
  if (proof !== null) {
955
977
  if (selection) {
956
978
  if (!pinRuntime("docker", selection.host, proof.engineId)) {
957
- return pinnedRuntimeUnavailable(preference);
979
+ return { usable: true, state: pinnedRuntimeUnavailable(preference) };
958
980
  }
959
981
  }
960
- return { status: "ready", preference, provider: "docker" };
982
+ return {
983
+ usable: true,
984
+ state: { status: "ready", preference, provider: "docker" },
985
+ };
961
986
  }
962
987
  return {
963
- status: "no-runtime",
964
- preference,
965
- message:
966
- preference === "docker"
967
- ? "No working Docker runtime was found. Install or start Docker, then run " +
968
- `\`${RUNTIME_RECHECK_COMMAND}\`.`
969
- : NO_RUNTIME_MESSAGE,
970
- action: RUNTIME_RECHECK_COMMAND,
988
+ usable: false,
989
+ state: {
990
+ status: "no-runtime",
991
+ preference,
992
+ message:
993
+ preference === "docker"
994
+ ? "No working Docker runtime was found. Install or start Docker, then run " +
995
+ `\`${RUNTIME_RECHECK_COMMAND}\`.`
996
+ : NO_RUNTIME_MESSAGE,
997
+ action: RUNTIME_RECHECK_COMMAND,
998
+ },
971
999
  };
972
1000
  }
973
1001
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runuai/host",
3
- "version": "0.9.65",
3
+ "version": "0.9.66",
4
4
  "description": "Uai host — runs ephemeral AI tasks in containers on a machine you control.",
5
5
  "license": "MIT",
6
6
  "author": "Uai Tech <team@runuai.com>",