Files
clawdbot/src/commands/agent/session.ts
Peter Steinberger c379191f80 chore: migrate to oxlint and oxfmt
Co-authored-by: Christoph Nakazawa <christoph.pojer@gmail.com>
2026-01-14 15:02:19 +00:00

96 lines
2.9 KiB
TypeScript

import crypto from "node:crypto";
import type { MsgContext } from "../../auto-reply/templating.js";
import {
normalizeThinkLevel,
normalizeVerboseLevel,
type ThinkLevel,
type VerboseLevel,
} from "../../auto-reply/thinking.js";
import type { ClawdbotConfig } from "../../config/config.js";
import {
DEFAULT_IDLE_MINUTES,
loadSessionStore,
resolveAgentIdFromSessionKey,
resolveSessionKey,
resolveStorePath,
type SessionEntry,
} from "../../config/sessions.js";
import { normalizeMainKey } from "../../routing/session-key.js";
export type SessionResolution = {
sessionId: string;
sessionKey?: string;
sessionEntry?: SessionEntry;
sessionStore?: Record<string, SessionEntry>;
storePath: string;
isNewSession: boolean;
persistedThinking?: ThinkLevel;
persistedVerbose?: VerboseLevel;
};
export function resolveSession(opts: {
cfg: ClawdbotConfig;
to?: string;
sessionId?: string;
sessionKey?: string;
}): SessionResolution {
const sessionCfg = opts.cfg.session;
const scope = sessionCfg?.scope ?? "per-sender";
const mainKey = normalizeMainKey(sessionCfg?.mainKey);
const idleMinutes = Math.max(sessionCfg?.idleMinutes ?? DEFAULT_IDLE_MINUTES, 1);
const idleMs = idleMinutes * 60_000;
const explicitSessionKey = opts.sessionKey?.trim();
const storeAgentId = resolveAgentIdFromSessionKey(explicitSessionKey);
const storePath = resolveStorePath(sessionCfg?.store, {
agentId: storeAgentId,
});
const sessionStore = loadSessionStore(storePath);
const now = Date.now();
const ctx: MsgContext | undefined = opts.to?.trim() ? { From: opts.to } : undefined;
let sessionKey: string | undefined =
explicitSessionKey ?? (ctx ? resolveSessionKey(scope, ctx, mainKey) : undefined);
let sessionEntry = sessionKey ? sessionStore[sessionKey] : undefined;
// If a session id was provided, prefer to re-use its entry (by id) even when no key was derived.
if (
!explicitSessionKey &&
opts.sessionId &&
(!sessionEntry || sessionEntry.sessionId !== opts.sessionId)
) {
const foundKey = Object.keys(sessionStore).find(
(key) => sessionStore[key]?.sessionId === opts.sessionId,
);
if (foundKey) {
sessionKey = sessionKey ?? foundKey;
sessionEntry = sessionStore[foundKey];
}
}
const fresh = sessionEntry && sessionEntry.updatedAt >= now - idleMs;
const sessionId =
opts.sessionId?.trim() || (fresh ? sessionEntry?.sessionId : undefined) || crypto.randomUUID();
const isNewSession = !fresh && !opts.sessionId;
const persistedThinking =
fresh && sessionEntry?.thinkingLevel
? normalizeThinkLevel(sessionEntry.thinkingLevel)
: undefined;
const persistedVerbose =
fresh && sessionEntry?.verboseLevel
? normalizeVerboseLevel(sessionEntry.verboseLevel)
: undefined;
return {
sessionId,
sessionKey,
sessionEntry,
sessionStore,
storePath,
isNewSession,
persistedThinking,
persistedVerbose,
};
}