@copilotkitnext/agent 0.0.0-max-changeset-20260109174803
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/dist/index.d.mts +199 -0
- package/dist/index.d.ts +199 -0
- package/dist/index.js +629 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +606 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +53 -0
- package/src/__tests__/basic-agent.test.ts +566 -0
- package/src/__tests__/config-tools-execution.test.ts +503 -0
- package/src/__tests__/property-overrides.test.ts +559 -0
- package/src/__tests__/state-tools.test.ts +391 -0
- package/src/__tests__/test-helpers.ts +130 -0
- package/src/__tests__/utils.test.ts +438 -0
- package/src/index.ts +1003 -0
- package/tsconfig.json +13 -0
- package/tsup.config.ts +11 -0
- package/vitest.config.ts +13 -0
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { BasicAgent } from "../index";
|
|
3
|
+
import { type RunAgentInput } from "@ag-ui/client";
|
|
4
|
+
import { streamText } from "ai";
|
|
5
|
+
import { mockStreamTextResponse, finish, collectEvents } from "./test-helpers";
|
|
6
|
+
|
|
7
|
+
// Mock the ai module
|
|
8
|
+
vi.mock("ai", () => ({
|
|
9
|
+
streamText: vi.fn(),
|
|
10
|
+
tool: vi.fn((config) => config),
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
// Mock the SDK clients
|
|
14
|
+
vi.mock("@ai-sdk/openai", () => ({
|
|
15
|
+
createOpenAI: vi.fn(() => (modelId: string) => ({
|
|
16
|
+
modelId,
|
|
17
|
+
provider: "openai",
|
|
18
|
+
})),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
vi.mock("@ai-sdk/anthropic", () => ({
|
|
22
|
+
createAnthropic: vi.fn(() => (modelId: string) => ({
|
|
23
|
+
modelId,
|
|
24
|
+
provider: "anthropic",
|
|
25
|
+
})),
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
describe("Property Overrides - Edge Cases", () => {
|
|
29
|
+
const originalEnv = process.env;
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
vi.clearAllMocks();
|
|
33
|
+
process.env = { ...originalEnv };
|
|
34
|
+
process.env.OPENAI_API_KEY = "test-key";
|
|
35
|
+
process.env.ANTHROPIC_API_KEY = "test-key";
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
process.env = originalEnv;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe("Model Override", () => {
|
|
43
|
+
it("should override model when allowed", async () => {
|
|
44
|
+
const agent = new BasicAgent({
|
|
45
|
+
model: "openai/gpt-4o",
|
|
46
|
+
overridableProperties: ["model"],
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
50
|
+
|
|
51
|
+
const input: RunAgentInput = {
|
|
52
|
+
threadId: "thread1",
|
|
53
|
+
runId: "run1",
|
|
54
|
+
messages: [],
|
|
55
|
+
tools: [],
|
|
56
|
+
context: [],
|
|
57
|
+
state: {},
|
|
58
|
+
forwardedProps: { model: "anthropic/claude-sonnet-4.5" },
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
await collectEvents(agent["run"](input));
|
|
62
|
+
|
|
63
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
64
|
+
expect(callArgs.model.provider).toBe("anthropic");
|
|
65
|
+
expect(callArgs.model.modelId).toBe("claude-sonnet-4.5");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("should accept LanguageModel instance for override", async () => {
|
|
69
|
+
const agent = new BasicAgent({
|
|
70
|
+
model: "openai/gpt-4o",
|
|
71
|
+
overridableProperties: ["model"],
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
75
|
+
|
|
76
|
+
const customModel = {
|
|
77
|
+
modelId: "custom-model",
|
|
78
|
+
provider: "custom",
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const input: RunAgentInput = {
|
|
82
|
+
threadId: "thread1",
|
|
83
|
+
runId: "run1",
|
|
84
|
+
messages: [],
|
|
85
|
+
tools: [],
|
|
86
|
+
context: [],
|
|
87
|
+
state: {},
|
|
88
|
+
forwardedProps: { model: customModel },
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
await collectEvents(agent["run"](input));
|
|
92
|
+
|
|
93
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
94
|
+
expect(callArgs.model).toBe(customModel);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("should ignore invalid model override types", async () => {
|
|
98
|
+
const agent = new BasicAgent({
|
|
99
|
+
model: "openai/gpt-4o",
|
|
100
|
+
overridableProperties: ["model"],
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
104
|
+
|
|
105
|
+
const input: RunAgentInput = {
|
|
106
|
+
threadId: "thread1",
|
|
107
|
+
runId: "run1",
|
|
108
|
+
messages: [],
|
|
109
|
+
tools: [],
|
|
110
|
+
context: [],
|
|
111
|
+
state: {},
|
|
112
|
+
forwardedProps: { model: 123 }, // Invalid type
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
await collectEvents(agent["run"](input));
|
|
116
|
+
|
|
117
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
118
|
+
expect(callArgs.model.modelId).toBe("gpt-4o"); // Original value
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe("ToolChoice Override", () => {
|
|
123
|
+
it("should override with 'auto'", async () => {
|
|
124
|
+
const agent = new BasicAgent({
|
|
125
|
+
model: "openai/gpt-4o",
|
|
126
|
+
toolChoice: "required",
|
|
127
|
+
overridableProperties: ["toolChoice"],
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
131
|
+
|
|
132
|
+
const input: RunAgentInput = {
|
|
133
|
+
threadId: "thread1",
|
|
134
|
+
runId: "run1",
|
|
135
|
+
messages: [],
|
|
136
|
+
tools: [],
|
|
137
|
+
context: [],
|
|
138
|
+
state: {},
|
|
139
|
+
forwardedProps: { toolChoice: "auto" },
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
await collectEvents(agent["run"](input));
|
|
143
|
+
|
|
144
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
145
|
+
expect(callArgs.toolChoice).toBe("auto");
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("should override with 'required'", async () => {
|
|
149
|
+
const agent = new BasicAgent({
|
|
150
|
+
model: "openai/gpt-4o",
|
|
151
|
+
toolChoice: "auto",
|
|
152
|
+
overridableProperties: ["toolChoice"],
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
156
|
+
|
|
157
|
+
const input: RunAgentInput = {
|
|
158
|
+
threadId: "thread1",
|
|
159
|
+
runId: "run1",
|
|
160
|
+
messages: [],
|
|
161
|
+
tools: [],
|
|
162
|
+
context: [],
|
|
163
|
+
state: {},
|
|
164
|
+
forwardedProps: { toolChoice: "required" },
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
await collectEvents(agent["run"](input));
|
|
168
|
+
|
|
169
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
170
|
+
expect(callArgs.toolChoice).toBe("required");
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("should override with 'none'", async () => {
|
|
174
|
+
const agent = new BasicAgent({
|
|
175
|
+
model: "openai/gpt-4o",
|
|
176
|
+
toolChoice: "auto",
|
|
177
|
+
overridableProperties: ["toolChoice"],
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
181
|
+
|
|
182
|
+
const input: RunAgentInput = {
|
|
183
|
+
threadId: "thread1",
|
|
184
|
+
runId: "run1",
|
|
185
|
+
messages: [],
|
|
186
|
+
tools: [],
|
|
187
|
+
context: [],
|
|
188
|
+
state: {},
|
|
189
|
+
forwardedProps: { toolChoice: "none" },
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
await collectEvents(agent["run"](input));
|
|
193
|
+
|
|
194
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
195
|
+
expect(callArgs.toolChoice).toBe("none");
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it("should override with specific tool selection", async () => {
|
|
199
|
+
const agent = new BasicAgent({
|
|
200
|
+
model: "openai/gpt-4o",
|
|
201
|
+
toolChoice: "auto",
|
|
202
|
+
overridableProperties: ["toolChoice"],
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
206
|
+
|
|
207
|
+
const input: RunAgentInput = {
|
|
208
|
+
threadId: "thread1",
|
|
209
|
+
runId: "run1",
|
|
210
|
+
messages: [],
|
|
211
|
+
tools: [],
|
|
212
|
+
context: [],
|
|
213
|
+
state: {},
|
|
214
|
+
forwardedProps: { toolChoice: { type: "tool", toolName: "specificTool" } },
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
await collectEvents(agent["run"](input));
|
|
218
|
+
|
|
219
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
220
|
+
expect(callArgs.toolChoice).toEqual({ type: "tool", toolName: "specificTool" });
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("should ignore invalid toolChoice values", async () => {
|
|
224
|
+
const agent = new BasicAgent({
|
|
225
|
+
model: "openai/gpt-4o",
|
|
226
|
+
toolChoice: "auto",
|
|
227
|
+
overridableProperties: ["toolChoice"],
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
231
|
+
|
|
232
|
+
const input: RunAgentInput = {
|
|
233
|
+
threadId: "thread1",
|
|
234
|
+
runId: "run1",
|
|
235
|
+
messages: [],
|
|
236
|
+
tools: [],
|
|
237
|
+
context: [],
|
|
238
|
+
state: {},
|
|
239
|
+
forwardedProps: { toolChoice: "invalid" },
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
await collectEvents(agent["run"](input));
|
|
243
|
+
|
|
244
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
245
|
+
expect(callArgs.toolChoice).toBe("auto"); // Original value
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
describe("StopSequences Override", () => {
|
|
250
|
+
it("should override stopSequences with valid array", async () => {
|
|
251
|
+
const agent = new BasicAgent({
|
|
252
|
+
model: "openai/gpt-4o",
|
|
253
|
+
stopSequences: ["STOP"],
|
|
254
|
+
overridableProperties: ["stopSequences"],
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
258
|
+
|
|
259
|
+
const input: RunAgentInput = {
|
|
260
|
+
threadId: "thread1",
|
|
261
|
+
runId: "run1",
|
|
262
|
+
messages: [],
|
|
263
|
+
tools: [],
|
|
264
|
+
context: [],
|
|
265
|
+
state: {},
|
|
266
|
+
forwardedProps: { stopSequences: ["END", "FINISH"] },
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
await collectEvents(agent["run"](input));
|
|
270
|
+
|
|
271
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
272
|
+
expect(callArgs.stopSequences).toEqual(["END", "FINISH"]);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it("should ignore stopSequences with non-string elements", async () => {
|
|
276
|
+
const agent = new BasicAgent({
|
|
277
|
+
model: "openai/gpt-4o",
|
|
278
|
+
stopSequences: ["STOP"],
|
|
279
|
+
overridableProperties: ["stopSequences"],
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
283
|
+
|
|
284
|
+
const input: RunAgentInput = {
|
|
285
|
+
threadId: "thread1",
|
|
286
|
+
runId: "run1",
|
|
287
|
+
messages: [],
|
|
288
|
+
tools: [],
|
|
289
|
+
context: [],
|
|
290
|
+
state: {},
|
|
291
|
+
forwardedProps: { stopSequences: ["STOP", 123, "END"] as any },
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
await collectEvents(agent["run"](input));
|
|
295
|
+
|
|
296
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
297
|
+
expect(callArgs.stopSequences).toEqual(["STOP"]); // Original value
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it("should ignore non-array stopSequences", async () => {
|
|
301
|
+
const agent = new BasicAgent({
|
|
302
|
+
model: "openai/gpt-4o",
|
|
303
|
+
stopSequences: ["STOP"],
|
|
304
|
+
overridableProperties: ["stopSequences"],
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
308
|
+
|
|
309
|
+
const input: RunAgentInput = {
|
|
310
|
+
threadId: "thread1",
|
|
311
|
+
runId: "run1",
|
|
312
|
+
messages: [],
|
|
313
|
+
tools: [],
|
|
314
|
+
context: [],
|
|
315
|
+
state: {},
|
|
316
|
+
forwardedProps: { stopSequences: "STOP" as any },
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
await collectEvents(agent["run"](input));
|
|
320
|
+
|
|
321
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
322
|
+
expect(callArgs.stopSequences).toEqual(["STOP"]); // Original value
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
describe("Numeric Property Overrides", () => {
|
|
327
|
+
it("should override all numeric properties when allowed", async () => {
|
|
328
|
+
const agent = new BasicAgent({
|
|
329
|
+
model: "openai/gpt-4o",
|
|
330
|
+
maxOutputTokens: 100,
|
|
331
|
+
temperature: 0.5,
|
|
332
|
+
topP: 0.9,
|
|
333
|
+
topK: 50,
|
|
334
|
+
presencePenalty: 0.0,
|
|
335
|
+
frequencyPenalty: 0.0,
|
|
336
|
+
seed: 123,
|
|
337
|
+
maxRetries: 3,
|
|
338
|
+
overridableProperties: [
|
|
339
|
+
"maxOutputTokens",
|
|
340
|
+
"temperature",
|
|
341
|
+
"topP",
|
|
342
|
+
"topK",
|
|
343
|
+
"presencePenalty",
|
|
344
|
+
"frequencyPenalty",
|
|
345
|
+
"seed",
|
|
346
|
+
"maxRetries",
|
|
347
|
+
],
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
351
|
+
|
|
352
|
+
const input: RunAgentInput = {
|
|
353
|
+
threadId: "thread1",
|
|
354
|
+
runId: "run1",
|
|
355
|
+
messages: [],
|
|
356
|
+
tools: [],
|
|
357
|
+
context: [],
|
|
358
|
+
state: {},
|
|
359
|
+
forwardedProps: {
|
|
360
|
+
maxOutputTokens: 500,
|
|
361
|
+
temperature: 0.8,
|
|
362
|
+
topP: 0.95,
|
|
363
|
+
topK: 100,
|
|
364
|
+
presencePenalty: 0.5,
|
|
365
|
+
frequencyPenalty: 0.5,
|
|
366
|
+
seed: 456,
|
|
367
|
+
maxRetries: 5,
|
|
368
|
+
},
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
await collectEvents(agent["run"](input));
|
|
372
|
+
|
|
373
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
374
|
+
expect(callArgs.maxOutputTokens).toBe(500);
|
|
375
|
+
expect(callArgs.temperature).toBe(0.8);
|
|
376
|
+
expect(callArgs.topP).toBe(0.95);
|
|
377
|
+
expect(callArgs.topK).toBe(100);
|
|
378
|
+
expect(callArgs.presencePenalty).toBe(0.5);
|
|
379
|
+
expect(callArgs.frequencyPenalty).toBe(0.5);
|
|
380
|
+
expect(callArgs.seed).toBe(456);
|
|
381
|
+
expect(callArgs.maxRetries).toBe(5);
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it("should ignore non-numeric values for numeric properties", async () => {
|
|
385
|
+
const agent = new BasicAgent({
|
|
386
|
+
model: "openai/gpt-4o",
|
|
387
|
+
temperature: 0.5,
|
|
388
|
+
overridableProperties: ["temperature"],
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
392
|
+
|
|
393
|
+
const input: RunAgentInput = {
|
|
394
|
+
threadId: "thread1",
|
|
395
|
+
runId: "run1",
|
|
396
|
+
messages: [],
|
|
397
|
+
tools: [],
|
|
398
|
+
context: [],
|
|
399
|
+
state: {},
|
|
400
|
+
forwardedProps: { temperature: "high" as any },
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
await collectEvents(agent["run"](input));
|
|
404
|
+
|
|
405
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
406
|
+
expect(callArgs.temperature).toBe(0.5); // Original value
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
describe("Multiple Property Overrides", () => {
|
|
411
|
+
it("should only override allowed properties", async () => {
|
|
412
|
+
const agent = new BasicAgent({
|
|
413
|
+
model: "openai/gpt-4o",
|
|
414
|
+
temperature: 0.5,
|
|
415
|
+
topP: 0.9,
|
|
416
|
+
maxOutputTokens: 100,
|
|
417
|
+
overridableProperties: ["temperature"], // Only temperature is overridable
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
421
|
+
|
|
422
|
+
const input: RunAgentInput = {
|
|
423
|
+
threadId: "thread1",
|
|
424
|
+
runId: "run1",
|
|
425
|
+
messages: [],
|
|
426
|
+
tools: [],
|
|
427
|
+
context: [],
|
|
428
|
+
state: {},
|
|
429
|
+
forwardedProps: {
|
|
430
|
+
temperature: 0.9,
|
|
431
|
+
topP: 0.5,
|
|
432
|
+
maxOutputTokens: 500,
|
|
433
|
+
},
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
await collectEvents(agent["run"](input));
|
|
437
|
+
|
|
438
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
439
|
+
expect(callArgs.temperature).toBe(0.9); // Overridden
|
|
440
|
+
expect(callArgs.topP).toBe(0.9); // Original
|
|
441
|
+
expect(callArgs.maxOutputTokens).toBe(100); // Original
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
it("should handle undefined forwardedProps", async () => {
|
|
445
|
+
const agent = new BasicAgent({
|
|
446
|
+
model: "openai/gpt-4o",
|
|
447
|
+
temperature: 0.5,
|
|
448
|
+
overridableProperties: ["temperature"],
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
452
|
+
|
|
453
|
+
const input: RunAgentInput = {
|
|
454
|
+
threadId: "thread1",
|
|
455
|
+
runId: "run1",
|
|
456
|
+
messages: [],
|
|
457
|
+
tools: [],
|
|
458
|
+
context: [],
|
|
459
|
+
state: {},
|
|
460
|
+
// No forwardedProps
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
await collectEvents(agent["run"](input));
|
|
464
|
+
|
|
465
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
466
|
+
expect(callArgs.temperature).toBe(0.5); // Original value
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
it("should handle non-object forwardedProps", async () => {
|
|
470
|
+
const agent = new BasicAgent({
|
|
471
|
+
model: "openai/gpt-4o",
|
|
472
|
+
temperature: 0.5,
|
|
473
|
+
overridableProperties: ["temperature"],
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
477
|
+
|
|
478
|
+
const input: RunAgentInput = {
|
|
479
|
+
threadId: "thread1",
|
|
480
|
+
runId: "run1",
|
|
481
|
+
messages: [],
|
|
482
|
+
tools: [],
|
|
483
|
+
context: [],
|
|
484
|
+
state: {},
|
|
485
|
+
forwardedProps: "not an object" as any,
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
await collectEvents(agent["run"](input));
|
|
489
|
+
|
|
490
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
491
|
+
expect(callArgs.temperature).toBe(0.5); // Original value
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
it("should handle undefined property values in forwardedProps", async () => {
|
|
495
|
+
const agent = new BasicAgent({
|
|
496
|
+
model: "openai/gpt-4o",
|
|
497
|
+
temperature: 0.5,
|
|
498
|
+
overridableProperties: ["temperature"],
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
vi.mocked(streamText).mockReturnValue(mockStreamTextResponse([finish()]) as any);
|
|
502
|
+
|
|
503
|
+
const input: RunAgentInput = {
|
|
504
|
+
threadId: "thread1",
|
|
505
|
+
runId: "run1",
|
|
506
|
+
messages: [],
|
|
507
|
+
tools: [],
|
|
508
|
+
context: [],
|
|
509
|
+
state: {},
|
|
510
|
+
forwardedProps: { temperature: undefined },
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
await collectEvents(agent["run"](input));
|
|
514
|
+
|
|
515
|
+
const callArgs = vi.mocked(streamText).mock.calls[0][0];
|
|
516
|
+
expect(callArgs.temperature).toBe(0.5); // Original value (undefined is ignored)
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
describe("canOverride method", () => {
|
|
521
|
+
it("should return true for overridable properties", () => {
|
|
522
|
+
const agent = new BasicAgent({
|
|
523
|
+
model: "openai/gpt-4o",
|
|
524
|
+
overridableProperties: ["temperature", "topP"],
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
expect(agent.canOverride("temperature")).toBe(true);
|
|
528
|
+
expect(agent.canOverride("topP")).toBe(true);
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
it("should return false for non-overridable properties", () => {
|
|
532
|
+
const agent = new BasicAgent({
|
|
533
|
+
model: "openai/gpt-4o",
|
|
534
|
+
overridableProperties: ["temperature"],
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
expect(agent.canOverride("topP")).toBe(false);
|
|
538
|
+
expect(agent.canOverride("seed")).toBe(false);
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
it("should return false when overridableProperties is undefined", () => {
|
|
542
|
+
const agent = new BasicAgent({
|
|
543
|
+
model: "openai/gpt-4o",
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
expect(agent.canOverride("temperature")).toBe(false);
|
|
547
|
+
expect(agent.canOverride("topP")).toBe(false);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
it("should return false when overridableProperties is empty array", () => {
|
|
551
|
+
const agent = new BasicAgent({
|
|
552
|
+
model: "openai/gpt-4o",
|
|
553
|
+
overridableProperties: [],
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
expect(agent.canOverride("temperature")).toBe(false);
|
|
557
|
+
});
|
|
558
|
+
});
|
|
559
|
+
});
|