mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-11 04:48:05 +00:00
refactor: drop file-era transcript fixture coverage
This commit is contained in:
@@ -76,8 +76,8 @@ interfaces that still look like the old file world:
|
||||
JSON as possible write targets.
|
||||
- Agent-owned tables live in per-agent SQLite databases. The global DB keeps
|
||||
registry/control-plane rows; transcript identity is a canonical
|
||||
`sqlite-transcript://<agent>/<session>.jsonl` locator derived from the
|
||||
per-agent transcript rows.
|
||||
`sqlite-transcript://<agent>/<session>` locator derived from the per-agent
|
||||
transcript rows.
|
||||
- Doctor already imports several legacy files. The cleanup is to make that a
|
||||
single explicit migration implementation that doctor calls, with a durable
|
||||
migration report.
|
||||
@@ -208,8 +208,8 @@ The remaining cleanup is mostly consolidation and deletion:
|
||||
SQLite; JSONL is now a legacy doctor input or in-memory export
|
||||
encoding, not a runtime state file.
|
||||
- Runtime session path resolution now canonicalizes active sessions to
|
||||
`sqlite-transcript://<agent>/<session>.jsonl` locators. Legacy absolute JSONL
|
||||
paths are doctor migration inputs instead of active runtime identity.
|
||||
`sqlite-transcript://<agent>/<session>` locators. Legacy absolute JSONL paths
|
||||
are doctor migration inputs instead of active runtime identity.
|
||||
- Gateway transcript-key lookup compares canonical transcript locators directly
|
||||
and no longer realpaths or stats transcript filenames.
|
||||
- Automatic compaction transcript rotation writes successor transcript rows
|
||||
@@ -248,10 +248,9 @@ The remaining cleanup is mostly consolidation and deletion:
|
||||
SQLite transcript rows directly. Runtime callers pass canonical SQLite
|
||||
locators, not writable `.jsonl` paths.
|
||||
- Fresh runtime session rows now use virtual
|
||||
`sqlite-transcript://<agent>/<session>.jsonl` locators instead of fake
|
||||
`sqlite-transcript://<agent>/<session>` locators instead of fake
|
||||
`agents/<agentId>/sessions/*.jsonl` paths. The old path builders remain for
|
||||
doctor imports, explicit debug/export artifacts, and path-compatibility
|
||||
tests.
|
||||
doctor imports and explicit debug/export artifacts.
|
||||
- Starting a new persisted transcript session now always allocates a fresh
|
||||
SQLite locator. The session manager no longer reuses a previous file-era
|
||||
transcript path as the identity for the new session.
|
||||
@@ -283,9 +282,9 @@ The remaining cleanup is mostly consolidation and deletion:
|
||||
classification helpers; transcript filtering now derives from SQLite row
|
||||
metadata during entry construction.
|
||||
- Memory-host and QMD session-export tests default to virtual
|
||||
`sqlite-transcript://<agent>/<session>.jsonl` locators. Old
|
||||
`sqlite-transcript://<agent>/<session>` locators. Old
|
||||
`agents/<agentId>/sessions/*.jsonl` paths stay covered only where a test is
|
||||
intentionally proving legacy path compatibility.
|
||||
intentionally proving doctor/import/export compatibility.
|
||||
- QA-lab raw session inspection now uses `sessions.list` through the gateway
|
||||
instead of reading `agents/qa/sessions/sessions.json`; MSteams feedback
|
||||
appends directly to SQLite transcripts without fabricating a JSONL path.
|
||||
|
||||
@@ -1204,7 +1204,6 @@ describe("CodexAppServerEventProjector", () => {
|
||||
expect(beforeCompaction).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
messageCount: 1,
|
||||
sessionFile: expect.stringMatching(/^sqlite-transcript:\/\/main\/session-1-.+\.jsonl$/u),
|
||||
messages: [expect.objectContaining({ role: "assistant" })],
|
||||
}),
|
||||
expect.objectContaining({
|
||||
@@ -1216,7 +1215,6 @@ describe("CodexAppServerEventProjector", () => {
|
||||
expect.objectContaining({
|
||||
messageCount: 1,
|
||||
compactedCount: -1,
|
||||
sessionFile: expect.stringMatching(/^sqlite-transcript:\/\/main\/session-1-.+\.jsonl$/u),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
runId: "run-1",
|
||||
|
||||
@@ -273,7 +273,6 @@ describe("generateVoiceResponse", () => {
|
||||
agentId: "main",
|
||||
sandboxSessionKey: "agent:main:voice:15550001111",
|
||||
workspaceDir: "/tmp/openclaw/workspace/main",
|
||||
sessionFile: expect.stringMatching(/^sqlite-transcript:\/\/main\/.+\.jsonl$/),
|
||||
}),
|
||||
);
|
||||
});
|
||||
@@ -311,7 +310,6 @@ describe("generateVoiceResponse", () => {
|
||||
agentId: "voice",
|
||||
sandboxSessionKey: "agent:voice:voice:15550001111",
|
||||
workspaceDir: "/tmp/openclaw/workspace/voice",
|
||||
sessionFile: expect.stringMatching(/^sqlite-transcript:\/\/voice\/.+\.jsonl$/),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -3,7 +3,6 @@ export {
|
||||
HEARTBEAT_TOKEN,
|
||||
SILENT_REPLY_TOKEN,
|
||||
hasInterSessionUserProvenance,
|
||||
isCompactionCheckpointTranscriptFileName,
|
||||
isCronRunSessionKey,
|
||||
isExecCompletionEvent,
|
||||
isHeartbeatUserMessage,
|
||||
|
||||
@@ -48,7 +48,6 @@ export {
|
||||
} from "../../../../src/config/config.js";
|
||||
export type { OpenClawConfig } from "../../../../src/config/config.js";
|
||||
export { resolveStateDir } from "../../../../src/config/paths.js";
|
||||
export { isCompactionCheckpointTranscriptFileName } from "../../../../src/config/sessions/artifacts.js";
|
||||
export {
|
||||
listSqliteSessionTranscripts,
|
||||
loadSqliteSessionTranscriptEvents,
|
||||
|
||||
@@ -194,33 +194,9 @@ describe("buildSessionTranscriptEntry", () => {
|
||||
expect(entry.lineMap).toEqual([]);
|
||||
});
|
||||
|
||||
it("skips checkpoint artifacts so snapshots do not double-index session content", async () => {
|
||||
const checkpointPath = path.join(
|
||||
tmpDir,
|
||||
"agents",
|
||||
"main",
|
||||
"sessions",
|
||||
"ordinary.checkpoint.11111111-1111-4111-8111-111111111111.jsonl",
|
||||
);
|
||||
seedTranscript({
|
||||
sessionId: "ordinary.checkpoint.11111111-1111-4111-8111-111111111111",
|
||||
transcriptPath: checkpointPath,
|
||||
events: [
|
||||
{
|
||||
type: "message",
|
||||
message: { role: "user", content: "Archived hello" },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await expect(buildSessionTranscriptEntry(checkpointPath)).resolves.toBeNull();
|
||||
});
|
||||
|
||||
it("keeps cron-run deleted archives opaque when the live session store entry is gone", async () => {
|
||||
const archivePath = path.join(tmpDir, "cron-run.jsonl.deleted.2026-02-16T22-27-33.000Z");
|
||||
it("keeps cron-run transcripts opaque when the live session store entry is gone", async () => {
|
||||
const transcriptRef = seedTranscript({
|
||||
sessionId: "cron-run-deleted",
|
||||
transcriptPath: archivePath,
|
||||
events: [
|
||||
{
|
||||
type: "message",
|
||||
@@ -243,11 +219,9 @@ describe("buildSessionTranscriptEntry", () => {
|
||||
expect(entry.generatedByCronRun).toBe(true);
|
||||
});
|
||||
|
||||
it("keeps cron-run reset archives opaque when session metadata preserves the cron key", async () => {
|
||||
const archivePath = path.join(tmpDir, "cron-run.jsonl.reset.2026-02-16T22-26-33.000Z");
|
||||
it("keeps cron-run transcripts opaque when session metadata preserves the cron key", async () => {
|
||||
const transcriptRef = seedTranscript({
|
||||
sessionId: "cron-run-reset",
|
||||
transcriptPath: archivePath,
|
||||
events: [
|
||||
{
|
||||
type: "session-meta",
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
HEARTBEAT_PROMPT,
|
||||
HEARTBEAT_TOKEN,
|
||||
hasInterSessionUserProvenance,
|
||||
isCompactionCheckpointTranscriptFileName,
|
||||
isCronRunSessionKey,
|
||||
isExecCompletionEvent,
|
||||
isHeartbeatUserMessage,
|
||||
@@ -57,16 +56,6 @@ export type SessionTranscriptDeltaStats = {
|
||||
updatedAt: number;
|
||||
};
|
||||
|
||||
function shouldSkipTranscriptFileForDreaming(absPath: string): boolean {
|
||||
const fileName = path.basename(absPath);
|
||||
// Compaction checkpoints are always skipped: they are derived snapshots of an
|
||||
// active session and would double-index the same content.
|
||||
if (isCompactionCheckpointTranscriptFileName(fileName)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isDreamingNarrativeBootstrapRecord(record: unknown): boolean {
|
||||
if (!record || typeof record !== "object" || Array.isArray(record)) {
|
||||
return false;
|
||||
@@ -205,7 +194,6 @@ export function sessionPathForTranscript(absPath: string): string {
|
||||
export function resolveSessionTranscriptScope(locator: string): {
|
||||
agentId: string;
|
||||
sessionId: string;
|
||||
transcriptPath?: string;
|
||||
} | null {
|
||||
const sqliteRef = parseSqliteSessionTranscriptRef(locator);
|
||||
if (sqliteRef) {
|
||||
@@ -457,19 +445,6 @@ export async function buildSessionTranscriptEntry(
|
||||
(total, entry) => total + JSON.stringify(entry.event).length + 1,
|
||||
0,
|
||||
);
|
||||
if (shouldSkipTranscriptFileForDreaming(absPath)) {
|
||||
return {
|
||||
path: sessionPathForTranscript(absPath),
|
||||
absPath,
|
||||
mtimeMs,
|
||||
size,
|
||||
messageCount,
|
||||
hash: hashText("\n\n"),
|
||||
content: "",
|
||||
lineMap: [],
|
||||
messageTimestampsMs: [],
|
||||
};
|
||||
}
|
||||
const collected: string[] = [];
|
||||
const lineMap: number[] = [];
|
||||
const messageTimestampsMs: number[] = [];
|
||||
|
||||
Reference in New Issue
Block a user