

















@@ -51,6 +51,14 @@ function registerXaiAutoEnableProbe(): XaiAutoEnableProbe {
5151return probe;
5252}
535354+function requireEntry<T extends { id?: string }>(entries: T[], id: string): T {
55+const entry = entries.find((candidate) => candidate.id === id);
56+if (!entry) {
57+throw new Error(`Expected entry ${id}`);
58+}
59+return entry;
60+}
61+5462describe("xai provider plugin", () => {
5563it("registers xAI speech providers for batch and streaming STT", async () => {
5664const { mediaProviders, realtimeTranscriptionProviders } = await registerProviderPlugin({
@@ -59,24 +67,12 @@ describe("xai provider plugin", () => {
5967name: "xAI Provider",
6068});
616962-expect(mediaProviders).toEqual(
63-expect.arrayContaining([
64-expect.objectContaining({
65-id: "xai",
66-capabilities: ["audio"],
67-defaultModels: { audio: "grok-stt" },
68-}),
69-]),
70-);
71-expect(realtimeTranscriptionProviders).toEqual(
72-expect.arrayContaining([
73-expect.objectContaining({
74-id: "xai",
75-label: "xAI Realtime Transcription",
76-aliases: expect.arrayContaining(["xai-realtime"]),
77-}),
78-]),
79-);
70+const mediaProvider = requireEntry(mediaProviders, "xai");
71+expect(mediaProvider.capabilities).toEqual(["audio"]);
72+expect(mediaProvider.defaultModels).toEqual({ audio: "grok-stt" });
73+const realtimeProvider = requireEntry(realtimeTranscriptionProviders, "xai");
74+expect(realtimeProvider.label).toBe("xAI Realtime Transcription");
75+expect(realtimeProvider.aliases).toContain("xai-realtime");
8076});
81778278it("declares setup auto-enable reasons for plugin-owned tool config", () => {
@@ -102,33 +98,27 @@ describe("xai provider plugin", () => {
10298it("owns replay policy for xAI OpenAI-compatible transports", async () => {
10399const provider = await registerSingleProviderPlugin(plugin);
104100105-expect(
106-provider.buildReplayPolicy?.({
107-provider: "xai",
108-modelApi: "openai-completions",
109-modelId: "grok-3",
110-} as never),
111-).toMatchObject({
112-sanitizeToolCallIds: true,
113-toolCallIdMode: "strict",
114-applyAssistantFirstOrderingFix: true,
115-validateGeminiTurns: true,
116-validateAnthropicTurns: true,
117-});
101+const completionsPolicy = provider.buildReplayPolicy?.({
102+provider: "xai",
103+modelApi: "openai-completions",
104+modelId: "grok-3",
105+} as never);
106+expect(completionsPolicy?.sanitizeToolCallIds).toBe(true);
107+expect(completionsPolicy?.toolCallIdMode).toBe("strict");
108+expect(completionsPolicy?.applyAssistantFirstOrderingFix).toBe(true);
109+expect(completionsPolicy?.validateGeminiTurns).toBe(true);
110+expect(completionsPolicy?.validateAnthropicTurns).toBe(true);
118111119-expect(
120-provider.buildReplayPolicy?.({
121-provider: "xai",
122-modelApi: "openai-responses",
123-modelId: "grok-4-fast",
124-} as never),
125-).toMatchObject({
126-sanitizeToolCallIds: true,
127-toolCallIdMode: "strict",
128-applyAssistantFirstOrderingFix: false,
129-validateGeminiTurns: false,
130-validateAnthropicTurns: false,
131-});
112+const responsesPolicy = provider.buildReplayPolicy?.({
113+provider: "xai",
114+modelApi: "openai-responses",
115+modelId: "grok-4-fast",
116+} as never);
117+expect(responsesPolicy?.sanitizeToolCallIds).toBe(true);
118+expect(responsesPolicy?.toolCallIdMode).toBe("strict");
119+expect(responsesPolicy?.applyAssistantFirstOrderingFix).toBe(false);
120+expect(responsesPolicy?.validateGeminiTurns).toBe(false);
121+expect(responsesPolicy?.validateAnthropicTurns).toBe(false);
132122});
133123134124it("wires provider stream shaping for fast mode and tool-stream defaults", async () => {
@@ -173,25 +163,22 @@ describe("xai provider plugin", () => {
173163it("owns forward-compatible Grok model resolution", async () => {
174164const provider = await registerSingleProviderPlugin(plugin);
175165176-expect(
177-provider.resolveDynamicModel?.({
178-provider: "xai",
179-modelId: "grok-4.3",
180-modelRegistry: { find: () => null } as never,
181-providerConfig: {
182-api: "openai-completions",
183-baseUrl: "https://api.x.ai/v1",
184-},
185-} as never),
186-).toMatchObject({
187-id: "grok-4.3",
166+const resolved = provider.resolveDynamicModel?.({
188167provider: "xai",
189-api: "openai-completions",
190-baseUrl: "https://api.x.ai/v1",
191-reasoning: true,
192-input: ["text", "image"],
193-contextWindow: 1_000_000,
194-});
168+modelId: "grok-4.3",
169+modelRegistry: { find: () => null } as never,
170+providerConfig: {
171+api: "openai-completions",
172+baseUrl: "https://api.x.ai/v1",
173+},
174+} as never);
175+expect(resolved?.id).toBe("grok-4.3");
176+expect(resolved?.provider).toBe("xai");
177+expect(resolved?.api).toBe("openai-completions");
178+expect(resolved?.baseUrl).toBe("https://api.x.ai/v1");
179+expect(resolved?.reasoning).toBe(true);
180+expect(resolved?.input).toEqual(["text", "image"]);
181+expect(resolved?.contextWindow).toBe(1_000_000);
195182});
196183197184it("marks modern Grok refs without accepting multi-agent ids", async () => {
@@ -214,41 +201,41 @@ describe("xai provider plugin", () => {
214201it("owns xai compat flags for direct and downstream routed models", async () => {
215202const provider = await registerSingleProviderPlugin(plugin);
216203217-expect(
218-provider.normalizeResolvedModel?.({
219-provider: "xai",
220-modelId: "grok-4-1-fast",
221-model: createProviderModel({ id: "grok-4-1-fast" }),
222-} as never),
223-).toMatchObject({
224-thinkingLevelMap: {
225-off: null,
226-minimal: null,
227-low: null,
228-medium: null,
229-high: null,
230-xhigh: null,
231-},
232-compat: {
233-toolSchemaProfile: "xai",
234-nativeWebSearchTool: true,
235-toolCallArgumentsEncoding: "html-entities",
236-},
204+const normalized = provider.normalizeResolvedModel?.({
205+provider: "xai",
206+modelId: "grok-4-1-fast",
207+model: createProviderModel({ id: "grok-4-1-fast" }),
208+} as never);
209+expect(normalized?.thinkingLevelMap).toEqual({
210+off: null,
211+minimal: null,
212+low: null,
213+medium: null,
214+high: null,
215+xhigh: null,
237216});
238-expect(
239-provider.contributeResolvedModelCompat?.({
217+const normalizedCompat = normalized?.compat as
218+| {
219+toolSchemaProfile?: string;
220+nativeWebSearchTool?: boolean;
221+toolCallArgumentsEncoding?: string;
222+}
223+| undefined;
224+expect(normalizedCompat?.toolSchemaProfile).toBe("xai");
225+expect(normalizedCompat?.nativeWebSearchTool).toBe(true);
226+expect(normalizedCompat?.toolCallArgumentsEncoding).toBe("html-entities");
227+228+const compat = provider.contributeResolvedModelCompat?.({
229+provider: "openrouter",
230+modelId: "x-ai/grok-4-1-fast",
231+model: createProviderModel({
232+id: "x-ai/grok-4-1-fast",
240233provider: "openrouter",
241-modelId: "x-ai/grok-4-1-fast",
242-model: createProviderModel({
243-id: "x-ai/grok-4-1-fast",
244-provider: "openrouter",
245-baseUrl: "https://openrouter.ai/api/v1",
246-}),
247-} as never),
248-).toMatchObject({
249-toolSchemaProfile: "xai",
250-nativeWebSearchTool: true,
251-toolCallArgumentsEncoding: "html-entities",
252-});
234+baseUrl: "https://openrouter.ai/api/v1",
235+}),
236+} as never);
237+expect(compat?.toolSchemaProfile).toBe("xai");
238+expect(compat?.nativeWebSearchTool).toBe(true);
239+expect(compat?.toolCallArgumentsEncoding).toBe("html-entities");
253240});
254241});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。