Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 63 additions & 3 deletions src/api/providers/__tests__/deepseek.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ describe("DeepSeekHandler", () => {
expect.objectContaining({
thinking: { type: "enabled" },
}),
{}, // Empty path options for non-Azure URLs
undefined, // No signal, non-Azure URL
)
const callArgs = mockCreate.mock.calls[0][0]
expect(callArgs.reasoning_effort).toBeUndefined()
Expand All @@ -517,7 +517,7 @@ describe("DeepSeekHandler", () => {
reasoning_effort: "high",
max_completion_tokens: 200_000,
}),
{},
undefined,
)
})

Expand Down Expand Up @@ -554,10 +554,27 @@ describe("DeepSeekHandler", () => {
thinking: { type: "enabled" },
reasoning_effort: "max",
}),
{},
undefined,
)
})

it("should pass Azure path even when abortSignal is not provided", async () => {
const azureHandler = new DeepSeekHandler({
...mockOptions,
deepSeekBaseUrl: "https://example.services.ai.azure.com",
})

const stream = azureHandler.createMessage(systemPrompt, messages)
for await (const _chunk of stream) {
// Consume the stream
}

expect(mockCreate).toHaveBeenCalledTimes(1)
const [requestOptions, signalArg] = mockCreate.mock.calls[0]
expect(requestOptions.model).toBe("deepseek-chat")
expect(signalArg).toBeUndefined()
})

it("should disable thinking for deepseek-v4 models when reasoning is disabled", async () => {
const v4Handler = new DeepSeekHandler({
...mockOptions,
Expand Down Expand Up @@ -640,5 +657,48 @@ describe("DeepSeekHandler", () => {
expect(toolCallChunks.length).toBeGreaterThan(0)
expect(toolCallChunks[0].name).toBe("get_weather")
})

it("should use metadata.abortSignal when provided in createMessage", async () => {
const controller = new AbortController()
mockCreate.mockResolvedValueOnce({
id: "test-completion",
choices: [{ message: { content: "Response with abort signal" } }],
})

const stream = handler.createMessage(systemPrompt, messages, { abortSignal: controller.signal })
const chunks: any[] = []
for await (const chunk of stream) {
chunks.push(chunk)
}

expect(chunks.length).toBeGreaterThan(0)
expect(mockCreate).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
signal: controller.signal,
}),
)
})

it("should use default signal when metadata.abortSignal not provided in createMessage", async () => {
mockCreate.mockResolvedValueOnce({
id: "test-completion",
choices: [{ message: { content: "Response without metadata" } }],
})

const stream = handler.createMessage(systemPrompt, messages)
const chunks: any[] = []
for await (const chunk of stream) {
chunks.push(chunk)
}

expect(chunks.length).toBeGreaterThan(0)
expect(mockCreate).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
signal: expect.any(AbortSignal),
}),
)
})
})
})
4 changes: 3 additions & 1 deletion src/api/providers/__tests__/lmstudio-native-tools.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ describe("LmStudioHandler Native Tools", () => {
}),
]),
}),
undefined,
)
// parallel_tool_calls should be true by default when not explicitly set
const callArgs = mockCreate.mock.calls[0][0]
Expand All @@ -109,6 +110,7 @@ describe("LmStudioHandler Native Tools", () => {
expect.objectContaining({
tool_choice: "auto",
}),
undefined,
)
})

Expand Down Expand Up @@ -221,9 +223,9 @@ describe("LmStudioHandler Native Tools", () => {
expect.objectContaining({
parallel_tool_calls: true,
}),
undefined,
)
})

it("should yield tool_call_end events when finish_reason is tool_calls", async () => {
mockCreate.mockImplementationOnce(() => ({
[Symbol.asyncIterator]: async function* () {
Expand Down
48 changes: 42 additions & 6 deletions src/api/providers/__tests__/lmstudio.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,15 @@ describe("LmStudioHandler", () => {
it("should complete prompt successfully", async () => {
const result = await handler.completePrompt("Test prompt")
expect(result).toBe("Test response")
expect(mockCreate).toHaveBeenCalledWith({
model: mockOptions.lmStudioModelId,
messages: [{ role: "user", content: "Test prompt" }],
temperature: 0,
stream: false,
})
expect(mockCreate).toHaveBeenCalledWith(
{
model: mockOptions.lmStudioModelId,
messages: [{ role: "user", content: "Test prompt" }],
temperature: 0,
stream: false,
},
undefined,
)
})

it("should handle API errors", async () => {
Expand All @@ -155,6 +158,39 @@ describe("LmStudioHandler", () => {
const result = await handler.completePrompt("Test prompt")
expect(result).toBe("")
})

it("should use metadata.abortSignal when provided in completePrompt", async () => {
mockCreate.mockResolvedValueOnce({
choices: [{ message: { content: "Response with abort signal" } }],
})

const controller = new AbortController()
const result = await handler.completePrompt("Test prompt", { abortSignal: controller.signal })

expect(result).toBe("Response with abort signal")
expect(mockCreate).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
signal: controller.signal,
}),
)
})

it("should use default signal when metadata.abortSignal not provided in completePrompt", async () => {
mockCreate.mockResolvedValueOnce({
choices: [{ message: { content: "Response without metadata" } }],
})

const result = await handler.completePrompt("Test prompt")

expect(result).toBe("Response without metadata")
expect(mockCreate).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
signal: expect.any(AbortSignal),
}),
)
})
})

describe("getModel", () => {
Expand Down
1 change: 1 addition & 0 deletions src/api/providers/__tests__/mimo.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ describe("MimoHandler", () => {
expect.objectContaining({
extra_body: { thinking: { type: "enabled" } },
}),
undefined,
)
})

Expand Down
33 changes: 33 additions & 0 deletions src/api/providers/__tests__/minimax.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,37 @@ describe("MiniMaxHandler", () => {
await expect(handler.completePrompt("test prompt")).rejects.toThrow()
})

it("should use metadata.abortSignal when provided in completePrompt", async () => {
mockCreate.mockResolvedValueOnce({
data: [{ type: "text", text: "Response with abort signal" }],
})

const controller = new AbortController()
const result = await handler.completePrompt("test prompt", { abortSignal: controller.signal })

expect(mockCreate).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
signal: controller.signal,
}),
)
})

it("should use default signal when metadata.abortSignal not provided in completePrompt", async () => {
mockCreate.mockResolvedValueOnce({
data: [{ type: "text", text: "Response without metadata" }],
})

await handler.completePrompt("test prompt")

expect(mockCreate).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
signal: expect.any(AbortSignal),
}),
)
})

it("createMessage should yield text content from stream", async () => {
const testContent = "This is test content from MiniMax stream"

Expand Down Expand Up @@ -305,6 +336,7 @@ describe("MiniMaxHandler", () => {
messages: expect.any(Array),
stream: true,
}),
undefined,
)
})

Expand All @@ -324,6 +356,7 @@ describe("MiniMaxHandler", () => {
expect.objectContaining({
temperature: 1,
}),
undefined,
)
})

Expand Down
35 changes: 35 additions & 0 deletions src/api/providers/__tests__/mistral.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -497,5 +497,40 @@ describe("MistralHandler", () => {
mockComplete.mockRejectedValueOnce(new Error("API Error"))
await expect(handler.completePrompt("Test prompt")).rejects.toThrow("Mistral completion error: API Error")
})

it("should use metadata.abortSignal when provided in completePrompt", async () => {
mockComplete.mockResolvedValueOnce({
id: "test-completion",
choices: [{ message: { content: "Response with abort signal" } }],
})

const controller = new AbortController()
const result = await handler.completePrompt("Test prompt", { abortSignal: controller.signal })

expect(result).toBe("Response with abort signal")
expect(mockComplete).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
signal: controller.signal,
}),
)
})

it("should use default signal when metadata.abortSignal not provided in completePrompt", async () => {
mockComplete.mockResolvedValueOnce({
id: "test-completion",
choices: [{ message: { content: "Response without metadata" } }],
})

const result = await handler.completePrompt("Test prompt")

expect(result).toBe("Response without metadata")
expect(mockComplete).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
signal: expect.any(AbortSignal),
}),
)
})
})
})
78 changes: 78 additions & 0 deletions src/api/providers/__tests__/openai.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,49 @@ describe("OpenAiHandler", () => {
}
}).rejects.toThrow("Rate limit exceeded")
})

it("should use metadata.abortSignal when provided in createMessage", async () => {
const controller = new AbortController()
mockCreate.mockResolvedValue({
id: "test-completion",
choices: [{ message: { content: "Response with abort signal" } }],
})

const stream = handler.createMessage("system prompt", testMessages, { abortSignal: controller.signal })
const chunks: any[] = []
for await (const chunk of stream) {
chunks.push(chunk)
}

expect(chunks.length).toBeGreaterThan(0)
expect(mockCreate).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
signal: controller.signal,
}),
)
})

it("should use default signal when metadata.abortSignal not provided in createMessage", async () => {
mockCreate.mockResolvedValue({
id: "test-completion",
choices: [{ message: { content: "Response without metadata" } }],
})

const stream = handler.createMessage("system prompt", testMessages)
const chunks: any[] = []
for await (const chunk of stream) {
chunks.push(chunk)
}

expect(chunks.length).toBeGreaterThan(0)
expect(mockCreate).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
signal: expect.any(AbortSignal),
}),
)
})
})

describe("completePrompt", () => {
Expand Down Expand Up @@ -627,6 +670,41 @@ describe("OpenAiHandler", () => {
const result = await handler.completePrompt("Test prompt")
expect(result).toBe("")
})

it("should use metadata.abortSignal when provided in completePrompt", async () => {
mockCreate.mockResolvedValue({
id: "test-completion",
choices: [{ message: { content: "Response with abort signal" } }],
})

const controller = new AbortController()
const result = await handler.completePrompt("Test prompt", { abortSignal: controller.signal })

expect(result).toBe("Response with abort signal")
expect(mockCreate).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
signal: controller.signal,
}),
)
})

it("should use default signal when metadata.abortSignal not provided in completePrompt", async () => {
mockCreate.mockResolvedValue({
id: "test-completion",
choices: [{ message: { content: "Response without metadata" } }],
})

const result = await handler.completePrompt("Test prompt")

expect(result).toBe("Response without metadata")
expect(mockCreate).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
signal: expect.any(AbortSignal),
}),
)
})
})

describe("getModel", () => {
Expand Down
Loading
Loading