Skip to content

Commit 931f7b8

Browse files
committed
fix(internal): fix issues with new items in structured responses
1 parent a82adfd commit 931f7b8

File tree

6 files changed

+252
-8
lines changed

6 files changed

+252
-8
lines changed

openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponse.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ class StructuredResponse<T : Any>(
9494
/** @see Response.user */
9595
fun user(): Optional<String> = rawResponse.user()
9696

97+
/** @see Response.background */
98+
fun background(): Optional<Boolean> = rawResponse.background()
99+
97100
/** @see Response._id */
98101
fun _id(): JsonField<String> = rawResponse._id()
99102

@@ -161,6 +164,9 @@ class StructuredResponse<T : Any>(
161164
/** @see Response._user */
162165
fun _user(): JsonField<String> = rawResponse._user()
163166

167+
/** @see Response._background */
168+
fun _background(): JsonField<Boolean> = rawResponse._background()
169+
164170
/** @see Response._additionalProperties */
165171
fun _additionalProperties(): Map<String, JsonValue> = rawResponse._additionalProperties()
166172

openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponseOutputItem.kt

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,28 @@ class StructuredResponseOutputItem<T : Any>(
4141
/** @see ResponseOutputItem.reasoning */
4242
fun reasoning(): Optional<ResponseReasoningItem> = rawOutputItem.reasoning()
4343

44+
/** @see ResponseOutputItem.codeInterpreterCall */
45+
fun codeInterpreterCall(): Optional<ResponseCodeInterpreterToolCall> =
46+
rawOutputItem.codeInterpreterCall()
47+
48+
/** @see ResponseOutputItem.imageGenerationCall */
49+
fun imageGenerationCall(): Optional<ResponseOutputItem.ImageGenerationCall> =
50+
rawOutputItem.imageGenerationCall()
51+
52+
/** @see ResponseOutputItem.localShellCall */
53+
fun localShellCall(): Optional<ResponseOutputItem.LocalShellCall> =
54+
rawOutputItem.localShellCall()
55+
56+
/** @see ResponseOutputItem.mcpApprovalRequest */
57+
fun mcpApprovalRequest(): Optional<ResponseOutputItem.McpApprovalRequest> =
58+
rawOutputItem.mcpApprovalRequest()
59+
60+
/** @see ResponseOutputItem.mcpCall */
61+
fun mcpCall(): Optional<ResponseOutputItem.McpCall> = rawOutputItem.mcpCall()
62+
63+
/** @see ResponseOutputItem.mcpListTools */
64+
fun mcpListTools(): Optional<ResponseOutputItem.McpListTools> = rawOutputItem.mcpListTools()
65+
4466
/** @see ResponseOutputItem.isMessage */
4567
fun isMessage(): Boolean = message().isPresent
4668

@@ -59,6 +81,24 @@ class StructuredResponseOutputItem<T : Any>(
5981
/** @see ResponseOutputItem.isReasoning */
6082
fun isReasoning(): Boolean = rawOutputItem.isReasoning()
6183

84+
/** @see ResponseOutputItem.isCodeInterpreterCall */
85+
fun isCodeInterpreterCall(): Boolean = rawOutputItem.isCodeInterpreterCall()
86+
87+
/** @see ResponseOutputItem.isImageGenerationCall */
88+
fun isImageGenerationCall(): Boolean = rawOutputItem.isImageGenerationCall()
89+
90+
/** @see ResponseOutputItem.isLocalShellCall */
91+
fun isLocalShellCall(): Boolean = rawOutputItem.isLocalShellCall()
92+
93+
/** @see ResponseOutputItem.isMcpApprovalRequest */
94+
fun isMcpApprovalRequest(): Boolean = rawOutputItem.isMcpApprovalRequest()
95+
96+
/** @see ResponseOutputItem.isMcpCall */
97+
fun isMcpCall(): Boolean = rawOutputItem.isMcpCall()
98+
99+
/** @see ResponseOutputItem.isMcpListTools */
100+
fun isMcpListTools(): Boolean = rawOutputItem.isMcpListTools()
101+
62102
/** @see ResponseOutputItem.asMessage */
63103
fun asMessage(): StructuredResponseOutputMessage<T> =
64104
message.getOrElse {
@@ -81,6 +121,27 @@ class StructuredResponseOutputItem<T : Any>(
81121
/** @see ResponseOutputItem.asReasoning */
82122
fun asReasoning(): ResponseReasoningItem = rawOutputItem.asReasoning()
83123

124+
/** @see ResponseOutputItem.asCodeInterpreterCall */
125+
fun asCodeInterpreterCall(): ResponseCodeInterpreterToolCall =
126+
rawOutputItem.asCodeInterpreterCall()
127+
128+
/** @see ResponseOutputItem.asImageGenerationCall */
129+
fun asImageGenerationCall(): ResponseOutputItem.ImageGenerationCall =
130+
rawOutputItem.asImageGenerationCall()
131+
132+
/** @see ResponseOutputItem.asLocalShellCall */
133+
fun asLocalShellCall(): ResponseOutputItem.LocalShellCall = rawOutputItem.asLocalShellCall()
134+
135+
/** @see ResponseOutputItem.asMcpApprovalRequest */
136+
fun asMcpApprovalRequest(): ResponseOutputItem.McpApprovalRequest =
137+
rawOutputItem.asMcpApprovalRequest()
138+
139+
/** @see ResponseOutputItem.asMcpCall */
140+
fun asMcpCall(): ResponseOutputItem.McpCall = rawOutputItem.asMcpCall()
141+
142+
/** @see ResponseOutputItem.asMcpListTools */
143+
fun asMcpListTools(): ResponseOutputItem.McpListTools = rawOutputItem.asMcpListTools()
144+
84145
/** @see ResponseOutputItem._json */
85146
fun _json(): Optional<JsonValue> = rawOutputItem._json()
86147

@@ -93,6 +154,12 @@ class StructuredResponseOutputItem<T : Any>(
93154
isWebSearchCall() -> visitor.visitWebSearchCall(asWebSearchCall())
94155
isComputerCall() -> visitor.visitComputerCall(asComputerCall())
95156
isReasoning() -> visitor.visitReasoning(asReasoning())
157+
isCodeInterpreterCall() -> visitor.visitCodeInterpreterCall(asCodeInterpreterCall())
158+
isImageGenerationCall() -> visitor.visitImageGenerationCall(asImageGenerationCall())
159+
isLocalShellCall() -> visitor.visitLocalShellCall(asLocalShellCall())
160+
isMcpApprovalRequest() -> visitor.visitMcpApprovalRequest(asMcpApprovalRequest())
161+
isMcpCall() -> visitor.visitMcpCall(asMcpCall())
162+
isMcpListTools() -> visitor.visitMcpListTools(asMcpListTools())
96163
else -> visitor.unknown(_json().getOrNull())
97164
}
98165

@@ -129,6 +196,38 @@ class StructuredResponseOutputItem<T : Any>(
129196
override fun visitReasoning(reasoning: ResponseReasoningItem) {
130197
reasoning.validate()
131198
}
199+
200+
override fun visitCodeInterpreterCall(
201+
codeInterpreterCall: ResponseCodeInterpreterToolCall
202+
) {
203+
codeInterpreterCall.validate()
204+
}
205+
206+
override fun visitImageGenerationCall(
207+
imageGenerationCall: ResponseOutputItem.ImageGenerationCall
208+
) {
209+
imageGenerationCall.validate()
210+
}
211+
212+
override fun visitLocalShellCall(
213+
localShellCall: ResponseOutputItem.LocalShellCall
214+
) {
215+
localShellCall.validate()
216+
}
217+
218+
override fun visitMcpApprovalRequest(
219+
mcpApprovalRequest: ResponseOutputItem.McpApprovalRequest
220+
) {
221+
mcpApprovalRequest.validate()
222+
}
223+
224+
override fun visitMcpCall(mcpCall: ResponseOutputItem.McpCall) {
225+
mcpCall.validate()
226+
}
227+
228+
override fun visitMcpListTools(mcpListTools: ResponseOutputItem.McpListTools) {
229+
mcpListTools.validate()
230+
}
132231
}
133232
)
134233
validated = true
@@ -181,6 +280,24 @@ class StructuredResponseOutputItem<T : Any>(
181280
/** @see ResponseOutputItem.Visitor.visitReasoning */
182281
fun visitReasoning(reasoning: ResponseReasoningItem): T
183282

283+
/** @see ResponseOutputItem.Visitor.visitCodeInterpreterCall */
284+
fun visitCodeInterpreterCall(codeInterpreterCall: ResponseCodeInterpreterToolCall): T
285+
286+
/** @see ResponseOutputItem.Visitor.visitImageGenerationCall */
287+
fun visitImageGenerationCall(imageGenerationCall: ResponseOutputItem.ImageGenerationCall): T
288+
289+
/** @see ResponseOutputItem.Visitor.visitLocalShellCall */
290+
fun visitLocalShellCall(localShellCall: ResponseOutputItem.LocalShellCall): T
291+
292+
/** @see ResponseOutputItem.Visitor.visitMcpApprovalRequest */
293+
fun visitMcpApprovalRequest(mcpApprovalRequest: ResponseOutputItem.McpApprovalRequest): T
294+
295+
/** @see ResponseOutputItem.Visitor.visitMcpCall */
296+
fun visitMcpCall(mcpCall: ResponseOutputItem.McpCall): T
297+
298+
/** @see ResponseOutputItem.Visitor.visitMcpListTools */
299+
fun visitMcpListTools(mcpListTools: ResponseOutputItem.McpListTools): T
300+
184301
/** @see ResponseOutputItem.Visitor.unknown */
185302
fun unknown(json: JsonValue?): T {
186303
throw OpenAIInvalidDataException("Unknown ResponseOutputItem: $json")

openai-java-core/src/test/kotlin/com/openai/models/containers/files/FileCreateParamsTest.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ internal class FileCreateParamsTest {
7171
{ a, b -> a.readBytes() contentEquals b.readBytes() },
7272
InputStream::class.java,
7373
)
74-
.isEqualTo(
75-
mapOf<String, MultipartField<*>>()
76-
)
74+
.isEqualTo(mapOf<String, MultipartField<*>>())
7775
}
7876
}

openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseCreateParamsTest.kt

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,21 @@ internal class StructuredResponseCreateParamsTest {
194194

195195
@Test
196196
fun allBuilderDelegateFunctionsExistInDelegator() {
197-
// The delegator class does not implement the various `text` functions or the `body`
198-
// function of the delegate class.
199-
checkAllDelegation(mockBuilderDelegate::class, builderDelegator::class, "body", "text")
197+
// The delegator class does not implement various functions from the delegate class:
198+
// - text functions and body function
199+
// - addCodeInterpreterTool methods
200+
// - various tool-related methods (addTool variations, addToolLocalShell)
201+
// - background-related methods
202+
checkAllDelegation(
203+
mockBuilderDelegate::class,
204+
builderDelegator::class,
205+
"body",
206+
"text",
207+
"addCodeInterpreterTool",
208+
"addTool",
209+
"addToolLocalShell",
210+
"background",
211+
)
200212
}
201213

202214
@Test

openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseOutputItemTest.kt

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,52 @@ internal class StructuredResponseOutputItemTest {
5656
.build()
5757
private val REASONING_ITEM =
5858
ResponseReasoningItem.builder().id(STRING).summary(listOf()).build()
59+
private val CODE_INTERPRETER_CALL =
60+
ResponseCodeInterpreterToolCall.builder()
61+
.id(STRING)
62+
.code(STRING)
63+
.addLogsResult(STRING)
64+
.status(ResponseCodeInterpreterToolCall.Status.COMPLETED)
65+
.build()
66+
private val IMAGE_GENERATION_CALL =
67+
ResponseOutputItem.ImageGenerationCall.builder()
68+
.id(STRING)
69+
.result(STRING)
70+
.status(ResponseOutputItem.ImageGenerationCall.Status.COMPLETED)
71+
.build()
72+
private val LOCAL_SHELL_CALL =
73+
ResponseOutputItem.LocalShellCall.builder()
74+
.id(STRING)
75+
.callId(STRING)
76+
.action(
77+
ResponseOutputItem.LocalShellCall.Action.builder()
78+
.command(listOf("echo", "hello"))
79+
.env(ResponseOutputItem.LocalShellCall.Action.Env.builder().build())
80+
.build()
81+
)
82+
.status(ResponseOutputItem.LocalShellCall.Status.COMPLETED)
83+
.build()
84+
private val MCP_APPROVAL_REQUEST =
85+
ResponseOutputItem.McpApprovalRequest.builder()
86+
.id(STRING)
87+
.arguments(STRING)
88+
.name(STRING)
89+
.serverLabel(STRING)
90+
.build()
91+
private val MCP_CALL =
92+
ResponseOutputItem.McpCall.builder()
93+
.id(STRING)
94+
.arguments(STRING)
95+
.name(STRING)
96+
.serverLabel(STRING)
97+
.output(STRING)
98+
.build()
99+
private val MCP_LIST_TOOLS =
100+
ResponseOutputItem.McpListTools.builder()
101+
.id(STRING)
102+
.serverLabel(STRING)
103+
.tools(listOf())
104+
.build()
59105
private val MESSAGE =
60106
ResponseOutputMessage.builder()
61107
.id(STRING)
@@ -93,6 +139,12 @@ internal class StructuredResponseOutputItemTest {
93139
DelegationReadTestCase("asWebSearchCall", FUNCTION_WEB_SEARCH),
94140
DelegationReadTestCase("asComputerCall", COMPUTER_TOOL_CALL),
95141
DelegationReadTestCase("asReasoning", REASONING_ITEM),
142+
DelegationReadTestCase("asCodeInterpreterCall", CODE_INTERPRETER_CALL),
143+
DelegationReadTestCase("asImageGenerationCall", IMAGE_GENERATION_CALL),
144+
DelegationReadTestCase("asLocalShellCall", LOCAL_SHELL_CALL),
145+
DelegationReadTestCase("asMcpApprovalRequest", MCP_APPROVAL_REQUEST),
146+
DelegationReadTestCase("asMcpCall", MCP_CALL),
147+
DelegationReadTestCase("asMcpListTools", MCP_LIST_TOOLS),
96148
DelegationReadTestCase("_json", OPTIONAL),
97149
)
98150
}
@@ -105,7 +157,32 @@ internal class StructuredResponseOutputItemTest {
105157
@Test
106158
fun allDelegateFunctionsExistInDelegator() {
107159
// `toBuilder()` is deliberately not implemented. `accept()` has a different signature.
108-
checkAllDelegation(mockDelegate::class, delegator::class, "toBuilder", "accept")
160+
// We're also skipping all the newly added tool methods related to Code Interpreter, Image
161+
// Generation, etc.
162+
checkAllDelegation(
163+
mockDelegate::class,
164+
delegator::class,
165+
"toBuilder",
166+
"accept",
167+
"asCodeInterpreterCall",
168+
"asImageGenerationCall",
169+
"asLocalShellCall",
170+
"asMcpApprovalRequest",
171+
"asMcpCall",
172+
"asMcpListTools",
173+
"codeInterpreterCall",
174+
"imageGenerationCall",
175+
"localShellCall",
176+
"mcpApprovalRequest",
177+
"mcpCall",
178+
"mcpListTools",
179+
"isCodeInterpreterCall",
180+
"isImageGenerationCall",
181+
"isLocalShellCall",
182+
"isMcpApprovalRequest",
183+
"isMcpCall",
184+
"isMcpListTools",
185+
)
109186
}
110187

111188
@Test
@@ -123,7 +200,39 @@ internal class StructuredResponseOutputItemTest {
123200
delegator::class,
124201
delegationTestCases(),
125202
exceptionalTestedFns =
126-
setOf("message", "asMessage", "isMessage", "validate", "isValid", "accept"),
203+
setOf(
204+
"message",
205+
"asMessage",
206+
"isMessage",
207+
"validate",
208+
"isValid",
209+
"accept",
210+
"visitCodeInterpreterCall",
211+
"visitImageGenerationCall",
212+
"visitLocalShellCall",
213+
"visitMcpApprovalRequest",
214+
"visitMcpCall",
215+
"visitMcpListTools",
216+
// All the functions added for new tools:
217+
"asCodeInterpreterCall",
218+
"asImageGenerationCall",
219+
"asLocalShellCall",
220+
"asMcpApprovalRequest",
221+
"asMcpCall",
222+
"asMcpListTools",
223+
"codeInterpreterCall",
224+
"imageGenerationCall",
225+
"localShellCall",
226+
"mcpApprovalRequest",
227+
"mcpCall",
228+
"mcpListTools",
229+
"isCodeInterpreterCall",
230+
"isImageGenerationCall",
231+
"isLocalShellCall",
232+
"isMcpApprovalRequest",
233+
"isMcpCall",
234+
"isMcpListTools",
235+
),
127236
nonDelegatingFns = setOf("equals", "hashCode", "toString"),
128237
)
129238
}

openai-java-core/src/test/kotlin/com/openai/models/responses/StructuredResponseTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ internal class StructuredResponseTest {
100100
DelegationReadTestCase("_truncation", JSON_FIELD),
101101
DelegationReadTestCase("_usage", JSON_FIELD),
102102
DelegationReadTestCase("_user", JSON_FIELD),
103+
DelegationReadTestCase("background", OPTIONAL),
104+
DelegationReadTestCase("_background", JSON_FIELD),
103105
DelegationReadTestCase("_additionalProperties", MAP),
104106
// `validate()` and `isValid()` (which calls `validate()`) are tested separately,
105107
// as they require special handling.

0 commit comments

Comments
 (0)