mirror of
https://github.com/openai/codex.git
synced 2026-11-02 19:43:24 +00:00
Add client-only web search result metadata
This commit is contained in:
@@ -4404,6 +4404,7 @@ async fn turn_event_counts_completed_tool_items() {
|
||||
id: "web-1".to_string(),
|
||||
query: "codex".to_string(),
|
||||
action: None,
|
||||
results: None,
|
||||
},
|
||||
ThreadItem::ImageGeneration {
|
||||
id: "image-1".to_string(),
|
||||
|
||||
@@ -2027,7 +2027,9 @@ fn tool_item_event(input: ToolItemEventInput<'_>) -> Option<TrackEventRequest> {
|
||||
},
|
||||
))
|
||||
}
|
||||
ThreadItem::WebSearch { id, query, action } => {
|
||||
ThreadItem::WebSearch {
|
||||
id, query, action, ..
|
||||
} => {
|
||||
let base = tool_item_base(
|
||||
thread_id,
|
||||
turn_id,
|
||||
|
||||
@@ -4511,6 +4511,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -5684,6 +5693,29 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"WindowsSandboxSetupCompletedNotification": {
|
||||
"properties": {
|
||||
"error": {
|
||||
|
||||
+32
@@ -18357,6 +18357,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -20829,6 +20838,29 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"WebSearchToolConfig": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
||||
+32
@@ -16136,6 +16136,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -18608,6 +18617,29 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"WebSearchToolConfig": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
||||
@@ -1102,6 +1102,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -1524,6 +1533,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1102,6 +1102,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -1524,6 +1533,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1247,6 +1247,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -1799,6 +1808,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1775,6 +1775,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -2405,6 +2414,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1566,6 +1566,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -2196,6 +2205,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
+32
@@ -1566,6 +1566,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -2196,6 +2205,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1566,6 +1566,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -2196,6 +2205,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1775,6 +1775,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -2431,6 +2440,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1566,6 +1566,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -2196,6 +2205,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1775,6 +1775,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -2405,6 +2414,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1566,6 +1566,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -2196,6 +2205,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1566,6 +1566,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -2196,6 +2205,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1247,6 +1247,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -1799,6 +1808,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1247,6 +1247,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -1799,6 +1808,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -1247,6 +1247,15 @@
|
||||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/WebSearchResult"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
@@ -1799,6 +1808,29 @@
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WebSearchResult": {
|
||||
"properties": {
|
||||
"snippet": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"title": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -25,6 +25,7 @@ import type { PatchApplyStatus } from "./PatchApplyStatus";
|
||||
import type { SubAgentActivityKind } from "./SubAgentActivityKind";
|
||||
import type { UserInput } from "./UserInput";
|
||||
import type { WebSearchAction } from "./WebSearchAction";
|
||||
import type { WebSearchResult } from "./WebSearchResult";
|
||||
|
||||
export type ThreadItem = { "type": "userMessage", id: string, clientId: string | null, content: Array<UserInput>, } | { "type": "hookPrompt", id: string, fragments: Array<HookPromptFragment>, } | { "type": "agentMessage", id: string, text: string, phase: MessagePhase | null, memoryCitation: MemoryCitation | null, } | { "type": "plan", id: string, text: string, } | { "type": "reasoning", id: string, summary: Array<string>, content: Array<string>, } | { "type": "commandExecution", id: string,
|
||||
/**
|
||||
@@ -105,4 +106,4 @@ reasoningEffort: ReasoningEffort | null,
|
||||
/**
|
||||
* Last known status of the target agents, when available.
|
||||
*/
|
||||
agentsStates: { [key in string]?: CollabAgentState }, } | { "type": "subAgentActivity", id: string, kind: SubAgentActivityKind, agentThreadId: string, agentPath: string, } | { "type": "webSearch", id: string, query: string, action: WebSearchAction | null, } | { "type": "imageView", id: string, path: LegacyAppPathString, } | { "type": "sleep", id: string, durationMs: number, } | { "type": "imageGeneration", id: string, status: string, revisedPrompt: string | null, result: string, savedPath?: AbsolutePathBuf, } | { "type": "enteredReviewMode", id: string, review: string, } | { "type": "exitedReviewMode", id: string, review: string, } | { "type": "contextCompaction", id: string, };
|
||||
agentsStates: { [key in string]?: CollabAgentState }, } | { "type": "subAgentActivity", id: string, kind: SubAgentActivityKind, agentThreadId: string, agentPath: string, } | { "type": "webSearch", id: string, query: string, action: WebSearchAction | null, results: Array<WebSearchResult> | null, } | { "type": "imageView", id: string, path: LegacyAppPathString, } | { "type": "sleep", id: string, durationMs: number, } | { "type": "imageGeneration", id: string, status: string, revisedPrompt: string | null, result: string, savedPath?: AbsolutePathBuf, } | { "type": "enteredReviewMode", id: string, review: string, } | { "type": "exitedReviewMode", id: string, review: string, } | { "type": "contextCompaction", id: string, };
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type WebSearchResult = { url: string, title: string | null, snippet: string | null, };
|
||||
@@ -499,6 +499,7 @@ export type { TurnsPage } from "./TurnsPage";
|
||||
export type { UserInput } from "./UserInput";
|
||||
export type { WarningNotification } from "./WarningNotification";
|
||||
export type { WebSearchAction } from "./WebSearchAction";
|
||||
export type { WebSearchResult } from "./WebSearchResult";
|
||||
export type { WindowsSandboxReadiness } from "./WindowsSandboxReadiness";
|
||||
export type { WindowsSandboxReadinessResponse } from "./WindowsSandboxReadinessResponse";
|
||||
export type { WindowsSandboxSetupCompletedNotification } from "./WindowsSandboxSetupCompletedNotification";
|
||||
|
||||
@@ -22,6 +22,7 @@ use crate::protocol::v2::TurnItemsView;
|
||||
use crate::protocol::v2::TurnStatus;
|
||||
use crate::protocol::v2::UserInput;
|
||||
use crate::protocol::v2::WebSearchAction;
|
||||
use crate::protocol::v2::WebSearchResult;
|
||||
use codex_protocol::items::parse_hook_prompt_message;
|
||||
use codex_protocol::models::MessagePhase;
|
||||
use codex_protocol::protocol::AgentReasoningEvent;
|
||||
@@ -615,6 +616,7 @@ impl ThreadHistoryBuilder {
|
||||
id: payload.call_id.clone(),
|
||||
query: String::new(),
|
||||
action: None,
|
||||
results: None,
|
||||
};
|
||||
self.upsert_item_in_current_turn(item);
|
||||
}
|
||||
@@ -624,6 +626,10 @@ impl ThreadHistoryBuilder {
|
||||
id: payload.call_id.clone(),
|
||||
query: payload.query.clone(),
|
||||
action: Some(WebSearchAction::from(payload.action.clone())),
|
||||
results: payload
|
||||
.results
|
||||
.clone()
|
||||
.map(|results| results.into_iter().map(WebSearchResult::from).collect()),
|
||||
};
|
||||
self.upsert_item_in_current_turn(item);
|
||||
}
|
||||
@@ -1556,6 +1562,7 @@ mod tests {
|
||||
use codex_protocol::items::SleepItem as CoreSleepItem;
|
||||
use codex_protocol::items::TurnItem as CoreTurnItem;
|
||||
use codex_protocol::items::UserMessageItem as CoreUserMessageItem;
|
||||
use codex_protocol::items::WebSearchResult as CoreWebSearchResult;
|
||||
use codex_protocol::items::build_hook_prompt_message;
|
||||
use codex_protocol::mcp::CallToolResult;
|
||||
use codex_protocol::models::ImageDetail;
|
||||
@@ -2443,6 +2450,11 @@ mod tests {
|
||||
query: Some("codex".into()),
|
||||
queries: None,
|
||||
},
|
||||
results: Some(vec![CoreWebSearchResult {
|
||||
url: "https://example.com/codex".into(),
|
||||
title: Some("Codex".into()),
|
||||
snippet: Some("Codex documentation".into()),
|
||||
}]),
|
||||
}),
|
||||
EventMsg::ExecCommandEnd(ExecCommandEndEvent {
|
||||
call_id: "exec-1".into(),
|
||||
@@ -2499,6 +2511,11 @@ mod tests {
|
||||
query: Some("codex".into()),
|
||||
queries: None,
|
||||
}),
|
||||
results: Some(vec![WebSearchResult {
|
||||
url: "https://example.com/codex".into(),
|
||||
title: Some("Codex".into()),
|
||||
snippet: Some("Codex documentation".into()),
|
||||
}]),
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -3917,6 +3934,7 @@ mod tests {
|
||||
query: Some("codex".into()),
|
||||
queries: None,
|
||||
},
|
||||
results: None,
|
||||
}),
|
||||
));
|
||||
|
||||
@@ -3932,6 +3950,7 @@ mod tests {
|
||||
query: Some("codex".into()),
|
||||
queries: None,
|
||||
}),
|
||||
results: None,
|
||||
},
|
||||
}],
|
||||
changed_turns: Vec::new(),
|
||||
@@ -4052,6 +4071,7 @@ mod tests {
|
||||
query: Some("codex".into()),
|
||||
queries: None,
|
||||
},
|
||||
results: None,
|
||||
})),
|
||||
]);
|
||||
|
||||
@@ -4067,6 +4087,7 @@ mod tests {
|
||||
query: Some("codex".into()),
|
||||
queries: None,
|
||||
}),
|
||||
results: None,
|
||||
},
|
||||
}],
|
||||
changed_turns: vec![ThreadHistoryTurnChange {
|
||||
|
||||
@@ -359,6 +359,7 @@ pub enum ThreadItem {
|
||||
id: String,
|
||||
query: String,
|
||||
action: Option<WebSearchAction>,
|
||||
results: Option<Vec<WebSearchResult>>,
|
||||
},
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase")]
|
||||
@@ -783,6 +784,25 @@ impl TryFrom<GuardianApprovalReviewAction> for CoreGuardianAssessmentAction {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct WebSearchResult {
|
||||
pub url: String,
|
||||
pub title: Option<String>,
|
||||
pub snippet: Option<String>,
|
||||
}
|
||||
|
||||
impl From<codex_protocol::items::WebSearchResult> for WebSearchResult {
|
||||
fn from(value: codex_protocol::items::WebSearchResult) -> Self {
|
||||
Self {
|
||||
url: value.url,
|
||||
title: value.title,
|
||||
snippet: value.snippet,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
#[ts(tag = "type", rename_all = "camelCase")]
|
||||
@@ -922,6 +942,9 @@ impl From<CoreTurnItem> for ThreadItem {
|
||||
id: search.id,
|
||||
query: search.query,
|
||||
action: Some(WebSearchAction::from(search.action)),
|
||||
results: search
|
||||
.results
|
||||
.map(|results| results.into_iter().map(Into::into).collect()),
|
||||
},
|
||||
CoreTurnItem::ImageView(image) => ThreadItem::ImageView {
|
||||
id: image.id,
|
||||
|
||||
@@ -20,6 +20,7 @@ use codex_protocol::items::SubAgentActivityItem;
|
||||
use codex_protocol::items::TurnItem;
|
||||
use codex_protocol::items::UserMessageItem;
|
||||
use codex_protocol::items::WebSearchItem;
|
||||
use codex_protocol::items::WebSearchResult as CoreWebSearchResult;
|
||||
use codex_protocol::mcp::CallToolResult;
|
||||
use codex_protocol::mcp::McpServerInfo;
|
||||
use codex_protocol::memory_citation::MemoryCitation as CoreMemoryCitation;
|
||||
@@ -2777,6 +2778,11 @@ fn core_turn_item_into_thread_item_converts_supported_variants() {
|
||||
query: Some("docs".to_string()),
|
||||
queries: None,
|
||||
},
|
||||
results: Some(vec![CoreWebSearchResult {
|
||||
url: "https://openai.com/docs".to_string(),
|
||||
title: Some("OpenAI docs".to_string()),
|
||||
snippet: Some("Documentation".to_string()),
|
||||
}]),
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
@@ -2788,6 +2794,11 @@ fn core_turn_item_into_thread_item_converts_supported_variants() {
|
||||
query: Some("docs".to_string()),
|
||||
queries: None,
|
||||
}),
|
||||
results: Some(vec![WebSearchResult {
|
||||
url: "https://openai.com/docs".to_string(),
|
||||
title: Some("OpenAI docs".to_string()),
|
||||
snippet: Some("Documentation".to_string()),
|
||||
}]),
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -187,6 +187,7 @@ async fn standalone_web_search_round_trips_output() -> Result<()> {
|
||||
id: call_id.to_string(),
|
||||
query: String::new(),
|
||||
action: Some(WebSearchAction::Other),
|
||||
results: None,
|
||||
}
|
||||
);
|
||||
let expected_completed_item = ThreadItem::WebSearch {
|
||||
@@ -196,6 +197,7 @@ async fn standalone_web_search_round_trips_output() -> Result<()> {
|
||||
query: Some("standalone web search".to_string()),
|
||||
queries: None,
|
||||
}),
|
||||
results: None,
|
||||
};
|
||||
assert_eq!(completed.item, expected_completed_item);
|
||||
|
||||
|
||||
@@ -204,6 +204,7 @@ pub fn parse_turn_item(item: &ResponseItem) -> Option<TurnItem> {
|
||||
id: id.clone().unwrap_or_default(),
|
||||
query,
|
||||
action,
|
||||
results: None,
|
||||
}))
|
||||
}
|
||||
ResponseItem::ImageGenerationCall {
|
||||
|
||||
@@ -508,6 +508,7 @@ fn parses_web_search_call() {
|
||||
query: Some("weather".to_string()),
|
||||
queries: None,
|
||||
},
|
||||
results: None,
|
||||
}
|
||||
),
|
||||
other => panic!("expected TurnItem::WebSearch, got {other:?}"),
|
||||
@@ -536,6 +537,7 @@ fn parses_web_search_open_page_call() {
|
||||
action: WebSearchAction::OpenPage {
|
||||
url: Some("https://example.com".to_string()),
|
||||
},
|
||||
results: None,
|
||||
}
|
||||
),
|
||||
other => panic!("expected TurnItem::WebSearch, got {other:?}"),
|
||||
@@ -566,6 +568,7 @@ fn parses_web_search_find_in_page_call() {
|
||||
url: Some("https://example.com".to_string()),
|
||||
pattern: Some("needle".to_string()),
|
||||
},
|
||||
results: None,
|
||||
}
|
||||
),
|
||||
other => panic!("expected TurnItem::WebSearch, got {other:?}"),
|
||||
@@ -589,6 +592,7 @@ fn parses_partial_web_search_call_without_action_as_other() {
|
||||
id: "ws_partial".to_string(),
|
||||
query: String::new(),
|
||||
action: WebSearchAction::Other,
|
||||
results: None,
|
||||
}
|
||||
),
|
||||
other => panic!("expected TurnItem::WebSearch, got {other:?}"),
|
||||
|
||||
@@ -273,6 +273,7 @@ mod tests {
|
||||
query: Some("rust trait object".to_string()),
|
||||
queries: None,
|
||||
},
|
||||
results: None,
|
||||
});
|
||||
call.turn_item_emitter.emit_started(item.clone()).await;
|
||||
call.turn_item_emitter.emit_completed(item).await;
|
||||
@@ -438,6 +439,7 @@ mod tests {
|
||||
query: Some("rust trait object".to_string()),
|
||||
queries: None,
|
||||
},
|
||||
results: None,
|
||||
};
|
||||
assert_eq!(started_item, expected);
|
||||
assert_eq!(completed_item, expected);
|
||||
@@ -487,6 +489,7 @@ mod tests {
|
||||
id: "search-1".to_string(),
|
||||
query: "contributors".to_string(),
|
||||
action: WebSearchAction::Other,
|
||||
results: None,
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -54,6 +54,7 @@ use crate::exec_events::TurnFailedEvent;
|
||||
use crate::exec_events::TurnStartedEvent;
|
||||
use crate::exec_events::Usage;
|
||||
use crate::exec_events::WebSearchItem;
|
||||
use crate::exec_events::WebSearchResult;
|
||||
|
||||
pub struct EventProcessorWithJsonOutput {
|
||||
last_message_path: Option<PathBuf>,
|
||||
@@ -297,6 +298,7 @@ impl EventProcessorWithJsonOutput {
|
||||
id: raw_id,
|
||||
query,
|
||||
action,
|
||||
results,
|
||||
} => Some(ExecThreadItem {
|
||||
id: make_id(),
|
||||
details: ThreadItemDetails::WebSearch(WebSearchItem {
|
||||
@@ -309,6 +311,16 @@ impl EventProcessorWithJsonOutput {
|
||||
.unwrap_or(WebSearchAction::Other),
|
||||
None => WebSearchAction::Other,
|
||||
},
|
||||
results: results.map(|results| {
|
||||
results
|
||||
.into_iter()
|
||||
.map(|result| WebSearchResult {
|
||||
url: result.url,
|
||||
title: result.title,
|
||||
snippet: result.snippet,
|
||||
})
|
||||
.collect()
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
_ => None,
|
||||
|
||||
@@ -296,6 +296,20 @@ pub struct WebSearchItem {
|
||||
pub id: String,
|
||||
pub query: String,
|
||||
pub action: WebSearchAction,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub results: Option<Vec<WebSearchResult>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||
pub struct WebSearchResult {
|
||||
pub url: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub title: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub snippet: Option<String>,
|
||||
}
|
||||
|
||||
/// An error notification.
|
||||
|
||||
@@ -138,6 +138,7 @@ pub use exec_events::TurnFailedEvent;
|
||||
pub use exec_events::TurnStartedEvent;
|
||||
pub use exec_events::Usage;
|
||||
pub use exec_events::WebSearchItem;
|
||||
pub use exec_events::WebSearchResult;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::future::Future;
|
||||
|
||||
@@ -27,6 +27,7 @@ use codex_app_server_protocol::TurnPlanUpdatedNotification;
|
||||
use codex_app_server_protocol::TurnStartedNotification;
|
||||
use codex_app_server_protocol::TurnStatus;
|
||||
use codex_app_server_protocol::WebSearchAction as ApiWebSearchAction;
|
||||
use codex_app_server_protocol::WebSearchResult as ApiWebSearchResult;
|
||||
use codex_protocol::SessionId;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
@@ -74,6 +75,7 @@ use codex_exec::TurnFailedEvent;
|
||||
use codex_exec::TurnStartedEvent;
|
||||
use codex_exec::Usage;
|
||||
use codex_exec::WebSearchItem;
|
||||
use codex_exec::WebSearchResult;
|
||||
|
||||
#[test]
|
||||
fn map_todo_items_preserves_text_and_completion_state() {
|
||||
@@ -369,6 +371,11 @@ fn web_search_completion_preserves_query_and_action() {
|
||||
query: Some("rust async await".to_string()),
|
||||
queries: None,
|
||||
}),
|
||||
results: Some(vec![ApiWebSearchResult {
|
||||
url: "https://example.com/rust-async".to_string(),
|
||||
title: Some("Async Rust".to_string()),
|
||||
snippet: Some("An introduction to async Rust.".to_string()),
|
||||
}]),
|
||||
},
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn_id: "turn-1".to_string(),
|
||||
@@ -389,6 +396,11 @@ fn web_search_completion_preserves_query_and_action() {
|
||||
query: Some("rust async await".to_string()),
|
||||
queries: None,
|
||||
},
|
||||
results: Some(vec![WebSearchResult {
|
||||
url: "https://example.com/rust-async".to_string(),
|
||||
title: Some("Async Rust".to_string()),
|
||||
snippet: Some("An introduction to async Rust.".to_string()),
|
||||
}]),
|
||||
}),
|
||||
},
|
||||
})],
|
||||
@@ -407,6 +419,7 @@ fn web_search_start_and_completion_reuse_item_id() {
|
||||
id: "search-1".to_string(),
|
||||
query: String::new(),
|
||||
action: None,
|
||||
results: None,
|
||||
},
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn_id: "turn-1".to_string(),
|
||||
@@ -422,6 +435,7 @@ fn web_search_start_and_completion_reuse_item_id() {
|
||||
query: Some("rust async await".to_string()),
|
||||
queries: None,
|
||||
}),
|
||||
results: None,
|
||||
},
|
||||
thread_id: "thread-1".to_string(),
|
||||
turn_id: "turn-1".to_string(),
|
||||
@@ -439,6 +453,7 @@ fn web_search_start_and_completion_reuse_item_id() {
|
||||
id: "search-1".to_string(),
|
||||
query: String::new(),
|
||||
action: WebSearchAction::Other,
|
||||
results: None,
|
||||
}),
|
||||
},
|
||||
})],
|
||||
@@ -458,6 +473,7 @@ fn web_search_start_and_completion_reuse_item_id() {
|
||||
query: Some("rust async await".to_string()),
|
||||
queries: None,
|
||||
},
|
||||
results: None,
|
||||
}),
|
||||
},
|
||||
})],
|
||||
|
||||
@@ -185,6 +185,7 @@ fn web_search_item(call_id: &str, action: WebSearchAction) -> ExtensionTurnItem
|
||||
id: call_id.to_string(),
|
||||
query: web_search_action_detail(&action),
|
||||
action,
|
||||
results: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ use crate::user_input::TextElement;
|
||||
use crate::user_input::UserInput;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use codex_utils_string::take_bytes_at_char_boundary;
|
||||
use quick_xml::de::from_str as from_xml_str;
|
||||
use quick_xml::se::to_string as to_xml_string;
|
||||
use schemars::JsonSchema;
|
||||
@@ -262,11 +263,97 @@ pub struct SubAgentActivityItem {
|
||||
pub agent_path: AgentPath,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq, Eq)]
|
||||
pub struct WebSearchResult {
|
||||
pub url: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub title: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub snippet: Option<String>,
|
||||
}
|
||||
|
||||
const MAX_WEB_SEARCH_RESULTS: usize = 20;
|
||||
const MAX_WEB_SEARCH_RESULT_URL_BYTES: usize = 512;
|
||||
const MAX_WEB_SEARCH_RESULT_TOTAL_URL_BYTES: usize = 2_048;
|
||||
const MAX_WEB_SEARCH_RESULT_TITLE_BYTES: usize = 256;
|
||||
const MAX_WEB_SEARCH_RESULT_SNIPPET_BYTES: usize = 512;
|
||||
const MAX_WEB_SEARCH_RESULT_TOTAL_TEXT_BYTES: usize = 4_096;
|
||||
|
||||
pub fn bounded_web_search_results(
|
||||
results: impl IntoIterator<Item = WebSearchResult>,
|
||||
) -> Vec<WebSearchResult> {
|
||||
let mut bounded_results = Vec::new();
|
||||
let mut total_url_bytes = 0usize;
|
||||
let mut total_text_bytes = 0usize;
|
||||
|
||||
for result in results {
|
||||
if bounded_results.len() == MAX_WEB_SEARCH_RESULTS {
|
||||
break;
|
||||
}
|
||||
if result.url.len() > MAX_WEB_SEARCH_RESULT_URL_BYTES
|
||||
|| total_url_bytes.saturating_add(result.url.len())
|
||||
> MAX_WEB_SEARCH_RESULT_TOTAL_URL_BYTES
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let title = bounded_web_search_result_text(
|
||||
result.title,
|
||||
MAX_WEB_SEARCH_RESULT_TITLE_BYTES,
|
||||
MAX_WEB_SEARCH_RESULT_TOTAL_TEXT_BYTES.saturating_sub(total_text_bytes),
|
||||
);
|
||||
total_text_bytes += title.as_ref().map_or(0, String::len);
|
||||
let snippet = bounded_web_search_result_text(
|
||||
result.snippet,
|
||||
MAX_WEB_SEARCH_RESULT_SNIPPET_BYTES,
|
||||
MAX_WEB_SEARCH_RESULT_TOTAL_TEXT_BYTES.saturating_sub(total_text_bytes),
|
||||
);
|
||||
total_text_bytes += snippet.as_ref().map_or(0, String::len);
|
||||
total_url_bytes += result.url.len();
|
||||
bounded_results.push(WebSearchResult {
|
||||
url: result.url,
|
||||
title,
|
||||
snippet,
|
||||
});
|
||||
}
|
||||
|
||||
bounded_results
|
||||
}
|
||||
|
||||
fn bounded_web_search_result_text(
|
||||
text: Option<String>,
|
||||
max_bytes: usize,
|
||||
remaining_bytes: usize,
|
||||
) -> Option<String> {
|
||||
let text = text?;
|
||||
let text = text.trim();
|
||||
let text = take_bytes_at_char_boundary(text, max_bytes.min(remaining_bytes));
|
||||
(!text.is_empty()).then(|| text.to_string())
|
||||
}
|
||||
|
||||
pub(crate) fn deserialize_web_search_results<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<Option<Vec<WebSearchResult>>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Ok(Option::<Vec<WebSearchResult>>::deserialize(deserializer)?.map(bounded_web_search_results))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
||||
pub struct WebSearchItem {
|
||||
pub id: String,
|
||||
pub query: String,
|
||||
pub action: WebSearchAction,
|
||||
#[serde(
|
||||
default,
|
||||
deserialize_with = "deserialize_web_search_results",
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
#[ts(optional)]
|
||||
pub results: Option<Vec<WebSearchResult>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
||||
@@ -649,4 +736,37 @@ mod tests {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bounds_web_search_result_text_and_total_payload() {
|
||||
let results = bounded_web_search_results((0..20).map(|index| WebSearchResult {
|
||||
url: format!("https://example.com/{index}"),
|
||||
title: Some("t".repeat(300)),
|
||||
snippet: Some("é".repeat(600)),
|
||||
}));
|
||||
|
||||
assert_eq!(results.len(), 20);
|
||||
assert!(
|
||||
results
|
||||
.iter()
|
||||
.filter_map(|result| result.title.as_ref())
|
||||
.all(|title| title.len() <= MAX_WEB_SEARCH_RESULT_TITLE_BYTES)
|
||||
);
|
||||
assert!(
|
||||
results
|
||||
.iter()
|
||||
.filter_map(|result| result.snippet.as_ref())
|
||||
.all(|snippet| snippet.len() <= MAX_WEB_SEARCH_RESULT_SNIPPET_BYTES)
|
||||
);
|
||||
assert!(
|
||||
results
|
||||
.iter()
|
||||
.map(|result| {
|
||||
result.title.as_ref().map_or(0, String::len)
|
||||
+ result.snippet.as_ref().map_or(0, String::len)
|
||||
})
|
||||
.sum::<usize>()
|
||||
<= MAX_WEB_SEARCH_RESULT_TOTAL_TEXT_BYTES
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,6 +382,7 @@ impl WebSearchItem {
|
||||
call_id: self.id.clone(),
|
||||
query: self.query.clone(),
|
||||
action: self.action.clone(),
|
||||
results: self.results.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ use crate::dynamic_tools::DynamicToolCallRequest;
|
||||
use crate::dynamic_tools::DynamicToolResponse;
|
||||
use crate::dynamic_tools::DynamicToolSpec;
|
||||
use crate::items::TurnItem;
|
||||
use crate::items::WebSearchResult;
|
||||
use crate::items::deserialize_web_search_results;
|
||||
use crate::mcp::CallToolResult;
|
||||
use crate::mcp::RequestId;
|
||||
use crate::memory_citation::MemoryCitation;
|
||||
@@ -2408,6 +2410,13 @@ pub struct WebSearchEndEvent {
|
||||
pub call_id: String,
|
||||
pub query: String,
|
||||
pub action: WebSearchAction,
|
||||
#[serde(
|
||||
default,
|
||||
deserialize_with = "deserialize_web_search_results",
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
#[ts(optional)]
|
||||
pub results: Option<Vec<WebSearchResult>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)]
|
||||
@@ -5038,6 +5047,7 @@ mod tests {
|
||||
query: Some("find docs".into()),
|
||||
queries: None,
|
||||
},
|
||||
results: None,
|
||||
}),
|
||||
started_at_ms: 0,
|
||||
};
|
||||
|
||||
@@ -139,7 +139,9 @@ impl ChatWidget {
|
||||
..
|
||||
} => self.on_mcp_tool_call_started(item),
|
||||
item @ ThreadItem::McpToolCall { .. } => self.on_mcp_tool_call_completed(item),
|
||||
ThreadItem::WebSearch { id, query, action } => {
|
||||
ThreadItem::WebSearch {
|
||||
id, query, action, ..
|
||||
} => {
|
||||
self.on_web_search_begin(id.clone());
|
||||
self.on_web_search_end(
|
||||
id,
|
||||
|
||||
Reference in New Issue
Block a user