fleet-memory/hindsight-clients/go/api_files.go
Nicolò Boschi 224b7b74c1
feat: accept pdf, images and office files (#390)
* feat: accept pdf, images and office files

* refactor: rename FileConverter to FileParser, simplify file retain API

- Rename engine/converters/ → engine/parsers/, FileConverter → FileParser,
  ConverterRegistry → FileParserRegistry, MarkitdownConverter → MarkitdownParser
- Rename env var HINDSIGHT_API_FILE_CONVERTER → HINDSIGHT_API_FILE_PARSER
- Remove async/document_tags params from FileRetainRequest (always async now)
- Add retain_files() to Python Hindsight client and retainFiles() to TypeScript client
- Add sample.pdf to doc examples for working file upload demonstrations
- Update test_file_retain.py to use new parser names and always-async behavior
- Fix Go client missing os import in api_files.go
- Simplify postgresql.py storage to minimal schema

* fix: update rust CLI tests to use is_supported_file instead of is_text_file

* fix: patch Go api_files.go to add missing 'os' import after generation

* fix: insert 'os' import after 'net/url' in api_files.go patch for correct position

* chore: regenerate OpenAPI spec and clients (converter→parser description update)
2026-02-17 18:15:03 +01:00

209 lines
6.5 KiB
Go

/*
Hindsight HTTP API
HTTP API for Hindsight
API version: 0.4.11
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package hindsight
import (
"bytes"
"context"
"io"
"net/http"
"net/url"
"os"
"strings"
)
// FilesAPIService FilesAPI service
type FilesAPIService service
type ApiFileRetainRequest struct {
ctx context.Context
ApiService *FilesAPIService
bankId string
files []*os.File
request *string
authorization *string
}
// Files to upload and convert
func (r ApiFileRetainRequest) Files(files []*os.File) ApiFileRetainRequest {
r.files = files
return r
}
// JSON string with FileRetainRequest model
func (r ApiFileRetainRequest) Request(request string) ApiFileRetainRequest {
r.request = &request
return r
}
func (r ApiFileRetainRequest) Authorization(authorization string) ApiFileRetainRequest {
r.authorization = &authorization
return r
}
func (r ApiFileRetainRequest) Execute() (*FileRetainResponse, *http.Response, error) {
return r.ApiService.FileRetainExecute(r)
}
/*
FileRetain Convert files to memories
Upload files (PDF, DOCX, etc.), convert them to markdown, and retain as memories.
This endpoint handles file upload, conversion, and memory creation in a single operation.
**Features:**
- Supports PDF, DOCX, PPTX, XLSX, images (with OCR), audio (with transcription)
- Automatic file-to-markdown conversion using pluggable parsers
- Files stored in object storage (PostgreSQL by default, S3 for production)
- Each file becomes a separate document with optional metadata/tags
- Always processes asynchronously — returns operation IDs immediately
**The system automatically:**
1. Stores uploaded files in object storage
2. Converts files to markdown
3. Creates document records with file metadata
4. Extracts facts and creates memory units (same as regular retain)
Use the operations endpoint to monitor progress.
**Request format:** multipart/form-data with:
- `files`: One or more files to upload
- `request`: JSON string with FileRetainRequest model (files_metadata)
**Note:** File parser is configured server-side via `HINDSIGHT_API_FILE_PARSER` (default: markitdown).
@param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
@param bankId
@return ApiFileRetainRequest
*/
func (a *FilesAPIService) FileRetain(ctx context.Context, bankId string) ApiFileRetainRequest {
return ApiFileRetainRequest{
ApiService: a,
ctx: ctx,
bankId: bankId,
}
}
// Execute executes the request
// @return FileRetainResponse
func (a *FilesAPIService) FileRetainExecute(r ApiFileRetainRequest) (*FileRetainResponse, *http.Response, error) {
var (
localVarHTTPMethod = http.MethodPost
localVarPostBody interface{}
formFiles []formFile
localVarReturnValue *FileRetainResponse
)
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "FilesAPIService.FileRetain")
if err != nil {
return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()}
}
localVarPath := localBasePath + "/v1/default/banks/{bank_id}/files/retain"
localVarPath = strings.Replace(localVarPath, "{"+"bank_id"+"}", url.PathEscape(parameterValueToString(r.bankId, "bankId")), -1)
localVarHeaderParams := make(map[string]string)
localVarQueryParams := url.Values{}
localVarFormParams := url.Values{}
if r.files == nil {
return localVarReturnValue, nil, reportError("files is required and must be specified")
}
if r.request == nil {
return localVarReturnValue, nil, reportError("request is required and must be specified")
}
// to determine the Content-Type header
localVarHTTPContentTypes := []string{"multipart/form-data"}
// set Content-Type header
localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes)
if localVarHTTPContentType != "" {
localVarHeaderParams["Content-Type"] = localVarHTTPContentType
}
// to determine the Accept header
localVarHTTPHeaderAccepts := []string{"application/json"}
// set Accept header
localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts)
if localVarHTTPHeaderAccept != "" {
localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept
}
if r.authorization != nil {
parameterAddToHeaderOrQuery(localVarHeaderParams, "authorization", r.authorization, "simple", "")
}
var filesLocalVarFormFileName string
var filesLocalVarFileName string
var filesLocalVarFileBytes []byte
filesLocalVarFormFileName = "files"
filesLocalVarFile := r.files
if filesLocalVarFile != nil {
// loop through the array to prepare multiple files upload
for _, filesLocalVarFileValue := range filesLocalVarFile {
fbs, _ := io.ReadAll(filesLocalVarFileValue)
filesLocalVarFileBytes = fbs
filesLocalVarFileName = filesLocalVarFileValue.Name()
filesLocalVarFileValue.Close()
formFiles = append(formFiles, formFile{fileBytes: filesLocalVarFileBytes, fileName: filesLocalVarFileName, formFileName: filesLocalVarFormFileName})
}
}
parameterAddToHeaderOrQuery(localVarFormParams, "request", r.request, "", "")
req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles)
if err != nil {
return localVarReturnValue, nil, err
}
localVarHTTPResponse, err := a.client.callAPI(req)
if err != nil || localVarHTTPResponse == nil {
return localVarReturnValue, localVarHTTPResponse, err
}
localVarBody, err := io.ReadAll(localVarHTTPResponse.Body)
localVarHTTPResponse.Body.Close()
localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody))
if err != nil {
return localVarReturnValue, localVarHTTPResponse, err
}
if localVarHTTPResponse.StatusCode >= 300 {
newErr := &GenericOpenAPIError{
body: localVarBody,
error: localVarHTTPResponse.Status,
}
if localVarHTTPResponse.StatusCode == 422 {
var v HTTPValidationError
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
if err != nil {
newErr.error = err.Error()
return localVarReturnValue, localVarHTTPResponse, newErr
}
newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v)
newErr.model = v
}
return localVarReturnValue, localVarHTTPResponse, newErr
}
err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
if err != nil {
newErr := &GenericOpenAPIError{
body: localVarBody,
error: err.Error(),
}
return localVarReturnValue, localVarHTTPResponse, newErr
}
return localVarReturnValue, localVarHTTPResponse, nil
}