



















@@ -4,6 +4,35 @@ import { HEARTBEAT_PROMPT } from "../auto-reply/heartbeat.js";
44import { buildSessionHistorySnapshot, SessionHistorySseState } from "./session-history-state.js";
55import * as sessionUtils from "./session-utils.js";
667+type HistorySnapshot = ReturnType<typeof buildSessionHistorySnapshot>;
8+9+function assistantTextMessage(text: string, seq: number) {
10+return {
11+role: "assistant" as const,
12+content: [{ type: "text" as const, text }],
13+__openclaw: { seq },
14+};
15+}
16+17+function userTextMessage(text: string, seq: number) {
18+return {
19+role: "user" as const,
20+content: [{ type: "text" as const, text }],
21+__openclaw: { seq },
22+};
23+}
24+25+function newStateWithUserText(text: string): SessionHistorySseState {
26+return SessionHistorySseState.fromRawSnapshot({
27+target: { sessionId: "sess-main" },
28+rawMessages: [userTextMessage(text, 1)],
29+});
30+}
31+32+function expectOnlyAssistantText(snapshot: HistorySnapshot, text: string, seq: number): void {
33+expect(snapshot.history.messages).toEqual([assistantTextMessage(text, seq)]);
34+}
35+736describe("SessionHistorySseState", () => {
837test("uses the initial raw snapshot for both first history and seq seeding", () => {
938const readSpy = vi.spyOn(sessionUtils, "readSessionMessagesAsync").mockResolvedValue([
@@ -58,18 +87,7 @@ describe("SessionHistorySseState", () => {
58875988test("reuses one canonical array for items and messages", () => {
6089const snapshot = buildSessionHistorySnapshot({
61-rawMessages: [
62-{
63-role: "assistant",
64-content: [{ type: "text", text: "first" }],
65-__openclaw: { seq: 1 },
66-},
67-{
68-role: "assistant",
69-content: [{ type: "text", text: "second" }],
70-__openclaw: { seq: 2 },
71-},
72-],
90+rawMessages: [assistantTextMessage("first", 1), assistantTextMessage("second", 2)],
7391limit: 1,
7492});
7593@@ -103,16 +121,7 @@ describe("SessionHistorySseState", () => {
103121});
104122105123test("emits message-tool mirror when silent control reply completes inline append", () => {
106-const state = SessionHistorySseState.fromRawSnapshot({
107-target: { sessionId: "sess-main" },
108-rawMessages: [
109-{
110-role: "user",
111-content: [{ type: "text", text: "reply here" }],
112-__openclaw: { seq: 1 },
113-},
114-],
115-});
124+const state = newStateWithUserText("reply here");
116125117126expect(
118127state.appendInlineMessage({
@@ -219,18 +228,7 @@ describe("SessionHistorySseState", () => {
219228220229test("does not coerce partial cursor values", () => {
221230const snapshot = buildSessionHistorySnapshot({
222-rawMessages: [
223-{
224-role: "assistant",
225-content: [{ type: "text", text: "first" }],
226-__openclaw: { seq: 1 },
227-},
228-{
229-role: "assistant",
230-content: [{ type: "text", text: "second" }],
231-__openclaw: { seq: 2 },
232-},
233-],
231+rawMessages: [assistantTextMessage("first", 1), assistantTextMessage("second", 2)],
234232cursor: "seq:2next",
235233});
236234@@ -314,16 +312,7 @@ describe("SessionHistorySseState", () => {
314312});
315313316314test("does not emit a no-op hidden inline control reply", () => {
317-const state = SessionHistorySseState.fromRawSnapshot({
318-target: { sessionId: "sess-main" },
319-rawMessages: [
320-{
321-role: "user",
322-content: [{ type: "text", text: "reply here" }],
323-__openclaw: { seq: 1 },
324-},
325-],
326-});
315+const state = newStateWithUserText("reply here");
327316328317const appended = state.appendInlineMessage({
329318message: {
@@ -528,21 +517,11 @@ describe("SessionHistorySseState", () => {
528517],
529518__openclaw: { seq: 1 },
530519},
531-{
532-role: "assistant",
533-content: [{ type: "text", text: "visible answer" }],
534-__openclaw: { seq: 2 },
535-},
520+assistantTextMessage("visible answer", 2),
536521],
537522});
538523539-expect(snapshot.history.messages).toEqual([
540-{
541-role: "assistant",
542-content: [{ type: "text", text: "visible answer" }],
543-__openclaw: { seq: 2 },
544-},
545-]);
524+expectOnlyAssistantText(snapshot, "visible answer", 2);
546525});
547526548527test("drops hidden runtime-context custom messages from projected history", () => {
@@ -555,21 +534,11 @@ describe("SessionHistorySseState", () => {
555534display: false,
556535__openclaw: { seq: 1 },
557536},
558-{
559-role: "assistant",
560-content: [{ type: "text", text: "visible answer" }],
561-__openclaw: { seq: 2 },
562-},
537+assistantTextMessage("visible answer", 2),
563538],
564539});
565540566-expect(snapshot.history.messages).toEqual([
567-{
568-role: "assistant",
569-content: [{ type: "text", text: "visible answer" }],
570-__openclaw: { seq: 2 },
571-},
572-]);
541+expectOnlyAssistantText(snapshot, "visible answer", 2);
573542expect(snapshot.rawTranscriptSeq).toBe(2);
574543});
575544此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。