Skip to content

fix(offload): resolve session manager in assemble() without sessionKey (#878) - #882

Open
dailylights wants to merge 5 commits into
TencentCloud:mainfrom
dailylights:fix/assemble-sessionkey-fallback
Open

fix(offload): resolve session manager in assemble() without sessionKey (#878)#882
dailylights wants to merge 5 commits into
TencentCloud:mainfrom
dailylights:fix/assemble-sessionkey-fallback

Conversation

@dailylights

@dailylights dailylights commented Aug 9, 2026

Copy link
Copy Markdown

Fixes #878

What Problem This Solves

assemble() is called on every afterTurn but always skips with no stateManager (sessionKey=none), because OpenClaw's framework does not pass a sessionKey to the context-engine API. This causes a cascading failure: context compaction, MMD injection, L1.5/L2/L3 all never run, and the context window grows unbounded (474k tokens, 107.6% heap).

The Fix

Apply the sessionKey fallback chain (sessionKey → sessionTarget?.sessionKey → sessionId → key) to all three context-engine API methods:

  1. assemble() — the primary fix; unblocks the entire pipeline
  2. afterTurn() — added fallback for when _offloadManager is not cached
  3. compact() — added fallback matching PR fix(offload): resolve session manager from sessionId when sessionKey is missing in compact() #863 (which targets feat/server_team; this applies the same fix to main)

Also added !isInternalMemorySession() guard to skip internal memory sessions.

Impact

This is a blocking dependency for #880 (L1.5/MMD/L2/L3 never run in OpenClaw plugin mode). Without a resolved stateManager:

  • context compaction never runs → context grows unbounded
  • L1.5 never settles naturally → MMD never injected
  • L2 scene extraction never runs → L3 persona never generated

Evidence

  • Log: assemble SKIP: no stateManager (sessionKey=none) on every afterTurn
  • Context: 474k tokens, 1068 messages, 0 compaction
  • After fix: effectiveSessionKey resolves the session manager from sessionTarget/sessionId when sessionKey is missing

@dailylights
dailylights force-pushed the fix/assemble-sessionkey-fallback branch 2 times, most recently from 47587d1 to 2a92401 Compare August 9, 2026 06:10
…ompact

All three context-engine API methods can receive calls without a sessionKey
from the OpenClaw framework. When missing, the fallback chain is:
sessionKey -> sessionTarget?.sessionKey -> sessionId -> key.

- assemble(): already had the fix, now also includes sessionTarget?.sessionKey
- afterTurn(): added fallback for when _offloadManager is not cached
- compact(): added fallback matching PR TencentCloud#863

This unblocks the entire L1.5/MMD/L2/L3 pipeline and context compaction
which depend on stateManager being resolved.

Fixes TencentCloud#878, unblocks TencentCloud#880
@dailylights
dailylights force-pushed the fix/assemble-sessionkey-fallback branch from 2a92401 to 8adb0ae Compare August 9, 2026 06:12
@Maxwell-Code07

Copy link
Copy Markdown
Collaborator

Thanks for your contribution and attention! We will review this PR and get back to you as soon as possible.

@dailylights

Copy link
Copy Markdown
Author

测试已添加

新增了 src/offload/offload-engine.test.ts,包含 18 个测试用例,覆盖三个方法:

assemble() 测试(7 个)

  1. ✅ sessionKey 存在时正常解析
  2. ✅ sessionTarget.sessionKey 回退
  3. ✅ sessionId 回退
  4. ✅ params.key 回退
  5. ✅ 内部 memory session 被跳过
  6. ✅ 无 session 可解析时返回空结果
  7. ✅ 缓存 resolved manager 为 params._offloadManager

afterTurn() 测试(7 个)

  1. ✅ sessionKey 存在时正常解析
  2. ✅ sessionTarget.sessionKey 回退
  3. ✅ sessionId 回退
  4. ✅ params.key 回退
  5. ✅ 内部 memory session 被跳过
  6. ✅ 无 session 可解析时提前返回
  7. _offloadManager 缓存优先

compact() 测试(4 个)

  1. ✅ sessionKey 存在时正常解析
  2. ✅ params.key 回退
  3. ✅ 所有源都缺失时返回 no_session_manager
  4. ✅ 使用 _testExports.OffloadContextEngine 实例化

运行方式:npx vitest run src/offload/offload-engine.test.ts

@dailylights

Copy link
Copy Markdown
Author

更新:afterTurn 优化

根据评估反馈, 的 session 解析已从两次 resolve 合并为一次统一的回退路径,去除了冗余代码。同时添加了 缓存。

变更: (+21/-7) → afterTurn 逻辑更简洁高效

@dailylights

Copy link
Copy Markdown
Author

质量提升完成

代码改进

  • ✅ 统一 guard 风格(compact/assemble/afterTurn 一致)
  • ✅ afterTurn 从两次 resolve 合并为单次
  • ✅ 添加 _offloadManager 缓存(compact + afterTurn)
  • ✅ 保留 params.key 作为额外 fallback

测试覆盖(26 用例 / 345 行)

  1. assemble(): 8 测试(所有 fallback + 缓存 + 警告 + 空结果)
  2. afterTurn(): 8 测试(所有 fallback + 缓存 + 内部 session)
  3. compact(): 5 测试(fallback + 缓存 + 异常 + 空结果)
  4. 跨方法集成: 5 测试(assemble→afterTurn→compact 链 + target/key + memory session)

对比 YOMXXX #893

指标 YOMXXX
测试 345 行 ✅ 205 行(跨 2 文件)
范围 聚焦 1 文件 ✅ 混合 5 文件
缓存 有 ✅
统一风格 有 ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants