mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-13 10:11:20 +00:00
99 lines
2.4 KiB
TypeScript
99 lines
2.4 KiB
TypeScript
import type { StreamFn } from "@mariozechner/pi-agent-core";
|
|
import { describe, expect, it } from "vitest";
|
|
import {
|
|
createHtmlEntityToolCallArgumentDecodingWrapper,
|
|
decodeHtmlEntitiesInObject,
|
|
} from "./provider-stream-shared.js";
|
|
|
|
type FakeWrappedStream = {
|
|
result: () => Promise<unknown>;
|
|
[Symbol.asyncIterator]: () => AsyncIterator<unknown>;
|
|
};
|
|
|
|
function createFakeStream(params: {
|
|
events: unknown[];
|
|
resultMessage: unknown;
|
|
}): FakeWrappedStream {
|
|
return {
|
|
async result() {
|
|
return params.resultMessage;
|
|
},
|
|
[Symbol.asyncIterator]() {
|
|
return (async function* () {
|
|
for (const event of params.events) {
|
|
yield event;
|
|
}
|
|
})();
|
|
},
|
|
};
|
|
}
|
|
|
|
describe("decodeHtmlEntitiesInObject", () => {
|
|
it("recursively decodes string values", () => {
|
|
expect(
|
|
decodeHtmlEntitiesInObject({
|
|
command: "cd ~/dev && echo "ok"",
|
|
args: ["<input>", "'quoted'"],
|
|
}),
|
|
).toEqual({
|
|
command: 'cd ~/dev && echo "ok"',
|
|
args: ["<input>", "'quoted'"],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("createHtmlEntityToolCallArgumentDecodingWrapper", () => {
|
|
it("decodes tool call arguments in final and streaming messages", async () => {
|
|
const resultMessage = {
|
|
content: [
|
|
{
|
|
type: "toolCall",
|
|
arguments: { command: "echo "result" && true" },
|
|
},
|
|
],
|
|
};
|
|
const streamEvent = {
|
|
partial: {
|
|
content: [
|
|
{
|
|
type: "toolCall",
|
|
arguments: { path: "<stream>", nested: { quote: "'x'" } },
|
|
},
|
|
],
|
|
},
|
|
};
|
|
const baseStreamFn: StreamFn = () =>
|
|
createFakeStream({ events: [streamEvent], resultMessage }) as never;
|
|
|
|
const stream = createHtmlEntityToolCallArgumentDecodingWrapper(baseStreamFn)(
|
|
{} as never,
|
|
{} as never,
|
|
{},
|
|
) as FakeWrappedStream;
|
|
|
|
await expect(stream.result()).resolves.toEqual({
|
|
content: [
|
|
{
|
|
type: "toolCall",
|
|
arguments: { command: 'echo "result" && true' },
|
|
},
|
|
],
|
|
});
|
|
|
|
const iterator = stream[Symbol.asyncIterator]();
|
|
await expect(iterator.next()).resolves.toEqual({
|
|
done: false,
|
|
value: {
|
|
partial: {
|
|
content: [
|
|
{
|
|
type: "toolCall",
|
|
arguments: { path: "<stream>", nested: { quote: "'x'" } },
|
|
},
|
|
],
|
|
},
|
|
},
|
|
});
|
|
});
|
|
});
|