clawdbot-d08: route transcript writers through accessor seam

This commit is contained in:
Josh Lehman
2026-05-31 18:21:03 -07:00
parent 1c31222d71
commit 8ee86ca2b7
5 changed files with 52 additions and 33 deletions

View File

@@ -6,7 +6,10 @@ import { sanitizeForLog } from "../../../packages/terminal-core/src/ansi.js";
import { formatAcpErrorChain } from "../../acp/runtime/errors.js";
import { normalizeReplyPayload } from "../../auto-reply/reply/normalize-reply.js";
import type { ThinkLevel, VerboseLevel } from "../../auto-reply/thinking.js";
import { appendSessionTranscriptMessage } from "../../config/sessions/transcript-append.js";
import {
appendTranscriptMessage,
publishTranscriptUpdate,
} from "../../config/sessions/session-accessor.js";
import {
readTailAssistantTextFromSessionTranscript,
resolveSessionTranscriptFile,
@@ -19,7 +22,6 @@ import { redactSensitiveText } from "../../logging/redact.js";
import { createSubsystemLogger } from "../../logging/subsystem.js";
import type { PluginMetadataSnapshot } from "../../plugins/plugin-metadata-snapshot.types.js";
import { annotateInterSessionPromptText } from "../../sessions/input-provenance.js";
import { emitSessionTranscriptUpdate } from "../../sessions/transcript-events.js";
import {
appendUserTurnTranscriptMessage,
type PersistedUserTurnMessage,
@@ -244,6 +246,12 @@ async function persistTextTurnTranscript(
...resolveSessionWriteLockOptions(params.config),
allowReentrant: true,
});
const transcriptScope = {
sessionFile,
sessionId: params.sessionId,
sessionKey: params.sessionKey,
agentId: params.sessionAgentId,
};
try {
const userMessage = params.userMessage;
if (userMessage || promptText) {
@@ -277,9 +285,7 @@ async function persistTextTurnTranscript(
}
}
if (appendAssistant) {
await appendSessionTranscriptMessage({
transcriptPath: sessionFile,
sessionId: params.sessionId,
await appendTranscriptMessage(transcriptScope, {
cwd: params.sessionCwd,
config: params.config,
message: {
@@ -299,8 +305,7 @@ async function persistTextTurnTranscript(
await lock.release();
}
emitSessionTranscriptUpdate({
sessionFile,
await publishTranscriptUpdate(transcriptScope, {
sessionKey: params.sessionKey,
agentId: params.sessionAgentId,
});

View File

@@ -5,7 +5,6 @@ import type { AgentMessage } from "../../agents/runtime/index.js";
import type { SessionManager } from "../../agents/sessions/session-manager.js";
import { redactTranscriptMessage } from "../../agents/transcript-redact.js";
import { formatErrorMessage } from "../../infra/errors.js";
import { emitSessionTranscriptUpdate } from "../../sessions/transcript-events.js";
import { extractAssistantVisibleText } from "../../shared/chat-message-content.js";
import type { OpenClawConfig } from "../types.openclaw.js";
import {
@@ -14,10 +13,10 @@ import {
resolveSessionFilePathOptions,
resolveSessionTranscriptPath,
} from "./paths.js";
import { appendTranscriptMessage, publishTranscriptUpdate } from "./session-accessor.js";
import { resolveAndPersistSessionFile } from "./session-file.js";
import { loadSessionStore, resolveSessionStoreEntry } from "./store.js";
import { parseSessionThreadInfo } from "./thread-info.js";
import { appendSessionTranscriptMessage } from "./transcript-append.js";
import { createSessionTranscriptHeader } from "./transcript-header.js";
import { writeJsonlEntry } from "./transcript-jsonl.js";
import { resolveMirroredTranscriptText } from "./transcript-mirror.js";
@@ -317,6 +316,13 @@ export async function appendExactAssistantMessageToSessionTranscript(params: {
...params.message,
...(explicitIdempotencyKey ? { idempotencyKey: explicitIdempotencyKey } : {}),
} as Parameters<SessionManager["appendMessage"]>[0];
const transcriptScope = {
sessionFile,
sessionId: entry.sessionId,
sessionKey: resolved.normalizedKey,
storePath,
...(params.agentId ? { agentId: params.agentId } : {}),
};
const {
messageId,
message: appendedMessage,
@@ -329,11 +335,10 @@ export async function appendExactAssistantMessageToSessionTranscript(params: {
sessionId: entry.sessionId,
cwd: entry.spawnedCwd,
});
return await appendSessionTranscriptMessage({
transcriptPath: sessionFile,
return await appendTranscriptMessage(transcriptScope, {
message,
...(explicitIdempotencyKey ? { idempotencyLookup: "scan" } : {}),
config: params.config,
...(params.config ? { config: params.config } : {}),
});
},
);
@@ -343,8 +348,7 @@ export async function appendExactAssistantMessageToSessionTranscript(params: {
switch (params.updateMode ?? "inline") {
case "inline":
emitSessionTranscriptUpdate({
sessionFile,
await publishTranscriptUpdate(transcriptScope, {
sessionKey,
...(params.agentId ? { agentId: params.agentId } : {}),
message: appendedMessage,
@@ -352,8 +356,7 @@ export async function appendExactAssistantMessageToSessionTranscript(params: {
});
break;
case "file-only":
emitSessionTranscriptUpdate({
sessionFile,
await publishTranscriptUpdate(transcriptScope, {
sessionKey,
...(params.agentId ? { agentId: params.agentId } : {}),
});

View File

@@ -1,8 +1,10 @@
import type { SessionManager } from "../../agents/sessions/session-manager.js";
import { appendSessionTranscriptMessage } from "../../config/sessions/transcript-append.js";
import {
appendTranscriptMessage,
publishTranscriptUpdate,
} from "../../config/sessions/session-accessor.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { formatErrorMessage } from "../../infra/errors.js";
import { emitSessionTranscriptUpdate } from "../../sessions/transcript-events.js";
type AppendMessageArg = Parameters<SessionManager["appendMessage"]>[0];
@@ -117,15 +119,18 @@ export async function appendInjectedAssistantMessageToTranscript(params: {
};
try {
const { messageId, message: appendedMessage } = await appendSessionTranscriptMessage({
transcriptPath: params.transcriptPath,
const transcriptScope = {
sessionFile: params.transcriptPath,
sessionKey: params.sessionKey ?? "",
...(params.agentId ? { agentId: params.agentId } : {}),
};
const { messageId, message: appendedMessage } = await appendTranscriptMessage(transcriptScope, {
message: messageBody,
now,
useRawWhenLinear: true,
config: params.config,
...(params.config ? { config: params.config } : {}),
});
emitSessionTranscriptUpdate({
sessionFile: params.transcriptPath,
await publishTranscriptUpdate(transcriptScope, {
...(params.sessionKey ? { sessionKey: params.sessionKey } : {}),
...(params.agentId ? { agentId: params.agentId } : {}),
message: appendedMessage,

View File

@@ -1978,7 +1978,7 @@ describe("gateway chat transcript writes (guardrail)", () => {
expect(chatSrc.includes("fs.appendFileSync(transcriptPath")).toBe(false);
expect(chatSrc).toContain("appendInjectedAssistantMessageToTranscript(");
expect(helperSrc).toContain("appendSessionTranscriptMessage({");
expect(helperSrc).toContain("appendTranscriptMessage(");
expect(helperSrc).toContain("useRawWhenLinear: true");
expect(helperSrc).not.toContain("SessionManager.open(params.transcriptPath)");
});

View File

@@ -1,17 +1,20 @@
import path from "node:path";
import { mimeTypeFromFilePath } from "@openclaw/media-core/mime";
import type { AgentMessage } from "../agents/runtime/index.js";
import { appendSessionTranscriptMessage } from "../config/sessions/transcript-append.js";
import {
appendTranscriptMessage,
publishTranscriptUpdate,
} from "../config/sessions/session-accessor.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import {
applyInputProvenanceToUserMessage,
type InputProvenance,
normalizeInputProvenance,
} from "./input-provenance.js";
import { emitSessionTranscriptUpdate } from "./transcript-events.js";
// User-turn transcript helpers persist the selected prompt/media as a user
// message before or during runtime execution, preserving provenance/idempotency.
type TranscriptAppendConfig = Parameters<typeof appendSessionTranscriptMessage>[0]["config"];
type TranscriptAppendConfig = OpenClawConfig;
type UserTurnSessionEntry = {
sessionId: string;
@@ -398,13 +401,17 @@ export async function appendUserTurnTranscriptMessage(
return undefined;
}
const appended = await appendSessionTranscriptMessage({
transcriptPath: params.transcriptPath,
const transcriptScope = {
sessionFile: params.transcriptPath,
sessionKey: params.sessionKey ?? "",
...(params.agentId ? { agentId: params.agentId } : {}),
...(params.sessionId ? { sessionId: params.sessionId } : {}),
...(params.cwd ? { cwd: params.cwd } : {}),
...(params.config ? { config: params.config } : {}),
};
const appended = await appendTranscriptMessage(transcriptScope, {
message: resolvedMessage,
idempotencyLookup: "scan",
...(params.cwd ? { cwd: params.cwd } : {}),
...(params.config ? { config: params.config } : {}),
prepareMessageAfterIdempotencyCheck: (message) =>
applyBeforeMessageWriteToUserTurn(message, params),
});
@@ -415,8 +422,7 @@ export async function appendUserTurnTranscriptMessage(
switch (params.updateMode ?? "inline") {
case "inline":
if (appended.appended) {
emitSessionTranscriptUpdate({
sessionFile: params.transcriptPath,
await publishTranscriptUpdate(transcriptScope, {
...(params.sessionKey ? { sessionKey: params.sessionKey } : {}),
...(params.agentId ? { agentId: params.agentId } : {}),
message: appended.message,