Repository: sashabaranov/go-openai
Pull request #799 (2024-07-19 06:49:57)

feat: Support Delete Message API
# Describe the change
- support Delete Message API
- No breaking changes

# OpenAI documentation 
relevant API doc from https://platform.openai.com/docs/api-reference/messages/deleteMessage


# Additional context
- fix lint

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/sashabaranov/go-openai/pull/799?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alex+Baranov) Report
Attention: Patch coverage is `77.77778%` with `2 lines` in your changes missing coverage. Please review.
> Project coverage is 98.74%. Comparing base [(`774fc9d`)](https://app.codecov.io/gh/sashabaranov/go-openai/commit/774fc9dd12ed60c10a9f9f03319ddb9cd5f8780c?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alex+Baranov) to head [(`0bdc97a`)](https://app.codecov.io/gh/sashabaranov/go-openai/commit/0bdc97a5c946ebfc95c4cdf9d5a1b40a32a676dc?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alex+Baranov).
> Report is 27 commits behind head on master.

| [Files](https://app.codecov.io/gh/sashabaranov/go-openai/pull/799?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alex+Baranov) | Patch % | Lines |
|---|---|---|
| [messages.go](https://app.codecov.io/gh/sashabaranov/go-openai/pull/799?src=pr&el=tree&filepath=messages.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alex+Baranov#diff-bWVzc2FnZXMuZ28=) | 75.00% | [1 Missing and 1 partial :warning: ](https://app.codecov.io/gh/sashabaranov/go-openai/pull/799?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alex+Baranov) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master     #799      +/-   ##
==========================================
+ Coverage   98.46%   98.74%   +0.28%     
==========================================
  Files          24       26       +2     
  Lines        1364     1351      -13     
==========================================
- Hits         1343     1334       -9     
+ Misses         15       10       -5     
- Partials        6        7       +1     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/sashabaranov/go-openai/pull/799?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alex+Baranov).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alex+Baranov).

sashabaranov: Thank you for the PR! Added a minor comment

Patch:
diff --git a/fine_tunes.go b/fine_tunes.go
index ca84078..74b47bf 100644
--- a/fine_tunes.go
+++ b/fine_tunes.go
@@ -115,7 +115,7 @@ func (c *Client) CreateFineTune(ctx context.Context, request FineTuneRequest) (r
 // This API will be officially deprecated on January 4th, 2024.
 // OpenAI recommends to migrate to the new fine tuning API implemented in fine_tuning_job.go.
 func (c *Client) CancelFineTune(ctx context.Context, fineTuneID string) (response FineTune, err error) {
-	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL("/fine-tunes/"+fineTuneID+"/cancel"))
+	req, err := c.newRequest(ctx, http.MethodPost, c.fullURL("/fine-tunes/"+fineTuneID+"/cancel")) //nolint:lll //this method is deprecated
 	if err != nil {
 		return
 	}
diff --git a/messages.go b/messages.go
index 6af1184..1fddd63 100644
--- a/messages.go
+++ b/messages.go
@@ -73,6 +73,14 @@ type MessageFilesList struct {
 	httpHeader
 }
 
+type MessageDeletionStatus struct {
+	ID      string `json:"id"`
+	Object  string `json:"object"`
+	Deleted bool   `json:"deleted"`
+
+	httpHeader
+}
+
 // CreateMessage creates a new message.
 func (c *Client) CreateMessage(ctx context.Context, threadID string, request MessageRequest) (msg Message, err error) {
 	urlSuffix := fmt.Sprintf("/threads/%s/%s", threadID, messagesSuffix)
@@ -186,3 +194,19 @@ func (c *Client) ListMessageFiles(
 	err = c.sendRequest(req, &files)
 	return
 }
+
+// DeleteMessage deletes a message..
+func (c *Client) DeleteMessage(
+	ctx context.Context,
+	threadID, messageID string,
+) (status MessageDeletionStatus, err error) {
+	urlSuffix := fmt.Sprintf("/threads/%s/%s/%s", threadID, messagesSuffix, messageID)
+	req, err := c.newRequest(ctx, http.MethodDelete, c.fullURL(urlSuffix),
+		withBetaAssistantVersion(c.config.AssistantVersion))
+	if err != nil {
+		return
+	}
+
+	err = c.sendRequest(req, &status)
+	return
+}


Test patch:
diff --git a/client_test.go b/client_test.go
index a0d3bb3..7119d8a 100644
--- a/client_test.go
+++ b/client_test.go
@@ -348,6 +348,9 @@ func TestClientReturnsRequestBuilderErrors(t *testing.T) {
 		{"ModifyMessage", func() (any, error) {
 			return client.ModifyMessage(ctx, "", "", nil)
 		}},
+		{"DeleteMessage", func() (any, error) {
+			return client.DeleteMessage(ctx, "", "")
+		}},
 		{"RetrieveMessageFile", func() (any, error) {
 			return client.RetrieveMessageFile(ctx, "", "", "")
 		}},
diff --git a/messages_test.go b/messages_test.go
index a18be20..71ceb4d 100644
--- a/messages_test.go
+++ b/messages_test.go
@@ -8,20 +8,17 @@ import (
 	"testing"
 
 	"github.com/sashabaranov/go-openai"
+	"github.com/sashabaranov/go-openai/internal/test"
 	"github.com/sashabaranov/go-openai/internal/test/checks"
 )
 
 var emptyStr = ""
 
-// TestMessages Tests the messages endpoint of the API using the mocked server.
-func TestMessages(t *testing.T) {
+func setupServerForTestMessage(t *testing.T, server *test.ServerTest) {
 	threadID := "thread_abc123"
 	messageID := "msg_abc123"
 	fileID := "file_abc123"
 
-	client, server, teardown := setupOpenAITestServer()
-	defer teardown()
-
 	server.RegisterHandler(
 		"/v1/threads/"+threadID+"/messages/"+messageID+"/files/"+fileID,
 		func(w http.ResponseWriter, r *http.Request) {
@@ -115,6 +112,13 @@ func TestMessages(t *testing.T) {
 						Metadata:    nil,
 					})
 				fmt.Fprintln(w, string(resBytes))
+			case http.MethodDelete:
+				resBytes, _ := json.Marshal(openai.MessageDeletionStatus{
+					ID:      messageID,
+					Object:  "thread.message.deleted",
+					Deleted: true,
+				})
+				fmt.Fprintln(w, string(resBytes))
 			default:
 				t.Fatalf("unsupported messages http method: %s", r.Method)
 			}
@@ -176,7 +180,18 @@ func TestMessages(t *testing.T) {
 			}
 		},
 	)
+}
 
+// TestMessages Tests the messages endpoint of the API using the mocked server.
+func TestMessages(t *testing.T) {
+	threadID := "thread_abc123"
+	messageID := "msg_abc123"
+	fileID := "file_abc123"
+
+	client, server, teardown := setupOpenAITestServer()
+	defer teardown()
+
+	setupServerForTestMessage(t, server)
 	ctx := context.Background()
 
 	// static assertion of return type
@@ -225,6 +240,17 @@ func TestMessages(t *testing.T) {
 		t.Fatalf("expected message metadata to get modified")
 	}
 
+	msgDel, err := client.DeleteMessage(ctx, threadID, messageID)
+	checks.NoError(t, err, "DeleteMessage error")
+	if msgDel.ID != messageID {
+		t.Fatalf("unexpected message id: '%s'", msg.ID)
+	}
+	if !msgDel.Deleted {
+		t.Fatalf("expected deleted is true")
+	}
+	_, err = client.DeleteMessage(ctx, threadID, "not_exist_id")
+	checks.HasError(t, err, "DeleteMessage error")
+
 	// message files
 	var msgFile openai.MessageFile
 	msgFile, err = client.RetrieveMessageFile(ctx, threadID, messageID, fileID)