





















@@ -321,4 +321,95 @@ describe("createStreamFnWithExtraParams sampling overrides", () => {
321321expect(first).not.toHaveProperty("responseFormat");
322322expect(first.temperature).toBe(0.4);
323323});
324+325+it("forwards frequency_penalty, presence_penalty, and seed from override into stream options", () => {
326+const underlying = vi.fn(() => ({
327+push: vi.fn(),
328+result: vi.fn(async () => undefined),
329+[Symbol.asyncIterator]: vi.fn(async function* () {}),
330+})) as unknown as StreamFn;
331+const agent: { streamFn?: StreamFn } = { streamFn: underlying };
332+333+applyExtraParamsToAgent(agent, undefined, "openai", "gpt-5.4", {
334+frequencyPenalty: 0.8,
335+presencePenalty: 0.3,
336+seed: 12345,
337+});
338+339+if (!agent.streamFn) {
340+throw new Error("expected extra params to wrap streamFn");
341+}
342+343+void agent.streamFn(
344+{ id: "gpt-5.4", api: "openai-completions", provider: "openai" } as never,
345+{ messages: [], tools: [] } as never,
346+undefined,
347+);
348+349+expect(underlying).toHaveBeenCalledTimes(1);
350+const callOptions = (underlying as unknown as { mock: { calls: unknown[][] } }).mock
351+.calls[0]?.[2] as
352+| {
353+frequencyPenalty?: number;
354+presencePenalty?: number;
355+seed?: number;
356+}
357+| undefined;
358+expect(callOptions?.frequencyPenalty).toBe(0.8);
359+expect(callOptions?.presencePenalty).toBe(0.3);
360+expect(callOptions?.seed).toBe(12345);
361+});
362+363+it("prefers camelCase runtime overrides over snake_case config for penalty params", () => {
364+const underlying = vi.fn(() => ({
365+push: vi.fn(),
366+result: vi.fn(async () => undefined),
367+[Symbol.asyncIterator]: vi.fn(async function* () {}),
368+})) as unknown as StreamFn;
369+const agent: { streamFn?: StreamFn } = { streamFn: underlying };
370+371+applyExtraParamsToAgent(
372+agent,
373+{
374+agents: {
375+defaults: {
376+models: {
377+"openai/gpt-5.4": {
378+params: {
379+frequency_penalty: 0.1,
380+presence_penalty: 0.1,
381+},
382+},
383+},
384+},
385+},
386+},
387+"openai",
388+"gpt-5.4",
389+{
390+frequencyPenalty: 0.9,
391+presencePenalty: 0.7,
392+},
393+);
394+395+if (!agent.streamFn) {
396+throw new Error("expected extra params to wrap streamFn");
397+}
398+399+void agent.streamFn(
400+{ id: "gpt-5.4", api: "openai-completions", provider: "openai" } as never,
401+{ messages: [], tools: [] } as never,
402+undefined,
403+);
404+405+const callOptions = (underlying as unknown as { mock: { calls: unknown[][] } }).mock
406+.calls[0]?.[2] as
407+| {
408+frequencyPenalty?: number;
409+presencePenalty?: number;
410+}
411+| undefined;
412+expect(callOptions?.frequencyPenalty).toBe(0.9);
413+expect(callOptions?.presencePenalty).toBe(0.7);
414+});
324415});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。