From cc4009603b80d388915922c74f1d3aed8de8db25 Mon Sep 17 00:00:00 2001 From: Ashwin Bharambe Date: Wed, 22 Oct 2025 11:07:06 -0700 Subject: [PATCH] update conversations API stubs --- docs/static/llama-stack-spec.html | 86 ++++------ docs/static/llama-stack-spec.yaml | 154 +++--------------- docs/static/stainless-llama-stack-spec.html | 86 ++++------ docs/static/stainless-llama-stack-spec.yaml | 154 +++--------------- .../apis/conversations/conversations.py | 29 +++- .../core/conversations/conversations.py | 19 ++- 6 files changed, 141 insertions(+), 387 deletions(-) diff --git a/docs/static/llama-stack-spec.html b/docs/static/llama-stack-spec.html index 55decda0b..cd64117fd 100644 --- a/docs/static/llama-stack-spec.html +++ b/docs/static/llama-stack-spec.html @@ -483,86 +483,42 @@ "name": "after", "in": "query", "description": "An item ID to list items after, used in pagination.", - "required": true, + "required": false, "schema": { - "oneOf": [ - { - "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```" - } - ] + "type": "string" } }, { "name": "include", "in": "query", "description": "Specify additional output data to include in the response.", - "required": true, + "required": false, "schema": { - "oneOf": [ - { - "type": "array", - "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```" - } - ] + "type": "array", + "items": { + "$ref": "#/components/schemas/ConversationItemInclude" + } } }, { "name": "limit", "in": "query", "description": "A limit on the number of objects to be returned (1-100, default 20).", - "required": true, + "required": false, "schema": { - "oneOf": [ - { - "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```" - } - ] + "type": "integer" } }, { "name": "order", "in": "query", "description": "The order to return items in (asc or desc, default desc).", - "required": true, + "required": false, "schema": { - "oneOf": [ - { - "type": "string", - "enum": [ - "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```" - } + "type": "string", + "enum": [ + "asc", + "desc" ] } } @@ -6355,6 +6311,20 @@ "title": "ConversationDeletedResource", "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": { "type": "object", "properties": { diff --git a/docs/static/llama-stack-spec.yaml b/docs/static/llama-stack-spec.yaml index 751e4892f..670138c4c 100644 --- a/docs/static/llama-stack-spec.yaml +++ b/docs/static/llama-stack-spec.yaml @@ -347,150 +347,35 @@ paths: in: query description: >- An item ID to list items after, used in pagination. - required: true + required: false schema: - oneOf: - - 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 - - ``` + type: string - name: include in: query description: >- Specify additional output data to include in the response. - required: true + required: false schema: - oneOf: - - type: array - 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. - - 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 - - ``` + type: array + items: + $ref: '#/components/schemas/ConversationItemInclude' - name: limit in: query description: >- A limit on the number of objects to be returned (1-100, default 20). - required: true + required: false schema: - oneOf: - - 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 - - ``` + type: integer - name: order in: query description: >- The order to return items in (asc or desc, default desc). - required: true + required: false schema: - oneOf: - - type: string - enum: - - 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. - - 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 - - ``` + type: string + enum: + - asc + - desc deprecated: false post: responses: @@ -4853,6 +4738,19 @@ components: - deleted title: ConversationDeletedResource 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: type: object properties: diff --git a/docs/static/stainless-llama-stack-spec.html b/docs/static/stainless-llama-stack-spec.html index 5db44e356..31433f76d 100644 --- a/docs/static/stainless-llama-stack-spec.html +++ b/docs/static/stainless-llama-stack-spec.html @@ -483,86 +483,42 @@ "name": "after", "in": "query", "description": "An item ID to list items after, used in pagination.", - "required": true, + "required": false, "schema": { - "oneOf": [ - { - "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```" - } - ] + "type": "string" } }, { "name": "include", "in": "query", "description": "Specify additional output data to include in the response.", - "required": true, + "required": false, "schema": { - "oneOf": [ - { - "type": "array", - "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```" - } - ] + "type": "array", + "items": { + "$ref": "#/components/schemas/ConversationItemInclude" + } } }, { "name": "limit", "in": "query", "description": "A limit on the number of objects to be returned (1-100, default 20).", - "required": true, + "required": false, "schema": { - "oneOf": [ - { - "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```" - } - ] + "type": "integer" } }, { "name": "order", "in": "query", "description": "The order to return items in (asc or desc, default desc).", - "required": true, + "required": false, "schema": { - "oneOf": [ - { - "type": "string", - "enum": [ - "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```" - } + "type": "string", + "enum": [ + "asc", + "desc" ] } } @@ -8027,6 +7983,20 @@ "title": "ConversationDeletedResource", "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": { "type": "object", "properties": { diff --git a/docs/static/stainless-llama-stack-spec.yaml b/docs/static/stainless-llama-stack-spec.yaml index 4c90d5670..2b0436946 100644 --- a/docs/static/stainless-llama-stack-spec.yaml +++ b/docs/static/stainless-llama-stack-spec.yaml @@ -350,150 +350,35 @@ paths: in: query description: >- An item ID to list items after, used in pagination. - required: true + required: false schema: - oneOf: - - 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 - - ``` + type: string - name: include in: query description: >- Specify additional output data to include in the response. - required: true + required: false schema: - oneOf: - - type: array - 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. - - 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 - - ``` + type: array + items: + $ref: '#/components/schemas/ConversationItemInclude' - name: limit in: query description: >- A limit on the number of objects to be returned (1-100, default 20). - required: true + required: false schema: - oneOf: - - 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 - - ``` + type: integer - name: order in: query description: >- The order to return items in (asc or desc, default desc). - required: true + required: false schema: - oneOf: - - type: string - enum: - - 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. - - 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 - - ``` + type: string + enum: + - asc + - desc deprecated: false post: responses: @@ -6066,6 +5951,19 @@ components: - deleted title: ConversationDeletedResource 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: type: object properties: diff --git a/llama_stack/apis/conversations/conversations.py b/llama_stack/apis/conversations/conversations.py index d7752995d..2adbd157a 100644 --- a/llama_stack/apis/conversations/conversations.py +++ b/llama_stack/apis/conversations/conversations.py @@ -4,11 +4,9 @@ # This source code is licensed under the terms described in the LICENSE file in # the root directory of this source tree. +from enum import StrEnum 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 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 class ConversationItemList(BaseModel): """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) - async def list( + async def list_items( self, conversation_id: str, - after: str | NotGiven = NOT_GIVEN, - include: list[ResponseIncludable] | NotGiven = NOT_GIVEN, - limit: int | NotGiven = NOT_GIVEN, - order: Literal["asc", "desc"] | NotGiven = NOT_GIVEN, + after: str | None = None, + include: list[ConversationItemInclude] | None = None, + limit: int | None = None, + order: Literal["asc", "desc"] | None = None, ) -> ConversationItemList: """List items. diff --git a/llama_stack/core/conversations/conversations.py b/llama_stack/core/conversations/conversations.py index d2537c7ee..09a2a40ab 100644 --- a/llama_stack/core/conversations/conversations.py +++ b/llama_stack/core/conversations/conversations.py @@ -7,9 +7,8 @@ import os import secrets import time -from typing import Any +from typing import Any, Literal -from openai import NOT_GIVEN from pydantic import BaseModel, TypeAdapter from llama_stack.apis.conversations.conversations import ( @@ -17,6 +16,7 @@ from llama_stack.apis.conversations.conversations import ( ConversationDeletedResource, ConversationItem, ConversationItemDeletedResource, + ConversationItemInclude, ConversationItemList, Conversations, Metadata, @@ -253,7 +253,14 @@ class ConversationServiceImpl(Conversations): adapter: TypeAdapter[ConversationItem] = TypeAdapter(ConversationItem) 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.""" if not conversation_id: 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}) 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"]) else: records.sort(key=lambda x: x["created_at"], reverse=True) - actual_limit = 20 - if limit != NOT_GIVEN and isinstance(limit, int): - actual_limit = limit + actual_limit = limit or 20 records = records[:actual_limit] items = [record["item_data"] for record in records]