Skip to content

Release v2.1.0

Choose a tag to compare

@github-actions github-actions released this 11 Nov 16:04
66d95ef
feat: Add get_asset_presigned_urls method to Compass clients (#162)

Add support for fetching presigned URLs for document assets.

The method accepts a list of asset requests and returns presigned URLs
with 1-hour TTL.
Requires permission on target documents and uses all-or-nothing
semantics (fails entirely if any asset pair is invalid).

## Motivation

It should be used to regenerate presigned URLs when necessary (for
example, when a user saved the chat history and gets back to it a few
days later - at this moment, the presigned URL should be regenerated).

The most reliable way to get asset bytes is to get the asset ID,
generate a presigned URL, and fetch the bytes (or just use the presigned
URL to show the preview in the browser directly).

Relevant discussions:
-
https://cohereai.slack.com/archives/C09P1T7HGM9/p1762436952417809?thread_ts=1762379184.158919&cid=C09P1T7HGM9
- https://cohereai.slack.com/archives/C06RB1CEAUQ/p1734348754478789

## HTTP Request Schema
HTTP Endpoint Request:
```
POST /{index_name}/assets/_presigned_urls
{
  "assets": [
    {"document_id": "doc_123", "asset_id": "asset_A_UUID"},
    {"document_id": "doc_456", "asset_id": "asset_B_UUID"}
  ]
}
```

HTTP Endpoint Response:
```
{
  "asset_urls": [
    {
      "document_id": "doc_123",
      "asset_id": "asset_A",
      "presigned_url": "https://.../asset_A?X-Amz-Signature=..."
    },
    {
      "document_id": "doc_456",
      "asset_id": "asset_B",
      "presigned_url": "https://.../asset_B?X-Amz-Signature=..."
    }
  ]
}
```


## Usage Example
```
def _download_asset_bytes(
    *,
    asset_id: UUID,
    client: CompassClient,
    index_name: str,
    parent_document_id: str,
) -> bytes:
    assets = [
        AssetPresignedUrlRequest(
            document_id=parent_document_id,
            asset_id=asset_id,
        )
    ]
    presigned_urls = client.get_asset_presigned_urls(index_name=index_name, assets=assets)

    if len(presigned_urls) == 0:
        raise Exception("no presigned urls have been received")
    
    if len(presigned_urls) > 1:
        raise Exception("too many presigned urls have been received: only one is expected")
    
    presigned_url = presigned_urls[0].presigned_url
    
    with httpx.Client(follow_redirects=True, timeout=60.0) as s:
        r: httpx.Response = s.get(presigned_url)
        r.raise_for_status()

        return r.content
```