mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-14 22:54:01 -06:00
63 lines
2.1 KiB
TypeScript
63 lines
2.1 KiB
TypeScript
/**
|
|
* Shared helpers for clearing assistant usage snapshots invalidated by
|
|
* transcript compaction.
|
|
*/
|
|
import type { AgentMessage } from "./runtime/index.js";
|
|
import { makeZeroUsageSnapshot } from "./usage.js";
|
|
|
|
function parseCompactionUsageTimestamp(value: unknown): number | null {
|
|
return parseDateFirstTimestampMs(value) ?? null;
|
|
}
|
|
|
|
export function stripStaleAssistantUsageBeforeLatestCompaction<TMessage extends AgentMessage>(
|
|
messages: TMessage[],
|
|
options: {
|
|
mutate?: boolean;
|
|
whenMissingCompactionSummary?: "preserve" | "zeroAssistantUsage";
|
|
} = {},
|
|
): TMessage[] {
|
|
const latestCompactionSummaryIndex = messages.findLastIndex(
|
|
(entry) => entry?.role === "compactionSummary",
|
|
);
|
|
const hasCompactionSummary = latestCompactionSummaryIndex !== -1;
|
|
if (!hasCompactionSummary && options.whenMissingCompactionSummary !== "zeroAssistantUsage") {
|
|
return messages;
|
|
}
|
|
|
|
const latestCompactionTimestamp = parseCompactionUsageTimestamp(
|
|
(messages[latestCompactionSummaryIndex] as { timestamp?: unknown } | undefined)?.timestamp,
|
|
);
|
|
let out = messages;
|
|
for (let i = 0; i < messages.length; i += 1) {
|
|
const candidate = messages[i] as
|
|
| (AgentMessage & { usage?: unknown; timestamp?: unknown })
|
|
| undefined;
|
|
if (
|
|
candidate?.role !== "assistant" ||
|
|
!candidate.usage ||
|
|
typeof candidate.usage !== "object"
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
const messageTimestamp = parseCompactionUsageTimestamp(candidate.timestamp);
|
|
const stale =
|
|
!hasCompactionSummary ||
|
|
(latestCompactionTimestamp !== null && messageTimestamp !== null
|
|
? messageTimestamp <= latestCompactionTimestamp
|
|
: i < latestCompactionSummaryIndex);
|
|
if (!stale) {
|
|
continue;
|
|
}
|
|
|
|
// Session runtime expects assistant usage to stay structurally valid during
|
|
// accounting. Keep stale snapshots present, but zeroed after compaction.
|
|
if (out === messages && !options.mutate) {
|
|
out = [...messages];
|
|
}
|
|
out[i] = { ...candidate, usage: makeZeroUsageSnapshot() } as TMessage;
|
|
}
|
|
return out;
|
|
}
|
|
import { parseDateFirstTimestampMs } from "@openclaw/normalization-core/number-coercion";
|