Skip to content

fix(offload): resolve session manager in assemble/afterTurn without sessionKey - #893

Open
YOMXXX wants to merge 3 commits into
TencentCloud:feat/server_teamfrom
YOMXXX:fix/878-assemble-sessionkey-fallback
Open

fix(offload): resolve session manager in assemble/afterTurn without sessionKey#893
YOMXXX wants to merge 3 commits into
TencentCloud:feat/server_teamfrom
YOMXXX:fix/878-assemble-sessionkey-fallback

Conversation

@YOMXXX

@YOMXXX YOMXXX commented Aug 9, 2026

Copy link
Copy Markdown

Fixes #878. Also addresses #880 (same root cause).

Problem

OffloadContextEngine.assemble() and afterTurn() only resolved their per-session manager when a top-level sessionKey was present. OpenClaw's afterTurn/assemble hook path passes sessionId (or sessionTarget.sessionKey) but not always sessionKey, so every turn logged:

assemble CALLED: ... sessionKey=?
assemble SKIP: no stateManager (sessionKey=none)

Since assemble() is the sole L1.5 trigger point, skipping it cascaded:

  • L1.5 never settled → MMD injection never ran (waiting for L1.5 to settle)
  • L2 scene extraction deferred forever
  • L3 compression skipped (below_mild with an unbounded context)
  • Context window grew unchecked toward the heap threshold

This is the same root cause as #862, but #862 only fixed the /compact path (compact()); the afterTurn/assemble path was left broken.

Change

Extend the stateManager fallback in both assemble() and afterTurn() to:
sessionKey → sessionId → sessionTarget?.sessionKey

mirroring the compact() resolution path (#862).

Verification

New src/offload/session-resolve.test.ts (3 tests):

  • assemble resolves manager from sessionId alone and reaches the L1.5 trigger
  • afterTurn resolves manager from sessionId alone without throwing
  • assemble skips cleanly when no session is resolvable

The first test fails on the unfixed code (judgeL15 never fires) and passes after the fix.

npm test + npm run build:plugin pass.

YOMXXX added 3 commits August 9, 2026 18:13
Issue TencentCloud#851: the plugin used to monkey-patch OpenClaw's compiled dist files
to inject event.messages into after_tool_call. The patch is removed in v2,
but the hook still gated L3 compression on classifyPatchEffectiveness() and
relied on the injected messages — on current OpenClaw versions (where
event.messages is absent) L3/MMD never ran.

- after_tool_call now fetches session messages through the official
  api.runtime.subagent.getSessionMessages({ sessionKey, limit }) when the
  event carries none
- removed the classifyPatchEffectiveness() patch check (the patch no longer
  exists)
- the handler takes an optional getSessionMessages callback, wired from the
  plugin api at registration

Fixes TencentCloud#851 (replaces the fragile dist-patch approach with the supported API)

Signed-off-by: 李冠辰 <liguanchen@xiaomi.com>
drain() invoked entry.task() directly; when a queued task threw
synchronously the call escaped before .finally() was registered,
leaving running=true forever. The queue stayed stuck, so every later
add() hung and onIdle() never resolved — silently stalling L1/L2/L3
flushes in the pipeline.

Wrap the task call in Promise.resolve().then() so the error is caught,
bookkeeping is finalized, and the next queued task runs normally.

Fixes TencentCloud#518

Signed-off-by: 李冠辰 <liguanchen@xiaomi.com>
…essionKey

OpenClaw's afterTurn/assemble path passes sessionId (or
sessionTarget.sessionKey) but not always a top-level sessionKey. The
stateManager fallback only guarded on params.sessionKey, so assemble()
returned early every turn: L1.5 never settled, MMD injection never ran,
and L2/L3 never fired (TencentCloud#878, TencentCloud#880).

Extend the fallback to sessionKey -> sessionId -> sessionTarget.sessionKey
in both assemble() and afterTurn(), mirroring the compact() fix (TencentCloud#862).

Adds a vitest suite covering: assemble resolving from sessionId only,
afterTurn resolving from sessionId only, and clean skip when no session
is resolvable.

Fixes TencentCloud#878

Signed-off-by: 李冠辰 <liguanchen@xiaomi.com>
@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.

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.

[Bug] assemble() always SKIPs: no stateManager (sessionKey=none) — context compaction never runs via afterTurn

2 participants