mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-29 17:45:15 +00:00
refactor: trim user turn transcript API
This commit is contained in:
@@ -9,10 +9,8 @@ import { createMockPluginRegistry } from "openclaw/plugin-sdk/plugin-test-runtim
|
||||
import { castAgentMessage } from "openclaw/plugin-sdk/test-fixtures";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
appendInlineUserTurnTranscriptMessage,
|
||||
appendUserTurnTranscriptMessage,
|
||||
buildPersistedUserTurnMediaInputsFromFields,
|
||||
buildPersistedUserTurnMediaFields,
|
||||
buildPersistedUserTurnMessage,
|
||||
createUserTurnTranscriptRecorder,
|
||||
mergePreparedUserTurnMessageForRuntime,
|
||||
@@ -137,71 +135,6 @@ describe("user turn transcript persistence", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildPersistedUserTurnMediaFields", () => {
|
||||
it("omits media fields when there is no structured media", () => {
|
||||
expect(buildPersistedUserTurnMediaFields(undefined)).toEqual({});
|
||||
expect(buildPersistedUserTurnMediaFields([])).toEqual({});
|
||||
expect(buildPersistedUserTurnMediaFields([{ path: " ", contentType: "image/png" }])).toEqual(
|
||||
{},
|
||||
);
|
||||
});
|
||||
|
||||
it("builds aligned transcript media fields from structured media facts", () => {
|
||||
expect(
|
||||
buildPersistedUserTurnMediaFields([
|
||||
{ path: "/tmp/a.png", contentType: "image/png" },
|
||||
{ path: "/tmp/b.jpg", contentType: "image/jpeg" },
|
||||
]),
|
||||
).toEqual({
|
||||
MediaPath: "/tmp/a.png",
|
||||
MediaPaths: ["/tmp/a.png", "/tmp/b.jpg"],
|
||||
MediaType: "image/png",
|
||||
MediaTypes: ["image/png", "image/jpeg"],
|
||||
});
|
||||
});
|
||||
|
||||
it("uses url-backed media when no local path is available", () => {
|
||||
expect(
|
||||
buildPersistedUserTurnMediaFields([
|
||||
{ url: "media://inbound/photo.png", contentType: "image/png" },
|
||||
]),
|
||||
).toEqual({
|
||||
MediaPath: "media://inbound/photo.png",
|
||||
MediaPaths: ["media://inbound/photo.png"],
|
||||
MediaType: "image/png",
|
||||
MediaTypes: ["image/png"],
|
||||
});
|
||||
});
|
||||
|
||||
it("falls back to kind and then octet-stream for media types", () => {
|
||||
expect(
|
||||
buildPersistedUserTurnMediaFields([
|
||||
{ path: "/tmp/doc", kind: "document" },
|
||||
{ path: "/tmp/blob" },
|
||||
]),
|
||||
).toEqual({
|
||||
MediaPath: "/tmp/doc",
|
||||
MediaPaths: ["/tmp/doc", "/tmp/blob"],
|
||||
MediaType: "document",
|
||||
MediaTypes: ["document", "application/octet-stream"],
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps media paths and types aligned when incomplete entries are skipped", () => {
|
||||
expect(
|
||||
buildPersistedUserTurnMediaFields([
|
||||
{ contentType: "image/png" },
|
||||
{ path: "/tmp/b.jpg", contentType: "image/jpeg" },
|
||||
]),
|
||||
).toEqual({
|
||||
MediaPath: "/tmp/b.jpg",
|
||||
MediaPaths: ["/tmp/b.jpg"],
|
||||
MediaType: "image/jpeg",
|
||||
MediaTypes: ["image/jpeg"],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildPersistedUserTurnMessage", () => {
|
||||
it("builds a plain user transcript message for text-only turns", () => {
|
||||
expect(
|
||||
@@ -419,11 +352,11 @@ describe("user turn transcript persistence", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("uses inline update mode through the convenience wrapper", async () => {
|
||||
it("uses inline update mode by default", async () => {
|
||||
const dir = createTempDir("openclaw-user-turn-append-inline-");
|
||||
const transcriptPath = path.join(dir, "session.jsonl");
|
||||
|
||||
const appended = await appendInlineUserTurnTranscriptMessage({
|
||||
const appended = await appendUserTurnTranscriptMessage({
|
||||
transcriptPath,
|
||||
sessionId: "session-1",
|
||||
sessionKey: "main",
|
||||
@@ -509,14 +442,14 @@ describe("user turn transcript persistence", () => {
|
||||
const dir = createTempDir("openclaw-user-turn-redacted-idempotent-");
|
||||
const transcriptPath = path.join(dir, "session.jsonl");
|
||||
|
||||
await appendInlineUserTurnTranscriptMessage({
|
||||
await appendUserTurnTranscriptMessage({
|
||||
transcriptPath,
|
||||
input: {
|
||||
text: "secret prompt",
|
||||
idempotencyKey: "chat-run-1:user",
|
||||
},
|
||||
});
|
||||
await appendInlineUserTurnTranscriptMessage({
|
||||
await appendUserTurnTranscriptMessage({
|
||||
transcriptPath,
|
||||
input: {
|
||||
text: "secret prompt",
|
||||
|
||||
@@ -9,14 +9,14 @@ import { logVerbose } from "../globals.js";
|
||||
import { mimeTypeFromFilePath } from "../media/mime.js";
|
||||
import { emitSessionTranscriptUpdate } from "./transcript-events.js";
|
||||
|
||||
export type PersistedUserTurnMediaInput = {
|
||||
type PersistedUserTurnMediaInput = {
|
||||
path?: string | null;
|
||||
url?: string | null;
|
||||
contentType?: string | null;
|
||||
kind?: string | null;
|
||||
};
|
||||
|
||||
export type PersistedUserTurnMediaFields = {
|
||||
type PersistedUserTurnMediaFields = {
|
||||
MediaPath?: string;
|
||||
MediaPaths?: string[];
|
||||
MediaType?: string;
|
||||
@@ -33,11 +33,9 @@ export type UserTurnInput = {
|
||||
mediaOnlyText?: string;
|
||||
};
|
||||
|
||||
export type BuildPersistedUserTurnMessageParams = UserTurnInput;
|
||||
type UserTurnTranscriptUpdateMode = "inline" | "file-only" | "none";
|
||||
|
||||
export type UserTurnTranscriptUpdateMode = "inline" | "file-only" | "none";
|
||||
|
||||
export type AppendUserTurnTranscriptMessageParams = {
|
||||
type AppendUserTurnTranscriptMessageParams = {
|
||||
transcriptPath: string;
|
||||
input?: UserTurnInput;
|
||||
message?: PersistedUserTurnMessage;
|
||||
@@ -49,12 +47,7 @@ export type AppendUserTurnTranscriptMessageParams = {
|
||||
updateMode?: UserTurnTranscriptUpdateMode;
|
||||
};
|
||||
|
||||
export type AppendInlineUserTurnTranscriptMessageParams = Omit<
|
||||
AppendUserTurnTranscriptMessageParams,
|
||||
"updateMode"
|
||||
>;
|
||||
|
||||
export type PersistUserTurnTranscriptParams = {
|
||||
type PersistUserTurnTranscriptParams = {
|
||||
input?: UserTurnInput;
|
||||
message?: PersistedUserTurnMessage;
|
||||
sessionId: string;
|
||||
@@ -69,12 +62,12 @@ export type PersistUserTurnTranscriptParams = {
|
||||
updateMode?: UserTurnTranscriptUpdateMode;
|
||||
};
|
||||
|
||||
export type UserTurnTranscriptPersistenceTarget = Omit<
|
||||
type UserTurnTranscriptPersistenceTarget = Omit<
|
||||
PersistUserTurnTranscriptParams,
|
||||
"input" | "message" | "updateMode"
|
||||
>;
|
||||
|
||||
export type UserTurnTranscriptFileTarget = {
|
||||
type UserTurnTranscriptFileTarget = {
|
||||
transcriptPath: string;
|
||||
sessionId?: string;
|
||||
agentId?: string;
|
||||
@@ -83,18 +76,16 @@ export type UserTurnTranscriptFileTarget = {
|
||||
config?: OpenClawConfig;
|
||||
};
|
||||
|
||||
export type UserTurnTranscriptTarget =
|
||||
| UserTurnTranscriptPersistenceTarget
|
||||
| UserTurnTranscriptFileTarget;
|
||||
type UserTurnTranscriptTarget = UserTurnTranscriptPersistenceTarget | UserTurnTranscriptFileTarget;
|
||||
|
||||
export type UserTurnTranscriptPersistResult = {
|
||||
type UserTurnTranscriptPersistResult = {
|
||||
sessionFile: string;
|
||||
sessionEntry: SessionEntry | undefined;
|
||||
messageId: string;
|
||||
message: PersistedUserTurnMessage;
|
||||
};
|
||||
|
||||
export type UserTurnTranscriptTargetResolver =
|
||||
type UserTurnTranscriptTargetResolver =
|
||||
| UserTurnTranscriptTarget
|
||||
| (() => UserTurnTranscriptTarget | undefined | Promise<UserTurnTranscriptTarget | undefined>);
|
||||
|
||||
@@ -117,7 +108,7 @@ export type UserTurnTranscriptRecorder = {
|
||||
}) => Promise<UserTurnTranscriptPersistResult | undefined>;
|
||||
};
|
||||
|
||||
export type CreateUserTurnTranscriptRecorderParams = {
|
||||
type CreateUserTurnTranscriptRecorderParams = {
|
||||
input?: UserTurnInput;
|
||||
message?: PersistedUserTurnMessage;
|
||||
target: UserTurnTranscriptTargetResolver;
|
||||
@@ -126,7 +117,7 @@ export type CreateUserTurnTranscriptRecorderParams = {
|
||||
onPersistenceError?: (error: unknown) => void;
|
||||
};
|
||||
|
||||
export type PersistedUserTurnTextFieldSource = {
|
||||
type PersistedUserTurnTextFieldSource = {
|
||||
Transcript?: string | null;
|
||||
RawBody?: string | null;
|
||||
CommandBody?: string | null;
|
||||
@@ -135,12 +126,12 @@ export type PersistedUserTurnTextFieldSource = {
|
||||
BodyStripped?: string | null;
|
||||
};
|
||||
|
||||
export type ResolvePersistedUserTurnTextOptions = {
|
||||
type ResolvePersistedUserTurnTextOptions = {
|
||||
hasMedia?: boolean;
|
||||
fallback?: string | null;
|
||||
};
|
||||
|
||||
export type PersistedUserTurnMediaFieldSource = {
|
||||
type PersistedUserTurnMediaFieldSource = {
|
||||
MediaPath?: string | null;
|
||||
MediaPaths?: readonly (string | null | undefined)[] | null;
|
||||
MediaUrl?: string | null;
|
||||
@@ -285,7 +276,7 @@ export function buildPersistedUserTurnMediaInputsFromFields(
|
||||
return media;
|
||||
}
|
||||
|
||||
export function buildPersistedUserTurnMediaFields(
|
||||
function buildPersistedUserTurnMediaFields(
|
||||
media: readonly PersistedUserTurnMediaInput[] | null | undefined,
|
||||
): PersistedUserTurnMediaFields {
|
||||
const entries = Array.isArray(media) ? media : [];
|
||||
@@ -305,9 +296,7 @@ export function buildPersistedUserTurnMediaFields(
|
||||
};
|
||||
}
|
||||
|
||||
export function buildPersistedUserTurnMessage(
|
||||
params: BuildPersistedUserTurnMessageParams,
|
||||
): PersistedUserTurnMessage {
|
||||
export function buildPersistedUserTurnMessage(params: UserTurnInput): PersistedUserTurnMessage {
|
||||
const mediaFields = buildPersistedUserTurnMediaFields(params.media);
|
||||
const hasMedia = Boolean(mediaFields.MediaPath);
|
||||
const text = normalizeTranscriptText(params.text);
|
||||
@@ -440,15 +429,6 @@ export async function appendUserTurnTranscriptMessage(
|
||||
};
|
||||
}
|
||||
|
||||
export async function appendInlineUserTurnTranscriptMessage(
|
||||
params: AppendInlineUserTurnTranscriptMessageParams,
|
||||
): ReturnType<typeof appendUserTurnTranscriptMessage> {
|
||||
return await appendUserTurnTranscriptMessage({
|
||||
...params,
|
||||
updateMode: "inline",
|
||||
});
|
||||
}
|
||||
|
||||
export async function persistUserTurnTranscript(
|
||||
params: PersistUserTurnTranscriptParams,
|
||||
): Promise<UserTurnTranscriptPersistResult | undefined> {
|
||||
|
||||
Reference in New Issue
Block a user