refactor: dedupe xai search response parsing

This commit is contained in:
Peter Steinberger
2026-04-06 18:15:27 +01:00
parent fe7059696b
commit 317e3f631a
4 changed files with 42 additions and 20 deletions

View File

@@ -51,4 +51,22 @@ describe("xai responses tool helpers", () => {
citations: ["https://example.com/b"],
});
});
it("includes inline citations only when enabled", () => {
const data = {
output_text: "Done",
citations: ["https://example.com/b"],
inline_citations: [{ start_index: 0, end_index: 4, url: "https://example.com/b" }],
};
expect(__testing.resolveXaiResponseTextCitationsAndInline(data, true)).toEqual({
content: "Done",
citations: ["https://example.com/b"],
inlineCitations: [{ start_index: 0, end_index: 4, url: "https://example.com/b" }],
});
expect(__testing.resolveXaiResponseTextCitationsAndInline(data, false)).toEqual({
content: "Done",
citations: ["https://example.com/b"],
inlineCitations: undefined,
});
});
});

View File

@@ -65,9 +65,29 @@ export function resolveXaiResponseTextAndCitations(data: XaiWebSearchResponse):
};
}
export function resolveXaiResponseTextCitationsAndInline(
data: XaiWebSearchResponse,
inlineCitationsEnabled: boolean,
): {
content: string;
citations: string[];
inlineCitations?: XaiWebSearchResponse["inline_citations"];
} {
const { content, citations } = resolveXaiResponseTextAndCitations(data);
return {
content,
citations,
inlineCitations:
inlineCitationsEnabled && Array.isArray(data.inline_citations)
? data.inline_citations
: undefined,
};
}
export const __testing = {
buildXaiResponsesToolBody,
extractXaiWebSearchContent,
resolveXaiResponseTextCitationsAndInline,
resolveXaiResponseTextAndCitations,
XAI_RESPONSES_ENDPOINT,
} as const;

View File

@@ -3,7 +3,7 @@ import { normalizeXaiModelId } from "../model-id.js";
import {
buildXaiResponsesToolBody,
extractXaiWebSearchContent,
resolveXaiResponseTextAndCitations,
resolveXaiResponseTextCitationsAndInline,
XAI_RESPONSES_ENDPOINT,
} from "./responses-tool-shared.js";
export { extractXaiWebSearchContent } from "./responses-tool-shared.js";
@@ -116,15 +116,7 @@ export async function requestXaiWebSearch(params: {
},
async (response) => {
const data = (await response.json()) as XaiWebSearchResponse;
const { content, citations } = resolveXaiResponseTextAndCitations(data);
return {
content,
citations,
inlineCitations:
params.inlineCitations && Array.isArray(data.inline_citations)
? data.inline_citations
: undefined,
};
return resolveXaiResponseTextCitationsAndInline(data, params.inlineCitations);
},
);
}

View File

@@ -1,7 +1,7 @@
import { postTrustedWebToolsJson, wrapWebContent } from "@openclaw/plugin-sdk/provider-web-search";
import {
buildXaiResponsesToolBody,
resolveXaiResponseTextAndCitations,
resolveXaiResponseTextCitationsAndInline,
XAI_RESPONSES_ENDPOINT,
} from "./responses-tool-shared.js";
import {
@@ -127,15 +127,7 @@ export async function requestXaiXSearch(params: {
},
async (response) => {
const data = (await response.json()) as XaiWebSearchResponse;
const { content, citations } = resolveXaiResponseTextAndCitations(data);
return {
content,
citations,
inlineCitations:
params.inlineCitations && Array.isArray(data.inline_citations)
? data.inline_citations
: undefined,
};
return resolveXaiResponseTextCitationsAndInline(data, params.inlineCitations);
},
);
}