mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
feat: add automatic web search support for OpenAI Native provider
- Add openAiNativeWebSearchEnabled configuration option to provider settings - Implement web search tool integration in Responses API requests - Handle web search events and store results for citation formatting - Add citation formatting with clickable links in markdown format - Display search status updates during web search operations - Append sources list with numbered citations at end of response This enables automatic web search for OpenAI Native provider when the openAiNativeWebSearchEnabled option is set to true. The model will automatically search the web when helpful and include inline citations with a Sources list containing clickable links.
This commit is contained in:
parent
44cbee5e75
commit
a93b162c0a
2 changed files with 66 additions and 2 deletions
|
|
@ -297,6 +297,8 @@ 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 automatic web search for OpenAI Native provider
|
||||
openAiNativeWebSearchEnabled: z.boolean().optional(),
|
||||
})
|
||||
|
||||
const mistralSchema = apiModelIdProviderModelSchema.extend({
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
|
|||
private responseIdResolver: ((value: string | undefined) => void) | undefined
|
||||
// Resolved service tier from Responses API (actual tier used by OpenAI)
|
||||
private lastServiceTier: ServiceTier | undefined
|
||||
// Store web search results for citation formatting
|
||||
private lastWebSearchResults: any[] | undefined
|
||||
|
||||
// Event types handled by the shared event processor to avoid duplication
|
||||
private readonly coreHandledEventTypes = new Set<string>([
|
||||
|
|
@ -245,6 +247,7 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
|
|||
store?: boolean
|
||||
instructions?: string
|
||||
service_tier?: ServiceTier
|
||||
tools?: Array<{ type: string }>
|
||||
}
|
||||
|
||||
// Validate requested tier against model support; if not supported, omit.
|
||||
|
|
@ -283,6 +286,10 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
|
|||
(requestedTier === "default" || allowedTierNames.has(requestedTier)) && {
|
||||
service_tier: requestedTier,
|
||||
}),
|
||||
// Enable web search if configured
|
||||
...(this.options.openAiNativeWebSearchEnabled && {
|
||||
tools: [{ type: "web_search" }],
|
||||
}),
|
||||
}
|
||||
|
||||
// Include text.verbosity only when the model explicitly supports it
|
||||
|
|
@ -887,11 +894,26 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
|
|||
}
|
||||
// Handle web search events
|
||||
else if (parsed.type === "response.web_search_call.searching") {
|
||||
// Web search in progress
|
||||
// Web search in progress - could yield status update
|
||||
if (parsed.query) {
|
||||
yield {
|
||||
type: "text",
|
||||
text: `\n[Searching web for: "${parsed.query}"]\n`,
|
||||
}
|
||||
}
|
||||
} else if (parsed.type === "response.web_search_call.in_progress") {
|
||||
// Processing web search results
|
||||
} else if (parsed.type === "response.web_search_call.completed") {
|
||||
// Web search completed
|
||||
// Web search completed - results will be included in the response
|
||||
if (parsed.results && Array.isArray(parsed.results)) {
|
||||
// Store search results for citation formatting
|
||||
this.lastWebSearchResults = parsed.results
|
||||
}
|
||||
} else if (parsed.type === "response.web_search_call.results") {
|
||||
// Alternative event for web search results
|
||||
if (parsed.results && Array.isArray(parsed.results)) {
|
||||
this.lastWebSearchResults = parsed.results
|
||||
}
|
||||
}
|
||||
// Handle code interpreter events
|
||||
else if (parsed.type === "response.code_interpreter_call_code.delta") {
|
||||
|
|
@ -1016,6 +1038,13 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
|
|||
}
|
||||
}
|
||||
|
||||
// After content is complete, append citations if we have web search results
|
||||
if (this.lastWebSearchResults && this.lastWebSearchResults.length > 0) {
|
||||
yield* this.formatWebSearchCitations(this.lastWebSearchResults)
|
||||
// Clear results after using them
|
||||
this.lastWebSearchResults = undefined
|
||||
}
|
||||
|
||||
// Usage for done/completed is already handled by processGpt5Event in SDK path.
|
||||
// For SSE path, usage often arrives separately; avoid double-emitting here.
|
||||
}
|
||||
|
|
@ -1304,6 +1333,11 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
|
|||
}
|
||||
}
|
||||
|
||||
// Enable web search if configured
|
||||
if (this.options.openAiNativeWebSearchEnabled) {
|
||||
requestBody.tools = [{ type: "web_search" }]
|
||||
}
|
||||
|
||||
// Only include temperature if the model supports it
|
||||
if (model.info.supportsTemperature !== false) {
|
||||
requestBody.temperature =
|
||||
|
|
@ -1352,4 +1386,32 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
|
|||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats web search results as citations with clickable links
|
||||
*/
|
||||
private async *formatWebSearchCitations(results: any[]): ApiStream {
|
||||
// Format citations with inline links
|
||||
const citations: string[] = []
|
||||
const sources: string[] = []
|
||||
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
const result = results[i]
|
||||
if (result.url && result.title) {
|
||||
const citationNum = i + 1
|
||||
// Create inline citation reference
|
||||
citations.push(`[${citationNum}]`)
|
||||
// Create source entry with clickable link
|
||||
sources.push(`[${citationNum}] [${result.title}](${result.url})`)
|
||||
}
|
||||
}
|
||||
|
||||
// Only output if we have citations
|
||||
if (sources.length > 0) {
|
||||
yield {
|
||||
type: "text",
|
||||
text: "\n\n**Sources:**\n" + sources.join("\n"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue