mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 17:10:49 +00:00
fix: trim stale blocked-content projection plumbing
This commit is contained in:
@@ -33,10 +33,6 @@ const header = `// Generated by scripts/protocol-gen-swift.ts — do not edit by
|
||||
.map((c) => ` case ${camelCase(c)} = "${c}"`)
|
||||
.join("\n")}\n}\n`;
|
||||
|
||||
const OPTIONAL_INIT_DEFAULTS = new Map<string, Set<string>>([
|
||||
["ChatHistoryParams", new Set(["includeblockedoriginalcontent"])],
|
||||
]);
|
||||
|
||||
const reserved = new Set([
|
||||
"associatedtype",
|
||||
"class",
|
||||
@@ -194,9 +190,7 @@ function emitStruct(name: string, schema: JsonSchema): string {
|
||||
.map(([key, prop]) => {
|
||||
const propName = safeName(key);
|
||||
const req = required.has(key);
|
||||
const defaultValue =
|
||||
!req && OPTIONAL_INIT_DEFAULTS.get(name)?.has(propName) ? " = nil" : "";
|
||||
return ` ${propName}: ${swiftType(prop, true)}${req ? "" : "?"}${defaultValue}`;
|
||||
return ` ${propName}: ${swiftType(prop, true)}${req ? "" : "?"}`;
|
||||
})
|
||||
.join(",\n") +
|
||||
")\n" +
|
||||
|
||||
@@ -79,7 +79,7 @@ function writeTranscript(tmpDir: string, sessionId: string, lines: unknown[]): s
|
||||
|
||||
function appendBlockedUserMessageWithSessionManager(params: {
|
||||
sessionFile: string;
|
||||
originalText: string;
|
||||
originalText?: string;
|
||||
redactedText: string;
|
||||
pluginId: string;
|
||||
reason: string;
|
||||
@@ -93,7 +93,6 @@ function appendBlockedUserMessageWithSessionManager(params: {
|
||||
...(params.idempotencyKey ? { idempotencyKey: params.idempotencyKey } : {}),
|
||||
__openclaw: {
|
||||
beforeAgentRunBlocked: {
|
||||
content: params.originalText ? [{ type: "text", text: params.originalText }] : [],
|
||||
blockedBy: params.pluginId,
|
||||
reason: params.reason,
|
||||
blockedAt: Date.now(),
|
||||
@@ -1305,7 +1304,7 @@ describe("readSessionMessages", () => {
|
||||
});
|
||||
|
||||
expect(messageId).toBeTruthy();
|
||||
const out = readSessionMessages(sessionId, storePath, sessionFile, {});
|
||||
const out = readSessionMessages(sessionId, storePath, sessionFile);
|
||||
expect(
|
||||
out.map((message) => ({
|
||||
role: (message as { role?: string }).role,
|
||||
@@ -1316,10 +1315,7 @@ describe("readSessionMessages", () => {
|
||||
{ role: "assistant", text: "hi" },
|
||||
{ role: "user", text: [{ type: "text", text: "Blocked by HITL test hook." }] },
|
||||
]);
|
||||
expect(
|
||||
(out[2] as { __openclaw?: { beforeAgentRunBlocked?: { content?: unknown } } }).__openclaw
|
||||
?.beforeAgentRunBlocked?.content,
|
||||
).toEqual([{ type: "text", text: "[hitl:block] hello" }]);
|
||||
expect(JSON.stringify(out)).not.toContain("[hitl:block] hello");
|
||||
});
|
||||
|
||||
test("keeps repeated blocked hook messages together in a new session", async () => {
|
||||
@@ -1352,25 +1348,23 @@ describe("readSessionMessages", () => {
|
||||
appendBlockedUserMessageWithSessionManager({
|
||||
sessionFile,
|
||||
originalText: "[hitl:block] second",
|
||||
redactedText: "Blocked by HITL test hook.",
|
||||
redactedText: "Blocked again by HITL test hook.",
|
||||
pluginId: "hitl-test-hooks",
|
||||
reason: "blocked by test policy",
|
||||
});
|
||||
|
||||
const out = readSessionMessages(sessionId, storePath, sessionFile, {});
|
||||
const out = readSessionMessages(sessionId, storePath, sessionFile);
|
||||
expect(
|
||||
out.map((message) => ({
|
||||
role: (message as { role?: string }).role,
|
||||
original: (
|
||||
message as {
|
||||
__openclaw?: { beforeAgentRunBlocked?: { content?: Array<{ text?: string }> } };
|
||||
}
|
||||
).__openclaw?.beforeAgentRunBlocked?.content?.[0]?.text,
|
||||
text: (message as { content?: Array<{ text?: string }> }).content?.[0]?.text,
|
||||
})),
|
||||
).toEqual([
|
||||
{ role: "user", original: "[hitl:block] first" },
|
||||
{ role: "user", original: "[hitl:block] second" },
|
||||
{ role: "user", text: "Blocked by HITL test hook." },
|
||||
{ role: "user", text: "Blocked again by HITL test hook." },
|
||||
]);
|
||||
expect(JSON.stringify(out)).not.toContain("[hitl:block] first");
|
||||
expect(JSON.stringify(out)).not.toContain("[hitl:block] second");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -139,13 +139,10 @@ export function attachOpenClawTranscriptMeta(
|
||||
};
|
||||
}
|
||||
|
||||
type SessionMessageProjectionOptions = Record<never, never>;
|
||||
|
||||
export function readSessionMessages(
|
||||
sessionId: string,
|
||||
storePath: string | undefined,
|
||||
sessionFile?: string,
|
||||
opts?: SessionMessageProjectionOptions,
|
||||
): unknown[] {
|
||||
const candidates = resolveSessionTranscriptCandidates(sessionId, storePath, sessionFile);
|
||||
|
||||
@@ -154,20 +151,20 @@ export function readSessionMessages(
|
||||
return [];
|
||||
}
|
||||
|
||||
return transcriptRecordsToMessages(readSelectedTranscriptRecords(filePath), opts);
|
||||
return transcriptRecordsToMessages(readSelectedTranscriptRecords(filePath));
|
||||
}
|
||||
|
||||
export type ReadRecentSessionMessagesOptions = SessionMessageProjectionOptions & {
|
||||
export type ReadRecentSessionMessagesOptions = {
|
||||
maxMessages: number;
|
||||
maxBytes?: number;
|
||||
maxLines?: number;
|
||||
};
|
||||
|
||||
export type ReadSessionMessagesAsyncOptions =
|
||||
| ({
|
||||
| {
|
||||
mode: "full";
|
||||
reason: string;
|
||||
} & SessionMessageProjectionOptions)
|
||||
}
|
||||
| ({
|
||||
mode: "recent";
|
||||
} & ReadRecentSessionMessagesOptions);
|
||||
@@ -233,7 +230,7 @@ export function readRecentSessionMessages(
|
||||
.filter((line) => line.trim().length > 0)
|
||||
.slice(-maxLines);
|
||||
|
||||
return parseRecentTranscriptTailMessages(lines, maxMessages, opts);
|
||||
return parseRecentTranscriptTailMessages(lines, maxMessages);
|
||||
}) ?? []
|
||||
);
|
||||
}
|
||||
@@ -429,14 +426,11 @@ function readSelectedTranscriptRecords(filePath: string): TailTranscriptRecord[]
|
||||
}
|
||||
}
|
||||
|
||||
function transcriptRecordsToMessages(
|
||||
records: TailTranscriptRecord[],
|
||||
opts?: SessionMessageProjectionOptions,
|
||||
): unknown[] {
|
||||
function transcriptRecordsToMessages(records: TailTranscriptRecord[]): unknown[] {
|
||||
const messages: unknown[] = [];
|
||||
let messageSeq = 0;
|
||||
for (const entry of records) {
|
||||
const message = parsedSessionEntryToMessage(entry.record, messageSeq + 1, opts);
|
||||
const message = parsedSessionEntryToMessage(entry.record, messageSeq + 1);
|
||||
if (message) {
|
||||
messageSeq += 1;
|
||||
messages.push(message);
|
||||
@@ -445,18 +439,12 @@ function transcriptRecordsToMessages(
|
||||
return messages;
|
||||
}
|
||||
|
||||
function parseRecentTranscriptTailMessages(
|
||||
lines: string[],
|
||||
maxMessages: number,
|
||||
opts?: SessionMessageProjectionOptions,
|
||||
): unknown[] {
|
||||
function parseRecentTranscriptTailMessages(lines: string[], maxMessages: number): unknown[] {
|
||||
const entries = lines.flatMap((line) => {
|
||||
const entry = parseTailTranscriptRecord(line);
|
||||
return entry ? [entry] : [];
|
||||
});
|
||||
return transcriptRecordsToMessages(selectActiveTranscriptRecords(entries), opts).slice(
|
||||
-maxMessages,
|
||||
);
|
||||
return transcriptRecordsToMessages(selectActiveTranscriptRecords(entries)).slice(-maxMessages);
|
||||
}
|
||||
|
||||
function visitTranscriptLines(filePath: string, visit: (line: string) => void): void {
|
||||
@@ -576,7 +564,7 @@ export async function readSessionMessagesAsync(
|
||||
return [];
|
||||
}
|
||||
const index = await readSessionTranscriptIndex(filePath);
|
||||
return index?.entries.flatMap((entry) => indexedTranscriptEntryToMessages(entry, opts)) ?? [];
|
||||
return index?.entries.flatMap((entry) => indexedTranscriptEntryToMessages(entry)) ?? [];
|
||||
}
|
||||
|
||||
export async function visitSessionMessagesAsync(
|
||||
@@ -584,7 +572,7 @@ export async function visitSessionMessagesAsync(
|
||||
storePath: string | undefined,
|
||||
sessionFile: string | undefined,
|
||||
visit: (message: unknown, seq: number) => void,
|
||||
opts: { mode: "full"; reason: string },
|
||||
_opts: { mode: "full"; reason: string },
|
||||
): Promise<number> {
|
||||
const filePath = findExistingTranscriptPath(sessionId, storePath, sessionFile);
|
||||
if (!filePath) {
|
||||
@@ -595,7 +583,7 @@ export async function visitSessionMessagesAsync(
|
||||
return 0;
|
||||
}
|
||||
for (const entry of index.entries) {
|
||||
const message = indexedTranscriptEntryToMessage(entry, opts);
|
||||
const message = indexedTranscriptEntryToMessage(entry);
|
||||
if (message) {
|
||||
visit(message, entry.seq);
|
||||
}
|
||||
@@ -674,7 +662,7 @@ export async function readRecentSessionMessagesAsync(
|
||||
...opts,
|
||||
maxMessages,
|
||||
});
|
||||
return parseRecentTranscriptTailMessages(lines, maxMessages, opts);
|
||||
return parseRecentTranscriptTailMessages(lines, maxMessages);
|
||||
}
|
||||
|
||||
export async function readRecentSessionMessagesWithStatsAsync(
|
||||
@@ -728,11 +716,7 @@ export function readRecentSessionTranscriptLines(params: {
|
||||
return { lines, totalLines };
|
||||
}
|
||||
|
||||
function parsedSessionEntryToMessage(
|
||||
parsed: unknown,
|
||||
seq: number,
|
||||
opts?: SessionMessageProjectionOptions,
|
||||
): unknown {
|
||||
function parsedSessionEntryToMessage(parsed: unknown, seq: number): unknown {
|
||||
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
||||
return null;
|
||||
}
|
||||
@@ -763,18 +747,12 @@ function parsedSessionEntryToMessage(
|
||||
return null;
|
||||
}
|
||||
|
||||
function indexedTranscriptEntryToMessage(
|
||||
entry: IndexedTranscriptEntry,
|
||||
opts?: SessionMessageProjectionOptions,
|
||||
): unknown {
|
||||
return parsedSessionEntryToMessage(entry.record, entry.seq, opts);
|
||||
function indexedTranscriptEntryToMessage(entry: IndexedTranscriptEntry): unknown {
|
||||
return parsedSessionEntryToMessage(entry.record, entry.seq);
|
||||
}
|
||||
|
||||
function indexedTranscriptEntryToMessages(
|
||||
entry: IndexedTranscriptEntry,
|
||||
opts?: SessionMessageProjectionOptions,
|
||||
): unknown[] {
|
||||
const message = indexedTranscriptEntryToMessage(entry, opts);
|
||||
function indexedTranscriptEntryToMessages(entry: IndexedTranscriptEntry): unknown[] {
|
||||
const message = indexedTranscriptEntryToMessage(entry);
|
||||
return message ? [message] : [];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user