Skip to content

fix(gateway): keep main sessions visible in active session lists#43984

Open
stim64045-spec wants to merge 2 commits intoopenclaw:mainfrom
stim64045-spec:fix/issue-43737
Open

fix(gateway): keep main sessions visible in active session lists#43984
stim64045-spec wants to merge 2 commits intoopenclaw:mainfrom
stim64045-spec:fix/issue-43737

Conversation

@stim64045-spec
Copy link
Copy Markdown
Contributor

@stim64045-spec stim64045-spec commented Mar 12, 2026

Summary

  • keep top-level agent main sessions in sessions.list even when activeMinutes hides stale conversations
  • preserve the recent-session filter for other stale sessions so the chat dropdown stays compact
  • add a regression test covering a stale main session alongside an active heartbeat session

Fixes #43737.

@openclaw-barnacle openclaw-barnacle bot added gateway Gateway runtime size: S labels Mar 12, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 12, 2026

Greptile Summary

This PR fixes a regression where the default agent's main session (agent:main:main) would disappear from the active session list when activeMinutes filtering was enabled and the session had gone stale. The fix introduces isPrimaryAgentSessionKey, which exempts all agents' main sessions from the recency cutoff so they always remain visible in the chat dropdown.

Key changes:

  • New isPrimaryAgentSessionKey helper in session-utils.ts identifies sessions whose rest segment matches the configured (or default) mainKey, as well as the legacy "global" and bare "main" key formats.
  • The activeMinutes filter in listSessionsFromStore is updated to call this helper, keeping main sessions visible regardless of age.
  • A regression test is added covering a 3-hour-old agent:main:main session that should survive alongside a fresh agent:heartbeat:main session when activeMinutes: 120 is set.

Issue identified:

  • The helper contains parsed.rest === normalizedMainKey || parsed.rest === "main". Because normalizeMainKey already returns "main" by default, the || parsed.rest === "main" branch is redundant in the normal case. However, when a user configures a custom mainKey (e.g. "primary"), the fallback silently pins every agent:X:main session from the old key layout — those sessions will never be removed by activeMinutes filtering, even after the user has fully migrated away from the default key.

Confidence Score: 3/5

  • Safe to merge for the default configuration, but carries a subtle permanent-pinning bug for users with a custom mainKey.
  • The core fix is correct and well-tested for the common case (default mainKey = "main"). The redundant || parsed.rest === "main" fallback is harmless in that default setup but becomes a real issue when cfg.session.mainKey is set to a non-default value — stale legacy sessions will bypass the activeMinutes filter indefinitely. Since the fix does not break existing behavior for the vast majority of users, it can merge, but the edge-case bug should be addressed.
  • src/gateway/session-utils.ts — specifically the isPrimaryAgentSessionKey helper, line 730.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/gateway/session-utils.ts
Line: 730

Comment:
**Stale sessions permanently pinned when custom `mainKey` is configured**

The condition `parsed.rest === normalizedMainKey || parsed.rest === "main"` has an unintended side-effect when a user configures a non-default `mainKey` (e.g. `cfg.session.mainKey = "primary"`):

- `normalizedMainKey` becomes `"primary"`
- `parsed.rest === normalizedMainKey` correctly pins `agent:X:primary` sessions
- **But** `|| parsed.rest === "main"` additionally pins any `agent:X:main` session from the old default key

This means that after a user migrates from the default `"main"` key to a custom one, their old stale `agent:X:main` sessions will be permanently exempt from `activeMinutes` filtering and will never disappear from the session list.

The fallback should only apply when no custom key has been configured:

```suggestion
  return parsed.rest === normalizedMainKey || (normalizedMainKey !== "main" ? false : parsed.rest === "main");
```

Or more simply — since `normalizeMainKey` already returns `"main"` when `cfg.session?.mainKey` is unset — the extra `|| parsed.rest === "main"` clause is entirely redundant for the default case and harmful for the custom-key case:

```suggestion
  return parsed.rest === normalizedMainKey;
```

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: 97e02ee

return false;
}
const normalizedMainKey = normalizeMainKey(cfg.session?.mainKey);
return parsed.rest === normalizedMainKey || parsed.rest === "main";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale sessions permanently pinned when custom mainKey is configured

The condition parsed.rest === normalizedMainKey || parsed.rest === "main" has an unintended side-effect when a user configures a non-default mainKey (e.g. cfg.session.mainKey = "primary"):

  • normalizedMainKey becomes "primary"
  • parsed.rest === normalizedMainKey correctly pins agent:X:primary sessions
  • But || parsed.rest === "main" additionally pins any agent:X:main session from the old default key

This means that after a user migrates from the default "main" key to a custom one, their old stale agent:X:main sessions will be permanently exempt from activeMinutes filtering and will never disappear from the session list.

The fallback should only apply when no custom key has been configured:

Suggested change
return parsed.rest === normalizedMainKey || parsed.rest === "main";
return parsed.rest === normalizedMainKey || (normalizedMainKey !== "main" ? false : parsed.rest === "main");

Or more simply — since normalizeMainKey already returns "main" when cfg.session?.mainKey is unset — the extra || parsed.rest === "main" clause is entirely redundant for the default case and harmful for the custom-key case:

Suggested change
return parsed.rest === normalizedMainKey || parsed.rest === "main";
return parsed.rest === normalizedMainKey;
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/gateway/session-utils.ts
Line: 730

Comment:
**Stale sessions permanently pinned when custom `mainKey` is configured**

The condition `parsed.rest === normalizedMainKey || parsed.rest === "main"` has an unintended side-effect when a user configures a non-default `mainKey` (e.g. `cfg.session.mainKey = "primary"`):

- `normalizedMainKey` becomes `"primary"`
- `parsed.rest === normalizedMainKey` correctly pins `agent:X:primary` sessions
- **But** `|| parsed.rest === "main"` additionally pins any `agent:X:main` session from the old default key

This means that after a user migrates from the default `"main"` key to a custom one, their old stale `agent:X:main` sessions will be permanently exempt from `activeMinutes` filtering and will never disappear from the session list.

The fallback should only apply when no custom key has been configured:

```suggestion
  return parsed.rest === normalizedMainKey || (normalizedMainKey !== "main" ? false : parsed.rest === "main");
```

Or more simply — since `normalizeMainKey` already returns `"main"` when `cfg.session?.mainKey` is unset — the extra `|| parsed.rest === "main"` clause is entirely redundant for the default case and harmful for the custom-key case:

```suggestion
  return parsed.rest === normalizedMainKey;
```

How can I resolve this? If you propose a fix, please make it concise.

@katoue

This comment was marked as spam.

@stim64045-spec
Copy link
Copy Markdown
Contributor Author

Addressed the custom mainKey edge case from review.

Updated isPrimaryAgentSessionKey so agent session keys are treated as primary only when their rest segment matches the configured normalized mainKey, while keeping the existing bare main / global handling. Added a focused regression test for the custom-mainKey filtering path.

Focused session-utils gateway tests pass on the updated branch.

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

Labels

gateway Gateway runtime size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: 'main' session is missing from the dropdown menu (only 'heartbeat' is visible)

2 participants