agent.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. from opendevin.controller import AgentController
  2. from opendevin.controller.agent import Agent
  3. from opendevin.controller.state.state import State
  4. from opendevin.core.config import AgentConfig, AppConfig, LLMConfig
  5. from opendevin.core.logger import opendevin_logger as logger
  6. from opendevin.events.stream import EventStream
  7. from opendevin.runtime import get_runtime_cls
  8. from opendevin.runtime.runtime import Runtime
  9. from opendevin.security import SecurityAnalyzer, options
  10. from opendevin.storage.files import FileStore
  11. class AgentSession:
  12. """Represents a session with an agent.
  13. Attributes:
  14. controller: The AgentController instance for controlling the agent.
  15. """
  16. sid: str
  17. event_stream: EventStream
  18. file_store: FileStore
  19. controller: AgentController | None = None
  20. runtime: Runtime | None = None
  21. security_analyzer: SecurityAnalyzer | None = None
  22. _closed: bool = False
  23. def __init__(self, sid: str, file_store: FileStore):
  24. """Initializes a new instance of the Session class."""
  25. self.sid = sid
  26. self.event_stream = EventStream(sid, file_store)
  27. self.file_store = file_store
  28. async def start(
  29. self,
  30. runtime_name: str,
  31. config: AppConfig,
  32. agent: Agent,
  33. max_iterations: int,
  34. max_budget_per_task: float | None = None,
  35. agent_to_llm_config: dict[str, LLMConfig] | None = None,
  36. agent_configs: dict[str, AgentConfig] | None = None,
  37. ):
  38. """Starts the agent session.
  39. Args:
  40. start_event: The start event data (optional).
  41. """
  42. if self.controller or self.runtime:
  43. raise Exception(
  44. 'Session already started. You need to close this session and start a new one.'
  45. )
  46. await self._create_security_analyzer(config.security.security_analyzer)
  47. await self._create_runtime(runtime_name, config, agent)
  48. await self._create_controller(
  49. agent,
  50. config.security.confirmation_mode,
  51. max_iterations,
  52. max_budget_per_task=max_budget_per_task,
  53. agent_to_llm_config=agent_to_llm_config,
  54. agent_configs=agent_configs,
  55. )
  56. async def close(self):
  57. if self._closed:
  58. return
  59. if self.controller is not None:
  60. end_state = self.controller.get_state()
  61. end_state.save_to_session(self.sid, self.file_store)
  62. await self.controller.close()
  63. if self.runtime is not None:
  64. await self.runtime.close()
  65. if self.security_analyzer is not None:
  66. await self.security_analyzer.close()
  67. self._closed = True
  68. async def _create_security_analyzer(self, security_analyzer: str | None):
  69. """Creates a SecurityAnalyzer instance that will be used to analyze the agent actions."""
  70. logger.info(f'Using security analyzer: {security_analyzer}')
  71. if security_analyzer:
  72. self.security_analyzer = options.SecurityAnalyzers.get(
  73. security_analyzer, SecurityAnalyzer
  74. )(self.event_stream)
  75. async def _create_runtime(self, runtime_name: str, config: AppConfig, agent: Agent):
  76. """Creates a runtime instance."""
  77. if self.runtime is not None:
  78. raise Exception('Runtime already created')
  79. logger.info(f'Using runtime: {runtime_name}')
  80. runtime_cls = get_runtime_cls(runtime_name)
  81. self.runtime = runtime_cls(
  82. config=config,
  83. event_stream=self.event_stream,
  84. sid=self.sid,
  85. plugins=agent.sandbox_plugins,
  86. )
  87. await self.runtime.ainit()
  88. async def _create_controller(
  89. self,
  90. agent: Agent,
  91. confirmation_mode: bool,
  92. max_iterations: int,
  93. max_budget_per_task: float | None = None,
  94. agent_to_llm_config: dict[str, LLMConfig] | None = None,
  95. agent_configs: dict[str, AgentConfig] | None = None,
  96. ):
  97. """Creates an AgentController instance."""
  98. if self.controller is not None:
  99. raise Exception('Controller already created')
  100. if self.runtime is None:
  101. raise Exception('Runtime must be initialized before the agent controller')
  102. logger.info(f'Agents: {agent_configs}')
  103. logger.info(f'Creating agent {agent.name} using LLM {agent.llm.config.model}')
  104. self.controller = AgentController(
  105. sid=self.sid,
  106. event_stream=self.event_stream,
  107. agent=agent,
  108. max_iterations=int(max_iterations),
  109. max_budget_per_task=max_budget_per_task,
  110. agent_to_llm_config=agent_to_llm_config,
  111. agent_configs=agent_configs,
  112. confirmation_mode=confirmation_mode,
  113. # AgentSession is designed to communicate with the frontend, so we don't want to
  114. # run the agent in headless mode.
  115. headless_mode=False,
  116. )
  117. try:
  118. agent_state = State.restore_from_session(self.sid, self.file_store)
  119. self.controller.set_initial_state(
  120. agent_state, max_iterations, confirmation_mode
  121. )
  122. logger.info(f'Restored agent state from session, sid: {self.sid}')
  123. except Exception as e:
  124. print('Error restoring state', e)