bootstrap.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. """Trusted deployment bootstrap for application runtimes.
  2. Factories are configured by the server operator, never by an API request. Each
  3. factory returns an object exposing ``application`` and ``services`` (or a
  4. two-item tuple with those values).
  5. """
  6. from __future__ import annotations
  7. import importlib
  8. import os
  9. from typing import Any, Callable
  10. from cyber_agent.application.runtime import (
  11. ApplicationRegistry,
  12. ApplicationRuntime,
  13. )
  14. APPLICATION_FACTORIES_ENV = "CYBER_AGENT_APPLICATION_FACTORIES"
  15. def _load_factory(reference: str) -> Callable[[], Any]:
  16. module_name, separator, attribute = reference.strip().partition(":")
  17. if not separator or not module_name or not attribute:
  18. raise ValueError(
  19. "Application factory must use the trusted module:callable form"
  20. )
  21. factory = getattr(importlib.import_module(module_name), attribute, None)
  22. if not callable(factory):
  23. raise ValueError(f"Application factory is not callable: {reference}")
  24. return factory
  25. def _components(value: Any) -> tuple[Any, Any]:
  26. if isinstance(value, tuple) and len(value) == 2:
  27. return value
  28. application = getattr(value, "application", None)
  29. services = getattr(value, "services", None)
  30. if application is None or services is None:
  31. raise ValueError(
  32. "Application factory must return (application, services) or a "
  33. "component object exposing both attributes"
  34. )
  35. return application, services
  36. def build_runtime_from_environment(
  37. *,
  38. trace_store: Any,
  39. llm_call: Callable[..., Any],
  40. utility_llm_call: Callable[..., Any] | None = None,
  41. environ: dict[str, str] | None = None,
  42. ) -> ApplicationRuntime | None:
  43. """Build one shared runtime from deployment-owned factory references."""
  44. source = os.environ if environ is None else environ
  45. configured = source.get(APPLICATION_FACTORIES_ENV, "").strip()
  46. if not configured:
  47. return None
  48. references = [item.strip() for item in configured.split(",") if item.strip()]
  49. registry = ApplicationRegistry()
  50. for reference in references:
  51. application, services = _components(_load_factory(reference)())
  52. registry.register(application, services)
  53. return ApplicationRuntime(
  54. registry=registry,
  55. trace_store=trace_store,
  56. llm_call=llm_call,
  57. utility_llm_call=utility_llm_call,
  58. )