Skip to content

feat: fire session reset hooks for daily and idle resets#2045

Open
BingqingLyu wants to merge 1 commit into
mainfrom
fork-pr-61675-feat-session-reset-hooks-lazy
Open

feat: fire session reset hooks for daily and idle resets#2045
BingqingLyu wants to merge 1 commit into
mainfrom
fork-pr-61675-feat-session-reset-hooks-lazy

Conversation

@BingqingLyu

@BingqingLyu BingqingLyu commented Apr 28, 2026

Copy link
Copy Markdown
Owner

Summary

Change Type (select all)

  • Bug fix
  • Feature

Scope (select all touched areas)

  • Memory / storage

Linked Issue/PR

Root Cause (if applicable)

  • Root cause: initSessionState() fires session_end/session_start plugin hooks for lazy resets but never fires triggerInternalHook or hookRunner.runBeforeReset. These only fire via emitResetCommandHooks() in commands-core.ts, which is only called for manual /new and /reset commands.
  • Missing detection / guardrail: No test asserted that internal hooks fire for lazy resets
  • Contributing context (if known): The lazy evaluation design means sessions aren't proactively killed — staleness is checked on next message arrival, a code path separate from manual commands

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
  • Target test or file: src/auto-reply/reply/session.stale-hooks.test.ts (new), src/hooks/bundled/session-memory/handler.test.ts (extended)
  • Scenario the test should lock in: Internal hook fires with action: "daily" / "idle" when session is stale; before_reset plugin hook fires for lazy resets; no double-fire on manual reset
  • Why this is the smallest reliable guardrail: Mocks triggerInternalHook and hookRunner to assert dispatch without side-effects
  • Existing test that already covers this (if any): session-hooks-context.test.ts covers session_end/session_start but not internal hooks or before_reset

User-visible / Behavior Changes

session-memory now saves session summaries on daily (4AM) and idle-timeout resets, not just manual /new and /reset. Plugin before_reset hook now fires for lazy resets, giving plugins pre-archive transcript access.

Diagram (if applicable)

Before:
[lazy reset] -> session_end + session_start hooks only

After:
[lazy reset] -> internal hook (command:daily/idle) + before_reset + session_end + session_start

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: Any
  • Runtime/container: Node.js 24
  • Integration/channel (if any): Any channel with daily or idle reset configured

Steps

  1. Configure a session with daily reset (default 4AM)
  2. Have an active session with messages before 4AM
  3. Send a message after 4AM (triggering lazy staleness detection)

Expected

  • session-memory saves a summary of the previous session
  • before_reset plugin hook fires with reason: "daily" and transcript messages

Actual (before this PR)

  • session-memory does not fire — no summary saved
  • before_reset plugin hook does not fire

Evidence

  • Failing test/log before + passing after

Human Verification (required)

  • Verified scenarios: Daily reset with stale session triggers session-memory save; idle reset triggers save; manual /new does not double-fire
  • Edge cases checked: First-ever session (no previous entry), system events (heartbeat), fresh session
  • What you did not verify: End-to-end with real LLM slug generation (mocked in tests)

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: before_reset receives the post-archive sessionFile path (after renameSync), not the original path. loadBeforeResetTranscript handles ENOENT by scanning for the latest .reset.* archived sibling.
    • Mitigation: This matches the manual reset path behavior. The stable post-archive path is intentional — it avoids racing transcript reads against the archive rename.

AI Disclosure

  • Mark as AI-assisted in the PR title or description
  • Note the degree of testing: fully tested — 10 unit tests (7 new + 3 extended) + manual daily/idle reset verification
  • Confirm: I understand what this code does and have verified the hook dispatch logic, guard conditions, and fire-and-forget patterns

🤖 AI-assisted with Claude Code

cc @vincentkoc (hooks/plugins CODEOWNER)

Wire internal hooks and before_reset plugin hook into the lazy
staleness path so they fire on daily (4AM) and idle-timeout resets,
not just manual /new and /reset commands.

Both hooks fire as fire-and-forget to avoid blocking the user's
message response (session-memory's LLM slug generation can take
up to 15s). commands-core is dynamically imported inside the
fire-and-forget block to avoid pulling its heavy dependency tree
into session.ts's static imports.

Export loadBeforeResetTranscript from commands-core for use by
session.ts. Update bundled session-memory hook registration and
filter to accept "daily" and "idle" actions.

Fixes openclaw#10142, openclaw#31266, openclaw#50891, openclaw#43524

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant