mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-28 12:33:34 +00:00
121 lines
3.6 KiB
TypeScript
121 lines
3.6 KiB
TypeScript
import { normalizeOptionalString } from "../../packages/normalization-core/src/string-coerce.js";
|
|
import { uniqueStrings } from "../../packages/normalization-core/src/string-normalization.js";
|
|
import type { SessionEntry } from "../config/sessions/types.js";
|
|
import { normalizeAgentId, resolveAgentIdFromSessionKey } from "../routing/session-key.js";
|
|
|
|
const SESSION_TRANSCRIPT_MEMORY_HIT_PREFIX = "transcript";
|
|
|
|
export type SessionTranscriptIdentity = {
|
|
agentId: string;
|
|
memoryKey: SessionTranscriptMemoryHitKey;
|
|
sessionId: string;
|
|
sessionKey: string;
|
|
};
|
|
|
|
export type SessionTranscriptMemoryHitIdentity = {
|
|
agentId: string;
|
|
key: SessionTranscriptMemoryHitKey;
|
|
sessionId: string;
|
|
};
|
|
|
|
export type SessionTranscriptMemoryHitKey = `transcript:${string}:${string}`;
|
|
|
|
export type SessionTranscriptReadParams = {
|
|
agentId?: string;
|
|
env?: NodeJS.ProcessEnv;
|
|
hydrateSkillPromptRefs?: boolean;
|
|
sessionId: string;
|
|
sessionKey: string;
|
|
storePath?: string;
|
|
threadId?: string | number;
|
|
};
|
|
|
|
export type SessionTranscriptMemoryHitKeyParams = {
|
|
agentId: string;
|
|
sessionId: string;
|
|
};
|
|
|
|
export type ResolveSessionTranscriptMemoryHitKeyParams = {
|
|
includeSyntheticFallback?: boolean;
|
|
key: string;
|
|
store: Record<string, SessionEntry>;
|
|
};
|
|
|
|
function requireMemoryKeySegment(value: string, label: string): string {
|
|
const normalized = normalizeOptionalString(value);
|
|
if (!normalized) {
|
|
throw new Error(`Cannot build session transcript memory hit key without ${label}.`);
|
|
}
|
|
return encodeURIComponent(normalized);
|
|
}
|
|
|
|
function decodeMemoryKeySegment(value: string): string | null {
|
|
try {
|
|
return normalizeOptionalString(decodeURIComponent(value)) ?? null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function syntheticSessionKey(identity: SessionTranscriptMemoryHitIdentity): string {
|
|
return `agent:${identity.agentId}:${identity.sessionId}`;
|
|
}
|
|
|
|
/**
|
|
* Builds the memory hit key for one session transcript.
|
|
*/
|
|
export function formatSessionTranscriptMemoryHitKey(
|
|
params: SessionTranscriptMemoryHitKeyParams,
|
|
): SessionTranscriptMemoryHitKey {
|
|
const agentId = requireMemoryKeySegment(normalizeAgentId(params.agentId), "agentId");
|
|
const sessionId = requireMemoryKeySegment(params.sessionId, "sessionId");
|
|
return `${SESSION_TRANSCRIPT_MEMORY_HIT_PREFIX}:${agentId}:${sessionId}`;
|
|
}
|
|
|
|
/**
|
|
* Parses a session transcript memory hit key.
|
|
*/
|
|
export function parseSessionTranscriptMemoryHitKey(
|
|
key: string,
|
|
): SessionTranscriptMemoryHitIdentity | null {
|
|
const parts = key.split(":");
|
|
if (parts.length !== 3 || parts[0] !== SESSION_TRANSCRIPT_MEMORY_HIT_PREFIX) {
|
|
return null;
|
|
}
|
|
const agentId = decodeMemoryKeySegment(parts[1] ?? "");
|
|
const sessionId = decodeMemoryKeySegment(parts[2] ?? "");
|
|
if (!agentId || !sessionId) {
|
|
return null;
|
|
}
|
|
return {
|
|
agentId: normalizeAgentId(agentId),
|
|
key: formatSessionTranscriptMemoryHitKey({ agentId, sessionId }),
|
|
sessionId,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Maps a session transcript memory hit key back to visible session store keys.
|
|
*/
|
|
export function resolveSessionTranscriptMemoryHitKeyToSessionKeys(
|
|
params: ResolveSessionTranscriptMemoryHitKeyParams,
|
|
): string[] {
|
|
const identity = parseSessionTranscriptMemoryHitKey(params.key);
|
|
if (!identity) {
|
|
return [];
|
|
}
|
|
const matches = Object.entries(params.store)
|
|
.filter(([sessionKey, entry]) => {
|
|
return (
|
|
entry.sessionId === identity.sessionId &&
|
|
normalizeAgentId(resolveAgentIdFromSessionKey(sessionKey)) === identity.agentId
|
|
);
|
|
})
|
|
.map(([sessionKey]) => sessionKey);
|
|
const deduped = uniqueStrings(matches);
|
|
if (deduped.length > 0) {
|
|
return deduped;
|
|
}
|
|
return params.includeSyntheticFallback === false ? [] : [syntheticSessionKey(identity)];
|
|
}
|