1"""

2 AgentOS v0.60 State Machine — Agent 生命周期状态管理。

3 状态：Idle → Thinking → Acting → Observing → (Complete|Failed|Paused)

4 含转换守卫、超时检测、恢复机制。

5"""

6

7 from __future__ import annotations

8

9 import time

10 import asyncio

11 from dataclasses import dataclass, field

12 from enum import Enum

13 from typing import Optional, Callable, Awaitable

14

15

16 class AgentState(str, Enum):

17

18 """Agent 状态枚举。"""

19

20 IDLE = "idle" # 空闲，等待任务

21 INITIALIZING = "initializing" # 加载配置/工具

22 THINKING = "thinking" # 推理/规划

23 ACTING = "acting" # 执行工具/调用模型

24 OBSERVING = "observing" # 处理工具返回/反思

25 WAITING = "waiting" # 等待外部输入(HITL)

26 PAUSED = "paused" # 手动暂停

27 COMPLETED = "completed" # 任务完成

28 FAILED = "failed" # 任务失败

29 CANCELLED = "cancelled" # 被取消

30 ERROR = "error" # 系统错误

31

32

33# 合法状态转换表

34 VALID_TRANSITIONS: dict[AgentState, set[AgentState]] = {

35 AgentState.IDLE: {AgentState.INITIALIZING, AgentState.CANCELLED},

36 AgentState.INITIALIZING: {AgentState.IDLE, AgentState.THINKING, AgentState.FAILED, AgentState.ERROR},

37 AgentState.THINKING: {AgentState.ACTING, AgentState.WAITING, AgentState.COMPLETED, AgentState.FAILED, AgentState.PAUSED, AgentState.ERROR},

38 AgentState.ACTING: {AgentState.OBSERVING, AgentState.FAILED, AgentState.ERROR},

39 AgentState.OBSERVING: {AgentState.THINKING, AgentState.ACTING, AgentState.COMPLETED, AgentState.FAILED, AgentState.ERROR},

40 AgentState.WAITING: {AgentState.THINKING, AgentState.ACTING, AgentState.CANCELLED, AgentState.PAUSED, AgentState.ERROR},

41 AgentState.PAUSED: {AgentState.THINKING, AgentState.ACTING, AgentState.OBSERVING, AgentState.CANCELLED, AgentState.ERROR},

42 AgentState.COMPLETED: set(), # 终态

43 AgentState.FAILED: {AgentState.IDLE, AgentState.ERROR},

44 AgentState.CANCELLED: {AgentState.IDLE, AgentState.ERROR},

45 AgentState.ERROR: {AgentState.IDLE, AgentState.FAILED},

46}

47

48

49@dataclass

50 class StateTransition:

51 """状态转换事件记录。"""

52

53 from_state: AgentState

54 to_state: AgentState

55 timestamp: float = field(default_factory=time.time)

56 reason: str = ""

57 metadata: dict = field(default_factory=dict)

58

59

60@dataclass

61 class StateMachineConfig:

62 """状态机运行时配置。"""

63

64 max_thinking_time: float = 300.0 # 推理超时（秒）

65 max_acting_time: float = 120.0 # 执行超时

66 max_observing_time: float = 60.0 # 观察超时

67 max_total_time: float = 3600.0 # 总超时

68 max_transitions: int = 500 # 最大状态转换次数

69 auto_recover: bool = True # 错误后自动恢复

70 max_retries_after_error: int = 3

71

72

73 class TransitionError(Exception):

74 """非法状态转换异常。"""

75

76 def __init__(self, from_state: AgentState, to_state: AgentState):

77 super().__init__(f"Invalid transition: {from_state.value} → {to_state.value}")

78 self.from_state = from_state

79 self.to_state = to_state

80

81

82 class StateTimeoutError(Exception):

83 """状态超时异常。"""

84

85 def __init__(self, state: AgentState, elapsed: float, limit: float):

86 super().__init__(f"{state.value} timeout: {elapsed:.1f}s > {limit:.1f}s")

87 self.state = state

88 self.elapsed = elapsed

89

90

91 class AgentStateMachine:

92 """Agent有限状态机，带守卫和超时检测。"""

93

94 def __init__(self, config: StateMachineConfig | None = None):

95 self.config = config or StateMachineConfig()

96 self._state: AgentState = AgentState.IDLE

97 self._history: list[StateTransition] = []

98 self._state_enter_time: float = time.time()

99 self._created_at: float = time.time()

100 self._error_count: int = 0

101 self._on_transition_hooks: dict[tuple[AgentState, AgentState], list[Callable]] = {}

102

103 @property

104 def state(self) -> AgentState:

105 return self._state

106

107 @property

108 def elapsed_total(self) -> float:

109 return time.time() - self._created_at

110

111 @property

112 def elapsed_in_state(self) -> float:

113 return time.time() - self._state_enter_time

114

115 @property

116 def history(self) -> list[StateTransition]:

117 return list(self._history)

118

119 def _guard(self, target: AgentState) -> bool:

120 """状态转换守卫。"""

121 valid = VALID_TRANSITIONS.get(self._state, set())

122 if target not in valid:

123 raise TransitionError(self._state, target)

124

125 if len(self._history) >= self.config.max_transitions:

126 raise RuntimeError(f"Max transitions ({self.config.max_transitions}) exceeded")

127

128 if self.elapsed_total >= self.config.max_total_time:

129 raise StateTimeoutError(self._state, self.elapsed_total, self.config.max_total_time)

130

131 return True

132

133 def _check_timeout(self):

134 """检查当前状态是否超时。"""

135 limits = {

136 AgentState.THINKING: self.config.max_thinking_time,

137 AgentState.ACTING: self.config.max_acting_time,

138 AgentState.OBSERVING: self.config.max_observing_time,

139 }

140 limit = limits.get(self._state)

141 if limit and self.elapsed_in_state > limit:

142 raise StateTimeoutError(self._state, self.elapsed_in_state, limit)

143

144 def transition(self, to_state: AgentState, reason: str = "",

145 metadata: dict | None = None) -> StateTransition:

146 """执行状态转换。"""

147 self._check_timeout()

148 self._guard(to_state)

149

150 transition = StateTransition(

151 from_state=self._state,

152 to_state=to_state,

153 reason=reason,

154 metadata=metadata or {},

155 )

156 self._history.append(transition)

157 self._state = to_state

158 self._state_enter_time = time.time()

159 self._fire_hooks(transition)

160 return transition

161

162 def on_transition(self, from_state: AgentState, to_state: AgentState):

163 """装饰器：注册状态转换钩子。"""

164 def decorator(fn):

165 key = (from_state, to_state)

166 self._on_transition_hooks.setdefault(key, []).append(fn)

167 return fn

168 return decorator

169

170 def _fire_hooks(self, transition: StateTransition):

171 key = (transition.from_state, transition.to_state)

172 for hook in self._on_transition_hooks.get(key, []):

173 hook(transition)

174

175 # ── 便利方法 ──────────────────────────────────────────────────────────

176

177 def start(self, reason: str = ""):

178 return self.transition(AgentState.INITIALIZING, reason)

179

180 def think(self, reason: str = ""):

181 return self.transition(AgentState.THINKING, reason)

182

183 def act(self, reason: str = ""):

184 return self.transition(AgentState.ACTING, reason)

185

186 def observe(self, reason: str = ""):

187 return self.transition(AgentState.OBSERVING, reason)

188

189 def complete(self, reason: str = ""):

190 return self.transition(AgentState.COMPLETED, reason)

191

192 def fail(self, reason: str = ""):

193 self._error_count += 1

194 return self.transition(AgentState.FAILED, reason)

195

196 def pause(self, reason: str = ""):

197 return self.transition(AgentState.PAUSED, reason)

198

199 def resume(self, reason: str = ""):

200 """从暂停恢复。"""

201 if self._state != AgentState.PAUSED:

202 raise TransitionError(self._state, AgentState.IDLE)

203 prev = self._history[-1].from_state if self._history else AgentState.IDLE

204 return self.transition(prev, reason=f"resumed: {reason}")

205

206 def cancel(self, reason: str = ""):

207 return self.transition(AgentState.CANCELLED, reason)

208

209 def error(self, reason: str = ""):

210 self._error_count += 1

211 return self.transition(AgentState.ERROR, reason)

212

213 def is_active(self) -> bool:

214 return self._state in (AgentState.THINKING, AgentState.ACTING, AgentState.OBSERVING)

215

216 def is_terminal(self) -> bool:

217 return self._state in (AgentState.COMPLETED, AgentState.FAILED, AgentState.CANCELLED)

218

219 def run_idle(self):

220 """错误/失败后回到空闲。"""

221 if self._state in (AgentState.FAILED, AgentState.CANCELLED, AgentState.ERROR):

222 return self.transition(AgentState.IDLE, "reset")

223 raise TransitionError(self._state, AgentState.IDLE)

224

225 def summary(self) -> dict:

226 return {

227 "state": self._state.value,

228 "elapsed_total": f"{self.elapsed_total:.1f}s",

229 "elapsed_in_state": f"{self.elapsed_in_state:.1f}s",

230 "transitions": len(self._history),

231 "error_count": self._error_count,

232 "is_active": self.is_active(),

233 "is_terminal": self.is_terminal(),

234 }