code: def components(
      models: Model | Sequence[Model] | dict[str, Model],
      wrap_script: bool = True,
      wrap_plot_info: bool = True,
      theme: ThemeLike = None,
  ) -> tuple[str, Any]:
      """Return HTML components to embed a Bokeh plot. The data for the plot is
      stored directly in the returned HTML.
  
      An example can be found in examples/embed/embed_multiple.py
  
      The returned components assume that BokehJS resources are **already loaded**.
      The HTML document or template in which they will be embedded needs to
      include scripts tags, either from a local URL or Bokeh's CDN (replacing
      ``x.y.z`` with the version of Bokeh you are using):
  
      .. code-block:: html
  
          <script src="https://cdn.bokeh.org/bokeh/release/bokeh-x.y.z.min.js"></script>
          <script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-x.y.z.min.js"></script>
          <script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-x.y.z.min.js"></script>
          <script src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-x.y.z.min.js"></script>
          <script src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-x.y.z.min.js"></script>
  
      Only the Bokeh core library ``bokeh-x.y.z.min.js`` is always required. The
      other scripts are optional and only need to be included if you want to use
      corresponding features:
  
      * The ``"bokeh-widgets"`` files are only necessary if you are using any of the
        :ref:`Bokeh widgets <ug_interaction_widgets>`.
      * The ``"bokeh-tables"`` files are only necessary if you are using Bokeh's
        :ref:`data tables <ug_interaction_widgets_examples_datatable>`.
      * The ``"bokeh-api"`` files are required to use the
        :ref:`BokehJS API <ug_advanced_bokehjs>` and must be loaded *after* the
        core BokehJS library.
      * The ``"bokeh-gl"`` files are required to enable
        :ref:`WebGL support <ug_output_webgl>`.
      * the ``"bokeh-mathjax"`` files are required to enable
        :ref:`MathJax support <ug_styling_mathtext>`.
  
      Args:
          models (Model|list|dict|tuple) :
              A single Model, a list/tuple of Models, or a dictionary of keys
              and Models.
  
          wrap_script (boolean, optional) :
              If True, the returned javascript is wrapped in a script tag.
              (default: True)
  
          wrap_plot_info (boolean, optional) :
              If True, returns ``<div>`` strings. Otherwise, return
              :class:`~bokeh.embed.RenderRoot` objects that can be used to build
              your own divs. (default: True)
  
          theme (Theme, optional) :
              Applies the specified theme when creating the components. If None,
              or not specified, and the supplied models constitute the full set
              of roots of a document, applies the theme of that document to the
              components. Otherwise applies the default theme.
  
      Returns:
          UTF-8 encoded *(script, div[s])* or *(raw_script, plot_info[s])*
  
      Examples:
  
          With default wrapping parameter values:
  
          .. code-block:: python
  
              components(plot)
              # => (script, plot_div)
  
              components((plot1, plot2))
              # => (script, (plot1_div, plot2_div))
  
              components({"Plot 1": plot1, "Plot 2": plot2})
              # => (script, {"Plot 1": plot1_div, "Plot 2": plot2_div})
  
      Examples:
  
          With wrapping parameters set to ``False``:
  
          .. code-block:: python
  
              components(plot, wrap_script=False, wrap_plot_info=False)
              # => (javascript, plot_root)
  
              components((plot1, plot2), wrap_script=False, wrap_plot_info=False)
              # => (javascript, (plot1_root, plot2_root))
  
              components({"Plot 1": plot1, "Plot 2": plot2}, wrap_script=False, wrap_plot_info=False)
              # => (javascript, {"Plot 1": plot1_root, "Plot 2": plot2_root})
  
      """
      # 1) Convert single items and dicts into list
      # XXX: was_single_object = isinstance(models, Model) #or isinstance(models, Document)
      was_single_object = False
  
      if isinstance(models, Model):
          was_single_object = True
          models = [models]
  
      models = _check_models_or_docs(models)  # type: ignore # XXX: this API needs to be refined
  
      # now convert dict to list, saving keys in the same order
      model_keys = None
      dict_type: type[dict[Any, Any]] = dict
      if isinstance(models, dict):
          dict_type = models.__class__
          model_keys = models.keys()
          models = list(models.values())
  
      # 2) Append models to one document. Either pre-existing or new and render
      with OutputDocumentFor(models, apply_theme=theme):
          (
              docs_json,
              [render_item],
          ) = standalone_docs_json_and_render_items(models)
  
      bundle = bundle_for_objs_and_resources(None, None)
      bundle.add(
          Script(script_for_render_items(docs_json, [render_item]))
      )
  
      script = bundle.scripts(tag=wrap_script)
  
      def div_for_root(root: RenderRoot) -> str:
          return ROOT_DIV.render(root=root, macros=MACROS)
  
      results: list[str] | list[RenderRoot]
      if wrap_plot_info:
          results = [div_for_root(root) for root in render_item.roots]
      else:
          results = list(render_item.roots)
  
      # 3) convert back to the input shape
      result: Any
      if was_single_object:
          result = results[0]
      elif model_keys is not None:
          result = dict_type(zip(model_keys, results))
      else:
          result = tuple(results)
  
      return script, result
  
imports: from __future__ import annotations
  import logging
  from typing import TYPE_CHECKING, Any, Literal, Sequence, TypedDict, Union, cast, overload
  from ..None import __version__
  from ..core.templates import AUTOLOAD_JS, AUTOLOAD_TAG, FILE, MACROS, ROOT_DIV
  from ..document.document import DEFAULT_TITLE, Document
  from ..model import Model
  from ..resources import Resources, ResourcesLike
  from ..themes import Theme
  from .bundle import Script, bundle_for_objs_and_resources
  from .elements import html_page_for_render_items, script_for_render_items
  from .util import FromCurdoc, OutputDocumentFor, RenderRoot, standalone_docs_json, standalone_docs_json_and_render_items
  from .wrappers import wrap_in_onload
label_desc: Use image node_id 8 for calling a global function with example usage: components(models, wrap_script, wrap_plot_info, theme) and returns: script,  result, ROOT_DIV