state.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import base64
  2. import pickle
  3. from dataclasses import dataclass, field
  4. from opendevin.controller.state.task import RootTask
  5. from opendevin.core.logger import opendevin_logger as logger
  6. from opendevin.core.metrics import Metrics
  7. from opendevin.core.schema import AgentState
  8. from opendevin.events.action import (
  9. Action,
  10. MessageAction,
  11. )
  12. from opendevin.events.observation import (
  13. CmdOutputObservation,
  14. Observation,
  15. )
  16. from opendevin.storage import get_file_store
  17. @dataclass
  18. class State:
  19. root_task: RootTask = field(default_factory=RootTask)
  20. iteration: int = 0
  21. max_iterations: int = 100
  22. # number of characters we have sent to and received from LLM so far for current task
  23. num_of_chars: int = 0
  24. background_commands_obs: list[CmdOutputObservation] = field(default_factory=list)
  25. history: list[tuple[Action, Observation]] = field(default_factory=list)
  26. updated_info: list[tuple[Action, Observation]] = field(default_factory=list)
  27. inputs: dict = field(default_factory=dict)
  28. outputs: dict = field(default_factory=dict)
  29. error: str | None = None
  30. agent_state: AgentState = AgentState.LOADING
  31. metrics: Metrics = Metrics()
  32. def save_to_session(self, sid: str):
  33. fs = get_file_store()
  34. pickled = pickle.dumps(self)
  35. encoded = base64.b64encode(pickled).decode('utf-8')
  36. try:
  37. fs.write(f'sessions/{sid}/agent_state.pkl', encoded)
  38. except Exception as e:
  39. logger.error(f'Failed to save state to session: {e}')
  40. raise e
  41. @staticmethod
  42. def restore_from_session(sid: str) -> 'State':
  43. fs = get_file_store()
  44. try:
  45. encoded = fs.read(f'sessions/{sid}/agent_state.pkl')
  46. pickled = base64.b64decode(encoded)
  47. state = pickle.loads(pickled)
  48. except Exception as e:
  49. logger.error(f'Failed to restore state from session: {e}')
  50. raise e
  51. return state
  52. def get_current_user_intent(self):
  53. # TODO: this is used to understand the user's main goal, but it's possible
  54. # the latest message is an interruption. We should look for a space where
  55. # the agent goes to FINISHED, and then look for the next user message.
  56. for action, obs in reversed(self.history):
  57. if isinstance(action, MessageAction) and action.source == 'user':
  58. return action.content