Files
openclaw/src/web/auto-reply/session-snapshot.ts
Echo c415ccaed5 feat(sessions): add channelIdleMinutes config for per-channel session idle durations (#1353)
* feat(sessions): add channelIdleMinutes config for per-channel session idle durations

Add new `channelIdleMinutes` config option to allow different session idle
timeouts per channel. For example, Discord sessions can now be configured
to last 7 days (10080 minutes) while other channels use shorter defaults.

Config example:
  sessions:
    channelIdleMinutes:
      discord: 10080  # 7 days

The channel-specific idle is passed as idleMinutesOverride to the existing
resolveSessionResetPolicy, integrating cleanly with the new reset policy
architecture.

* fix

* feat: add per-channel session reset overrides (#1353) (thanks @cash-echo-bot)

---------

Co-authored-by: Cash Williams <cashwilliams@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-01-21 19:10:31 +00:00

70 lines
2.0 KiB
TypeScript

import type { loadConfig } from "../../config/config.js";
import {
evaluateSessionFreshness,
loadSessionStore,
resolveChannelResetConfig,
resolveThreadFlag,
resolveSessionResetPolicy,
resolveSessionResetType,
resolveSessionKey,
resolveStorePath,
} from "../../config/sessions.js";
import { normalizeMainKey } from "../../routing/session-key.js";
export function getSessionSnapshot(
cfg: ReturnType<typeof loadConfig>,
from: string,
_isHeartbeat = false,
ctx?: {
sessionKey?: string | null;
isGroup?: boolean;
messageThreadId?: string | number | null;
threadLabel?: string | null;
threadStarterBody?: string | null;
parentSessionKey?: string | null;
},
) {
const sessionCfg = cfg.session;
const scope = sessionCfg?.scope ?? "per-sender";
const key =
ctx?.sessionKey?.trim() ??
resolveSessionKey(
scope,
{ From: from, To: "", Body: "" },
normalizeMainKey(sessionCfg?.mainKey),
);
const store = loadSessionStore(resolveStorePath(sessionCfg?.store));
const entry = store[key];
const isThread = resolveThreadFlag({
sessionKey: key,
messageThreadId: ctx?.messageThreadId ?? null,
threadLabel: ctx?.threadLabel ?? null,
threadStarterBody: ctx?.threadStarterBody ?? null,
parentSessionKey: ctx?.parentSessionKey ?? null,
});
const resetType = resolveSessionResetType({ sessionKey: key, isGroup: ctx?.isGroup, isThread });
const channelReset = resolveChannelResetConfig({
sessionCfg,
channel: entry?.lastChannel ?? entry?.channel,
});
const resetPolicy = resolveSessionResetPolicy({
sessionCfg,
resetType,
resetOverride: channelReset,
});
const now = Date.now();
const freshness = entry
? evaluateSessionFreshness({ updatedAt: entry.updatedAt, now, policy: resetPolicy })
: { fresh: false };
return {
key,
entry,
fresh: freshness.fresh,
resetPolicy,
resetType,
dailyResetAt: freshness.dailyResetAt,
idleExpiresAt: freshness.idleExpiresAt,
};
}