Skip to content

Commit 2f2e4e3

Browse files
committed
AIX: OpenAI Responses: handle web_search_calls even for obscure types
1 parent 913c821 commit 2f2e4e3

2 files changed

Lines changed: 56 additions & 3 deletions

File tree

src/modules/aix/server/dispatch/chatGenerate/parsers/openai.responses.parser.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,27 @@ const OPENAI_RESPONSES_DEBUG_EVENT_SEQUENCE = false; // true: shows the sequence
1313
const OPENAI_RESPONSES_SAME_PART_SPACER = '\n\n'; // true: shows the sequence of events
1414

1515

16+
/**
17+
* Safely sanitizes a URL for display in placeholders by removing query parameters and paths
18+
* to prevent leaking sensitive information while keeping the domain recognizable.
19+
*/
20+
function sanitizeUrlForDisplay(url: string | null): string {
21+
if (!url) return 'unknown';
22+
try {
23+
const urlObj = new URL(url);
24+
// Return just the protocol and hostname (e.g., "https://example.com")
25+
return `${urlObj.protocol}//${urlObj.hostname}`;
26+
} catch (error) {
27+
// If URL parsing fails, try to extract just the domain part manually
28+
const match = url.match(/^https?:\/\/([^/?#]+)/);
29+
if (match)
30+
return `${url.split('://')[0]}://${match[1]}`;
31+
// Fallback: return a generic indicator
32+
return 'website';
33+
}
34+
}
35+
36+
1637
type TResponse = OpenAIWire_API_Responses.Response;
1738
type TOutputItem = OpenAIWire_API_Responses.Response['output'][number];
1839
type TEventType = OpenAIWire_API_Responses.StreamingEvent['type'];
@@ -311,8 +332,25 @@ export function createOpenAIResponsesEventParser(): ChatGenerateParseFunction {
311332
pt.sendVoidPlaceholder('web_search', `${action.query}: completed`);
312333
break;
313334

335+
case 'open_page':
336+
// Action: opening/visiting a specific web page
337+
const sanitizedUrl = sanitizeUrlForDisplay(action.url);
338+
pt.sendVoidPlaceholder('web_search', `Opening ${action.url ? sanitizedUrl : 'Opening page...'}`);
339+
break;
340+
341+
case 'find_in_page':
342+
// Action: searching for a pattern within an opened page
343+
const sanitizedPageUrl = sanitizeUrlForDisplay(action.url);
344+
if (action.pattern && action.url)
345+
pt.sendVoidPlaceholder('web_search', `Searching for "${action.pattern}" on ${sanitizedPageUrl}`);
346+
else if (action.pattern)
347+
pt.sendVoidPlaceholder('web_search', `Searching for "${action.pattern}"`);
348+
else
349+
pt.sendVoidPlaceholder('web_search', 'Searching in page...');
350+
break;
351+
314352
default:
315-
console.log(`[DEV] AIX: Unknown web_search_call action type: ${action.type}`, { action });
353+
console.log(`[DEV] AIX: Unknown web_search_call action type: ${action?.type}`, { action });
316354
break;
317355
}
318356
break;

src/modules/aix/server/dispatch/wiretypes/openai.wiretypes.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -973,9 +973,9 @@ export namespace OpenAIWire_Responses_Items {
973973

974974
// action may be present with `include: ['web_search_call.action.sources']`
975975
action: z.union([
976-
// This comes from looking at the payload, and taking inspiration from other messages
976+
977+
// Action type: 'search' - lists all the search results of a web search, once done
977978
z.object({
978-
// known action type: 'search': lists all the search results of a web search, once done
979979
type: z.literal('search'),
980980
query: z.string().optional(), // query might not always be present in done event
981981
sources: z.array(z.object({
@@ -987,8 +987,23 @@ export namespace OpenAIWire_Responses_Items {
987987
end_index: z.number().optional(),
988988
})).optional(),
989989
}),
990+
991+
// Action type: 'open_page' - opens/visits a specific web page
992+
z.object({
993+
type: z.literal('open_page'),
994+
url: z.string().nullable(), // URL to open (can be null in some cases)
995+
}),
996+
997+
// Action type: 'find_in_page' - searches for a pattern within an opened page
998+
z.object({
999+
type: z.literal('find_in_page'),
1000+
pattern: z.string(), // text pattern to search for
1001+
url: z.string(), // URL of the page being searched
1002+
}),
1003+
9901004
// Future-proof: any other action type with flexible structure
9911005
z.any(),
1006+
9921007
]).optional(),
9931008
});
9941009

0 commit comments

Comments
 (0)