mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 22:24:46 +00:00
Centralize agent stable serialization for cache tracing, models config fingerprinting, and tool-loop hashing. Adds focused coverage for sorted keys, true cycles, repeated references, cache-trace edge types, and circular tool-call hashing. Verification: - pnpm test src/agents/stable-stringify.test.ts src/agents/tool-loop-detection.test.ts src/agents/cache-trace.test.ts -- --reporter=verbose - OPENCLAW_TESTBOX=0 pnpm check:changed - GitHub CI: https://github.com/openclaw/openclaw/actions/runs/25716851500 - Real behavior proof: https://github.com/openclaw/openclaw/actions/runs/25717047037 Co-authored-by: Gabriel Piss <gabriel@gabeos.dev>
47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { stableStringify } from "./stable-stringify.js";
|
|
|
|
describe("stableStringify", () => {
|
|
it("sorts object keys recursively", () => {
|
|
expect(stableStringify({ b: { d: 4, c: 3 }, a: 1 })).toBe('{"a":1,"b":{"c":3,"d":4}}');
|
|
});
|
|
|
|
it("marks true circular references without collapsing repeated references", () => {
|
|
const shared = { value: 1 };
|
|
const root: Record<string, unknown> = { first: shared, second: shared };
|
|
root.self = root;
|
|
|
|
expect(stableStringify(root)).toBe(
|
|
'{"first":{"value":1},"second":{"value":1},"self":"[Circular]"}',
|
|
);
|
|
});
|
|
|
|
it("handles circular arrays without treating later siblings as circular", () => {
|
|
const shared = { value: "same" };
|
|
const items: unknown[] = [shared, shared];
|
|
items.push(items);
|
|
|
|
expect(stableStringify(items)).toBe('[{"value":"same"},{"value":"same"},"[Circular]"]');
|
|
});
|
|
|
|
it("serializes cache-trace edge types deterministically", () => {
|
|
const error = new Error("boom");
|
|
error.stack = "Error: boom\n at test";
|
|
|
|
expect(
|
|
stableStringify({
|
|
bytes: new Uint8Array([1, 2, 3]),
|
|
error,
|
|
finite: 1,
|
|
infinity: Infinity,
|
|
nan: Number.NaN,
|
|
nil: null,
|
|
token: 123n,
|
|
undef: undefined,
|
|
}),
|
|
).toBe(
|
|
'{"bytes":{"data":"AQID","type":"Uint8Array"},"error":{"message":"boom","name":"Error","stack":"Error: boom\\n at test"},"finite":1,"infinity":"Infinity","nan":"NaN","nil":null,"token":"123","undef":undefined}',
|
|
);
|
|
});
|
|
});
|