惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
人人都是产品经理
人人都是产品经理
Hugging Face - Blog
Hugging Face - Blog
罗磊的独立博客
博客园 - 【当耐特】
D
Docker
Y
Y Combinator Blog
L
LangChain Blog
博客园 - 三生石上(FineUI控件)
I
InfoQ
阮一峰的网络日志
阮一峰的网络日志
F
Fortinet All Blogs
J
Java Code Geeks
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
V2EX
B
Blog
The GitHub Blog
The GitHub Blog
腾讯CDC
MongoDB | Blog
MongoDB | Blog
博客园 - Franky
爱范儿
爱范儿
A
About on SuperTechFans
量子位
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix: assistant reply lost between compaction summary and ...
maweibin · 2026-06-23 · via Recent Commits to openclaw:main
1+

/**

2+

* Live proof script for PR #95484 — assistant reply lost after compaction rotation.

3+

*

4+

* Demonstrates that:

5+

* 1. BEFORE fix: successor context shows [compactionSummary, user, ...]

6+

* — the assistant reply is silently dropped.

7+

* 2. AFTER fix: successor context shows [compactionSummary, assistant, user, ...]

8+

* — the assistant reply is preserved.

9+

*

10+

* Usage: node --import tsx scripts/repro/issue-76729-compaction-assistant-loss-proof.mts

11+

*/

12+

import { mkdtempSync, rmSync } from "node:fs";

13+

import { join } from "node:path";

14+

import { tmpdir } from "node:os";

15+

import { SessionManager } from "openclaw/plugin-sdk/agent-sessions";

16+

import type { AgentMessage } from "openclaw/plugin-sdk/agent-core";

17+

import type { TextContent } from "openclaw/plugin-sdk/llm";

18+

import { makeAgentAssistantMessage } from "../../src/agents/test-helpers/agent-message-fixtures.js";

19+

import { rotateTranscriptAfterCompaction } from "../../src/agents/embedded-agent-runner/compaction-successor-transcript.js";

20+21+

const sessionDir = mkdtempSync(join(tmpdir(), "compaction-proof-"));

22+

console.log("Session dir:", sessionDir);

23+

console.log();

24+25+

const manager = SessionManager.create(sessionDir, sessionDir);

26+27+

// Build session: user("Summarize") → assistant("Here is the summary") → user("Analyze Q3") → assistant("Q3 analysis...") → compaction(firstKept=user_Analyze_Q3)

28+

manager.appendMessage({ role: "user", content: "Summarize reports", timestamp: 1 });

29+

manager.appendMessage(makeAgentAssistantMessage({ content: [{ type: "text", text: "Here is the summary" }], timestamp: 2 }));

30+

const firstKeptId = manager.appendMessage({ role: "user", content: "Analyze Q3", timestamp: 3 });

31+

manager.appendMessage(makeAgentAssistantMessage({ content: [{ type: "text", text: "Q3 analysis shows..." }], timestamp: 4 }));

32+

manager.appendCompaction("Summary of previous work.", firstKeptId, 5000);

33+34+

// Post-compaction

35+

manager.appendMessage({ role: "user", content: "Any more insights?", timestamp: 5 });

36+

manager.appendMessage(makeAgentAssistantMessage({ content: [{ type: "text", text: "Additional insights" }], timestamp: 6 }));

37+38+

const sessionFile = manager.getSessionFile()!;

39+

console.log("Source session file:", sessionFile);

40+

console.log();

41+42+

const result = await rotateTranscriptAfterCompaction({

43+

sessionManager: manager,

44+

sessionFile,

45+

now: () => new Date("2026-06-21T12:00:00.000Z"),

46+

});

47+48+

console.log("Rotation result:", JSON.stringify(result, null, 2));

49+

console.log();

50+51+

// Open successor and inspect context

52+

const successor = SessionManager.open(result.sessionFile!);

53+

const context = successor.buildSessionContext();

54+55+

console.log("=== SUCCESSOR CONTEXT ===");

56+

console.log("Roles:", JSON.stringify(context.messages.map((m) => m.role)));

57+58+

for (const msg of context.messages) {

59+

if (msg.role === "compactionSummary") {

60+

const summary = (msg as AgentMessage & { summary: string }).summary;

61+

console.log(` [compactionSummary] summary="${summary}"`);

62+

} else if ("content" in msg) {

63+

const text = Array.isArray(msg.content)

64+

? (msg.content[0] as TextContent)?.text ?? JSON.stringify(msg.content)

65+

: msg.content;

66+

console.log(` [${msg.role}] "${text}"`);

67+

}

68+

}

69+

console.log();

70+71+

const roles = context.messages.map((m) => m.role);

72+

console.log("=== VERIFICATION ===");

73+

console.log("Role sequence:", JSON.stringify(roles));

74+

console.log("compactionSummary → assistant (no gap):", roles[0] === "compactionSummary" && roles[1] === "assistant");

75+

console.log("BEFORE fix shows: [compactionSummary, user, assistant, ...] ← missing assistant");

76+

console.log("AFTER fix shows:", JSON.stringify(roles));

77+

console.log();

78+79+

// Cleanup

80+

rmSync(sessionDir, { recursive: true, force: true });

81+

console.log("Temp dir cleaned up.");