Skip to content

prompts.save() is typed to return PromptMetadata, but the actual response is item-shaped (like FileItem) #120

Description

@kryachkow

Name and Version

latest

Summary

Prompts.save() / AsyncPrompts.save() declare a return type of PromptMetadata, but a PUT of a resource returns an item metadata object, not a folder-listing object. This is the same class of bug that was fixed for files.upload() in #118 — the fix there is not yet applied to prompts (and, for consistency, to conversation items).

Current state

PromptMetadata is the folder-listing shape (it carries items and next_token, which are always empty/None on a save() response):

class PromptItem(BaseMetadata):
    updated_at: int
    resource_type: Literal["PROMPT"]


class PromptMetadata(BaseMetadata):
    content_length: int | None = None
    next_token: str | None = None
    items: list[PromptItem] | None
    resource_type: Literal["PROMPT"]

prompts.save() casts the response to PromptMetadata, so:

  • items / next_token are dead fields on every save() result.
  • The fields the server actually returns for an item — etag, createdAt, updatedAt, author — are untyped (they only survive because the models allow extra fields).

ConversationItem has the same limited shape (updated_at only), missing etag / created_at / author that the server returns for listed items.

What is the expected behavior?

In ai-dial-core (com.epam.aidial.core.storage.data) the model hierarchy is:

MetadataBase (abstract)
├── ResourceFolderMetadata   (FOLDER; adds items, nextToken)      ← GET /metadata listing
└── ResourceItemMetadata     (ITEM; adds createdAt, updatedAt, etag, author)
     └── FileMetadata         (adds contentLength, contentType)   ← PUT file upload response

ResourceController.putResource returns ResourceItemMetadata for all resource types (files, prompts, conversations). There is no prompt/conversation-specific subclass — prompts and conversations use the generic ResourceItemMetadata (item) and ResourceFolderMetadata (folder).

So a PUT prompt returns an item with nodeType=ITEM, createdAt/updatedAt/etag/author, and no items/nextToken.

What do you see instead?

Mirror the approach already used for files (where FileItem extends the shared ResourceItemMetadata base introduced in #118):

  1. Make PromptItem and ConversationItem extend ResourceItemMetadata, so they gain properly typed created_at, updated_at, etag, author:

    class PromptItem(ResourceItemMetadata):
        resource_type: Literal["PROMPT"]
    
    class ConversationItem(ResourceItemMetadata):
        resource_type: Literal["CONVERSATION"]
  2. Change Prompts.save() / AsyncPrompts.save() to return PromptItem (cast_to=PromptItem) instead of PromptMetadata.

  3. Keep get_metadata() returning the folder-listing types (PromptMetadata / ConversationMetadata).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions