forked from All-Hands-AI/OpenHands
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstate.py
79 lines (72 loc) · 2.81 KB
/
state.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import base64
import pickle
from dataclasses import dataclass, field
from opendevin.controller.state.task import RootTask
from opendevin.core.logger import opendevin_logger as logger
from opendevin.core.metrics import Metrics
from opendevin.core.schema import AgentState
from opendevin.events.action import (
Action,
MessageAction,
)
from opendevin.events.observation import (
CmdOutputObservation,
Observation,
)
from opendevin.storage import get_file_store
RESUMABLE_STATES = [
AgentState.RUNNING,
AgentState.PAUSED,
AgentState.AWAITING_USER_INPUT,
AgentState.FINISHED,
]
@dataclass
class State:
root_task: RootTask = field(default_factory=RootTask)
iteration: int = 0
max_iterations: int = 100
# number of characters we have sent to and received from LLM so far for current task
num_of_chars: int = 0
background_commands_obs: list[CmdOutputObservation] = field(default_factory=list)
history: list[tuple[Action, Observation]] = field(default_factory=list)
updated_info: list[tuple[Action, Observation]] = field(default_factory=list)
inputs: dict = field(default_factory=dict)
outputs: dict = field(default_factory=dict)
error: str | None = None
agent_state: AgentState = AgentState.LOADING
resume_state: AgentState | None = None
metrics: Metrics = Metrics()
# root agent has level 0, and every delegate increases the level by one
delegate_level: int = 0
def save_to_session(self, sid: str):
fs = get_file_store()
pickled = pickle.dumps(self)
encoded = base64.b64encode(pickled).decode('utf-8')
try:
fs.write(f'sessions/{sid}/agent_state.pkl', encoded)
except Exception as e:
logger.error(f'Failed to save state to session: {e}')
raise e
@staticmethod
def restore_from_session(sid: str) -> 'State':
fs = get_file_store()
try:
encoded = fs.read(f'sessions/{sid}/agent_state.pkl')
pickled = base64.b64decode(encoded)
state = pickle.loads(pickled)
except Exception as e:
logger.error(f'Failed to restore state from session: {e}')
raise e
if state.agent_state in RESUMABLE_STATES:
state.resume_state = state.agent_state
else:
state.resume_state = None
state.agent_state = AgentState.LOADING
return state
def get_current_user_intent(self):
# TODO: this is used to understand the user's main goal, but it's possible
# the latest message is an interruption. We should look for a space where
# the agent goes to FINISHED, and then look for the next user message.
for action, obs in reversed(self.history):
if isinstance(action, MessageAction) and action.source == 'user':
return action.content