update conversations API stubs

This commit is contained in:
Ashwin Bharambe 2025-10-22 11:07:06 -07:00
parent 5da1b4f81e
commit cc4009603b
6 changed files with 141 additions and 387 deletions

View file

@ -483,86 +483,42 @@
"name": "after", "name": "after",
"in": "query", "in": "query",
"description": "An item ID to list items after, used in pagination.", "description": "An item ID to list items after, used in pagination.",
"required": true, "required": false,
"schema": { "schema": {
"oneOf": [ "type": "string"
{
"type": "string"
},
{
"type": "object",
"title": "NotGiven",
"description": "For parameters with a meaningful None value, we need to distinguish between the user explicitly passing None, and the user not passing the parameter at all.\nUser code shouldn't need to use not_given directly.\n\nFor example:\n\n```py\ndef create(timeout: Timeout | None | NotGiven = not_given): ...\n\n\ncreate(timeout=1) # 1s timeout\ncreate(timeout=None) # No timeout\ncreate() # Default timeout behavior\n```"
}
]
} }
}, },
{ {
"name": "include", "name": "include",
"in": "query", "in": "query",
"description": "Specify additional output data to include in the response.", "description": "Specify additional output data to include in the response.",
"required": true, "required": false,
"schema": { "schema": {
"oneOf": [ "type": "array",
{ "items": {
"type": "array", "$ref": "#/components/schemas/ConversationItemInclude"
"items": { }
"type": "string",
"enum": [
"code_interpreter_call.outputs",
"computer_call_output.output.image_url",
"file_search_call.results",
"message.input_image.image_url",
"message.output_text.logprobs",
"reasoning.encrypted_content"
]
}
},
{
"type": "object",
"title": "NotGiven",
"description": "For parameters with a meaningful None value, we need to distinguish between the user explicitly passing None, and the user not passing the parameter at all.\nUser code shouldn't need to use not_given directly.\n\nFor example:\n\n```py\ndef create(timeout: Timeout | None | NotGiven = not_given): ...\n\n\ncreate(timeout=1) # 1s timeout\ncreate(timeout=None) # No timeout\ncreate() # Default timeout behavior\n```"
}
]
} }
}, },
{ {
"name": "limit", "name": "limit",
"in": "query", "in": "query",
"description": "A limit on the number of objects to be returned (1-100, default 20).", "description": "A limit on the number of objects to be returned (1-100, default 20).",
"required": true, "required": false,
"schema": { "schema": {
"oneOf": [ "type": "integer"
{
"type": "integer"
},
{
"type": "object",
"title": "NotGiven",
"description": "For parameters with a meaningful None value, we need to distinguish between the user explicitly passing None, and the user not passing the parameter at all.\nUser code shouldn't need to use not_given directly.\n\nFor example:\n\n```py\ndef create(timeout: Timeout | None | NotGiven = not_given): ...\n\n\ncreate(timeout=1) # 1s timeout\ncreate(timeout=None) # No timeout\ncreate() # Default timeout behavior\n```"
}
]
} }
}, },
{ {
"name": "order", "name": "order",
"in": "query", "in": "query",
"description": "The order to return items in (asc or desc, default desc).", "description": "The order to return items in (asc or desc, default desc).",
"required": true, "required": false,
"schema": { "schema": {
"oneOf": [ "type": "string",
{ "enum": [
"type": "string", "asc",
"enum": [ "desc"
"asc",
"desc"
]
},
{
"type": "object",
"title": "NotGiven",
"description": "For parameters with a meaningful None value, we need to distinguish between the user explicitly passing None, and the user not passing the parameter at all.\nUser code shouldn't need to use not_given directly.\n\nFor example:\n\n```py\ndef create(timeout: Timeout | None | NotGiven = not_given): ...\n\n\ncreate(timeout=1) # 1s timeout\ncreate(timeout=None) # No timeout\ncreate() # Default timeout behavior\n```"
}
] ]
} }
} }
@ -6355,6 +6311,20 @@
"title": "ConversationDeletedResource", "title": "ConversationDeletedResource",
"description": "Response for deleted conversation." "description": "Response for deleted conversation."
}, },
"ConversationItemInclude": {
"type": "string",
"enum": [
"web_search_call.action.sources",
"code_interpreter_call.outputs",
"computer_call_output.output.image_url",
"file_search_call.results",
"message.input_image.image_url",
"message.output_text.logprobs",
"reasoning.encrypted_content"
],
"title": "ConversationItemInclude",
"description": "Specify additional output data to include in the model response."
},
"ConversationItemList": { "ConversationItemList": {
"type": "object", "type": "object",
"properties": { "properties": {

View file

@ -347,150 +347,35 @@ paths:
in: query in: query
description: >- description: >-
An item ID to list items after, used in pagination. An item ID to list items after, used in pagination.
required: true required: false
schema: schema:
oneOf: type: string
- type: string
- type: object
title: NotGiven
description: >-
For parameters with a meaningful None value, we need to distinguish
between the user explicitly passing None, and the user not passing
the parameter at all.
User code shouldn't need to use not_given directly.
For example:
```py
def create(timeout: Timeout | None | NotGiven = not_given): ...
create(timeout=1) # 1s timeout
create(timeout=None) # No timeout
create() # Default timeout behavior
```
- name: include - name: include
in: query in: query
description: >- description: >-
Specify additional output data to include in the response. Specify additional output data to include in the response.
required: true required: false
schema: schema:
oneOf: type: array
- type: array items:
items: $ref: '#/components/schemas/ConversationItemInclude'
type: string
enum:
- code_interpreter_call.outputs
- computer_call_output.output.image_url
- file_search_call.results
- message.input_image.image_url
- message.output_text.logprobs
- reasoning.encrypted_content
- type: object
title: NotGiven
description: >-
For parameters with a meaningful None value, we need to distinguish
between the user explicitly passing None, and the user not passing
the parameter at all.
User code shouldn't need to use not_given directly.
For example:
```py
def create(timeout: Timeout | None | NotGiven = not_given): ...
create(timeout=1) # 1s timeout
create(timeout=None) # No timeout
create() # Default timeout behavior
```
- name: limit - name: limit
in: query in: query
description: >- description: >-
A limit on the number of objects to be returned (1-100, default 20). A limit on the number of objects to be returned (1-100, default 20).
required: true required: false
schema: schema:
oneOf: type: integer
- type: integer
- type: object
title: NotGiven
description: >-
For parameters with a meaningful None value, we need to distinguish
between the user explicitly passing None, and the user not passing
the parameter at all.
User code shouldn't need to use not_given directly.
For example:
```py
def create(timeout: Timeout | None | NotGiven = not_given): ...
create(timeout=1) # 1s timeout
create(timeout=None) # No timeout
create() # Default timeout behavior
```
- name: order - name: order
in: query in: query
description: >- description: >-
The order to return items in (asc or desc, default desc). The order to return items in (asc or desc, default desc).
required: true required: false
schema: schema:
oneOf: type: string
- type: string enum:
enum: - asc
- asc - desc
- desc
- type: object
title: NotGiven
description: >-
For parameters with a meaningful None value, we need to distinguish
between the user explicitly passing None, and the user not passing
the parameter at all.
User code shouldn't need to use not_given directly.
For example:
```py
def create(timeout: Timeout | None | NotGiven = not_given): ...
create(timeout=1) # 1s timeout
create(timeout=None) # No timeout
create() # Default timeout behavior
```
deprecated: false deprecated: false
post: post:
responses: responses:
@ -4853,6 +4738,19 @@ components:
- deleted - deleted
title: ConversationDeletedResource title: ConversationDeletedResource
description: Response for deleted conversation. description: Response for deleted conversation.
ConversationItemInclude:
type: string
enum:
- web_search_call.action.sources
- code_interpreter_call.outputs
- computer_call_output.output.image_url
- file_search_call.results
- message.input_image.image_url
- message.output_text.logprobs
- reasoning.encrypted_content
title: ConversationItemInclude
description: >-
Specify additional output data to include in the model response.
ConversationItemList: ConversationItemList:
type: object type: object
properties: properties:

View file

@ -483,86 +483,42 @@
"name": "after", "name": "after",
"in": "query", "in": "query",
"description": "An item ID to list items after, used in pagination.", "description": "An item ID to list items after, used in pagination.",
"required": true, "required": false,
"schema": { "schema": {
"oneOf": [ "type": "string"
{
"type": "string"
},
{
"type": "object",
"title": "NotGiven",
"description": "For parameters with a meaningful None value, we need to distinguish between the user explicitly passing None, and the user not passing the parameter at all.\nUser code shouldn't need to use not_given directly.\n\nFor example:\n\n```py\ndef create(timeout: Timeout | None | NotGiven = not_given): ...\n\n\ncreate(timeout=1) # 1s timeout\ncreate(timeout=None) # No timeout\ncreate() # Default timeout behavior\n```"
}
]
} }
}, },
{ {
"name": "include", "name": "include",
"in": "query", "in": "query",
"description": "Specify additional output data to include in the response.", "description": "Specify additional output data to include in the response.",
"required": true, "required": false,
"schema": { "schema": {
"oneOf": [ "type": "array",
{ "items": {
"type": "array", "$ref": "#/components/schemas/ConversationItemInclude"
"items": { }
"type": "string",
"enum": [
"code_interpreter_call.outputs",
"computer_call_output.output.image_url",
"file_search_call.results",
"message.input_image.image_url",
"message.output_text.logprobs",
"reasoning.encrypted_content"
]
}
},
{
"type": "object",
"title": "NotGiven",
"description": "For parameters with a meaningful None value, we need to distinguish between the user explicitly passing None, and the user not passing the parameter at all.\nUser code shouldn't need to use not_given directly.\n\nFor example:\n\n```py\ndef create(timeout: Timeout | None | NotGiven = not_given): ...\n\n\ncreate(timeout=1) # 1s timeout\ncreate(timeout=None) # No timeout\ncreate() # Default timeout behavior\n```"
}
]
} }
}, },
{ {
"name": "limit", "name": "limit",
"in": "query", "in": "query",
"description": "A limit on the number of objects to be returned (1-100, default 20).", "description": "A limit on the number of objects to be returned (1-100, default 20).",
"required": true, "required": false,
"schema": { "schema": {
"oneOf": [ "type": "integer"
{
"type": "integer"
},
{
"type": "object",
"title": "NotGiven",
"description": "For parameters with a meaningful None value, we need to distinguish between the user explicitly passing None, and the user not passing the parameter at all.\nUser code shouldn't need to use not_given directly.\n\nFor example:\n\n```py\ndef create(timeout: Timeout | None | NotGiven = not_given): ...\n\n\ncreate(timeout=1) # 1s timeout\ncreate(timeout=None) # No timeout\ncreate() # Default timeout behavior\n```"
}
]
} }
}, },
{ {
"name": "order", "name": "order",
"in": "query", "in": "query",
"description": "The order to return items in (asc or desc, default desc).", "description": "The order to return items in (asc or desc, default desc).",
"required": true, "required": false,
"schema": { "schema": {
"oneOf": [ "type": "string",
{ "enum": [
"type": "string", "asc",
"enum": [ "desc"
"asc",
"desc"
]
},
{
"type": "object",
"title": "NotGiven",
"description": "For parameters with a meaningful None value, we need to distinguish between the user explicitly passing None, and the user not passing the parameter at all.\nUser code shouldn't need to use not_given directly.\n\nFor example:\n\n```py\ndef create(timeout: Timeout | None | NotGiven = not_given): ...\n\n\ncreate(timeout=1) # 1s timeout\ncreate(timeout=None) # No timeout\ncreate() # Default timeout behavior\n```"
}
] ]
} }
} }
@ -8027,6 +7983,20 @@
"title": "ConversationDeletedResource", "title": "ConversationDeletedResource",
"description": "Response for deleted conversation." "description": "Response for deleted conversation."
}, },
"ConversationItemInclude": {
"type": "string",
"enum": [
"web_search_call.action.sources",
"code_interpreter_call.outputs",
"computer_call_output.output.image_url",
"file_search_call.results",
"message.input_image.image_url",
"message.output_text.logprobs",
"reasoning.encrypted_content"
],
"title": "ConversationItemInclude",
"description": "Specify additional output data to include in the model response."
},
"ConversationItemList": { "ConversationItemList": {
"type": "object", "type": "object",
"properties": { "properties": {

View file

@ -350,150 +350,35 @@ paths:
in: query in: query
description: >- description: >-
An item ID to list items after, used in pagination. An item ID to list items after, used in pagination.
required: true required: false
schema: schema:
oneOf: type: string
- type: string
- type: object
title: NotGiven
description: >-
For parameters with a meaningful None value, we need to distinguish
between the user explicitly passing None, and the user not passing
the parameter at all.
User code shouldn't need to use not_given directly.
For example:
```py
def create(timeout: Timeout | None | NotGiven = not_given): ...
create(timeout=1) # 1s timeout
create(timeout=None) # No timeout
create() # Default timeout behavior
```
- name: include - name: include
in: query in: query
description: >- description: >-
Specify additional output data to include in the response. Specify additional output data to include in the response.
required: true required: false
schema: schema:
oneOf: type: array
- type: array items:
items: $ref: '#/components/schemas/ConversationItemInclude'
type: string
enum:
- code_interpreter_call.outputs
- computer_call_output.output.image_url
- file_search_call.results
- message.input_image.image_url
- message.output_text.logprobs
- reasoning.encrypted_content
- type: object
title: NotGiven
description: >-
For parameters with a meaningful None value, we need to distinguish
between the user explicitly passing None, and the user not passing
the parameter at all.
User code shouldn't need to use not_given directly.
For example:
```py
def create(timeout: Timeout | None | NotGiven = not_given): ...
create(timeout=1) # 1s timeout
create(timeout=None) # No timeout
create() # Default timeout behavior
```
- name: limit - name: limit
in: query in: query
description: >- description: >-
A limit on the number of objects to be returned (1-100, default 20). A limit on the number of objects to be returned (1-100, default 20).
required: true required: false
schema: schema:
oneOf: type: integer
- type: integer
- type: object
title: NotGiven
description: >-
For parameters with a meaningful None value, we need to distinguish
between the user explicitly passing None, and the user not passing
the parameter at all.
User code shouldn't need to use not_given directly.
For example:
```py
def create(timeout: Timeout | None | NotGiven = not_given): ...
create(timeout=1) # 1s timeout
create(timeout=None) # No timeout
create() # Default timeout behavior
```
- name: order - name: order
in: query in: query
description: >- description: >-
The order to return items in (asc or desc, default desc). The order to return items in (asc or desc, default desc).
required: true required: false
schema: schema:
oneOf: type: string
- type: string enum:
enum: - asc
- asc - desc
- desc
- type: object
title: NotGiven
description: >-
For parameters with a meaningful None value, we need to distinguish
between the user explicitly passing None, and the user not passing
the parameter at all.
User code shouldn't need to use not_given directly.
For example:
```py
def create(timeout: Timeout | None | NotGiven = not_given): ...
create(timeout=1) # 1s timeout
create(timeout=None) # No timeout
create() # Default timeout behavior
```
deprecated: false deprecated: false
post: post:
responses: responses:
@ -6066,6 +5951,19 @@ components:
- deleted - deleted
title: ConversationDeletedResource title: ConversationDeletedResource
description: Response for deleted conversation. description: Response for deleted conversation.
ConversationItemInclude:
type: string
enum:
- web_search_call.action.sources
- code_interpreter_call.outputs
- computer_call_output.output.image_url
- file_search_call.results
- message.input_image.image_url
- message.output_text.logprobs
- reasoning.encrypted_content
title: ConversationItemInclude
description: >-
Specify additional output data to include in the model response.
ConversationItemList: ConversationItemList:
type: object type: object
properties: properties:

View file

@ -4,11 +4,9 @@
# This source code is licensed under the terms described in the LICENSE file in # This source code is licensed under the terms described in the LICENSE file in
# the root directory of this source tree. # the root directory of this source tree.
from enum import StrEnum
from typing import Annotated, Literal, Protocol, runtime_checkable from typing import Annotated, Literal, Protocol, runtime_checkable
from openai import NOT_GIVEN
from openai._types import NotGiven
from openai.types.responses.response_includable import ResponseIncludable
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from llama_stack.apis.agents.openai_responses import ( from llama_stack.apis.agents.openai_responses import (
@ -150,6 +148,21 @@ class ConversationItemCreateRequest(BaseModel):
) )
@json_schema_type
class ConversationItemInclude(StrEnum):
"""
Specify additional output data to include in the model response.
"""
web_search_call_action_sources = "web_search_call.action.sources"
code_interpreter_call_outputs = "code_interpreter_call.outputs"
computer_call_output_output_image_url = "computer_call_output.output.image_url"
file_search_call_results = "file_search_call.results"
message_input_image_image_url = "message.input_image.image_url"
message_output_text_logprobs = "message.output_text.logprobs"
reasoning_encrypted_content = "reasoning.encrypted_content"
@json_schema_type @json_schema_type
class ConversationItemList(BaseModel): class ConversationItemList(BaseModel):
"""List of conversation items with pagination.""" """List of conversation items with pagination."""
@ -250,13 +263,13 @@ class Conversations(Protocol):
... ...
@webmethod(route="/conversations/{conversation_id}/items", method="GET", level=LLAMA_STACK_API_V1) @webmethod(route="/conversations/{conversation_id}/items", method="GET", level=LLAMA_STACK_API_V1)
async def list( async def list_items(
self, self,
conversation_id: str, conversation_id: str,
after: str | NotGiven = NOT_GIVEN, after: str | None = None,
include: list[ResponseIncludable] | NotGiven = NOT_GIVEN, include: list[ConversationItemInclude] | None = None,
limit: int | NotGiven = NOT_GIVEN, limit: int | None = None,
order: Literal["asc", "desc"] | NotGiven = NOT_GIVEN, order: Literal["asc", "desc"] | None = None,
) -> ConversationItemList: ) -> ConversationItemList:
"""List items. """List items.

View file

@ -7,9 +7,8 @@
import os import os
import secrets import secrets
import time import time
from typing import Any from typing import Any, Literal
from openai import NOT_GIVEN
from pydantic import BaseModel, TypeAdapter from pydantic import BaseModel, TypeAdapter
from llama_stack.apis.conversations.conversations import ( from llama_stack.apis.conversations.conversations import (
@ -17,6 +16,7 @@ from llama_stack.apis.conversations.conversations import (
ConversationDeletedResource, ConversationDeletedResource,
ConversationItem, ConversationItem,
ConversationItemDeletedResource, ConversationItemDeletedResource,
ConversationItemInclude,
ConversationItemList, ConversationItemList,
Conversations, Conversations,
Metadata, Metadata,
@ -253,7 +253,14 @@ class ConversationServiceImpl(Conversations):
adapter: TypeAdapter[ConversationItem] = TypeAdapter(ConversationItem) adapter: TypeAdapter[ConversationItem] = TypeAdapter(ConversationItem)
return adapter.validate_python(record["item_data"]) return adapter.validate_python(record["item_data"])
async def list(self, conversation_id: str, after=NOT_GIVEN, include=NOT_GIVEN, limit=NOT_GIVEN, order=NOT_GIVEN): async def list_items(
self,
conversation_id: str,
after: str | None = None,
include: list[ConversationItemInclude] | None = None,
limit: int | None = None,
order: Literal["asc", "desc"] | None = None,
) -> ConversationItemList:
"""List items in the conversation.""" """List items in the conversation."""
if not conversation_id: if not conversation_id:
raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}") raise ValueError(f"Expected a non-empty value for `conversation_id` but received {conversation_id!r}")
@ -264,14 +271,12 @@ class ConversationServiceImpl(Conversations):
result = await self.sql_store.fetch_all(table="conversation_items", where={"conversation_id": conversation_id}) result = await self.sql_store.fetch_all(table="conversation_items", where={"conversation_id": conversation_id})
records = result.data records = result.data
if order != NOT_GIVEN and order == "asc": if order is not None and order == "asc":
records.sort(key=lambda x: x["created_at"]) records.sort(key=lambda x: x["created_at"])
else: else:
records.sort(key=lambda x: x["created_at"], reverse=True) records.sort(key=lambda x: x["created_at"], reverse=True)
actual_limit = 20 actual_limit = limit or 20
if limit != NOT_GIVEN and isinstance(limit, int):
actual_limit = limit
records = records[:actual_limit] records = records[:actual_limit]
items = [record["item_data"] for record in records] items = [record["item_data"] for record in records]