mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
feat: add openAiNativeStatelessMode configuration option
- Add openAiNativeStatelessMode boolean option to OpenAI Native provider settings - Update provider to check this setting and override metadata.store accordingly - Add comprehensive tests for the new configuration option - Maintain backward compatibility (defaults to current behavior) Fixes #7789
This commit is contained in:
parent
0ce4e891fd
commit
53df91c0a8
3 changed files with 111 additions and 2 deletions
|
|
@ -228,6 +228,10 @@ const openAiNativeSchema = apiModelIdProviderModelSchema.extend({
|
|||
// OpenAI Responses API service tier for openai-native provider only.
|
||||
// UI should only expose this when the selected model supports flex/priority.
|
||||
openAiNativeServiceTier: serviceTierSchema.optional(),
|
||||
// Enable stateless mode for OpenAI Responses API (sets store: false)
|
||||
// When enabled, responses won't be stored for 30 days and can't be referenced
|
||||
// in future requests using previous_response_id
|
||||
openAiNativeStatelessMode: z.boolean().optional(),
|
||||
})
|
||||
|
||||
const mistralSchema = apiModelIdProviderModelSchema.extend({
|
||||
|
|
|
|||
|
|
@ -859,6 +859,109 @@ describe("OpenAiNativeHandler", () => {
|
|||
expect(secondCallBody.previous_response_id).toBe("resp_789")
|
||||
})
|
||||
|
||||
it("should respect openAiNativeStatelessMode configuration", async () => {
|
||||
// Test with stateless mode enabled
|
||||
const statelessHandler = new OpenAiNativeHandler({
|
||||
...mockOptions,
|
||||
openAiNativeStatelessMode: true,
|
||||
})
|
||||
|
||||
// Mock fetch for Responses API
|
||||
const mockFetch = vitest.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
body: new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(
|
||||
new TextEncoder().encode('data: {"type":"response.text.delta","delta":"Test"}\n\n'),
|
||||
)
|
||||
controller.enqueue(new TextEncoder().encode("data: [DONE]\n\n"))
|
||||
controller.close()
|
||||
},
|
||||
}),
|
||||
})
|
||||
global.fetch = mockFetch as any
|
||||
|
||||
// Mock SDK to fail
|
||||
mockResponsesCreate.mockRejectedValue(new Error("SDK not available"))
|
||||
|
||||
const stream = statelessHandler.createMessage(systemPrompt, messages, { taskId: "test-task" })
|
||||
const chunks = []
|
||||
for await (const chunk of stream) {
|
||||
chunks.push(chunk)
|
||||
}
|
||||
|
||||
// Verify that store is set to false when stateless mode is enabled
|
||||
const requestBody = JSON.parse(mockFetch.mock.calls[0][1].body)
|
||||
expect(requestBody.store).toBe(false)
|
||||
})
|
||||
|
||||
it("should use metadata.store when stateless mode is disabled", async () => {
|
||||
// Test with stateless mode disabled (default)
|
||||
const handler = new OpenAiNativeHandler(mockOptions)
|
||||
|
||||
// Mock fetch for Responses API
|
||||
const mockFetch = vitest.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
body: new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(
|
||||
new TextEncoder().encode('data: {"type":"response.text.delta","delta":"Test"}\n\n'),
|
||||
)
|
||||
controller.enqueue(new TextEncoder().encode("data: [DONE]\n\n"))
|
||||
controller.close()
|
||||
},
|
||||
}),
|
||||
})
|
||||
global.fetch = mockFetch as any
|
||||
|
||||
// Mock SDK to fail
|
||||
mockResponsesCreate.mockRejectedValue(new Error("SDK not available"))
|
||||
|
||||
// Test with metadata.store = false
|
||||
const stream = handler.createMessage(systemPrompt, messages, { taskId: "test-task", store: false })
|
||||
const chunks = []
|
||||
for await (const chunk of stream) {
|
||||
chunks.push(chunk)
|
||||
}
|
||||
|
||||
// Verify that store is set to false when metadata.store is false
|
||||
const requestBody = JSON.parse(mockFetch.mock.calls[0][1].body)
|
||||
expect(requestBody.store).toBe(false)
|
||||
})
|
||||
|
||||
it("should default to store:true when stateless mode is disabled and metadata.store is not set", async () => {
|
||||
// Test with stateless mode disabled and no metadata.store
|
||||
const handler = new OpenAiNativeHandler(mockOptions)
|
||||
|
||||
// Mock fetch for Responses API
|
||||
const mockFetch = vitest.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
body: new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(
|
||||
new TextEncoder().encode('data: {"type":"response.text.delta","delta":"Test"}\n\n'),
|
||||
)
|
||||
controller.enqueue(new TextEncoder().encode("data: [DONE]\n\n"))
|
||||
controller.close()
|
||||
},
|
||||
}),
|
||||
})
|
||||
global.fetch = mockFetch as any
|
||||
|
||||
// Mock SDK to fail
|
||||
mockResponsesCreate.mockRejectedValue(new Error("SDK not available"))
|
||||
|
||||
const stream = handler.createMessage(systemPrompt, messages, { taskId: "test-task" })
|
||||
const chunks = []
|
||||
for await (const chunk of stream) {
|
||||
chunks.push(chunk)
|
||||
}
|
||||
|
||||
// Verify that store defaults to true
|
||||
const requestBody = JSON.parse(mockFetch.mock.calls[0][1].body)
|
||||
expect(requestBody.store).toBe(true)
|
||||
})
|
||||
|
||||
it("should retry with full conversation when previous_response_id fails", async () => {
|
||||
// This test verifies the fix for context loss bug when previous_response_id becomes invalid
|
||||
const mockFetch = vitest
|
||||
|
|
|
|||
|
|
@ -255,7 +255,8 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
|
|||
model: model.id,
|
||||
input: formattedInput,
|
||||
stream: true,
|
||||
store: metadata?.store !== false, // Default to true unless explicitly set to false
|
||||
// Check if stateless mode is enabled in configuration, otherwise use metadata.store
|
||||
store: this.options.openAiNativeStatelessMode ? false : metadata?.store !== false,
|
||||
// Always include instructions (system prompt) for Responses API.
|
||||
// Unlike Chat Completions, system/developer roles in input have no special semantics here.
|
||||
// The official way to set system behavior is the top-level `instructions` field.
|
||||
|
|
@ -1286,7 +1287,8 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
|
|||
},
|
||||
],
|
||||
stream: false, // Non-streaming for completePrompt
|
||||
store: false, // Don't store prompt completions
|
||||
// Use stateless mode if configured, otherwise don't store prompt completions
|
||||
store: this.options.openAiNativeStatelessMode ? false : false,
|
||||
}
|
||||
|
||||
// Include service tier if selected and supported
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue