code: def start_experiment(
      action: Literal["create", "resume", "view"],
      exp_id: str,
      config: ExperimentConfig,
      port: int,
      debug: bool,
      run_mode: RunMode,
      url_prefix: str | None,
      tuner_command_channel: str | None = None,
      tags: list[str] = [],
  ) -> Popen:
      foreground = run_mode.value == "foreground"
      if url_prefix is not None:
          url_prefix = url_prefix.strip("/")
      nni_manager_args = NniManagerArgs(
          action,
          exp_id,
          config,
          port,
          debug,
          foreground,
          url_prefix,
          tuner_command_channel,
      )
  
      _ensure_port_idle(port)
      websocket_platforms = [
          "hybrid",
          "remote",
          "openpai",
          "kubeflow",
          "frameworkcontroller",
          "adl",
      ]
      if (
          action != "view"
          and nni_manager_args.mode in websocket_platforms
      ):
          _ensure_port_idle(
              port + 1,
              f"{nni_manager_args.mode} requires an additional port",
          )
  
      link = Path(config.experiment_working_directory, "_latest")
      try:
          if link.exists():
              link.unlink()
          link.symlink_to(exp_id, target_is_directory=True)
      except Exception:
          if sys.platform != "win32":
              _logger.warning(f"Failed to create link {link}")
  
      proc = None
      try:
          _logger.info(
              "Creating experiment, Experiment ID: ${CYAN}%s", exp_id
          )
          proc = _start_rest_server(nni_manager_args, run_mode)
          start_time = int(time.time() * 1000)
  
          _logger.info("Starting web server...")
          _check_rest_server(port, url_prefix=url_prefix)
  
          Experiments().add_experiment(
              exp_id,
              port,
              start_time,
              nni_manager_args.mode,
              config.experiment_name,
              pid=proc.pid,
              logDir=cast(str, config.experiment_working_directory),
              tag=tags,
              prefixUrl=url_prefix,
          )
  
          _logger.info("Setting up...")
          rest.post(port, "/experiment", config.json(), url_prefix)
  
      except Exception as e:
          _logger.error("Create experiment failed: %s", e)
          if proc is not None:
              with contextlib.suppress(Exception):
                  proc.kill()
  
          log = Path(
              nni_manager_args.experiments_directory,
              nni_manager_args.experiment_id,
              "log",
              "nnictl_stderr.log",
          )
          if log.exists():
              _logger.warning("NNI manager stderr:")
              _logger.warning(log.read_text())
  
          raise
  
      return proc
  
imports: from __future__ import annotations
  import contextlib
  from dataclasses import dataclass, fields
  from datetime import datetime
  import logging
  import os.path
  from pathlib import Path
  import socket
  from subprocess import Popen
  import sys
  import time
  from typing import Any, TYPE_CHECKING, cast
  from typing_extensions import Literal
  from .config import ExperimentConfig
  from .None import rest
  from ..tools.nnictl.config_utils import Experiments, Config
  from ..tools.nnictl.nnictl_utils import update_experiment
label_desc: Use image node_id 1 for calling a global function with example usage: start_experiment(action, exp_id, config, port, debug, run_mode, url_prefix, tuner_command_channel, tags) and returns: proc