fix(onepassword): preserve Unicode in audit reason truncation (#106424)

* fix(onepassword): preserve Unicode in audit reason truncation

* test(onepassword): strengthen Unicode audit boundary proof

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
Leon-SK668
2026-07-14 08:01:14 +08:00
committed by GitHub
parent 48817f6cea
commit 5864fa2dbf
2 changed files with 35 additions and 1 deletions

View File

@@ -127,4 +127,37 @@ describe("1Password CLI output", () => {
expect(rows[0]?.reason).toHaveLength(80);
expect(JSON.stringify(rows)).not.toContain(["fixture", "value"].join("-"));
});
it("preserves complete surrogate pairs at the audit reason boundary", async () => {
const store = new MemoryKeyedStore<AuditRow>();
await store.register("split", {
timestampMs: 1000,
agentId: "agent-a",
sessionKey: "session-a",
toolCallId: "call-a",
slug: "alpha",
reason: `${"x".repeat(76)}\u{1f600}tail`,
outcome: "auto",
});
await store.register("fits", {
timestampMs: 2000,
agentId: "agent-a",
sessionKey: "session-a",
toolCallId: "call-b",
slug: "alpha",
reason: `${"x".repeat(75)}\u{1f600}tail`,
outcome: "auto",
});
const { onepassword, write } = setupCommands(store);
await onepassword.child("audit").run({ limit: "2" });
const output = String(write.mock.calls[0]?.[0]);
expect(output).not.toContain("\\ud83d");
const rows = JSON.parse(output) as Array<Record<string, unknown>>;
expect(rows.map((row) => row.reason)).toEqual([
`${"x".repeat(75)}\u{1f600}...`,
`${"x".repeat(76)}...`,
]);
});
});

View File

@@ -1,4 +1,5 @@
import type { PluginStateKeyedStore } from "openclaw/plugin-sdk/plugin-state-runtime";
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
import type { AuditRow } from "./broker.js";
import type { OnePasswordConfig } from "./config.js";
import type { OpClient } from "./op-client.js";
@@ -30,7 +31,7 @@ function parseLimit(value: unknown): number {
}
function truncateReason(reason: string): string {
return reason.length <= 80 ? reason : `${reason.slice(0, 77)}...`;
return reason.length <= 80 ? reason : `${truncateUtf16Safe(reason, 77)}...`;
}
async function buildStatus(