mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 18:20:44 +00:00
test: share pi embedded helper setup
This commit is contained in:
@@ -121,6 +121,26 @@ async function emitMcpMediaToolResult(ctx: EmbeddedPiSubscribeContext, mediaPath
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleCaseVariantBuiltinMedia(mediaPathOrUrl: string) {
|
||||||
|
const ctx = createMockContext({
|
||||||
|
shouldEmitToolOutput: false,
|
||||||
|
onToolResult: vi.fn(),
|
||||||
|
builtinToolNames: new Set(["web_search"]),
|
||||||
|
});
|
||||||
|
|
||||||
|
await handleToolExecutionEnd(ctx, {
|
||||||
|
type: "tool_execution_end",
|
||||||
|
toolName: "Web_Search",
|
||||||
|
toolCallId: "tc-1",
|
||||||
|
isError: false,
|
||||||
|
result: {
|
||||||
|
content: [{ type: "text", text: `MEDIA:${mediaPathOrUrl}` }],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
describe("handleToolExecutionEnd media emission", () => {
|
describe("handleToolExecutionEnd media emission", () => {
|
||||||
it("does not warn for read tool when path is provided via file_path alias", async () => {
|
it("does not warn for read tool when path is provided via file_path alias", async () => {
|
||||||
const ctx = createMockContext();
|
const ctx = createMockContext();
|
||||||
@@ -176,41 +196,13 @@ describe("handleToolExecutionEnd media emission", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("does NOT emit local media for case-variant collisions with trusted built-ins", async () => {
|
it("does NOT emit local media for case-variant collisions with trusted built-ins", async () => {
|
||||||
const ctx = createMockContext({
|
const ctx = await handleCaseVariantBuiltinMedia("/tmp/secret.png");
|
||||||
shouldEmitToolOutput: false,
|
|
||||||
onToolResult: vi.fn(),
|
|
||||||
builtinToolNames: new Set(["web_search"]),
|
|
||||||
});
|
|
||||||
|
|
||||||
await handleToolExecutionEnd(ctx, {
|
|
||||||
type: "tool_execution_end",
|
|
||||||
toolName: "Web_Search",
|
|
||||||
toolCallId: "tc-1",
|
|
||||||
isError: false,
|
|
||||||
result: {
|
|
||||||
content: [{ type: "text", text: "MEDIA:/tmp/secret.png" }],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(ctx.state.pendingToolMediaUrls).toEqual([]);
|
expect(ctx.state.pendingToolMediaUrls).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("still emits remote media for case-variant collisions with trusted built-ins", async () => {
|
it("still emits remote media for case-variant collisions with trusted built-ins", async () => {
|
||||||
const ctx = createMockContext({
|
const ctx = await handleCaseVariantBuiltinMedia("https://example.com/file.png");
|
||||||
shouldEmitToolOutput: false,
|
|
||||||
onToolResult: vi.fn(),
|
|
||||||
builtinToolNames: new Set(["web_search"]),
|
|
||||||
});
|
|
||||||
|
|
||||||
await handleToolExecutionEnd(ctx, {
|
|
||||||
type: "tool_execution_end",
|
|
||||||
toolName: "Web_Search",
|
|
||||||
toolCallId: "tc-1",
|
|
||||||
isError: false,
|
|
||||||
result: {
|
|
||||||
content: [{ type: "text", text: "MEDIA:https://example.com/file.png" }],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(ctx.state.pendingToolMediaUrls).toEqual(["https://example.com/file.png"]);
|
expect(ctx.state.pendingToolMediaUrls).toEqual(["https://example.com/file.png"]);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -74,6 +74,30 @@ function emitOpenAiResponsesFinalMessageEnd(params: {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function emitSuppressedCommentary(params: {
|
||||||
|
emit: TextEndBlockReplyHarness["emit"];
|
||||||
|
text: string;
|
||||||
|
}) {
|
||||||
|
params.emit({ type: "message_start", message: { role: "assistant" } });
|
||||||
|
emitOpenAiResponsesTextDeltaAndEnd({
|
||||||
|
emit: params.emit,
|
||||||
|
text: params.text,
|
||||||
|
id: "item_commentary",
|
||||||
|
phase: "commentary",
|
||||||
|
});
|
||||||
|
await Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
function expectSingleBlockReplyText(params: {
|
||||||
|
onBlockReply: ReturnType<typeof vi.fn>;
|
||||||
|
subscription: TextEndBlockReplyHarness["subscription"];
|
||||||
|
text: string;
|
||||||
|
}) {
|
||||||
|
expect(params.onBlockReply).toHaveBeenCalledTimes(1);
|
||||||
|
expect(params.onBlockReply.mock.calls[0]?.[0]?.text).toBe(params.text);
|
||||||
|
expect(params.subscription.assistantTexts).toEqual([params.text]);
|
||||||
|
}
|
||||||
|
|
||||||
describe("subscribeEmbeddedPiSession", () => {
|
describe("subscribeEmbeddedPiSession", () => {
|
||||||
it("emits block replies on text_end and does not duplicate on message_end", async () => {
|
it("emits block replies on text_end and does not duplicate on message_end", async () => {
|
||||||
const onBlockReply = vi.fn();
|
const onBlockReply = vi.fn();
|
||||||
@@ -167,14 +191,7 @@ describe("subscribeEmbeddedPiSession", () => {
|
|||||||
const onBlockReply = vi.fn();
|
const onBlockReply = vi.fn();
|
||||||
const { emit, subscription } = createTextEndBlockReplyHarness({ onBlockReply });
|
const { emit, subscription } = createTextEndBlockReplyHarness({ onBlockReply });
|
||||||
|
|
||||||
emit({ type: "message_start", message: { role: "assistant" } });
|
await emitSuppressedCommentary({ emit, text: "Working..." });
|
||||||
emitOpenAiResponsesTextDeltaAndEnd({
|
|
||||||
emit,
|
|
||||||
text: "Working...",
|
|
||||||
id: "item_commentary",
|
|
||||||
phase: "commentary",
|
|
||||||
});
|
|
||||||
await Promise.resolve();
|
|
||||||
|
|
||||||
expect(onBlockReply).not.toHaveBeenCalled();
|
expect(onBlockReply).not.toHaveBeenCalled();
|
||||||
expect(subscription.assistantTexts).toEqual([]);
|
expect(subscription.assistantTexts).toEqual([]);
|
||||||
@@ -189,9 +206,7 @@ describe("subscribeEmbeddedPiSession", () => {
|
|||||||
|
|
||||||
emitOpenAiResponsesFinalMessageEnd({ emit, commentaryText: "Working...", finalText: "Done." });
|
emitOpenAiResponsesFinalMessageEnd({ emit, commentaryText: "Working...", finalText: "Done." });
|
||||||
|
|
||||||
expect(onBlockReply).toHaveBeenCalledTimes(1);
|
expectSingleBlockReplyText({ onBlockReply, subscription, text: "Done." });
|
||||||
expect(onBlockReply.mock.calls[0]?.[0]?.text).toBe("Done.");
|
|
||||||
expect(subscription.assistantTexts).toEqual(["Done."]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("emits the full final answer on text_end when it extends suppressed commentary", async () => {
|
it("emits the full final answer on text_end when it extends suppressed commentary", async () => {
|
||||||
@@ -253,19 +268,10 @@ describe("subscribeEmbeddedPiSession", () => {
|
|||||||
const onBlockReply = vi.fn();
|
const onBlockReply = vi.fn();
|
||||||
const { emit, subscription } = createTextEndBlockReplyHarness({ onBlockReply });
|
const { emit, subscription } = createTextEndBlockReplyHarness({ onBlockReply });
|
||||||
|
|
||||||
emit({ type: "message_start", message: { role: "assistant" } });
|
await emitSuppressedCommentary({ emit, text: "Working..." });
|
||||||
emitOpenAiResponsesTextDeltaAndEnd({
|
|
||||||
emit,
|
|
||||||
text: "Working...",
|
|
||||||
id: "item_commentary",
|
|
||||||
phase: "commentary",
|
|
||||||
});
|
|
||||||
await Promise.resolve();
|
|
||||||
|
|
||||||
emitOpenAiResponsesFinalMessageEnd({ emit, commentaryText: "Working...", finalText: "Done." });
|
emitOpenAiResponsesFinalMessageEnd({ emit, commentaryText: "Working...", finalText: "Done." });
|
||||||
|
|
||||||
expect(onBlockReply).toHaveBeenCalledTimes(1);
|
expectSingleBlockReplyText({ onBlockReply, subscription, text: "Done." });
|
||||||
expect(onBlockReply.mock.calls[0]?.[0]?.text).toBe("Done.");
|
|
||||||
expect(subscription.assistantTexts).toEqual(["Done."]);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user