diff --git a/aisdk/ai/provider/openai/internal/codec/decode.go b/aisdk/ai/provider/openai/internal/codec/decode.go index 30f4cabc..d719e257 100644 --- a/aisdk/ai/provider/openai/internal/codec/decode.go +++ b/aisdk/ai/provider/openai/internal/codec/decode.go @@ -187,9 +187,11 @@ func decodeComputerCall(computerCall responses.ResponseComputerToolCall) (*api.T // Create tool call block with provider metadata return &api.ToolCallBlock{ - ToolCallID: computerCall.ID, // TODO: use computerCall.CallID instead + // The CallID is what's needed to respond to the tool call, not the "ID" field. + // https://platform.openai.com/docs/api-reference/responses/object#responses-object-output-computer_tool_call + ToolCallID: computerCall.CallID, ToolName: ComputerUseToolID, - Args: json.RawMessage(computerCall.RawJSON()), // TODO: pass the Action instead. + Args: json.RawMessage(computerCall.Action.RawJSON()), // The Action is the only argument to the computer call. ProviderMetadata: api.NewProviderMetadata(map[string]any{ProviderName: metadata}), }, nil } diff --git a/aisdk/ai/provider/openai/internal/codec/decode_test.go b/aisdk/ai/provider/openai/internal/codec/decode_test.go index a355c6f1..a94ebeb5 100644 --- a/aisdk/ai/provider/openai/internal/codec/decode_test.go +++ b/aisdk/ai/provider/openai/internal/codec/decode_test.go @@ -640,22 +640,24 @@ func TestDecodeToolCalls(t *testing.T) { }, }, { - name: "computer call", + name: "computer call with no safety checks field", response: `{ "output": [ { "type": "computer_call", "id": "comp1", - "command": "ls -la", - "working_directory": "/tmp" + "call_id": "call_123", + "action": { + "type": "screenshot" + } } ] }`, want: []api.ContentBlock{ &api.ToolCallBlock{ - ToolCallID: "comp1", + ToolCallID: "call_123", ToolName: "openai.computer_use_preview", - Args: json.RawMessage(`{"command":"ls -la","working_directory":"/tmp","id":"comp1","type":"computer_call"}`), + Args: json.RawMessage(`{"type":"screenshot"}`), ProviderMetadata: api.NewProviderMetadata(map[string]any{ "openai": &Metadata{ ComputerSafetyChecks: []ComputerSafetyCheck{}, @@ -670,9 +672,10 @@ func TestDecodeToolCalls(t *testing.T) { "output": [ { "type": "computer_call", - "id": "comp2", - "command": "rm -rf /", - "working_directory": "/", + "call_id": "call_123", + "action": { + "type": "screenshot" + }, "pending_safety_checks": [ { "id": "check1", @@ -690,9 +693,9 @@ func TestDecodeToolCalls(t *testing.T) { }`, want: []api.ContentBlock{ &api.ToolCallBlock{ - ToolCallID: "comp2", + ToolCallID: "call_123", ToolName: "openai.computer_use_preview", - Args: json.RawMessage(`{"command":"rm -rf /","working_directory":"/","id":"comp2","type":"computer_call","pending_safety_checks":[{"id":"check1","code":"file_access","message":"File access requested"},{"id":"check2","code":"dangerous_command","message":"Potentially dangerous command detected"}]}`), + Args: json.RawMessage(`{"type":"screenshot"}`), ProviderMetadata: api.NewProviderMetadata(map[string]any{ "openai": &Metadata{ ComputerSafetyChecks: []ComputerSafetyCheck{ @@ -718,18 +721,19 @@ func TestDecodeToolCalls(t *testing.T) { "output": [ { "type": "computer_call", - "id": "comp3", - "command": "echo hello", - "working_directory": "/tmp", + "call_id": "call_123", + "action": { + "type": "screenshot" + }, "pending_safety_checks": [] } ] }`, want: []api.ContentBlock{ &api.ToolCallBlock{ - ToolCallID: "comp3", + ToolCallID: "call_123", ToolName: "openai.computer_use_preview", - Args: json.RawMessage(`{"command":"echo hello","working_directory":"/tmp","id":"comp3","type":"computer_call","pending_safety_checks":[]}`), + Args: json.RawMessage(`{"type":"screenshot"}`), ProviderMetadata: api.NewProviderMetadata(map[string]any{ "openai": &Metadata{ ComputerSafetyChecks: []ComputerSafetyCheck{},