clawdbot-4a6: defer transcript identity api to contract

This commit is contained in:
Josh Lehman
2026-06-01 09:46:03 -07:00
parent 661dfc7d61
commit dfb367ae6b
4 changed files with 10 additions and 64 deletions

View File

@@ -1,2 +1,2 @@
612a1bd7e585b9f2ab3661137e9cf335598d4cd13e6863be88a4c29fe17a3173 plugin-sdk-api-baseline.json
50172cdfae7d3fb6b5d060be0899ca2afdc3b2adc8629e3b65a03d55755065a0 plugin-sdk-api-baseline.jsonl
5db28bde1ec593bd1aaa08d1b95b466ac79e422d7677d1ce8c64e75eb4b06eee plugin-sdk-api-baseline.json
4f308dd4bb49e9775a0499228e55103ecd7a687d382f2116b7e8ec16927bb2a3 plugin-sdk-api-baseline.jsonl

View File

@@ -148,16 +148,11 @@ export { resolveGroupSessionKey } from "../config/sessions/group.js";
export { canonicalizeMainSessionAlias } from "../config/sessions/main-session.js";
export {
clearSessionStoreCacheForTest,
cleanupSessionLifecycleArtifacts,
recordSessionMetaFromInbound,
saveSessionStore,
updateLastRoute,
updateSessionStore,
} from "../config/sessions/store.js";
export type {
SessionLifecycleArtifactCleanupParams,
SessionLifecycleArtifactCleanupResult,
} from "../config/sessions/store.js";
export {
evaluateSessionFreshness,
resolveChannelResetConfig,

View File

@@ -11,10 +11,6 @@ describe("extractTranscriptStemFromSessionsMemoryHit", () => {
expect(extractTranscriptStemFromSessionsMemoryHit("sessions/abc-uuid.jsonl")).toBe("abc-uuid");
});
it("reads storage-neutral transcript keys without basename parsing", () => {
expect(extractTranscriptStemFromSessionsMemoryHit("transcript:main:abc-uuid")).toBe("abc-uuid");
});
it("handles plain basename jsonl", () => {
expect(extractTranscriptStemFromSessionsMemoryHit("def-topic-thread.jsonl")).toBe(
"def-topic-thread",
@@ -145,16 +141,6 @@ describe("extractTranscriptStemFromSessionsMemoryHit", () => {
});
describe("extractTranscriptIdentityFromSessionsMemoryHit", () => {
it("extracts owner metadata from storage-neutral transcript keys", () => {
expect(
extractTranscriptIdentityFromSessionsMemoryHit("transcript:agent-a:session:with:colon"),
).toEqual({
stem: "session:with:colon",
ownerAgentId: "agent-a",
archived: false,
});
});
it("extracts owner metadata from agent-scoped session archive paths", () => {
expect(
extractTranscriptIdentityFromSessionsMemoryHit(
@@ -207,16 +193,6 @@ describe("resolveTranscriptStemToSessionKeys", () => {
expect(keys).toEqual(["agent:main:s1", "agent:peer:s2"]);
});
it("accepts storage-neutral entries while preserving the legacy store parameter", () => {
const entries: Record<string, SessionEntry> = {
"agent:main:s1": baseEntry({ sessionId: "sqlite-session" }),
};
expect(resolveTranscriptStemToSessionKeys({ entries, stem: "sqlite-session" })).toEqual([
"agent:main:s1",
]);
});
it("falls back to archived owner metadata when deleted archives are gone from the live store", () => {
const keys = resolveTranscriptStemToSessionKeys({
store: {},

View File

@@ -7,7 +7,6 @@ import { normalizeAgentId } from "../routing/session-key.js";
export { loadCombinedSessionStoreForGateway } from "../config/sessions/combined-store-gateway.js";
const TRANSCRIPT_KEY_PREFIX = "transcript:";
const QMD_ARCHIVE_STEM_RE = /^(.+)-jsonl-(reset|deleted)-(.+)$/;
const QMD_ARCHIVE_TIMESTAMP_RE =
/^(\d{4}-\d{2}-\d{2})[tT](\d{2}-\d{2}-\d{2})(?:(?:\.|-)(\d{3}))?[zZ]$/;
@@ -47,24 +46,7 @@ export type SessionTranscriptHitIdentity = {
archived: boolean;
};
function parseTranscriptKey(hitPath: string): { base: string; ownerAgentId?: string } | null {
if (!hitPath.startsWith(TRANSCRIPT_KEY_PREFIX)) {
return null;
}
const parts = hitPath.slice(TRANSCRIPT_KEY_PREFIX.length).split(":");
const agentId = parts.shift()?.trim();
const sessionId = parts.join(":").trim();
if (!agentId || !sessionId) {
return null;
}
return { base: sessionId, ownerAgentId: normalizeAgentId(agentId) };
}
function parseSessionsPath(hitPath: string): { base: string; ownerAgentId?: string } | null {
const transcriptKey = parseTranscriptKey(hitPath);
if (transcriptKey) {
return transcriptKey;
}
function parseSessionsPath(hitPath: string): { base: string; ownerAgentId?: string } {
const normalized = hitPath.replace(/\\/g, "/");
const fromSessionsRoot = normalized.startsWith("sessions/")
? normalized.slice("sessions/".length)
@@ -79,9 +61,10 @@ function parseSessionsPath(hitPath: string): { base: string; ownerAgentId?: stri
}
/**
* Derive transcript stem `S` from a memory search hit key for `source === "sessions"`.
* Storage-neutral hits use `transcript:<agent>:<session>`. Legacy file/QMD
* paths remain accepted so older session collections stay visibility-gated.
* Derive transcript stem `S` from a memory search hit path for `source === "sessions"`.
* Builtin index uses `sessions/<basename>.jsonl`; QMD exports use `<stem>.md`.
* Archived transcripts (`.jsonl.reset.<iso>` / `.jsonl.deleted.<iso>`) resolve
* to the same stem as the live `.jsonl` they were rotated from.
*/
export function extractTranscriptStemFromSessionsMemoryHit(hitPath: string): string | null {
return extractTranscriptIdentityFromSessionsMemoryHit(hitPath)?.stem ?? null;
@@ -91,14 +74,7 @@ export function extractTranscriptIdentityFromSessionsMemoryHit(
hitPath: string,
): SessionTranscriptHitIdentity | null {
const isQmdPath = hitPath.replace(/\\/g, "/").startsWith("qmd/");
const parsed = parseSessionsPath(hitPath);
if (!parsed) {
return null;
}
const { base, ownerAgentId } = parsed;
if (hitPath.startsWith(TRANSCRIPT_KEY_PREFIX)) {
return { stem: base, ownerAgentId, archived: false };
}
const { base, ownerAgentId } = parseSessionsPath(hitPath);
const archivedStem = parseUsageCountedSessionIdFromFileName(base);
if (archivedStem && base !== `${archivedStem}.jsonl`) {
return { stem: archivedStem, ownerAgentId, archived: true };
@@ -136,13 +112,12 @@ export function extractTranscriptIdentityFromSessionsMemoryHit(
* `createSessionVisibilityGuard`), including cross-agent cases.
*/
export function resolveTranscriptStemToSessionKeys(params: {
store?: Record<string, SessionEntry>;
entries?: Record<string, SessionEntry>;
store: Record<string, SessionEntry>;
stem: string;
archivedOwnerAgentId?: string;
allowQmdSlugFallback?: boolean;
}): string[] {
const store = params.entries ?? params.store ?? {};
const { store } = params;
const matches: string[] = [];
const stemAsFile = params.stem.endsWith(".jsonl") ? params.stem : `${params.stem}.jsonl`;
const parsedStemId = parseUsageCountedSessionIdFromFileName(stemAsFile);