github.com/anthropics/anthropic-sdk-go@v1.70.1/file.go (about)

     1  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
     2  
     3  package anthropic
     4  
     5  import (
     6  	"bytes"
     7  	"context"
     8  	"errors"
     9  	"fmt"
    10  	"io"
    11  	"mime/multipart"
    12  	"net/http"
    13  	"net/url"
    14  	"slices"
    15  	"time"
    16  
    17  	"github.com/anthropics/anthropic-sdk-go/internal/apiform"
    18  	"github.com/anthropics/anthropic-sdk-go/internal/apijson"
    19  	"github.com/anthropics/anthropic-sdk-go/internal/apiquery"
    20  	"github.com/anthropics/anthropic-sdk-go/internal/requestconfig"
    21  	"github.com/anthropics/anthropic-sdk-go/option"
    22  	"github.com/anthropics/anthropic-sdk-go/packages/pagination"
    23  	"github.com/anthropics/anthropic-sdk-go/packages/param"
    24  	"github.com/anthropics/anthropic-sdk-go/packages/respjson"
    25  	"github.com/anthropics/anthropic-sdk-go/shared/constant"
    26  )
    27  
    28  // FileService contains methods and other services that help with interacting with
    29  // the anthropic API.
    30  //
    31  // Note, unlike clients, this service does not read variables from the environment
    32  // automatically. You should not instantiate this service directly, and instead use
    33  // the [NewFileService] method instead.
    34  type FileService struct {
    35  	Options []option.RequestOption
    36  }
    37  
    38  // NewFileService generates a new service that applies the given options to each
    39  // request. These options are applied after the parent client's options (if there
    40  // is one), and before any request-specific options.
    41  func NewFileService(opts ...option.RequestOption) (r FileService) {
    42  	r = FileService{}
    43  	r.Options = opts
    44  	return
    45  }
    46  
    47  // List Files
    48  func (r *FileService) List(ctx context.Context, params FileListParams, opts ...option.RequestOption) (res *pagination.PageCursor[FileMetadata], err error) {
    49  	var raw *http.Response
    50  	if !param.IsOmitted(params.WorkspaceID) {
    51  		opts = append(opts, option.WithHeader("anthropic-workspace-id", fmt.Sprintf("%v", params.WorkspaceID.Value)))
    52  	}
    53  	opts = slices.Concat(r.Options, opts)
    54  	opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...)
    55  	path := "v1/files"
    56  	cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, params, &res, opts...)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  	err = cfg.Execute()
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  	res.SetPageConfig(cfg, raw)
    65  	return res, nil
    66  }
    67  
    68  // List Files
    69  func (r *FileService) ListAutoPaging(ctx context.Context, params FileListParams, opts ...option.RequestOption) *pagination.PageCursorAutoPager[FileMetadata] {
    70  	return pagination.NewPageCursorAutoPager(r.List(ctx, params, opts...))
    71  }
    72  
    73  // Delete File
    74  func (r *FileService) Delete(ctx context.Context, fileID string, body FileDeleteParams, opts ...option.RequestOption) (res *DeletedFile, err error) {
    75  	if !param.IsOmitted(body.WorkspaceID) {
    76  		opts = append(opts, option.WithHeader("anthropic-workspace-id", fmt.Sprintf("%v", body.WorkspaceID.Value)))
    77  	}
    78  	opts = slices.Concat(r.Options, opts)
    79  	if fileID == "" {
    80  		err = errors.New("missing required file_id parameter")
    81  		return nil, err
    82  	}
    83  	path := fmt.Sprintf("v1/files/%s", fileID)
    84  	err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, &res, opts...)
    85  	return res, err
    86  }
    87  
    88  // Download File
    89  func (r *FileService) Download(ctx context.Context, fileID string, query FileDownloadParams, opts ...option.RequestOption) (res *http.Response, err error) {
    90  	if !param.IsOmitted(query.WorkspaceID) {
    91  		opts = append(opts, option.WithHeader("anthropic-workspace-id", fmt.Sprintf("%v", query.WorkspaceID.Value)))
    92  	}
    93  	opts = slices.Concat(r.Options, opts)
    94  	opts = append([]option.RequestOption{option.WithHeader("Accept", "application/binary")}, opts...)
    95  	if fileID == "" {
    96  		err = errors.New("missing required file_id parameter")
    97  		return nil, err
    98  	}
    99  	path := fmt.Sprintf("v1/files/%s/content", fileID)
   100  	err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
   101  	return res, err
   102  }
   103  
   104  // Get File Metadata
   105  func (r *FileService) GetMetadata(ctx context.Context, fileID string, query FileGetMetadataParams, opts ...option.RequestOption) (res *FileMetadata, err error) {
   106  	if !param.IsOmitted(query.WorkspaceID) {
   107  		opts = append(opts, option.WithHeader("anthropic-workspace-id", fmt.Sprintf("%v", query.WorkspaceID.Value)))
   108  	}
   109  	opts = slices.Concat(r.Options, opts)
   110  	if fileID == "" {
   111  		err = errors.New("missing required file_id parameter")
   112  		return nil, err
   113  	}
   114  	path := fmt.Sprintf("v1/files/%s", fileID)
   115  	err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
   116  	return res, err
   117  }
   118  
   119  // Upload File
   120  func (r *FileService) Upload(ctx context.Context, params FileUploadParams, opts ...option.RequestOption) (res *FileMetadata, err error) {
   121  	if !param.IsOmitted(params.WorkspaceID) {
   122  		opts = append(opts, option.WithHeader("anthropic-workspace-id", fmt.Sprintf("%v", params.WorkspaceID.Value)))
   123  	}
   124  	opts = slices.Concat(r.Options, opts)
   125  	path := "v1/files"
   126  	err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &res, opts...)
   127  	return res, err
   128  }
   129  
   130  type DeletedFile struct {
   131  	// ID of the deleted file.
   132  	ID string `json:"id" api:"required"`
   133  	// Deleted object type.
   134  	//
   135  	// For file deletion, this is always `"file_deleted"`.
   136  	//
   137  	// Any of "file_deleted".
   138  	Type DeletedFileType `json:"type"`
   139  	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
   140  	JSON struct {
   141  		ID          respjson.Field
   142  		Type        respjson.Field
   143  		ExtraFields map[string]respjson.Field
   144  		raw         string
   145  	} `json:"-"`
   146  }
   147  
   148  // Returns the unmodified JSON received from the API
   149  func (r DeletedFile) RawJSON() string { return r.JSON.raw }
   150  func (r *DeletedFile) UnmarshalJSON(data []byte) error {
   151  	return apijson.UnmarshalRoot(data, r)
   152  }
   153  
   154  // Deleted object type.
   155  //
   156  // For file deletion, this is always `"file_deleted"`.
   157  type DeletedFileType string
   158  
   159  const (
   160  	DeletedFileTypeFileDeleted DeletedFileType = "file_deleted"
   161  )
   162  
   163  type FileMetadata struct {
   164  	// Unique object identifier.
   165  	//
   166  	// The format and length of IDs may change over time.
   167  	ID string `json:"id" api:"required"`
   168  	// RFC 3339 datetime string representing when the file was created.
   169  	CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"`
   170  	// Original filename of the uploaded file.
   171  	Filename string `json:"filename" api:"required"`
   172  	// MIME type of the file.
   173  	MimeType string `json:"mime_type" api:"required"`
   174  	// Size of the file in bytes.
   175  	SizeBytes int64 `json:"size_bytes" api:"required"`
   176  	// Object type.
   177  	//
   178  	// For files, this is always `"file"`.
   179  	Type constant.File `json:"type" default:"file"`
   180  	// Whether the file can be downloaded.
   181  	Downloadable bool `json:"downloadable"`
   182  	// RFC 3339 datetime string representing when the file will expire and become
   183  	// unavailable for download. Null if the file does not expire. For files uploaded
   184  	// with `expires_in_seconds`, this is the upload time plus that value.
   185  	ExpiresAt time.Time `json:"expires_at" api:"nullable" format:"date-time"`
   186  	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
   187  	JSON struct {
   188  		ID           respjson.Field
   189  		CreatedAt    respjson.Field
   190  		Filename     respjson.Field
   191  		MimeType     respjson.Field
   192  		SizeBytes    respjson.Field
   193  		Type         respjson.Field
   194  		Downloadable respjson.Field
   195  		ExpiresAt    respjson.Field
   196  		ExtraFields  map[string]respjson.Field
   197  		raw          string
   198  	} `json:"-"`
   199  }
   200  
   201  // Returns the unmodified JSON received from the API
   202  func (r FileMetadata) RawJSON() string { return r.JSON.raw }
   203  func (r *FileMetadata) UnmarshalJSON(data []byte) error {
   204  	return apijson.UnmarshalRoot(data, r)
   205  }
   206  
   207  type FileListParams struct {
   208  	// Opaque page cursor returned in a prior list response's `next_page`. Prefixed
   209  	// `page_`.
   210  	Page param.Opt[string] `query:"page,omitzero" json:"-"`
   211  	// Number of items to return per page.
   212  	//
   213  	// Defaults to `20`. Ranges from `1` to `1000`.
   214  	Limit       param.Opt[int64]  `query:"limit,omitzero" json:"-"`
   215  	WorkspaceID param.Opt[string] `header:"anthropic-workspace-id,omitzero" json:"-"`
   216  	// Restrict the result set to Files whose `id` is in this list. At most 100 entries
   217  	// (after de-duplication). Mutually exclusive with `page` and `limit`. When
   218  	// supplied, the response is always a single page (`next_page` is null). IDs that
   219  	// do not resolve to a visible File — including deleted Files — are silently
   220  	// omitted.
   221  	IDs []string `query:"ids,omitzero" json:"-"`
   222  	paramObj
   223  }
   224  
   225  // URLQuery serializes [FileListParams]'s query parameters as `url.Values`.
   226  func (r FileListParams) URLQuery() (v url.Values, err error) {
   227  	return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
   228  		ArrayFormat:  apiquery.ArrayQueryFormatBrackets,
   229  		NestedFormat: apiquery.NestedQueryFormatBrackets,
   230  	})
   231  }
   232  
   233  type FileDeleteParams struct {
   234  	WorkspaceID param.Opt[string] `header:"anthropic-workspace-id,omitzero" json:"-"`
   235  	paramObj
   236  }
   237  
   238  type FileDownloadParams struct {
   239  	WorkspaceID param.Opt[string] `header:"anthropic-workspace-id,omitzero" json:"-"`
   240  	paramObj
   241  }
   242  
   243  type FileGetMetadataParams struct {
   244  	WorkspaceID param.Opt[string] `header:"anthropic-workspace-id,omitzero" json:"-"`
   245  	paramObj
   246  }
   247  
   248  type FileUploadParams struct {
   249  	// The file to upload. Only the final path component of the part's `filename` is
   250  	// kept; an absent or empty `filename` is replaced with `unnamed` plus the
   251  	// extension for the file's stored `mime_type`, when known.
   252  	File io.Reader `json:"file,omitzero" api:"required" format:"binary"`
   253  	// Seconds from upload until the file expires and its bytes become permanently
   254  	// unavailable. Must be between 3600 (one hour) and 7776000 (ninety days).
   255  	ExpiresInSeconds param.Opt[int64]  `json:"expires_in_seconds,omitzero"`
   256  	WorkspaceID      param.Opt[string] `header:"anthropic-workspace-id,omitzero" json:"-"`
   257  	paramObj
   258  }
   259  
   260  func (r FileUploadParams) MarshalMultipart() (data []byte, contentType string, err error) {
   261  	buf := bytes.NewBuffer(nil)
   262  	writer := multipart.NewWriter(buf)
   263  	err = apiform.MarshalRoot(r, writer)
   264  	if err == nil {
   265  		err = apiform.WriteExtras(writer, r.ExtraFields())
   266  	}
   267  	if err != nil {
   268  		writer.Close()
   269  		return nil, "", err
   270  	}
   271  	err = writer.Close()
   272  	if err != nil {
   273  		return nil, "", err
   274  	}
   275  	return buf.Bytes(), writer.FormDataContentType(), nil
   276  }