fix(web-search): parsed double-encoded zai results

Decoded the extra JSON string layer returned by Z.AI MCP search and kept structured payloads out of answer text.

Added regression coverage for source extraction and plain prose preservation.

Fixes #8000
This commit is contained in:
roboomp
2026-08-08 09:04:04 +00:00
parent 08819b279c
commit a709a6604f
3 changed files with 26 additions and 8 deletions
+4
View File
@@ -2,6 +2,10 @@
## [Unreleased]
### Fixed
- Fixed Z.AI web search dropping sources and exposing raw JSON when MCP responses double-encode content text ([#8000](https://github.com/can1357/oh-my-pi/issues/8000)).
## [17.2.11] - 2026-08-07
### Added
@@ -353,11 +353,20 @@ function parseSearchPayload(rawResult: unknown): {
for (const part of content) {
const text = isRecord(part) ? asString(part.text) : null;
if (!text) continue;
textParts.push(text);
try {
candidates.push(JSON.parse(text));
let parsed: unknown = JSON.parse(text);
if (typeof parsed === "string") {
try {
parsed = JSON.parse(parsed);
} catch {
// The decoded string is answer text rather than another JSON payload.
}
}
candidates.push(parsed);
if (getSearchResults(parsed).length === 0) textParts.push(text);
} catch {
// Not JSON payload; keep as fallback answer text.
// Non-JSON content is preserved as answer text.
textParts.push(text);
}
}
}
@@ -9,7 +9,7 @@ interface CapturedRequest {
}
describe("Z.AI web search provider", () => {
it("initializes a Streamable HTTP MCP session before calling web_search_prime", async () => {
it("initializes a Streamable HTTP MCP session and parses doubly encoded results", async () => {
const capturedRequests: CapturedRequest[] = [];
const fetchImpl: FetchImpl = (_input, init) => {
const request = {
@@ -53,16 +53,20 @@ describe("Z.AI web search provider", () => {
content: [
{
type: "text",
text: JSON.stringify({
search_result: [
text: JSON.stringify(
JSON.stringify([
{
title: "Z.AI search result",
content: "Search result content",
link: "https://example.com/zai",
media: "Example",
},
],
}),
]),
),
},
{
type: "text",
text: "Plain prose answer.",
},
],
},
@@ -107,6 +111,7 @@ describe("Z.AI web search provider", () => {
author: "Example",
},
]);
expect(response.answer).toBe("Plain prose answer.");
});
function createMcpFetch(): { fetchImpl: FetchImpl; capturedRequests: CapturedRequest[] } {