Преглед на файлове

fix(runtime): session 观测截断 — 治本 claude-code 大上下文 resume 卡死

实测根因:`_MAX_OBS_LENGTH=3000` 的截断只在 `_compress_state`(无 session 的
provider 压 state 用);claude-code **session 模式**的观测值直接进
`_last_observation[0]` 完全没截断 → 读个大文件(ReadFile 整文件)→ obs 上万字符
→ 原样成为下次 resume 的 prompt(实测 prompt=19896)→ claude-code 首字节卡死。

修:新增 `_MAX_SESSION_OBS_LENGTH=8000`,session 模式下把进 _last_observation 的
观测值封顶(超出截断 + 提示用 ReadFile offset/limit 读片段、勿整篇重读)。
单个巨型工具结果不再能卡死会话。无 session 模式不受影响(走 _compress_state)。

与前一修(45s 超时 + ConversationLam 重试)配合:截断治本(prompt 不再撑到 2 万)、
超时+重试兜底瞬时抖动。lambdagent 567 全绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
kenny67nju преди 2 месеца
родител
ревизия
5930806002
променени са 1 файла, в които са добавени 20 реда и са изтрити 2 реда
  1. 20 2
      lambdagent/src/lambdagent/fromconfig/compiler.py

+ 20 - 2
lambdagent/src/lambdagent/fromconfig/compiler.py

@@ -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