|
|
@@ -95,6 +95,11 @@ def _check_implicit_terminate(thought: str) -> bool:
|
|
|
|
|
|
_MAX_STATE_WINDOW = 3 # Keep last N steps in full
|
|
|
_MAX_OBS_LENGTH = 3000 # Truncate observations (800 was too small, causing retry loops)
|
|
|
+# Session 模式(claude-code --resume)下,最近一次工具观测值会原样成为下一次
|
|
|
+# resume 的 prompt。一个大文件 dump(如 ReadFile 整文件)会把 prompt 撑到上万字符,
|
|
|
+# 触发 claude-code 首字节卡死(实测 prompt=19896 → 45s STALL)。这里给 session 观测
|
|
|
+# 一个上限:足够大(保留充分上下文),但封顶让单个巨型工具结果无法卡死会话。
|
|
|
+_MAX_SESSION_OBS_LENGTH = 8000
|
|
|
_MAX_THOUGHT_LENGTH = 500 # Truncate thoughts in history
|
|
|
|
|
|
|
|
|
@@ -1204,8 +1209,21 @@ def _compile_react(cfg: Dict, overrides: Dict) -> Term:
|
|
|
_consecutive_failures.pop(tool_name, None)
|
|
|
|
|
|
# ── Phase 5: Prepare next state ──
|
|
|
- # Store observation for session-resume mode
|
|
|
- _last_observation[0] = f"Tool: {tool_name}\nResult:\n{observation}{give_up_hint}"
|
|
|
+ # Store observation for session-resume mode. CAP it in session mode:
|
|
|
+ # this obs becomes the NEXT resume prompt as-is, so a 20K-char file dump
|
|
|
+ # balloons the prompt and wedges claude-code's first byte (observed
|
|
|
+ # prompt=19896 → 45s stall). Truncate so one huge tool result can't stall
|
|
|
+ # the session; the agent can re-read specific ranges via ReadFile
|
|
|
+ # offset/limit. Stateless mode is unaffected (state goes through
|
|
|
+ # _compress_state's own truncation).
|
|
|
+ _obs_for_session = observation
|
|
|
+ if _has_session and len(_obs_for_session) > _MAX_SESSION_OBS_LENGTH:
|
|
|
+ _obs_for_session = (
|
|
|
+ _obs_for_session[:_MAX_SESSION_OBS_LENGTH]
|
|
|
+ + f"\n... [已截断,工具结果共 {len(observation)} 字符。如需更多,"
|
|
|
+ f"请用 ReadFile 的 offset/limit 读取具体片段,不要整篇重读]"
|
|
|
+ )
|
|
|
+ _last_observation[0] = f"Tool: {tool_name}\nResult:\n{_obs_for_session}{give_up_hint}"
|
|
|
|
|
|
# Return state with step marker (for stop_condition detection)
|
|
|
# observation_with_hint preserves the give-up SYSTEM message so the
|