From 056bcf651a3b4b375fddf5f635243f96d50e4b27 Mon Sep 17 00:00:00 2001
From: Stephanie
Date: Tue, 28 Jul 2026 21:19:18 -0400
Subject: [PATCH 001/197] add /v1/skills endpoint
Signed-off-by: Stephanie
---
src/app/endpoints/skills.py | 66 ++++++++++
src/app/main.py | 1 +
src/app/routers.py | 2 +
.../api/responses/successful/__init__.py | 2 +
.../api/responses/successful/catalog.py | 27 ++++
src/models/config.py | 1 +
src/utils/pydantic_ai_helpers.py | 20 +++
tests/unit/app/endpoints/test_skills.py | 117 ++++++++++++++++++
tests/unit/utils/test_pydantic_ai.py | 20 +++
9 files changed, 256 insertions(+)
create mode 100644 src/app/endpoints/skills.py
create mode 100644 tests/unit/app/endpoints/test_skills.py
diff --git a/src/app/endpoints/skills.py b/src/app/endpoints/skills.py
new file mode 100644
index 000000000..62b053fb6
--- /dev/null
+++ b/src/app/endpoints/skills.py
@@ -0,0 +1,66 @@
+"""Handler for REST API call to list loaded agent skills."""
+
+from typing import Annotated, Any
+
+from fastapi import APIRouter, Request
+from fastapi.params import Depends
+
+from authentication import get_auth_dependency
+from authentication.interface import AuthTuple
+from authorization.middleware import authorize
+from configuration import configuration
+from log import get_logger
+from models.api.responses.constants import UNAUTHORIZED_OPENAPI_EXAMPLES
+from models.api.responses.error import (
+ ForbiddenResponse,
+ InternalServerErrorResponse,
+ UnauthorizedResponse,
+)
+from models.api.responses.successful import SkillsResponse
+from models.config import Action
+from utils.endpoints import check_configuration_loaded
+from utils.pydantic_ai_helpers import get_skills_metadata
+
+logger = get_logger(__name__)
+router = APIRouter(tags=["skills"])
+
+
+skills_responses: dict[int | str, dict[str, Any]] = {
+ 200: SkillsResponse.openapi_response(),
+ 401: UnauthorizedResponse.openapi_response(examples=UNAUTHORIZED_OPENAPI_EXAMPLES),
+ 403: ForbiddenResponse.openapi_response(examples=["endpoint"]),
+ 500: InternalServerErrorResponse.openapi_response(examples=["configuration"]),
+}
+
+
+@router.get("/skills", responses=skills_responses)
+@authorize(Action.GET_SKILLS)
+async def skills_endpoint_handler(
+ request: Request,
+ auth: Annotated[AuthTuple, Depends(get_auth_dependency())],
+) -> SkillsResponse:
+ """Handle requests to the /skills endpoint.
+
+ Process GET requests to the /skills endpoint, returning a list of loaded
+ agent skills with their metadata (name, description).
+
+ ### Parameters:
+ - request: The incoming HTTP request (used by middleware).
+ - auth: Authentication tuple from the auth dependency (used by middleware).
+
+ ### Raises:
+ - HTTPException: with status 401 for unauthorized access.
+ - HTTPException: with status 403 if permission is denied.
+ - HTTPException: with status 500 and a detail object containing `response`
+ and `cause` when service configuration is wrong or incomplete.
+
+ ### Returns:
+ - SkillsResponse: An object containing the list of loaded skills.
+ """
+ _ = auth
+ _ = request
+
+ check_configuration_loaded(configuration)
+
+ skills_metadata = get_skills_metadata(configuration.configuration.skills)
+ return SkillsResponse(skills=skills_metadata)
diff --git a/src/app/main.py b/src/app/main.py
index 0cf61752c..21e9f8e7a 100644
--- a/src/app/main.py
+++ b/src/app/main.py
@@ -63,6 +63,7 @@
"description": "Saved prompts configuration and management.",
},
{"name": "shields", "description": "Safety shields."},
+ {"name": "skills", "description": "Agent skills."},
{"name": "streaming_query", "description": "Streaming query (SSE)."},
{"name": "streaming_query_interrupt", "description": "Streaming interrupt."},
{"name": "tools", "description": "Tools."},
diff --git a/src/app/routers.py b/src/app/routers.py
index c10aa5173..f13de514f 100644
--- a/src/app/routers.py
+++ b/src/app/routers.py
@@ -27,6 +27,7 @@
root,
saved_prompts,
shields,
+ skills,
stream_interrupt,
streaming_query,
tools,
@@ -55,6 +56,7 @@ def include_routers(app: FastAPI) -> None:
app.include_router(mcp_auth.router, prefix="/v1")
app.include_router(mcp_servers.router, prefix="/v1")
app.include_router(shields.router, prefix="/v1")
+ app.include_router(skills.router, prefix="/v1")
app.include_router(providers.router, prefix="/v1")
app.include_router(prompts.router, prefix="/v1")
app.include_router(rags.router, prefix="/v1")
diff --git a/src/models/api/responses/successful/__init__.py b/src/models/api/responses/successful/__init__.py
index b99c72a0a..534eedca5 100644
--- a/src/models/api/responses/successful/__init__.py
+++ b/src/models/api/responses/successful/__init__.py
@@ -7,6 +7,7 @@
RAGInfoResponse,
RAGListResponse,
ShieldsResponse,
+ SkillsResponse,
ToolsResponse,
)
from models.api.responses.successful.configuration import ConfigurationResponse
@@ -100,6 +101,7 @@
"SavedPromptsConfigResponse",
"SavedPromptsListResponse",
"ShieldsResponse",
+ "SkillsResponse",
"StatusResponse",
"StreamingInterruptResponse",
"StreamingQueryResponse",
diff --git a/src/models/api/responses/successful/catalog.py b/src/models/api/responses/successful/catalog.py
index 3d357a724..c48cc40b1 100644
--- a/src/models/api/responses/successful/catalog.py
+++ b/src/models/api/responses/successful/catalog.py
@@ -7,6 +7,33 @@
from models.api.responses.successful.bases import AbstractSuccessfulResponse
+class SkillsResponse(AbstractSuccessfulResponse):
+ """Model representing a response to skills request."""
+
+ skills: list[dict[str, Any]] = Field(
+ description="List of loaded skills with metadata",
+ )
+
+ model_config = {
+ "json_schema_extra": {
+ "examples": [
+ {
+ "skills": [
+ {
+ "name": "code-review",
+ "description": "Review code for quality and security",
+ },
+ {
+ "name": "openshift-troubleshooting",
+ "description": "Troubleshoot OpenShift cluster issues",
+ },
+ ],
+ }
+ ]
+ }
+ }
+
+
class ModelsResponse(AbstractSuccessfulResponse):
"""Model representing a response to models request."""
diff --git a/src/models/config.py b/src/models/config.py
index 462b038f5..566ced67b 100644
--- a/src/models/config.py
+++ b/src/models/config.py
@@ -1273,6 +1273,7 @@ class Action(str, Enum):
FEEDBACK = "feedback"
GET_MODELS = "get_models"
GET_TOOLS = "get_tools"
+ GET_SKILLS = "get_skills"
GET_SHIELDS = "get_shields"
LIST_PROVIDERS = "list_providers"
GET_PROVIDER = "get_provider"
diff --git a/src/utils/pydantic_ai_helpers.py b/src/utils/pydantic_ai_helpers.py
index 38bf71e92..0bf8c6ef8 100644
--- a/src/utils/pydantic_ai_helpers.py
+++ b/src/utils/pydantic_ai_helpers.py
@@ -104,6 +104,26 @@ def _capability_tools_from_toolset(toolset: Any) -> list[dict[str, Any]]:
return tool_dicts
+def get_skills_metadata(
+ skills: Optional[SkillsConfiguration],
+) -> list[dict[str, Any]]:
+ """Return metadata for all loaded skills.
+
+ Parameters:
+ skills: Agent skills configuration from LCS, or None when skills are disabled.
+
+ Returns:
+ List of dicts with ``name`` and ``description`` for each loaded skill.
+ """
+ capability = _skills_capability(skills)
+ if capability is None:
+ return []
+ return [
+ {"name": skill.name, "description": skill.description}
+ for skill in capability.toolset.skills.values()
+ ]
+
+
def get_agent_capability_tools(
skills: Optional[SkillsConfiguration],
) -> list[dict[str, Any]]:
diff --git a/tests/unit/app/endpoints/test_skills.py b/tests/unit/app/endpoints/test_skills.py
new file mode 100644
index 000000000..41a01f363
--- /dev/null
+++ b/tests/unit/app/endpoints/test_skills.py
@@ -0,0 +1,117 @@
+"""Unit tests for skills endpoint."""
+
+from pathlib import Path
+
+import pytest
+from fastapi import Request
+from pytest_mock import MockerFixture
+
+from app.endpoints.skills import skills_endpoint_handler
+from authentication.interface import AuthTuple
+from models.api.responses.successful import SkillsResponse
+from models.config import SkillsConfiguration
+from tests.unit.utils.auth_helpers import mock_authorization_resolvers
+
+MOCK_AUTH: AuthTuple = ("mock_user_id", "mock_username", True, "mock_token")
+
+
+@pytest.mark.asyncio
+async def test_skills_loaded(
+ mocker: MockerFixture,
+ tmp_path: Path,
+) -> None:
+ """Test that loaded skills are returned with name and description."""
+ mock_authorization_resolvers(mocker)
+
+ skills_root = tmp_path / "skills"
+ for name, desc in [
+ ("code-review", "Review code for quality and security"),
+ ("openshift-troubleshooting", "Troubleshoot OpenShift cluster issues"),
+ ]:
+ skill_dir = skills_root / name
+ skill_dir.mkdir(parents=True)
+ (skill_dir / "SKILL.md").write_text(
+ f"---\nname: {name}\ndescription: {desc}\n---\n\nInstructions.\n",
+ encoding="utf-8",
+ )
+
+ skills_config = SkillsConfiguration(paths=[skills_root])
+ mock_config = mocker.patch("app.endpoints.skills.configuration")
+ mock_config.configuration.skills = skills_config
+
+ request = Request(scope={"type": "http"})
+ response = await skills_endpoint_handler(auth=MOCK_AUTH, request=request)
+
+ assert isinstance(response, SkillsResponse)
+ assert len(response.skills) == 2
+ names = {s["name"] for s in response.skills}
+ assert names == {"code-review", "openshift-troubleshooting"}
+ for skill in response.skills:
+ assert "name" in skill
+ assert "description" in skill
+
+
+@pytest.mark.asyncio
+async def test_no_skills_configured(
+ mocker: MockerFixture,
+) -> None:
+ """Test that an empty list is returned when no skills are configured."""
+ mock_authorization_resolvers(mocker)
+
+ mock_config = mocker.patch("app.endpoints.skills.configuration")
+ mock_config.configuration.skills = None
+
+ request = Request(scope={"type": "http"})
+ response = await skills_endpoint_handler(auth=MOCK_AUTH, request=request)
+
+ assert isinstance(response, SkillsResponse)
+ assert response.skills == []
+
+
+@pytest.mark.asyncio
+async def test_empty_skills_paths(
+ mocker: MockerFixture,
+) -> None:
+ """Test that an empty list is returned when skills paths are empty."""
+ mock_authorization_resolvers(mocker)
+
+ mock_config = mocker.patch("app.endpoints.skills.configuration")
+ mock_config.configuration.skills = SkillsConfiguration(paths=[])
+
+ request = Request(scope={"type": "http"})
+ response = await skills_endpoint_handler(auth=MOCK_AUTH, request=request)
+
+ assert isinstance(response, SkillsResponse)
+ assert response.skills == []
+
+
+@pytest.mark.asyncio
+async def test_skills_with_references(
+ mocker: MockerFixture,
+ tmp_path: Path,
+) -> None:
+ """Test that skills with references/ subdirectory are listed correctly."""
+ mock_authorization_resolvers(mocker)
+
+ skills_root = tmp_path / "skills"
+ skill_dir = skills_root / "rhdh-dynamic-plugins"
+ skill_dir.mkdir(parents=True)
+ (skill_dir / "SKILL.md").write_text(
+ "---\nname: rhdh-dynamic-plugins\ndescription: RHDH dynamic plugins guide\n---\n\nInstructions.\n",
+ encoding="utf-8",
+ )
+ refs_dir = skill_dir / "references"
+ refs_dir.mkdir()
+ (refs_dir / "plugin-list.md").write_text("# Plugins\n- plugin-a\n", encoding="utf-8")
+
+ skills_config = SkillsConfiguration(paths=[skills_root])
+ mock_config = mocker.patch("app.endpoints.skills.configuration")
+ mock_config.configuration.skills = skills_config
+
+ request = Request(scope={"type": "http"})
+ response = await skills_endpoint_handler(auth=MOCK_AUTH, request=request)
+
+ assert isinstance(response, SkillsResponse)
+ assert len(response.skills) == 1
+ assert response.skills[0]["name"] == "rhdh-dynamic-plugins"
+ assert response.skills[0]["description"] == "RHDH dynamic plugins guide"
diff --git a/tests/unit/utils/test_pydantic_ai.py b/tests/unit/utils/test_pydantic_ai.py
index 05809386f..a70c440d7 100644
--- a/tests/unit/utils/test_pydantic_ai.py
+++ b/tests/unit/utils/test_pydantic_ai.py
@@ -15,6 +15,7 @@
_skills_capability,
build_agent,
get_agent_capability_tools,
+ get_skills_metadata,
)
@@ -183,6 +184,25 @@ def test_agent_excludes_tool_capabilities_when_no_tools(
assert SkillsCapability not in capability_types
+class TestGetSkillsMetadata:
+ """Tests for get_skills_metadata."""
+
+ def test_returns_empty_list_when_skills_not_configured(self) -> None:
+ """Test that missing skills configuration yields no metadata."""
+ assert get_skills_metadata(None) == []
+ assert get_skills_metadata(SkillsConfiguration(paths=[])) == []
+
+ def test_returns_metadata_when_configured(
+ self, mock_skills_configuration: SkillsConfiguration
+ ) -> None:
+ """Test that configured skills return name and description."""
+ metadata = get_skills_metadata(mock_skills_configuration)
+
+ assert len(metadata) == 1
+ assert metadata[0]["name"] == "test-skill"
+ assert metadata[0]["description"] == "Test skill."
+
+
class TestGetAgentCapabilityTools:
"""Tests for get_agent_capability_tools."""
From d5cabc582bef68bb5819204bf62d316db37bbf5c Mon Sep 17 00:00:00 2001
From: Stephanie
Date: Thu, 30 Jul 2026 11:03:08 -0400
Subject: [PATCH 002/197] update openapi doc
Signed-off-by: Stephanie
---
docs/devel_doc/openapi.json | 188 ++++++++++++++++++++++++++++++++++++
1 file changed, 188 insertions(+)
diff --git a/docs/devel_doc/openapi.json b/docs/devel_doc/openapi.json
index 3e7cfe5cc..79db98597 100644
--- a/docs/devel_doc/openapi.json
+++ b/docs/devel_doc/openapi.json
@@ -1671,6 +1671,156 @@
}
}
},
+ "/v1/skills": {
+ "get": {
+ "tags": [
+ "skills"
+ ],
+ "summary": "Skills Endpoint Handler",
+ "description": "Handle requests to the /skills endpoint.\n\nProcess GET requests to the /skills endpoint, returning a list of loaded\nagent skills with their metadata (name, description).\n\n### Parameters:\n- request: The incoming HTTP request (used by middleware).\n- auth: Authentication tuple from the auth dependency (used by middleware).\n\n### Raises:\n- HTTPException: with status 401 for unauthorized access.\n- HTTPException: with status 403 if permission is denied.\n- HTTPException: with status 500 and a detail object containing `response`\n and `cause` when service configuration is wrong or incomplete.\n\n### Returns:\n- SkillsResponse: An object containing the list of loaded skills.",
+ "operationId": "skills_endpoint_handler_v1_skills_get",
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SkillsResponse"
+ },
+ "example": {
+ "skills": [
+ {
+ "description": "Review code for quality and security",
+ "name": "code-review"
+ },
+ {
+ "description": "Troubleshoot OpenShift cluster issues",
+ "name": "openshift-troubleshooting"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/UnauthorizedResponse"
+ },
+ "examples": {
+ "missing header": {
+ "value": {
+ "detail": {
+ "cause": "No Authorization header found",
+ "response": "Missing or invalid credentials provided by client"
+ }
+ }
+ },
+ "missing token": {
+ "value": {
+ "detail": {
+ "cause": "No token found in Authorization header",
+ "response": "Missing or invalid credentials provided by client"
+ }
+ }
+ },
+ "expired token": {
+ "value": {
+ "detail": {
+ "cause": "Token has expired",
+ "response": "Missing or invalid credentials provided by client"
+ }
+ }
+ },
+ "invalid signature": {
+ "value": {
+ "detail": {
+ "cause": "Invalid token signature",
+ "response": "Missing or invalid credentials provided by client"
+ }
+ }
+ },
+ "invalid key": {
+ "value": {
+ "detail": {
+ "cause": "Token signed by unknown key",
+ "response": "Missing or invalid credentials provided by client"
+ }
+ }
+ },
+ "missing claim": {
+ "value": {
+ "detail": {
+ "cause": "Token missing claim: user_id",
+ "response": "Missing or invalid credentials provided by client"
+ }
+ }
+ },
+ "invalid k8s token": {
+ "value": {
+ "detail": {
+ "cause": "Invalid or expired Kubernetes token",
+ "response": "Missing or invalid credentials provided by client"
+ }
+ }
+ },
+ "invalid jwk token": {
+ "value": {
+ "detail": {
+ "cause": "Authentication key server returned invalid data",
+ "response": "Missing or invalid credentials provided by client"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Permission denied",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ForbiddenResponse"
+ },
+ "examples": {
+ "endpoint": {
+ "value": {
+ "detail": {
+ "cause": "User 6789 is not authorized to access this endpoint.",
+ "response": "User does not have permission to access this endpoint"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/InternalServerErrorResponse"
+ },
+ "examples": {
+ "configuration": {
+ "value": {
+ "detail": {
+ "cause": "Lightspeed Stack configuration has not been initialized.",
+ "response": "Configuration is not loaded"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/v1/providers": {
"get": {
"tags": [
@@ -11646,6 +11796,7 @@
"feedback",
"get_models",
"get_tools",
+ "get_skills",
"get_shields",
"list_providers",
"get_provider",
@@ -20812,6 +20963,39 @@
"title": "SkillsConfiguration",
"description": "Agent skills configuration.\n\nSpecifies paths to skill directories. Skill metadata (name, description)\nis read from SKILL.md frontmatter at startup.\n\nEach path can point to either:\n- A directory containing a SKILL.md file (single skill)\n- A directory containing subdirectories with SKILL.md files (multiple skills)\n\nPaths are validated at startup to ensure they exist and contain valid SKILL.md files."
},
+ "SkillsResponse": {
+ "properties": {
+ "skills": {
+ "items": {
+ "additionalProperties": true,
+ "type": "object"
+ },
+ "type": "array",
+ "title": "Skills",
+ "description": "List of loaded skills with metadata"
+ }
+ },
+ "type": "object",
+ "required": [
+ "skills"
+ ],
+ "title": "SkillsResponse",
+ "description": "Model representing a response to skills request.",
+ "examples": [
+ {
+ "skills": [
+ {
+ "description": "Review code for quality and security",
+ "name": "code-review"
+ },
+ {
+ "description": "Troubleshoot OpenShift cluster issues",
+ "name": "openshift-troubleshooting"
+ }
+ ]
+ }
+ ]
+ },
"SolrVectorSearchRequest": {
"properties": {
"mode": {
@@ -22392,6 +22576,10 @@
"name": "shields",
"description": "Safety shields."
},
+ {
+ "name": "skills",
+ "description": "Agent skills."
+ },
{
"name": "streaming_query",
"description": "Streaming query (SSE)."
From 450a1d3dd61ecb163a205d031acd54b08e440a3d Mon Sep 17 00:00:00 2001
From: Stephanie
Date: Thu, 30 Jul 2026 11:05:58 -0400
Subject: [PATCH 003/197] fix formatting
Signed-off-by: Stephanie
---
tests/unit/app/endpoints/test_skills.py | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/tests/unit/app/endpoints/test_skills.py b/tests/unit/app/endpoints/test_skills.py
index 41a01f363..c175fc62c 100644
--- a/tests/unit/app/endpoints/test_skills.py
+++ b/tests/unit/app/endpoints/test_skills.py
@@ -94,15 +94,17 @@ async def test_skills_with_references(
mock_authorization_resolvers(mocker)
skills_root = tmp_path / "skills"
- skill_dir = skills_root / "rhdh-dynamic-plugins"
+ skill_dir = skills_root / "dynamic-plugins"
skill_dir.mkdir(parents=True)
(skill_dir / "SKILL.md").write_text(
- "---\nname: rhdh-dynamic-plugins\ndescription: RHDH dynamic plugins guide\n---\n\nInstructions.\n",
+ "---\nname: dynamic-plugins\ndescription: Dynamic plugins guide\n---\n\nInstructions.\n",
encoding="utf-8",
)
refs_dir = skill_dir / "references"
refs_dir.mkdir()
- (refs_dir / "plugin-list.md").write_text("# Plugins\n- plugin-a\n", encoding="utf-8")
+ (refs_dir / "plugin-list.md").write_text(
+ "# Plugins\n- plugin-a\n", encoding="utf-8"
+ )
skills_config = SkillsConfiguration(paths=[skills_root])
mock_config = mocker.patch("app.endpoints.skills.configuration")
@@ -113,5 +115,5 @@ async def test_skills_with_references(
assert isinstance(response, SkillsResponse)
assert len(response.skills) == 1
- assert response.skills[0]["name"] == "rhdh-dynamic-plugins"
- assert response.skills[0]["description"] == "RHDH dynamic plugins guide"
+ assert response.skills[0]["name"] == "dynamic-plugins"
+ assert response.skills[0]["description"] == "Dynamic plugins guide"
From aae3d695ed0e40a72a2eb2d4198fd0dcc2fe1fa1 Mon Sep 17 00:00:00 2001
From: Stephanie
Date: Thu, 30 Jul 2026 11:43:11 -0400
Subject: [PATCH 004/197] fix coderabbit review comment
Signed-off-by: Stephanie
---
docs/devel_doc/openapi.json | 24 +++++++++++++++++--
src/app/endpoints/skills.py | 5 +++-
.../api/responses/successful/catalog.py | 3 ++-
src/models/common/skills.py | 17 +++++++++++++
src/utils/pydantic_ai_helpers.py | 7 +++---
tests/unit/app/endpoints/test_skills.py | 10 ++++----
tests/unit/app/test_routers.py | 7 ++++--
tests/unit/utils/test_pydantic_ai.py | 4 ++--
8 files changed, 61 insertions(+), 16 deletions(-)
create mode 100644 src/models/common/skills.py
diff --git a/docs/devel_doc/openapi.json b/docs/devel_doc/openapi.json
index 79db98597..ce08d3640 100644
--- a/docs/devel_doc/openapi.json
+++ b/docs/devel_doc/openapi.json
@@ -20946,6 +20946,27 @@
}
]
},
+ "SkillMetadata": {
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Name",
+ "description": "Unique name of the skill"
+ },
+ "description": {
+ "type": "string",
+ "title": "Description",
+ "description": "Human readable description of what the skill does"
+ }
+ },
+ "type": "object",
+ "required": [
+ "name",
+ "description"
+ ],
+ "title": "SkillMetadata",
+ "description": "Metadata describing a single loaded agent skill.\n\nAttributes:\n name: Unique name of the skill.\n description: Human readable description of what the skill does."
+ },
"SkillsConfiguration": {
"properties": {
"paths": {
@@ -20967,8 +20988,7 @@
"properties": {
"skills": {
"items": {
- "additionalProperties": true,
- "type": "object"
+ "$ref": "#/components/schemas/SkillMetadata"
},
"type": "array",
"title": "Skills",
diff --git a/src/app/endpoints/skills.py b/src/app/endpoints/skills.py
index 62b053fb6..8fd8abdb8 100644
--- a/src/app/endpoints/skills.py
+++ b/src/app/endpoints/skills.py
@@ -3,6 +3,7 @@
from typing import Annotated, Any
from fastapi import APIRouter, Request
+from fastapi.concurrency import run_in_threadpool
from fastapi.params import Depends
from authentication import get_auth_dependency
@@ -62,5 +63,7 @@ async def skills_endpoint_handler(
check_configuration_loaded(configuration)
- skills_metadata = get_skills_metadata(configuration.configuration.skills)
+ skills_metadata = await run_in_threadpool(
+ get_skills_metadata, configuration.configuration.skills
+ )
return SkillsResponse(skills=skills_metadata)
diff --git a/src/models/api/responses/successful/catalog.py b/src/models/api/responses/successful/catalog.py
index c48cc40b1..b7207d5bf 100644
--- a/src/models/api/responses/successful/catalog.py
+++ b/src/models/api/responses/successful/catalog.py
@@ -5,12 +5,13 @@
from pydantic import Field
from models.api.responses.successful.bases import AbstractSuccessfulResponse
+from models.common.skills import SkillMetadata
class SkillsResponse(AbstractSuccessfulResponse):
"""Model representing a response to skills request."""
- skills: list[dict[str, Any]] = Field(
+ skills: list[SkillMetadata] = Field(
description="List of loaded skills with metadata",
)
diff --git a/src/models/common/skills.py b/src/models/common/skills.py
new file mode 100644
index 000000000..422c3e937
--- /dev/null
+++ b/src/models/common/skills.py
@@ -0,0 +1,17 @@
+"""Metadata models for agent skills shared across the skills endpoint and helpers."""
+
+from pydantic import BaseModel, Field
+
+
+class SkillMetadata(BaseModel):
+ """Metadata describing a single loaded agent skill.
+
+ Attributes:
+ name: Unique name of the skill.
+ description: Human readable description of what the skill does.
+ """
+
+ name: str = Field(..., description="Unique name of the skill")
+ description: str = Field(
+ ..., description="Human readable description of what the skill does"
+ )
diff --git a/src/utils/pydantic_ai_helpers.py b/src/utils/pydantic_ai_helpers.py
index 0bf8c6ef8..d3341057d 100644
--- a/src/utils/pydantic_ai_helpers.py
+++ b/src/utils/pydantic_ai_helpers.py
@@ -12,6 +12,7 @@
from pydantic_ai_skills import SkillsCapability
from models.common.responses.responses_api_params import ResponsesApiParams
+from models.common.skills import SkillMetadata
from models.config import SkillsConfiguration
from pydantic_ai_lightspeed.llamastack import (
LlamaStackResponsesModel,
@@ -106,20 +107,20 @@ def _capability_tools_from_toolset(toolset: Any) -> list[dict[str, Any]]:
def get_skills_metadata(
skills: Optional[SkillsConfiguration],
-) -> list[dict[str, Any]]:
+) -> list[SkillMetadata]:
"""Return metadata for all loaded skills.
Parameters:
skills: Agent skills configuration from LCS, or None when skills are disabled.
Returns:
- List of dicts with ``name`` and ``description`` for each loaded skill.
+ List of ``SkillMetadata`` with ``name`` and ``description`` for each loaded skill.
"""
capability = _skills_capability(skills)
if capability is None:
return []
return [
- {"name": skill.name, "description": skill.description}
+ SkillMetadata(name=skill.name, description=skill.description)
for skill in capability.toolset.skills.values()
]
diff --git a/tests/unit/app/endpoints/test_skills.py b/tests/unit/app/endpoints/test_skills.py
index c175fc62c..5a5b65c87 100644
--- a/tests/unit/app/endpoints/test_skills.py
+++ b/tests/unit/app/endpoints/test_skills.py
@@ -44,11 +44,11 @@ async def test_skills_loaded(
assert isinstance(response, SkillsResponse)
assert len(response.skills) == 2
- names = {s["name"] for s in response.skills}
+ names = {s.name for s in response.skills}
assert names == {"code-review", "openshift-troubleshooting"}
for skill in response.skills:
- assert "name" in skill
- assert "description" in skill
+ assert skill.name
+ assert skill.description
@pytest.mark.asyncio
@@ -115,5 +115,5 @@ async def test_skills_with_references(
assert isinstance(response, SkillsResponse)
assert len(response.skills) == 1
- assert response.skills[0]["name"] == "dynamic-plugins"
- assert response.skills[0]["description"] == "Dynamic plugins guide"
+ assert response.skills[0].name == "dynamic-plugins"
+ assert response.skills[0].description == "Dynamic plugins guide"
diff --git a/tests/unit/app/test_routers.py b/tests/unit/app/test_routers.py
index c35ab5723..7dde54b6c 100644
--- a/tests/unit/app/test_routers.py
+++ b/tests/unit/app/test_routers.py
@@ -30,6 +30,7 @@
root,
saved_prompts,
shields,
+ skills,
stream_interrupt,
streaming_query,
tools,
@@ -122,7 +123,7 @@ def test_include_routers() -> None:
include_routers(app)
# are all routers added?
- assert len(app.routers) == 25
+ assert len(app.routers) == 26
assert root.router in app.get_routers()
assert info.router in app.get_routers()
assert models.router in app.get_routers()
@@ -130,6 +131,7 @@ def test_include_routers() -> None:
assert mcp_auth.router in app.get_routers()
assert mcp_servers.router in app.get_routers()
assert shields.router in app.get_routers()
+ assert skills.router in app.get_routers()
assert providers.router in app.get_routers()
assert prompts.router in app.get_routers()
assert saved_prompts.router in app.get_routers()
@@ -164,7 +166,7 @@ def test_check_prefixes() -> None:
include_routers(app)
# are all routers added?
- assert len(app.routers) == 25
+ assert len(app.routers) == 26
assert app.get_router_prefix(root.router) == ""
assert app.get_router_prefix(info.router) == "/v1"
assert app.get_router_prefix(models.router) == "/v1"
@@ -172,6 +174,7 @@ def test_check_prefixes() -> None:
assert app.get_router_prefix(mcp_auth.router) == "/v1"
assert app.get_router_prefix(mcp_servers.router) == "/v1"
assert app.get_router_prefix(shields.router) == "/v1"
+ assert app.get_router_prefix(skills.router) == "/v1"
assert app.get_router_prefix(providers.router) == "/v1"
assert app.get_router_prefix(prompts.router) == "/v1"
assert app.get_router_prefix(saved_prompts.router) == "/v1"
diff --git a/tests/unit/utils/test_pydantic_ai.py b/tests/unit/utils/test_pydantic_ai.py
index a70c440d7..ae837bd99 100644
--- a/tests/unit/utils/test_pydantic_ai.py
+++ b/tests/unit/utils/test_pydantic_ai.py
@@ -199,8 +199,8 @@ def test_returns_metadata_when_configured(
metadata = get_skills_metadata(mock_skills_configuration)
assert len(metadata) == 1
- assert metadata[0]["name"] == "test-skill"
- assert metadata[0]["description"] == "Test skill."
+ assert metadata[0].name == "test-skill"
+ assert metadata[0].description == "Test skill."
class TestGetAgentCapabilityTools:
From 3f5a80d2e1e78cb83dd4404ddeffcd05852240e9 Mon Sep 17 00:00:00 2001
From: Stephanie
Date: Fri, 31 Jul 2026 12:07:36 -0400
Subject: [PATCH 005/197] address review comments
Signed-off-by: Stephanie
---
README.md | 46 ++++++++++
docs/devel_doc/ARCHITECTURE.md | 4 +
docs/models/responses_succ.md | 27 ++++++
docs/user_doc/skills_guide.md | 32 +++++++
src/models/common/__init__.py | 2 +
src/utils/models_dumper.py | 2 +
tests/e2e/features/skills.feature | 54 ++++++++++++
.../endpoints/test_skills_integration.py | 87 +++++++++++++++++++
8 files changed, 254 insertions(+)
create mode 100644 tests/integration/endpoints/test_skills_integration.py
diff --git a/README.md b/README.md
index 13ae757c6..1cccd295f 100644
--- a/README.md
+++ b/README.md
@@ -1248,6 +1248,52 @@ will be returned.
}
```
+## Skills endpoint
+
+**Endpoint:** `GET /v1/skills`
+
+Process GET requests and return the list of agent skills loaded from the
+directories configured under `skills.paths` in the service configuration
+(see [Agent Skills](#agent-skills) and the [Agent Skills Guide](docs/user_doc/skills_guide.md)
+for configuration and authoring instructions). Each skill's name and
+description are read from its `SKILL.md` frontmatter.
+
+This endpoint reads the configured skill directories directly and does not
+invoke an LLM or agent — it is intended for clients (e.g. the RHDH UI or
+other tooling) that need a deterministic way to introspect configured
+skills without the cost, latency, or non-determinism of an LLM tool call.
+This is distinct from the `list_skills` tool that the agent itself may
+invoke during a `/v1/query` or `/v1/streaming_query` turn.
+
+```bash
+curl http://localhost:8080/v1/skills
+```
+
+**Response Body:**
+```json
+{
+ "skills": [
+ {
+ "name": "code-review",
+ "description": "Review code for quality and security"
+ },
+ {
+ "name": "openshift-troubleshooting",
+ "description": "Troubleshoot OpenShift cluster issues"
+ }
+ ]
+}
+```
+
+If no skills are configured (or `skills.paths` is empty), the endpoint
+returns an empty list:
+
+```json
+{
+ "skills": []
+}
+```
+
# Database structure
diff --git a/docs/devel_doc/ARCHITECTURE.md b/docs/devel_doc/ARCHITECTURE.md
index b3bf18635..f77a6a63a 100644
--- a/docs/devel_doc/ARCHITECTURE.md
+++ b/docs/devel_doc/ARCHITECTURE.md
@@ -503,6 +503,10 @@ This section documents the REST API endpoints exposed by LCore for client intera
**List Shields:** `GET /shields`
- Returns available guardrails
+**List Skills:** `GET /skills`
+- Returns loaded agent skills (name and description) from the configured
+ skill directories, without requiring an LLM/agent turn
+
**List RAG Databases:** `GET /rags`
- Returns configured vector stores
diff --git a/docs/models/responses_succ.md b/docs/models/responses_succ.md
index 8a4918102..9dcf5255c 100644
--- a/docs/models/responses_succ.md
+++ b/docs/models/responses_succ.md
@@ -2134,6 +2134,22 @@ Model representing a response to shields request.
| shields | array | List of shields available |
+## SkillMetadata
+
+
+Metadata describing a single loaded agent skill.
+
+Attributes:
+ name: Unique name of the skill.
+ description: Human readable description of what the skill does.
+
+
+| Field | Type | Description |
+|-------|------|-------------|
+| name | string | Unique name of the skill |
+| description | string | Human readable description of what the skill does |
+
+
## SkillsConfiguration
@@ -2154,6 +2170,17 @@ Paths are validated at startup to ensure they exist and contain valid SKILL.md f
| paths | array | Paths to skill directories or directories containing skill subdirectories. |
+## SkillsResponse
+
+
+Model representing a response to skills request.
+
+
+| Field | Type | Description |
+|-------|------|-------------|
+| skills | array | List of loaded skills with metadata |
+
+
## SplunkConfiguration
diff --git a/docs/user_doc/skills_guide.md b/docs/user_doc/skills_guide.md
index 33462062c..46c14a72d 100644
--- a/docs/user_doc/skills_guide.md
+++ b/docs/user_doc/skills_guide.md
@@ -16,6 +16,7 @@ This guide covers how to configure Agent Skills in Lightspeed Core Stack and how
- [Frontmatter Fields](#frontmatter-fields)
- [Body Content](#body-content)
- [Creating a Skill](#creating-a-skill)
+- [Inspecting Loaded Skills via REST API](#inspecting-loaded-skills-via-rest-api)
- [How Skills Work at Runtime](#how-skills-work-at-runtime)
- [Limitations](#limitations)
- [References](#references)
@@ -207,6 +208,37 @@ Skills are loaded at startup. Restart Lightspeed Core Stack to pick up new or mo
See [examples/skills/](../examples/skills/) for complete working examples.
+# Inspecting Loaded Skills via REST API
+
+`GET /v1/skills` returns the name and description of every skill loaded
+from the configured `skills.paths`, without going through an LLM/agent
+turn:
+
+```bash
+curl http://localhost:8080/v1/skills
+```
+
+```json
+{
+ "skills": [
+ {
+ "name": "code-review",
+ "description": "Review code for quality and security"
+ },
+ {
+ "name": "openshift-troubleshooting",
+ "description": "Troubleshoot OpenShift cluster issues"
+ }
+ ]
+}
+```
+
+This is useful for clients (e.g. UI integrations or deployment tooling)
+that need to display or verify which skills are configured, and don't
+want to rely on the LLM invoking the `list_skills` tool described below.
+If no skills are configured, `skills` is an empty list. See the
+[README](../../README.md#skills-endpoint) for the full endpoint reference.
+
# How Skills Work at Runtime
Skills use a progressive disclosure pattern with three LLM tools:
diff --git a/src/models/common/__init__.py b/src/models/common/__init__.py
index f3f599087..2789a907a 100644
--- a/src/models/common/__init__.py
+++ b/src/models/common/__init__.py
@@ -18,6 +18,7 @@
ShieldModerationResult,
)
from models.common.query import Attachment, SolrVectorSearchRequest
+from models.common.skills import SkillMetadata
from models.common.transcripts import Transcript, TranscriptMetadata
from models.common.turn_summary import (
MCPListToolsSummary,
@@ -48,6 +49,7 @@
"ShieldModerationBlocked",
"ShieldModerationPassed",
"ShieldModerationResult",
+ "SkillMetadata",
"SolrVectorSearchRequest",
"ToolCallSummary",
"ToolInfoSummary",
diff --git a/src/utils/models_dumper.py b/src/utils/models_dumper.py
index 6a240b7e6..b66457e90 100644
--- a/src/utils/models_dumper.py
+++ b/src/utils/models_dumper.py
@@ -73,6 +73,7 @@
s.SavedPromptResponse,
s.SavedPromptsListResponse,
s.ShieldsResponse,
+ s.SkillsResponse,
s.StatusResponse,
s.StreamingInterruptResponse,
s.StreamingQueryResponse,
@@ -116,6 +117,7 @@
c.ReferencedDocument,
c.ShieldModerationBlocked,
c.ShieldModerationPassed,
+ c.SkillMetadata,
c.SolrVectorSearchRequest,
c.ToolCallSummary,
c.ToolInfoSummary,
diff --git a/tests/e2e/features/skills.feature b/tests/e2e/features/skills.feature
index a8d86e800..d4fd68dc3 100644
--- a/tests/e2e/features/skills.feature
+++ b/tests/e2e/features/skills.feature
@@ -178,6 +178,60 @@ Feature: Agent skills tests
}
"""
+ # --- GET /v1/skills endpoint ---
+
+ @SkillsConfig
+ Scenario: GET /v1/skills returns metadata for configured skills
+ Given The service uses the lightspeed-stack-skills.yaml configuration
+ And The service is restarted
+ When I access REST API endpoint "skills" using HTTP GET method
+ Then The status code of the response is 200
+ And The body of the response is the following
+ """
+ {
+ "skills": [
+ {
+ "name": "echo",
+ "description": "Echo back the user's input exactly as provided. Use when a user asks to echo, repeat, or mirror text."
+ }
+ ]
+ }
+ """
+
+ Scenario: GET /v1/skills returns an empty list when no skills are configured
+ Given The service uses the lightspeed-stack.yaml configuration
+ And The service is restarted
+ When I access REST API endpoint "skills" using HTTP GET method
+ Then The status code of the response is 200
+ And The body of the response is the following
+ """
+ {
+ "skills": []
+ }
+ """
+
+ @SkillsMultiConfig
+ Scenario: GET /v1/skills discovers all skills in a skills directory
+ Given The service uses the lightspeed-stack-skills-directory.yaml configuration
+ And The service is restarted
+ When I access REST API endpoint "skills" using HTTP GET method
+ Then The status code of the response is 200
+ And The body of the response is the following
+ """
+ {
+ "skills": [
+ {
+ "name": "echo",
+ "description": "Echo back the user's input exactly as provided. Use when a user asks to echo, repeat, or mirror text."
+ },
+ {
+ "name": "summarize",
+ "description": "Summarize text into a concise single-sentence overview. Use when a user asks to summarize, condense, or shorten text."
+ }
+ ]
+ }
+ """
+
# --- Skill discovery ---
@SkillsConfig
diff --git a/tests/integration/endpoints/test_skills_integration.py b/tests/integration/endpoints/test_skills_integration.py
new file mode 100644
index 000000000..603d9c136
--- /dev/null
+++ b/tests/integration/endpoints/test_skills_integration.py
@@ -0,0 +1,87 @@
+"""Integration tests for the /v1/skills endpoint.
+
+Unlike the unit tests in tests/unit/app/endpoints/test_skills.py (which mock
+out the whole `configuration` module), these tests load a real configuration
+object via the `test_config` fixture and only attach a `SkillsConfiguration`
+pointing at skill directories written to a temporary path. This exercises the
+real configuration-loaded checks and the real skill-discovery code path
+(`utils.pydantic_ai_helpers.get_skills_metadata`) end-to-end.
+"""
+
+from pathlib import Path
+
+import pytest
+from fastapi import Request
+
+from app.endpoints.skills import skills_endpoint_handler
+from authentication.interface import AuthTuple
+from configuration import AppConfig
+from models.api.responses.successful import SkillsResponse
+from models.config import SkillsConfiguration
+
+
+def _write_skill(skills_root: Path, name: str, description: str) -> None:
+ """Write a minimal SKILL.md file for the given skill name under skills_root."""
+ skill_dir = skills_root / name
+ skill_dir.mkdir(parents=True)
+ (skill_dir / "SKILL.md").write_text(
+ f"---\nname: {name}\ndescription: {description}\n---\n\nInstructions.\n",
+ encoding="utf-8",
+ )
+
+
+@pytest.mark.asyncio
+async def test_skills_endpoint_returns_configured_skills(
+ test_config: AppConfig,
+ test_request: Request,
+ test_auth: AuthTuple,
+ tmp_path: Path,
+) -> None:
+ """Test that /v1/skills returns metadata for all configured skills.
+
+ Parameters:
+ ----------
+ test_config: Real loaded configuration (from tests/configuration/lightspeed-stack.yaml).
+ test_request: FastAPI request.
+ test_auth: noop authentication tuple.
+ tmp_path: pytest tmp path fixture used to host real SKILL.md files on disk.
+ """
+ skills_root = tmp_path / "skills"
+ _write_skill(skills_root, "code-review", "Review code for quality and security")
+ _write_skill(
+ skills_root, "openshift-troubleshooting", "Troubleshoot OpenShift issues"
+ )
+
+ test_config.configuration.skills = SkillsConfiguration(paths=[skills_root])
+
+ response = await skills_endpoint_handler(request=test_request, auth=test_auth)
+
+ assert isinstance(response, SkillsResponse)
+ assert len(response.skills) == 2
+ names = {skill.name for skill in response.skills}
+ assert names == {"code-review", "openshift-troubleshooting"}
+ for skill in response.skills:
+ assert skill.name
+ assert skill.description
+
+
+@pytest.mark.asyncio
+async def test_skills_endpoint_returns_empty_list_when_unconfigured(
+ test_config: AppConfig,
+ test_request: Request,
+ test_auth: AuthTuple,
+) -> None:
+ """Test that /v1/skills returns an empty list when no skills are configured.
+
+ Parameters:
+ ----------
+ test_config: Real loaded configuration (from tests/configuration/lightspeed-stack.yaml).
+ test_request: FastAPI request.
+ test_auth: noop authentication tuple.
+ """
+ test_config.configuration.skills = None
+
+ response = await skills_endpoint_handler(request=test_request, auth=test_auth)
+
+ assert isinstance(response, SkillsResponse)
+ assert response.skills == []
From 95bccef5d6e4a2128456e2148565d1b893db25af Mon Sep 17 00:00:00 2001
From: Stephanie
Date: Fri, 31 Jul 2026 12:25:45 -0400
Subject: [PATCH 006/197] fix coderabbit review
Signed-off-by: Stephanie
---
docs/user_doc/skills_guide.md | 4 +++-
src/models/api/responses/successful/catalog.py | 6 +++++-
.../integration/endpoints/test_skills_integration.py | 11 ++++++++++-
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/docs/user_doc/skills_guide.md b/docs/user_doc/skills_guide.md
index 46c14a72d..7e1776879 100644
--- a/docs/user_doc/skills_guide.md
+++ b/docs/user_doc/skills_guide.md
@@ -212,7 +212,9 @@ See [examples/skills/](../examples/skills/) for complete working examples.
`GET /v1/skills` returns the name and description of every skill loaded
from the configured `skills.paths`, without going through an LLM/agent
-turn:
+turn. If authentication is enabled, include the appropriate credentials
+(e.g. `-H "Authorization: Bearer "`); otherwise the request
+returns `401`/`403`:
```bash
curl http://localhost:8080/v1/skills
diff --git a/src/models/api/responses/successful/catalog.py b/src/models/api/responses/successful/catalog.py
index b7207d5bf..f928646c0 100644
--- a/src/models/api/responses/successful/catalog.py
+++ b/src/models/api/responses/successful/catalog.py
@@ -9,7 +9,11 @@
class SkillsResponse(AbstractSuccessfulResponse):
- """Model representing a response to skills request."""
+ """Model representing a response to skills request.
+
+ Attributes:
+ skills: List of loaded skills with metadata (name and description).
+ """
skills: list[SkillMetadata] = Field(
description="List of loaded skills with metadata",
diff --git a/tests/integration/endpoints/test_skills_integration.py b/tests/integration/endpoints/test_skills_integration.py
index 603d9c136..1a96c5ff8 100644
--- a/tests/integration/endpoints/test_skills_integration.py
+++ b/tests/integration/endpoints/test_skills_integration.py
@@ -21,7 +21,16 @@
def _write_skill(skills_root: Path, name: str, description: str) -> None:
- """Write a minimal SKILL.md file for the given skill name under skills_root."""
+ """Write a minimal SKILL.md file for one skill.
+
+ Parameters:
+ skills_root: Root directory that contains the skill directory.
+ name: Skill name, used as both the directory name and frontmatter value.
+ description: Skill description written into the frontmatter.
+
+ Returns:
+ None.
+ """
skill_dir = skills_root / name
skill_dir.mkdir(parents=True)
(skill_dir / "SKILL.md").write_text(
From 19e5bd70739128c07db0a06c60f862121c95b451 Mon Sep 17 00:00:00 2001
From: Jordan Dubrick
Date: Fri, 31 Jul 2026 13:17:27 -0400
Subject: [PATCH 007/197] allow for string or int for ports in postgres
Signed-off-by: Jordan Dubrick
---
docs/devel_doc/openapi.json | 10 +++-
src/models/config.py | 10 ++--
tests/unit/models/config/test_byok_rag.py | 15 +++++
tests/unit/models/config/test_vector_store.py | 60 +++++++++++++++++++
tests/unit/utils/test_models_dumper.py | 15 ++++-
5 files changed, 101 insertions(+), 9 deletions(-)
diff --git a/docs/devel_doc/openapi.json b/docs/devel_doc/openapi.json
index f66ea5cbd..252dc5926 100644
--- a/docs/devel_doc/openapi.json
+++ b/docs/devel_doc/openapi.json
@@ -12717,12 +12717,15 @@
{
"type": "string"
},
+ {
+ "type": "integer"
+ },
{
"type": "null"
}
],
"title": "PostgreSQL port",
- "description": "PostgreSQL port for remote::pgvector. Defaults to ${env.POSTGRES_PORT} when rag_type is remote::pgvector."
+ "description": "PostgreSQL port for remote::pgvector. Defaults to ${env.POSTGRES_PORT} when rag_type is remote::pgvector. Accepts string placeholders and integer values."
},
"db": {
"anyOf": [
@@ -17519,12 +17522,15 @@
{
"type": "string"
},
+ {
+ "type": "integer"
+ },
{
"type": "null"
}
],
"title": "PostgreSQL port",
- "description": "PostgreSQL port. Defaults to ${env.POSTGRES_PORT}."
+ "description": "PostgreSQL port. Defaults to ${env.POSTGRES_PORT}. Accepts string placeholders and integer values."
},
"db": {
"anyOf": [
diff --git a/src/models/config.py b/src/models/config.py
index 0449a233d..8b27f9218 100644
--- a/src/models/config.py
+++ b/src/models/config.py
@@ -2085,11 +2085,12 @@ class ByokRag(ConfigurationBase):
"Defaults to ${env.POSTGRES_HOST} when rag_type is remote::pgvector.",
)
- port: Optional[str] = Field(
+ port: Optional[str | int] = Field(
default=None,
title="PostgreSQL port",
description="PostgreSQL port for remote::pgvector. "
- "Defaults to ${env.POSTGRES_PORT} when rag_type is remote::pgvector.",
+ "Defaults to ${env.POSTGRES_PORT} when rag_type is remote::pgvector. "
+ "Accepts string placeholders and integer values.",
)
db: Optional[str] = Field(
@@ -2153,10 +2154,11 @@ class PgvectorVectorStoreProviderConfig(ConfigurationBase):
description="PostgreSQL host. Defaults to ${env.POSTGRES_HOST}.",
)
- port: Optional[str] = Field(
+ port: Optional[str | int] = Field(
default=None,
title="PostgreSQL port",
- description="PostgreSQL port. Defaults to ${env.POSTGRES_PORT}.",
+ description="PostgreSQL port. Defaults to ${env.POSTGRES_PORT}. "
+ "Accepts string placeholders and integer values.",
)
db: Optional[str] = Field(
diff --git a/tests/unit/models/config/test_byok_rag.py b/tests/unit/models/config/test_byok_rag.py
index 1ac098299..6bddcb96d 100644
--- a/tests/unit/models/config/test_byok_rag.py
+++ b/tests/unit/models/config/test_byok_rag.py
@@ -247,6 +247,21 @@ def test_byok_rag_pgvector_custom_connection_fields() -> None:
assert store.password.get_secret_value() == "secret" # pylint: disable=no-member
+def test_byok_rag_pgvector_accepts_int_port() -> None:
+ """Int port (from replace_env_vars coercion) must validate for pgvector."""
+ store = ByokRag(
+ rag_id="pg_store",
+ rag_type="remote::pgvector",
+ vector_db_id="vs_pg",
+ host="db.example.com",
+ port=5432,
+ db="my_knowledge",
+ user="admin",
+ password="secret",
+ )
+ assert store.port == 5432
+
+
def test_byok_rag_pgvector_partial_overrides() -> None:
"""Test pgvector fills only missing connection fields with defaults."""
store = ByokRag(
diff --git a/tests/unit/models/config/test_vector_store.py b/tests/unit/models/config/test_vector_store.py
index ad3c13fba..b051a33d0 100644
--- a/tests/unit/models/config/test_vector_store.py
+++ b/tests/unit/models/config/test_vector_store.py
@@ -5,6 +5,7 @@
import pytest
import yaml
+from llama_stack.core.stack import replace_env_vars
from pydantic import SecretStr, TypeAdapter, ValidationError
from models.config import Configuration, VectorStoreProvider
@@ -93,6 +94,65 @@ def test_pgvector_applies_env_defaults() -> None:
assert provider.config.password == SecretStr("${env.POSTGRES_PASSWORD}")
+def test_pgvector_accepts_int_port_from_env_substitution(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ """Int port after replace_env_vars type coercion must validate.
+
+ Llama Stack's replace_env_vars converts digit-only env values to int via
+ _convert_string_to_proper_type. LCORE loads config through that helper, so
+ port must accept int as well as str / ${env.*} placeholders.
+ """
+ monkeypatch.setenv("PGVECTOR_PORT", "5432")
+ resolved = replace_env_vars({"port": "${env.PGVECTOR_PORT:=5432}"})
+ assert resolved["port"] == 5432
+ assert isinstance(resolved["port"], int)
+
+ provider = _PROVIDER_ADAPTER.validate_python(
+ {
+ "id": "nb-pg",
+ "type": "pgvector",
+ "embedding_model": "/emb",
+ "embedding_dimension": 768,
+ "config": {
+ "host": "db.example.com",
+ "port": resolved["port"],
+ "db": "vectors",
+ "user": "pguser",
+ "password": "secret",
+ },
+ }
+ )
+ assert provider.config.port == 5432
+
+
+def test_pgvector_accepts_int_port_from_env_default(
+ monkeypatch: pytest.MonkeyPatch,
+) -> None:
+ """Unset env with :=default still coerces the default to int and validates."""
+ monkeypatch.delenv("PGVECTOR_PORT", raising=False)
+ resolved = replace_env_vars({"port": "${env.PGVECTOR_PORT:=5432}"})
+ assert resolved["port"] == 5432
+ assert isinstance(resolved["port"], int)
+
+ provider = _PROVIDER_ADAPTER.validate_python(
+ {
+ "id": "nb-pg",
+ "type": "pgvector",
+ "embedding_model": "/emb",
+ "embedding_dimension": 768,
+ "config": {
+ "host": "db.example.com",
+ "port": resolved["port"],
+ "db": "vectors",
+ "user": "pguser",
+ "password": "secret",
+ },
+ }
+ )
+ assert provider.config.port == 5432
+
+
def test_rejects_byok_prefix_id() -> None:
"""Provider id must not use the byok_ prefix reserved for BYOK RAG."""
with pytest.raises(ValidationError, match="byok_"):
diff --git a/tests/unit/utils/test_models_dumper.py b/tests/unit/utils/test_models_dumper.py
index 0a6cf445f..060846351 100644
--- a/tests/unit/utils/test_models_dumper.py
+++ b/tests/unit/utils/test_models_dumper.py
@@ -541,10 +541,19 @@ def test_dump_models(tmpdir: Path) -> None:
"title": "PostgreSQL host"
},
"port": {
- "type": "string",
- "nullable": true,
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "integer"
+ },
+ {
+ "type": "null"
+ }
+ ],
"default": null,
- "description": "PostgreSQL port for remote::pgvector. Defaults to ${env.POSTGRES_PORT} when rag_type is remote::pgvector.",
+ "description": "PostgreSQL port for remote::pgvector. Defaults to ${env.POSTGRES_PORT} when rag_type is remote::pgvector. Accepts string placeholders and integer values.",
"title": "PostgreSQL port"
},
"db": {
From a58e9dba57ad7771514469b4748a6f6dc1701ed1 Mon Sep 17 00:00:00 2001
From: Jordan Dubrick
Date: Fri, 31 Jul 2026 13:31:26 -0400
Subject: [PATCH 008/197] address coderabbit
Signed-off-by: Jordan Dubrick
---
tests/unit/models/config/test_vector_store.py | 9 ++++++++-
tests/unit/utils/test_models_dumper.py | 6 ++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/tests/unit/models/config/test_vector_store.py b/tests/unit/models/config/test_vector_store.py
index b051a33d0..a5d4917f9 100644
--- a/tests/unit/models/config/test_vector_store.py
+++ b/tests/unit/models/config/test_vector_store.py
@@ -102,6 +102,9 @@ def test_pgvector_accepts_int_port_from_env_substitution(
Llama Stack's replace_env_vars converts digit-only env values to int via
_convert_string_to_proper_type. LCORE loads config through that helper, so
port must accept int as well as str / ${env.*} placeholders.
+
+ Parameters:
+ monkeypatch: Fixture that sets and restores environment variables.
"""
monkeypatch.setenv("PGVECTOR_PORT", "5432")
resolved = replace_env_vars({"port": "${env.PGVECTOR_PORT:=5432}"})
@@ -129,7 +132,11 @@ def test_pgvector_accepts_int_port_from_env_substitution(
def test_pgvector_accepts_int_port_from_env_default(
monkeypatch: pytest.MonkeyPatch,
) -> None:
- """Unset env with :=default still coerces the default to int and validates."""
+ """Unset env with :=default still coerces the default to int and validates.
+
+ Parameters:
+ monkeypatch: Fixture that removes and restores environment variables.
+ """
monkeypatch.delenv("PGVECTOR_PORT", raising=False)
resolved = replace_env_vars({"port": "${env.PGVECTOR_PORT:=5432}"})
assert resolved["port"] == 5432
diff --git a/tests/unit/utils/test_models_dumper.py b/tests/unit/utils/test_models_dumper.py
index 060846351..7798ee99a 100644
--- a/tests/unit/utils/test_models_dumper.py
+++ b/tests/unit/utils/test_models_dumper.py
@@ -9164,6 +9164,12 @@ def test_dump_models(tmpdir: Path) -> None:
schemas = components["schemas"]
assert schemas is not None
+ # ByokRag.port accepts str placeholders, int values, and null.
+ port_schema = schemas["ByokRag"]["properties"]["port"]
+ assert {"type": "string"} in port_schema["anyOf"]
+ assert {"type": "integer"} in port_schema["anyOf"]
+ assert {"type": "null"} in port_schema["anyOf"]
+
# list of schemas expected in a dump
expected_schemas = (
"A2AStateConfiguration",
From e78fceaa62c5e0819695d20b8e9c58e848e36de7 Mon Sep 17 00:00:00 2001
From: Stephanie
Date: Fri, 31 Jul 2026 14:01:21 -0400
Subject: [PATCH 009/197] update docs
Signed-off-by: Stephanie
---
README.md | 5 +++++
docs/devel_doc/openapi.json | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 37002ecf4..853600852 100644
--- a/README.md
+++ b/README.md
@@ -1265,11 +1265,16 @@ skills without the cost, latency, or non-determinism of an LLM tool call.
This is distinct from the `list_skills` tool that the agent itself may
invoke during a `/v1/query` or `/v1/streaming_query` turn.
+If [authentication](#authentication) is enabled, include the appropriate
+credentials (e.g. `-H "Authorization: Bearer "`); otherwise the
+request returns `401`/`403`.
+
```bash
curl http://localhost:8080/v1/skills
```
**Response Body:**
+
```json
{
"skills": [
diff --git a/docs/devel_doc/openapi.json b/docs/devel_doc/openapi.json
index 860ff2ac1..547bd8660 100644
--- a/docs/devel_doc/openapi.json
+++ b/docs/devel_doc/openapi.json
@@ -21039,7 +21039,7 @@
"skills"
],
"title": "SkillsResponse",
- "description": "Model representing a response to skills request.",
+ "description": "Model representing a response to skills request.\n\nAttributes:\n skills: List of loaded skills with metadata (name and description).",
"examples": [
{
"skills": [
From a23454c2bcbc3e761881f310ff826b6eddb8d00e Mon Sep 17 00:00:00 2001
From: Maxim Svistunov
Date: Mon, 3 Aug 2026 13:19:51 +0200
Subject: [PATCH 010/197] LCORE-2872: validate config_format_version against
detected config shape
Implement R11's optional explicit format marker: the root Configuration
gains config_format_version (Literal "legacy"/"unified", default None),
previously rejected outright by extra="forbid". When set, the value is
cross-checked in check_unified_vs_legacy against the shape detected from
the configuration body: "unified" requires a synthesis input (a non-empty
inference.providers, a non-empty vector_store.providers, or a
llama_stack.config block), "legacy" requires its absence. Remote-only
configurations (url, no synthesis input) count as legacy-compatible. A
mismatch fails at load with an error naming config_format_version, giving
the e2e scenario authored in LCORE-2341 (unified-mode-validation.feature)
a real validation path instead of an accidental extra-forbid error. The
mutual-exclusion and missing-run-source checks keep precedence, so their
errors are unchanged.
Unit tests cover: default None, accepted-when-agreeing (unified body,
legacy body, remote-only body with "legacy"), rejected-on-mismatch in
both directions plus "unified" on a remote-only body, and rejection of
values outside the literal. The dump-configuration snapshot expectations
gain the new field, and docs/devel_doc/openapi.json is regenerated since
the Configuration schema is exposed via /v1/config.
---
docs/devel_doc/openapi.json | 16 ++++
src/models/config.py | 33 ++++++-
.../models/config/test_dump_configuration.py | 10 ++
.../config/test_llama_stack_configuration.py | 94 +++++++++++++++++++
4 files changed, 151 insertions(+), 2 deletions(-)
diff --git a/docs/devel_doc/openapi.json b/docs/devel_doc/openapi.json
index 073109e41..935800781 100644
--- a/docs/devel_doc/openapi.json
+++ b/docs/devel_doc/openapi.json
@@ -12987,6 +12987,22 @@
"title": "Service name",
"description": "Name of the service. That value will be used in REST API endpoints."
},
+ "config_format_version": {
+ "anyOf": [
+ {
+ "type": "string",
+ "enum": [
+ "legacy",
+ "unified"
+ ]
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "title": "Configuration format version",
+ "description": "Optional explicit marker of the configuration format. When set, it must agree with the shape detected from the configuration body: 'unified' requires a synthesis input (a non-empty inference.providers, a non-empty vector_store.providers, or a llama_stack.config block), 'legacy' requires no synthesis input. Reserved as the lever for a future breaking change of the unified schema (R11)."
+ },
"service": {
"$ref": "#/components/schemas/ServiceConfiguration",
"title": "Service configuration",
diff --git a/src/models/config.py b/src/models/config.py
index 941507ce1..cfc95820d 100644
--- a/src/models/config.py
+++ b/src/models/config.py
@@ -2962,6 +2962,18 @@ class Configuration(ConfigurationBase):
description="Name of the service. That value will be used in REST API endpoints.",
)
+ config_format_version: Optional[Literal["legacy", "unified"]] = Field(
+ None,
+ title="Configuration format version",
+ description="Optional explicit marker of the configuration format. "
+ "When set, it must agree with the shape detected from the "
+ "configuration body: 'unified' requires a synthesis input (a "
+ "non-empty inference.providers, a non-empty vector_store.providers, "
+ "or a llama_stack.config block), 'legacy' requires no synthesis "
+ "input. Reserved as the lever for a future breaking change of the "
+ "unified schema (R11).",
+ )
+
service: ServiceConfiguration = Field(
...,
title="Service configuration",
@@ -3343,14 +3355,19 @@ def check_unified_vs_legacy(self) -> Self:
- Library mode needs *some* run source — a synthesis input or the
legacy path. ``inference.providers`` or ``vector_store.providers``
alone is sufficient; no ``llama_stack.config`` block is required.
+ - An explicit ``config_format_version``, when set, must agree with
+ the detected shape (R11): ``unified`` requires a synthesis input,
+ ``legacy`` requires its absence (remote-only configs count as
+ legacy-compatible).
Returns:
Self: The validated configuration instance.
Raises:
ValueError: If a synthesis input and the legacy
- ``library_client_config_path`` are set together, or if library
- mode has no run source at all.
+ ``library_client_config_path`` are set together, if library
+ mode has no run source at all, or if ``config_format_version``
+ contradicts the detected shape.
"""
# pylint: disable=no-member
synthesis_input = (
@@ -3380,6 +3397,18 @@ def check_unified_vs_legacy(self) -> Self:
"vector_store.providers, a llama_stack.config block, or "
"library_client_config_path."
)
+ if self.config_format_version is not None:
+ detected = "unified" if synthesis_input else "legacy"
+ if self.config_format_version != detected:
+ raise ValueError(
+ f"config_format_version is '{self.config_format_version}' "
+ f"but the configuration body is {detected}-shaped: a "
+ "unified configuration carries a synthesis input (a "
+ "non-empty inference.providers, a non-empty "
+ "vector_store.providers, or a llama_stack.config block), "
+ "a legacy one does not. Fix config_format_version or the "
+ "configuration body."
+ )
return self
def dump(self, filename: str | Path = "configuration.json") -> None:
diff --git a/tests/unit/models/config/test_dump_configuration.py b/tests/unit/models/config/test_dump_configuration.py
index 36dc1011e..4e879e6bb 100644
--- a/tests/unit/models/config/test_dump_configuration.py
+++ b/tests/unit/models/config/test_dump_configuration.py
@@ -132,6 +132,7 @@ def test_dump_configuration_minimal_cfg(tmp_path: Path) -> None:
# check the whole deserialized JSON file content
assert content == {
"name": "test_name",
+ "config_format_version": None,
"service": {
"host": "localhost",
"port": 8080,
@@ -347,6 +348,7 @@ def test_dump_configuration_valid_values(tmp_path: Path) -> None:
# check the whole deserialized JSON file content
assert content == {
"name": "test_name",
+ "config_format_version": None,
"service": {
"host": "localhost",
"port": 8080,
@@ -712,6 +714,7 @@ def test_dump_configuration_with_quota_limiters(tmp_path: Path) -> None:
# check the whole deserialized JSON file content
assert content == {
"name": "test_name",
+ "config_format_version": None,
"service": {
"host": "localhost",
"port": 8080,
@@ -976,6 +979,7 @@ def test_dump_configuration_with_quota_limiters_different_values(
# check the whole deserialized JSON file content
assert content == {
"name": "test_name",
+ "config_format_version": None,
"service": {
"host": "localhost",
"port": 8080,
@@ -1273,6 +1277,7 @@ def test_dump_configuration_byok(tmp_path: Path) -> None:
# check the whole deserialized JSON file content
assert content == {
"name": "test_name",
+ "config_format_version": None,
"service": {
"host": "localhost",
"port": 8080,
@@ -1512,6 +1517,7 @@ def test_dump_configuration_pg_namespace(tmp_path: Path) -> None:
# check the whole deserialized JSON file content
assert content == {
"name": "test_name",
+ "config_format_version": None,
"service": {
"host": "localhost",
"port": 8080,
@@ -1896,6 +1902,7 @@ def test_dump_configuration_allow_degraded_mode(tmp_path: Path) -> None:
# check the whole deserialized JSON file content
assert content == {
"name": "test_name",
+ "config_format_version": None,
"service": {
"host": "localhost",
"port": 8080,
@@ -2126,6 +2133,7 @@ def test_dump_configuration_max_retries_settings(tmp_path: Path) -> None:
# check the whole deserialized JSON file content
assert content == {
"name": "test_name",
+ "config_format_version": None,
"service": {
"host": "localhost",
"port": 8080,
@@ -2356,6 +2364,7 @@ def test_dump_configuration_retry_count_settings(tmp_path: Path) -> None:
# check the whole deserialized JSON file content
assert content == {
"name": "test_name",
+ "config_format_version": None,
"service": {
"host": "localhost",
"port": 8080,
@@ -2593,6 +2602,7 @@ def test_dump_configuration_specific_compaction_values(tmp_path: Path) -> None:
# check the whole deserialized JSON file content
assert content == {
"name": "test_name",
+ "config_format_version": None,
"service": {
"host": "localhost",
"port": 8080,
diff --git a/tests/unit/models/config/test_llama_stack_configuration.py b/tests/unit/models/config/test_llama_stack_configuration.py
index c22139c35..4d5bd8999 100644
--- a/tests/unit/models/config/test_llama_stack_configuration.py
+++ b/tests/unit/models/config/test_llama_stack_configuration.py
@@ -358,3 +358,97 @@ def test_root_accepts_remote_url_with_unified_config() -> None:
}
cfg = Configuration(**config_dict)
assert cfg.llama_stack.config is not None # pylint: disable=no-member
+
+
+# ---------------------------------------------------------------------------
+# config_format_version cross-validation (LCORE-2872, R11)
+# ---------------------------------------------------------------------------
+
+
+def _unified_body(config_dict: dict[str, Any]) -> dict[str, Any]:
+ """Give the base config a unified shape (synthesis input present)."""
+ config_dict["llama_stack"] = {"use_as_library_client": True}
+ config_dict["inference"] = {
+ "providers": [{"type": "openai", "api_key_env": "OPENAI_API_KEY"}]
+ }
+ return config_dict
+
+
+def _legacy_body(config_dict: dict[str, Any]) -> dict[str, Any]:
+ """Give the base config a legacy shape (external run.yaml path)."""
+ config_dict["llama_stack"] = {
+ "use_as_library_client": True,
+ "library_client_config_path": "tests/configuration/run.yaml",
+ }
+ return config_dict
+
+
+def _remote_body(config_dict: dict[str, Any]) -> dict[str, Any]:
+ """Give the base config a remote shape (url only, no synthesis input)."""
+ config_dict["llama_stack"] = {
+ "use_as_library_client": False,
+ "url": "http://localhost:8321",
+ }
+ return config_dict
+
+
+def test_root_config_format_version_defaults_to_none() -> None:
+ """The field is optional; an unversioned config loads with None."""
+ cfg = Configuration(**_unified_body(_base_config_dict()))
+ assert cfg.config_format_version is None
+
+
+def test_root_accepts_config_format_version_unified_with_unified_body() -> None:
+ """'unified' agrees with a body that has a synthesis input."""
+ config_dict = _unified_body(_base_config_dict())
+ config_dict["config_format_version"] = "unified"
+ cfg = Configuration(**config_dict)
+ assert cfg.config_format_version == "unified"
+
+
+def test_root_accepts_config_format_version_legacy_with_legacy_body() -> None:
+ """'legacy' agrees with a body driven by library_client_config_path."""
+ config_dict = _legacy_body(_base_config_dict())
+ config_dict["config_format_version"] = "legacy"
+ cfg = Configuration(**config_dict)
+ assert cfg.config_format_version == "legacy"
+
+
+def test_root_accepts_config_format_version_legacy_with_remote_body() -> None:
+ """'legacy' agrees with a remote-only body (no synthesis input)."""
+ config_dict = _remote_body(_base_config_dict())
+ config_dict["config_format_version"] = "legacy"
+ cfg = Configuration(**config_dict)
+ assert cfg.config_format_version == "legacy"
+
+
+def test_root_rejects_config_format_version_legacy_with_unified_body() -> None:
+ """'legacy' with a unified-shaped body fails; error names the field."""
+ config_dict = _unified_body(_base_config_dict())
+ config_dict["config_format_version"] = "legacy"
+ with pytest.raises(ValidationError, match="config_format_version"):
+ Configuration(**config_dict)
+
+
+def test_root_rejects_config_format_version_unified_with_legacy_body() -> None:
+ """'unified' with a legacy-shaped body fails; error names the field."""
+ config_dict = _legacy_body(_base_config_dict())
+ config_dict["config_format_version"] = "unified"
+ with pytest.raises(ValidationError, match="config_format_version"):
+ Configuration(**config_dict)
+
+
+def test_root_rejects_config_format_version_unified_with_remote_body() -> None:
+ """'unified' with a remote-only body (no synthesis input) fails."""
+ config_dict = _remote_body(_base_config_dict())
+ config_dict["config_format_version"] = "unified"
+ with pytest.raises(ValidationError, match="config_format_version"):
+ Configuration(**config_dict)
+
+
+def test_root_rejects_unknown_config_format_version_value() -> None:
+ """Values outside the 'legacy'/'unified' literal are rejected."""
+ config_dict = _unified_body(_base_config_dict())
+ config_dict["config_format_version"] = "v2"
+ with pytest.raises(ValidationError, match="Input should be 'legacy' or 'unified'"):
+ Configuration(**config_dict)
From f3e6952350c119c5f79d0bb85da1f8e16725230f Mon Sep 17 00:00:00 2001
From: Maxim Svistunov
Date: Mon, 3 Aug 2026 16:06:38 +0200
Subject: [PATCH 011/197] LCORE-2872: extend config_format_version test
coverage
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Address review feedback on the marker tests:
- Cover all three synthesis inputs as the unified signal, not only
inference.providers: 'unified' is accepted on a body driven solely by
vector_store.providers and on one driven solely by a llama_stack.config
block.
- Make the legacy/remote helpers explicit: both provider lists the
detection looks at are now emptied in the fixtures rather than relying
on the base fixture carrying neither section.
- Pin validation precedence: a sourceless library config with a 'unified'
marker fails on the missing-run-source error, and an ambiguous
unified+legacy body with a 'legacy' marker fails on the mutual-exclusion
error — the marker cross-check stays last so pre-existing error
messages never change.
---
.../config/test_llama_stack_configuration.py | 76 +++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/tests/unit/models/config/test_llama_stack_configuration.py b/tests/unit/models/config/test_llama_stack_configuration.py
index 4d5bd8999..f89d1abc2 100644
--- a/tests/unit/models/config/test_llama_stack_configuration.py
+++ b/tests/unit/models/config/test_llama_stack_configuration.py
@@ -374,8 +374,20 @@ def _unified_body(config_dict: dict[str, Any]) -> dict[str, Any]:
return config_dict
+def _clear_synthesis_inputs(config_dict: dict[str, Any]) -> dict[str, Any]:
+ """Explicitly empty both provider lists the unified detection looks at.
+
+ The base fixture carries neither section today, but the legacy/remote
+ helpers must not silently become unified-shaped if it ever gains one.
+ """
+ config_dict["inference"] = {"providers": []}
+ config_dict["vector_store"] = {"providers": []}
+ return config_dict
+
+
def _legacy_body(config_dict: dict[str, Any]) -> dict[str, Any]:
"""Give the base config a legacy shape (external run.yaml path)."""
+ config_dict = _clear_synthesis_inputs(config_dict)
config_dict["llama_stack"] = {
"use_as_library_client": True,
"library_client_config_path": "tests/configuration/run.yaml",
@@ -385,6 +397,7 @@ def _legacy_body(config_dict: dict[str, Any]) -> dict[str, Any]:
def _remote_body(config_dict: dict[str, Any]) -> dict[str, Any]:
"""Give the base config a remote shape (url only, no synthesis input)."""
+ config_dict = _clear_synthesis_inputs(config_dict)
config_dict["llama_stack"] = {
"use_as_library_client": False,
"url": "http://localhost:8321",
@@ -452,3 +465,66 @@ def test_root_rejects_unknown_config_format_version_value() -> None:
config_dict["config_format_version"] = "v2"
with pytest.raises(ValidationError, match="Input should be 'legacy' or 'unified'"):
Configuration(**config_dict)
+
+
+def test_root_accepts_unified_marker_with_vector_store_providers_body() -> None:
+ """'unified' agrees with a body whose only synthesis input is vector_store."""
+ config_dict = _base_config_dict()
+ config_dict["llama_stack"] = {"use_as_library_client": True}
+ config_dict["inference"] = {"providers": []}
+ config_dict["vector_store"] = {
+ "default_provider": "notebooks",
+ "providers": [
+ {
+ "id": "notebooks",
+ "type": "faiss",
+ "embedding_model": "/rag-content/embeddings_model",
+ "embedding_dimension": 768,
+ "config": {"path": "/var/lib/notebooks.db"},
+ }
+ ],
+ }
+ config_dict["config_format_version"] = "unified"
+ cfg = Configuration(**config_dict)
+ assert cfg.config_format_version == "unified"
+
+
+def test_root_accepts_unified_marker_with_config_block_body() -> None:
+ """'unified' agrees with a body whose only synthesis input is llama_stack.config."""
+ config_dict = _clear_synthesis_inputs(_base_config_dict())
+ config_dict["llama_stack"] = {
+ "use_as_library_client": True,
+ "config": {"baseline": "default"},
+ }
+ config_dict["config_format_version"] = "unified"
+ cfg = Configuration(**config_dict)
+ assert cfg.config_format_version == "unified"
+
+
+def test_missing_run_source_error_precedes_marker_check() -> None:
+ """Library mode without a run source fails on that, not on the marker.
+
+ A 'unified' marker on a sourceless library config is also a mismatch,
+ but the missing-run-source check runs first and its error must win.
+ """
+ config_dict = _clear_synthesis_inputs(_base_config_dict())
+ config_dict["llama_stack"] = {"use_as_library_client": True}
+ config_dict["config_format_version"] = "unified"
+ with pytest.raises(ValidationError, match="requires a run-configuration source"):
+ Configuration(**config_dict)
+
+
+def test_mutual_exclusion_error_precedes_marker_check() -> None:
+ """Ambiguous unified+legacy bodies fail on mutual exclusion, not the marker.
+
+ A 'legacy' marker on such a body is also a mismatch (the body carries a
+ synthesis input), but the mutual-exclusion check runs first and its
+ --migrate-config guidance must win.
+ """
+ config_dict = _unified_body(_base_config_dict())
+ config_dict["llama_stack"][
+ "library_client_config_path"
+ ] = "tests/configuration/run.yaml"
+ config_dict["config_format_version"] = "legacy"
+ with pytest.raises(ValidationError, match="mutually exclusive"):
+ Configuration(**config_dict)
From 57442087bdfb1cd3ca76a0a09692cd17322cf3f6 Mon Sep 17 00:00:00 2001
From: Maxim Svistunov
Date: Sun, 5 Jul 2026 20:19:09 +0200
Subject: [PATCH 012/197] LCORE-2747: record integration-tests ticket in
config-merge design docs
Add LCORE-2747 (integration tests for unified-mode synthesis) to the spike
doc's Proposed JIRAs under the "E2E and test-config coverage" epic, and
cross-reference it from the spec doc's R7 acceptance-surface row. Records that
R7's integration-level coverage is tracked by a dedicated ticket, filed
post-spike during implementation. Doc-only.
---
.../llama-stack-config-merge-spike.md | 16 ++++++++++++++++
.../llama-stack-config-merge.md | 2 +-
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/docs/design/llama-stack-config-merge/llama-stack-config-merge-spike.md b/docs/design/llama-stack-config-merge/llama-stack-config-merge-spike.md
index d013f923a..4c36d9649 100644
--- a/docs/design/llama-stack-config-merge/llama-stack-config-merge-spike.md
+++ b/docs/design/llama-stack-config-merge/llama-stack-config-merge-spike.md
@@ -740,6 +740,22 @@ To verify: `uv run make test-e2e` runs every new scenario green and
behave reports zero undefined steps.
```
+
+
+#### LCORE-2747: Integration tests for unified-mode synthesis
+
+**Description**: Add pytest integration tests under `tests/integration/` that
+exercise the unified-mode synthesis path (baseline → enrichment → high-level
+inference → native_override) and confirm enrichment parity with legacy mode, so
+requirement R7 ("enrichment yields the same synthesized result in unified mode
+as legacy for equivalent inputs") is verified at the integration level, not only
+by unit tests. Fills the gap between the synthesizer unit tests (LCORE-2336) and
+the behave e2e suite (LCORE-2341 / LCORE-2343). Filed post-spike during
+implementation.
+
+**Blocked by**: LCORE-2336 (synthesizer), LCORE-2337 (migrate-then-synthesize
+parity cases).
+
### Epic: Documentation for unified mode
Make the single-file unified configuration the primary documented path,
diff --git a/docs/design/llama-stack-config-merge/llama-stack-config-merge.md b/docs/design/llama-stack-config-merge/llama-stack-config-merge.md
index 7a315a0fc..cf43a6107 100644
--- a/docs/design/llama-stack-config-merge/llama-stack-config-merge.md
+++ b/docs/design/llama-stack-config-merge/llama-stack-config-merge.md
@@ -151,7 +151,7 @@ files — authors read it to write Gherkin scenarios.
| R4 | `--migrate-config` on a legacy pair yields a unified file driving byte-identical LS behavior; migrate→synthesize round-trips to the original `run.yaml` | e2e + unit (round-trip) |
| R5 | `native_override` overlapping a baseline/high-level key deep-merges: maps merge, lists replace wholesale, scalars replace | unit (parametric) + e2e (one scalar + one list key) |
| R6 | Synthesized `run.yaml` on disk carries `${env.FOO}` refs for LCORE-emitted secrets, never resolved values | e2e (inspect file) + unit |
-| R7 | Enrichment (Azure Entra ID, BYOK RAG, Solr/OKP) yields the same synthesized result in unified mode as legacy for equivalent inputs | unit + integration |
+| R7 | Enrichment (Azure Entra ID, BYOK RAG, Solr/OKP) yields the same synthesized result in unified mode as legacy for equivalent inputs | unit + integration (integration coverage tracked by LCORE-2747) |
| R8 | A relative `profile:` path resolves against the loaded `lightspeed-stack.yaml` directory; absolute paths always resolve | e2e + unit |
| R9 | Unknown fields rejected (`extra="forbid"`); root validator enforces synthesis-input ⊕ legacy mutual exclusion | unit |
| R10 | Synthesized file written to the persistent known path with mode `0600`, path logged at startup; `--synthesized-config-output` overrides the location | e2e (perms + path) + unit |
From 96f5fc2162276d678ccf9b33f3c30b1c1c0d606d Mon Sep 17 00:00:00 2001
From: Maxim Svistunov
Date: Mon, 3 Aug 2026 13:20:16 +0200
Subject: [PATCH 013/197] LCORE-2747: add integration tests for unified-mode
synthesis
Exercise the unified-mode synthesis path end to end through real YAML
files on disk, filling the gap between the LCORE-2336 synthesizer unit
tests and the LCORE-2341/2343 behave e2e suite:
- R7 enrichment parity: synthesize_configuration over a unified config
whose profile is the operator's legacy run.yaml equals the legacy
generate_configuration output, for BYOK RAG, Solr/OKP, Azure Entra ID,
and all three combined. The run.yaml fixture deliberately carries
pre-existing vector_io/models/storage entries so the append-to-existing
enrichment paths are compared, not just creation from nothing. One
parity case additionally routes the unified file through the real
AppConfig.load_configuration + synthesize_to_file flow, mirroring
client.AsyncLlamaStackClientHolder (this variant caught that ByokRag
requires db_path for inline::faiss, which raw-dict tests bypass).
- Baseline selection through the real load + synthesis path: default
(shipped src/data/default_run.yaml), empty + native_override (T7
reproduction), and profile (with ensure_mcp_tool_runtime applied), plus
native_override deep-merge semantics (lists replace, dicts merge,
scalars win) and the 0600 output mode (R10).
- Migrate-then-synthesize (LCORE-2337): the no-enrichment round-trip
reproduces the original run.yaml; the with-enrichment parity case is a
strict xfail documenting LCORE-3370 (enrichment artifacts in
list-shaped run.yaml sections are lost because native_override merges
last with list replacement).
- Mode detection via AppConfig.load_configuration on real files: both
mutual-exclusion shapes, missing run source, and the minimal
inference.providers-only unified config.
---
tests/integration/test_unified_synthesis.py | 489 ++++++++++++++++++++
1 file changed, 489 insertions(+)
create mode 100644 tests/integration/test_unified_synthesis.py
diff --git a/tests/integration/test_unified_synthesis.py b/tests/integration/test_unified_synthesis.py
new file mode 100644
index 000000000..b0b9a7db0
--- /dev/null
+++ b/tests/integration/test_unified_synthesis.py
@@ -0,0 +1,489 @@
+"""Integration tests for unified-mode synthesis (LCORE-2747).
+
+These tests exercise the unified-mode synthesis path end to end — baseline
+selection, enrichment, high-level inference expansion, and native_override
+deep-merge — through real YAML files on disk, and confirm enrichment parity
+with the legacy two-file path (requirement R7: enrichment yields the same
+synthesized result in unified mode as legacy for equivalent inputs).
+
+They fill the gap between the synthesizer unit tests (LCORE-2336, functions
+in isolation) and the behave e2e suite (LCORE-2341/LCORE-2343, full running
+service): everything here goes through the real configuration-load and
+synthesis pipeline (``AppConfig.load_configuration``,
+``synthesize_to_file``) without standing up the whole service.
+"""
+
+import copy
+import os
+import stat
+from pathlib import Path
+from typing import Any
+
+import pytest
+import yaml
+from pydantic import ValidationError
+
+from configuration import configuration
+from llama_stack_configuration import (
+ generate_configuration,
+ load_default_baseline,
+ migrate_config_dumb,
+ synthesize_configuration,
+ synthesize_to_file,
+)
+
+# A complete, valid lightspeed-stack.yaml used as the base for configs that
+# are loaded through the real AppConfig.load_configuration pipeline;
+# individual tests override its llama_stack / inference sections.
+_BASE_CONFIG_PATH = "tests/configuration/lightspeed-stack.yaml"
+
+# A representative operator-authored legacy run.yaml. It deliberately carries
+# pre-existing entries in every section the enrichment touches (an existing
+# vector_io provider, registered models, storage backends) so parity is
+# checked for the append-to-existing paths, not just creation from nothing.
+# It also already contains the default MCP tool_runtime provider: the unified
+# pipeline runs ensure_mcp_tool_runtime for non-empty baselines while the
+# legacy path does not, so exact parity is only expected for run.yaml files
+# that (like all shipped ones) already carry that provider.
+_OPERATOR_RUN_YAML: dict[str, Any] = {
+ "version": 2,
+ "apis": ["agents", "inference", "safety", "tool_runtime", "vector_io"],
+ "providers": {
+ "inference": [
+ {
+ "provider_id": "azure",
+ "provider_type": "remote::azure",
+ "config": {
+ "api_key": "${env.AZURE_API_KEY}",
+ "api_base": "https://azure.example.com",
+ },
+ },
+ {
+ "provider_id": "sentence-transformers",
+ "provider_type": "inline::sentence-transformers",
+ },
+ ],
+ "vector_io": [
+ {
+ "provider_id": "faiss",
+ "provider_type": "inline::faiss",
+ "config": {
+ "persistence": {
+ "backend": "kv_default",
+ "namespace": "vector_io::faiss",
+ }
+ },
+ }
+ ],
+ "tool_runtime": [
+ {
+ "provider_id": "model-context-protocol",
+ "provider_type": "remote::model-context-protocol",
+ "config": {},
+ }
+ ],
+ },
+ "storage": {
+ "backends": {
+ "kv_default": {
+ "type": "kv_sqlite",
+ "db_path": ".llama/kv_default.db",
+ }
+ }
+ },
+ "registered_resources": {
+ "models": [
+ {
+ "model_id": "gpt-4o-mini",
+ "provider_id": "azure",
+ "model_type": "llm",
+ }
+ ]
+ },
+ "safety": {"default_shield_id": None, "excluded_categories": []},
+}
+
+# Enrichment inputs equivalent between the two modes: each dict is both the
+# lightspeed config passed to legacy generate_configuration and the extra
+# root-level content of the unified lightspeed-stack.yaml.
+_BYOK_INPUTS: dict[str, Any] = {
+ "byok_rag": [
+ {
+ "rag_id": "kb1",
+ "vector_db_id": "kb1",
+ "db_path": "/var/lib/kb1/faiss_store.db",
+ "embedding_model": "nomic-ai/nomic-embed-text-v1.5",
+ "embedding_dimension": 768,
+ }
+ ]
+}
+
+_SOLR_INPUTS: dict[str, Any] = {
+ "rag": {"inline": ["okp"]},
+ "okp": {
+ "rhokp_url": "https://okp.example.com",
+ "chunk_filter_query": "product:openshift",
+ },
+}
+
+_AZURE_INPUTS: dict[str, Any] = {
+ "azure_entra_id": {
+ "tenant_id": "test-tenant",
+ "client_id": "test-client",
+ "client_secret_path": "/run/secrets/azure",
+ }
+}
+
+
+def _write_yaml(path: Path, data: dict[str, Any]) -> Path:
+ """Serialize ``data`` to ``path`` as YAML and return the path."""
+ path.write_text(yaml.dump(data, default_flow_style=False), encoding="utf-8")
+ return path
+
+
+def _legacy_enriched(tmp_path: Path, enrichment: dict[str, Any]) -> dict[str, Any]:
+ """Run the legacy two-file path: enrich the operator run.yaml on disk."""
+ run_path = _write_yaml(tmp_path / "run.yaml", _OPERATOR_RUN_YAML)
+ out_path = tmp_path / "legacy-enriched.yaml"
+ generate_configuration(str(run_path), str(out_path), enrichment)
+ return yaml.safe_load(out_path.read_text(encoding="utf-8"))
+
+
+def _base_config_dict() -> dict[str, Any]:
+ """Load the base lightspeed-stack.yaml fixture as a fresh dict."""
+ with open(_BASE_CONFIG_PATH, "r", encoding="utf-8") as file:
+ return copy.deepcopy(yaml.safe_load(file))
+
+
+def _load_and_synthesize(
+ tmp_path: Path, lcs_dict: dict[str, Any]
+) -> tuple[dict[str, Any], Path]:
+ """Load a unified config through the real pipeline and synthesize it.
+
+ Mirrors the runtime flow: the config file is validated via
+ ``AppConfig.load_configuration`` (the same entry point the service uses),
+ then — like ``client.AsyncLlamaStackClientHolder`` — the raw operator
+ YAML is re-read and handed to ``synthesize_to_file``.
+
+ Returns the synthesized run.yaml as a dict plus the output file path.
+ """
+ cfg_path = _write_yaml(tmp_path / "lightspeed-stack.yaml", lcs_dict)
+ configuration.load_configuration(str(cfg_path))
+ raw = yaml.safe_load(cfg_path.read_text(encoding="utf-8"))
+ out_path = tmp_path / "synthesized-run.yaml"
+ synthesize_to_file(raw, str(out_path), str(tmp_path))
+ return yaml.safe_load(out_path.read_text(encoding="utf-8")), out_path
+
+
+# ---------------------------------------------------------------------------
+# R7 enrichment parity: unified synthesis vs legacy generate_configuration
+# ---------------------------------------------------------------------------
+
+
+@pytest.mark.parametrize(
+ "enrichment",
+ [
+ pytest.param(_BYOK_INPUTS, id="byok-rag"),
+ pytest.param(_SOLR_INPUTS, id="solr-okp"),
+ pytest.param(_AZURE_INPUTS, id="azure-entra-id"),
+ pytest.param(
+ {**_BYOK_INPUTS, **_SOLR_INPUTS, **_AZURE_INPUTS}, id="all-combined"
+ ),
+ ],
+)
+def test_synthesis_parity_with_legacy_enrichment(
+ tmp_path: Path, enrichment: dict[str, Any]
+) -> None:
+ """Unified synthesis equals legacy enrichment for equivalent inputs (R7).
+
+ The unified equivalent of a legacy (run.yaml + enrichment inputs) setup
+ uses the very same run.yaml as its synthesis profile: both paths then
+ start from identical content and apply the same enrichment.
+ """
+ legacy = _legacy_enriched(tmp_path, enrichment)
+
+ run_path = tmp_path / "run.yaml" # written by _legacy_enriched
+ unified_cfg: dict[str, Any] = {
+ "llama_stack": {
+ "use_as_library_client": True,
+ "config": {"profile": str(run_path)},
+ },
+ **enrichment,
+ }
+ synthesized = synthesize_configuration(unified_cfg, config_file_dir=str(tmp_path))
+
+ assert synthesized == legacy
+
+
+def test_synthesis_parity_holds_through_real_config_load(tmp_path: Path) -> None:
+ """R7 parity holds when the unified config passes the real load pipeline.
+
+ Same comparison as above for the BYOK case, but the unified file is a
+ complete lightspeed-stack.yaml validated by AppConfig.load_configuration
+ and synthesized to disk via synthesize_to_file — the exact runtime flow.
+ """
+ legacy = _legacy_enriched(tmp_path, _BYOK_INPUTS)
+
+ lcs_dict = _base_config_dict()
+ lcs_dict["llama_stack"] = {
+ "use_as_library_client": True,
+ "config": {"profile": "run.yaml"}, # relative to the config file dir
+ }
+ lcs_dict.update(_BYOK_INPUTS)
+ synthesized, _ = _load_and_synthesize(tmp_path, lcs_dict)
+
+ assert synthesized == legacy
+
+
+# ---------------------------------------------------------------------------
+# Baseline selection through the real load + synthesis path
+# ---------------------------------------------------------------------------
+
+
+def test_default_baseline_through_real_load(tmp_path: Path) -> None:
+ """baseline: default synthesizes from the shipped src/data/default_run.yaml."""
+ lcs_dict = _base_config_dict()
+ lcs_dict["llama_stack"] = {
+ "use_as_library_client": True,
+ "config": {"baseline": "default"},
+ }
+ synthesized, _ = _load_and_synthesize(tmp_path, lcs_dict)
+
+ baseline = load_default_baseline()
+ assert synthesized["version"] == baseline["version"]
+ assert set(baseline["apis"]).issubset(set(synthesized["apis"]))
+ mcp_ids = {p["provider_id"] for p in synthesized["providers"]["tool_runtime"]}
+ assert "model-context-protocol" in mcp_ids
+
+
+def test_empty_baseline_with_native_override_through_real_load(
+ tmp_path: Path,
+) -> None:
+ """baseline: empty + native_override reproduces the override exactly (T7)."""
+ lcs_dict = _base_config_dict()
+ lcs_dict["llama_stack"] = {
+ "use_as_library_client": True,
+ "config": {
+ "baseline": "empty",
+ "native_override": copy.deepcopy(_OPERATOR_RUN_YAML),
+ },
+ }
+ synthesized, _ = _load_and_synthesize(tmp_path, lcs_dict)
+
+ assert synthesized == _OPERATOR_RUN_YAML
+
+
+def test_profile_baseline_through_real_load_gets_mcp_ensured(
+ tmp_path: Path,
+) -> None:
+ """A profile baseline is loaded from disk and MCP tool_runtime is ensured."""
+ profile = {
+ "version": 2,
+ "apis": ["inference"],
+ "marker": "from-profile",
+ }
+ _write_yaml(tmp_path / "my-profile.yaml", profile)
+
+ lcs_dict = _base_config_dict()
+ lcs_dict["llama_stack"] = {
+ "use_as_library_client": True,
+ "config": {"profile": "my-profile.yaml"},
+ }
+ synthesized, _ = _load_and_synthesize(tmp_path, lcs_dict)
+
+ assert synthesized["marker"] == "from-profile"
+ # ensure_mcp_tool_runtime ran (profile baselines are not "empty")
+ assert "tool_runtime" in synthesized["apis"]
+ mcp_ids = {p["provider_id"] for p in synthesized["providers"]["tool_runtime"]}
+ assert "model-context-protocol" in mcp_ids
+
+
+def test_native_override_deep_merge_through_real_load(tmp_path: Path) -> None:
+ """native_override merges over the profile: scalars win, lists replace."""
+ profile = {
+ "version": 2,
+ "apis": ["inference", "tool_runtime"],
+ "providers": {
+ "inference": [{"provider_id": "old", "provider_type": "remote::openai"}],
+ "tool_runtime": [
+ {
+ "provider_id": "model-context-protocol",
+ "provider_type": "remote::model-context-protocol",
+ "config": {},
+ }
+ ],
+ },
+ "safety": {"default_shield_id": "guard", "excluded_categories": []},
+ }
+ _write_yaml(tmp_path / "my-profile.yaml", profile)
+
+ lcs_dict = _base_config_dict()
+ lcs_dict["llama_stack"] = {
+ "use_as_library_client": True,
+ "config": {
+ "profile": "my-profile.yaml",
+ "native_override": {
+ "providers": {
+ "inference": [
+ {"provider_id": "new", "provider_type": "remote::vllm"}
+ ]
+ },
+ "safety": {"default_shield_id": "other-guard"},
+ "added_key": "added-value",
+ },
+ },
+ }
+ synthesized, _ = _load_and_synthesize(tmp_path, lcs_dict)
+
+ # list replaced wholesale (deep_merge_list_replace semantics, R5)
+ assert synthesized["providers"]["inference"] == [
+ {"provider_id": "new", "provider_type": "remote::vllm"}
+ ]
+ # sibling dict keys merge: overridden scalar wins, untouched one survives
+ assert synthesized["safety"]["default_shield_id"] == "other-guard"
+ assert synthesized["safety"]["excluded_categories"] == []
+ # brand-new top-level key added
+ assert synthesized["added_key"] == "added-value"
+ # untouched profile content survives
+ assert synthesized["version"] == 2
+
+
+def test_synthesized_file_written_owner_only(tmp_path: Path) -> None:
+ """The synthesized run.yaml lands on disk with mode 0600 (R10)."""
+ lcs_dict = _base_config_dict()
+ lcs_dict["llama_stack"] = {
+ "use_as_library_client": True,
+ "config": {"baseline": "empty", "native_override": {"version": 2}},
+ }
+ _, out_path = _load_and_synthesize(tmp_path, lcs_dict)
+
+ assert stat.S_IMODE(os.stat(out_path).st_mode) == 0o600
+
+
+# ---------------------------------------------------------------------------
+# Migrate-then-synthesize parity (LCORE-2337 migration tool)
+# ---------------------------------------------------------------------------
+
+
+def _migrate_then_synthesize(
+ tmp_path: Path, run_yaml: dict[str, Any], enrichment: dict[str, Any]
+) -> tuple[dict[str, Any], dict[str, Any]]:
+ """Enrich a legacy pair both ways: directly, and after --migrate-config.
+
+ Returns (legacy_enriched, migrated_synthesized) for comparison.
+ """
+ run_path = _write_yaml(tmp_path / "run.yaml", run_yaml)
+ lcs_dict = _base_config_dict()
+ lcs_dict["llama_stack"] = {
+ "use_as_library_client": True,
+ "library_client_config_path": str(run_path),
+ }
+ lcs_dict.update(enrichment)
+ lcs_path = _write_yaml(tmp_path / "lightspeed-stack.yaml", lcs_dict)
+
+ legacy_out = tmp_path / "legacy-enriched.yaml"
+ generate_configuration(str(run_path), str(legacy_out), lcs_dict)
+ legacy = yaml.safe_load(legacy_out.read_text(encoding="utf-8"))
+
+ unified_path = tmp_path / "unified.yaml"
+ migrate_config_dumb(str(run_path), str(lcs_path), str(unified_path))
+ # the migrated file must load through the real validation pipeline
+ configuration.load_configuration(str(unified_path))
+ migrated_raw = yaml.safe_load(unified_path.read_text(encoding="utf-8"))
+ synthesized = synthesize_configuration(migrated_raw, config_file_dir=str(tmp_path))
+ return legacy, synthesized
+
+
+def test_migrate_then_synthesize_round_trip_without_enrichment(
+ tmp_path: Path,
+) -> None:
+ """Migrating a pair with no enrichment inputs reproduces run.yaml (T7)."""
+ legacy, synthesized = _migrate_then_synthesize(tmp_path, _OPERATOR_RUN_YAML, {})
+ assert synthesized == _OPERATOR_RUN_YAML
+ assert legacy == synthesized
+
+
+@pytest.mark.xfail(
+ strict=True,
+ reason="Known defect (LCORE-3370): dumb migration lifts run.yaml "
+ "into native_override, which deep-merges after enrichment and replaces "
+ "lists wholesale (R5) — so BYOK/Solr vector_io providers, registered "
+ "embedding models, and the Azure model_validation enrichment are lost "
+ "whenever the original run.yaml already carried those list sections. "
+ "Contradicts migrate_config_dumb's enrichment-keeps-working promise.",
+)
+def test_migrate_then_synthesize_preserves_enrichment_parity(
+ tmp_path: Path,
+) -> None:
+ """A migrated config still enriches like legacy mode did (R7 after R4).
+
+ migrate_config_dumb keeps byok_rag/rag/okp/azure_entra_id untouched, so
+ synthesizing the migrated config must yield the same result the legacy
+ path produced for the original pair.
+ """
+ enrichment = {**_BYOK_INPUTS, **_SOLR_INPUTS, **_AZURE_INPUTS}
+ legacy, synthesized = _migrate_then_synthesize(
+ tmp_path, _OPERATOR_RUN_YAML, enrichment
+ )
+ assert synthesized == legacy
+
+
+# ---------------------------------------------------------------------------
+# Mode detection via the real config load
+# ---------------------------------------------------------------------------
+
+
+def test_load_rejects_config_block_and_legacy_path_together(
+ tmp_path: Path,
+) -> None:
+ """A llama_stack.config block plus a legacy path fails the real load (R3)."""
+ lcs_dict = _base_config_dict()
+ lcs_dict["llama_stack"] = {
+ "use_as_library_client": True,
+ "library_client_config_path": "tests/configuration/run.yaml",
+ "config": {"baseline": "default"},
+ }
+ cfg_path = _write_yaml(tmp_path / "lightspeed-stack.yaml", lcs_dict)
+ with pytest.raises(ValidationError, match="--migrate-config"):
+ configuration.load_configuration(str(cfg_path))
+
+
+def test_load_rejects_inference_providers_and_legacy_path_together(
+ tmp_path: Path,
+) -> None:
+ """Top-level inference.providers plus a legacy path fails the real load."""
+ lcs_dict = _base_config_dict()
+ lcs_dict["llama_stack"] = {
+ "use_as_library_client": True,
+ "library_client_config_path": "tests/configuration/run.yaml",
+ }
+ lcs_dict["inference"] = {
+ "providers": [{"type": "openai", "api_key_env": "OPENAI_API_KEY"}]
+ }
+ cfg_path = _write_yaml(tmp_path / "lightspeed-stack.yaml", lcs_dict)
+ with pytest.raises(ValidationError, match="mutually exclusive"):
+ configuration.load_configuration(str(cfg_path))
+
+
+def test_load_rejects_library_mode_without_run_source(tmp_path: Path) -> None:
+ """Library mode with neither synthesis input nor legacy path fails."""
+ lcs_dict = _base_config_dict()
+ lcs_dict["llama_stack"] = {"use_as_library_client": True}
+ cfg_path = _write_yaml(tmp_path / "lightspeed-stack.yaml", lcs_dict)
+ with pytest.raises(ValidationError, match="requires a run-configuration source"):
+ configuration.load_configuration(str(cfg_path))
+
+
+def test_load_accepts_minimal_unified_config(tmp_path: Path) -> None:
+ """A minimal unified config (inference.providers only) loads cleanly."""
+ lcs_dict = _base_config_dict()
+ lcs_dict["llama_stack"] = {"use_as_library_client": True}
+ lcs_dict["inference"] = {
+ "providers": [{"type": "openai", "api_key_env": "OPENAI_API_KEY"}]
+ }
+ cfg_path = _write_yaml(tmp_path / "lightspeed-stack.yaml", lcs_dict)
+ configuration.load_configuration(str(cfg_path))
+
+ loaded = configuration.configuration
+ assert loaded.llama_stack.config is None
+ assert loaded.inference.providers[0].type == "openai"
From 20da845ed9605d974e831745c9296aa4b8aac0f3 Mon Sep 17 00:00:00 2001
From: Anik Bhattacharjee
Date: Mon, 3 Aug 2026 11:55:20 -0400
Subject: [PATCH 014/197] LCORE-1801: Fix hardcoded Python version in Makefile
run-stack target
Fixed hardcoded python3.12 reference in Makefile
---
Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index 6220d63d2..963e05e22 100644
--- a/Makefile
+++ b/Makefile
@@ -37,9 +37,9 @@ CONTAINER_RUNTIME ?= $(shell command -v podman 2>/dev/null || command -v docker
run-stack: ## Run lightspeed-stack directly, without building dependent service/s
@if [ "$${OTEL_SDK_DISABLED:-true}" = "false" ]; then \
- uv run opentelemetry-instrument python3.12 src/lightspeed_stack.py -c $(CONFIG); \
+ uv run opentelemetry-instrument python src/lightspeed_stack.py -c $(CONFIG); \
else \
- uv run python3.12 src/lightspeed_stack.py -c $(CONFIG); \
+ uv run python src/lightspeed_stack.py -c $(CONFIG); \
fi
run: start-llama-stack-container ## Run the service locally with dependent services
From 872448c3556444fa03f5fd42b0008cb9a9a43f33 Mon Sep 17 00:00:00 2001
From: Andrej Simurka
Date: Mon, 3 Aug 2026 12:45:39 +0200
Subject: [PATCH 015/197] Removed watsonX workaround
---
.github/workflows/e2e_tests_providers.yaml | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/.github/workflows/e2e_tests_providers.yaml b/.github/workflows/e2e_tests_providers.yaml
index 267a8f414..c18935252 100644
--- a/.github/workflows/e2e_tests_providers.yaml
+++ b/.github/workflows/e2e_tests_providers.yaml
@@ -29,7 +29,7 @@ jobs:
e2e_default_model: google/gemini-2.5-flash
e2e_default_provider: google-vertex
- environment: watsonx
- e2e_default_model: watsonx/meta-llama/llama-3-3-70b-instruct
+ e2e_default_model: meta-llama/llama-3-3-70b-instruct
e2e_default_provider: watsonx
- environment: bedrock
e2e_default_model: deepseek.v3-v1:0
@@ -330,10 +330,6 @@ jobs:
if: matrix.environment == 'watsonx' && matrix.mode == 'server'
run: sleep 3600 # 120 minutes
- - name: Remove the prefix for watsonx default model
- if: matrix.environment == 'watsonx'
- run: echo "E2E_DEFAULT_MODEL_OVERRIDE=meta-llama/llama-3-3-70b-instruct" >> $GITHUB_ENV
-
- name: Run e2e tests
env:
TERM: xterm-256color
From 86272d92996d332b4795f9b78f4b7414dc3b5c75 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Tue, 4 Aug 2026 09:17:21 +0200
Subject: [PATCH 016/197] LCORE-2922: Updated dependencies
---
uv.lock | 108 ++++++++++++++++++++++++++++----------------------------
1 file changed, 54 insertions(+), 54 deletions(-)
diff --git a/uv.lock b/uv.lock
index 17e814fcd..3432c559a 100644
--- a/uv.lock
+++ b/uv.lock
@@ -460,39 +460,39 @@ wheels = [
[[package]]
name = "cffi"
-version = "2.1.0"
+version = "2.1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pycparser", marker = "implementation_name != 'PyPy'" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/57/5f/ff100cae70ebe9d8df1c01a00e510e45d9adb5c1fdda84791b199141de97/cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9", size = 531036, upload-time = "2026-07-06T21:34:30.382Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/1e/85/990925db5df586ec90beb97529c853497e7f85ba0234830447faf41c3057/cffi-2.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f", size = 184829, upload-time = "2026-07-06T21:32:44.324Z" },
- { url = "https://files.pythonhosted.org/packages/4b/92/e7bb136ad6b5352603732cf907ef862ca103f20f2031c1735a46300c20c9/cffi-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde", size = 184728, upload-time = "2026-07-06T21:32:45.683Z" },
- { url = "https://files.pythonhosted.org/packages/c3/c0/d1ec30ffb370f748f2fb54425972bfef9871e0132e82fb589c46b6676049/cffi-2.1.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d", size = 214815, upload-time = "2026-07-06T21:32:48.557Z" },
- { url = "https://files.pythonhosted.org/packages/1b/dc/5620cf930688be01f2d673804291de757a934c90b946dbdc3d84130c2ea4/cffi-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7", size = 222429, upload-time = "2026-07-06T21:32:49.848Z" },
- { url = "https://files.pythonhosted.org/packages/4b/a4/77b53abbf7a1e0beb9637edbef2a94d15f9c822f591e85d439ffd91519a6/cffi-2.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b", size = 210315, upload-time = "2026-07-06T21:32:51.221Z" },
- { url = "https://files.pythonhosted.org/packages/58/0c/f528df19cc94b675087324d4760d9e6d5bfae97d6217aa4fac43de4f5fcc/cffi-2.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7", size = 208859, upload-time = "2026-07-06T21:32:52.512Z" },
- { url = "https://files.pythonhosted.org/packages/62/f2/c9522a81c32132799a1972c39f5c5f8b4c8b9f00488a23feaa6c06f07741/cffi-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66", size = 221844, upload-time = "2026-07-06T21:32:53.704Z" },
- { url = "https://files.pythonhosted.org/packages/6e/28/bd53988b9833e8f8ad539d26f4c07a6b3f6bcb1e9e02e7ca038250b3428d/cffi-2.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe", size = 225287, upload-time = "2026-07-06T21:32:54.907Z" },
- { url = "https://files.pythonhosted.org/packages/79/99/0d0fd37f055224085f42bbb2c022d002e17dde4a97972822327b07d84101/cffi-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b", size = 223681, upload-time = "2026-07-06T21:32:56.329Z" },
- { url = "https://files.pythonhosted.org/packages/b0/80/c138990aa2a70b1a269f6e06348729836d733d6f970867943f61d367f8cc/cffi-2.1.0-cp312-cp312-win32.whl", hash = "sha256:9b8f0f26ca4e7513c534d351eca551947d053fac438f2a04ac96d882909b0d3a", size = 175269, upload-time = "2026-07-06T21:32:57.777Z" },
- { url = "https://files.pythonhosted.org/packages/a8/eb/f636456ff21a83fc13c032b58cc5dde061691546ac79efa284b2989b7982/cffi-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97f080ea627e2863524c5af3836e2270b5f5dfff1f104392b959f8df0c5d384", size = 185881, upload-time = "2026-07-06T21:32:59.253Z" },
- { url = "https://files.pythonhosted.org/packages/dd/2c/400ea43e721727dca8a65c4521390e9196757caba4a45643acb2b63271b8/cffi-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:6d194185eabd279f1c05ebe3504265ddfc5ad2b58d0714f7db9f01da592e9eb6", size = 180088, upload-time = "2026-07-06T21:33:02.278Z" },
- { url = "https://files.pythonhosted.org/packages/96/88/a996879e2eeccb815f6e3a5967b12a308257412acec882039d386bd2aa7b/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:10537b1df4967ca26d21e5072d7d54188354483b91dc75058968d3f0cf13fbda", size = 194331, upload-time = "2026-07-06T21:33:03.697Z" },
- { url = "https://files.pythonhosted.org/packages/58/85/7ae00d5c8dd6266f4e944c3db630f3c5c9a98b61d469c714d848b1d8138a/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a95b05f9baf29b91171b3a8bd2020b028835243e7b0ff6bb23e2a3c228518b1b", size = 196966, upload-time = "2026-07-06T21:33:05.353Z" },
- { url = "https://files.pythonhosted.org/packages/8c/e9/45c3a76ad8d43ad9261f4c95436da61128d3ca545d72b9612c0ab5be0b1c/cffi-2.1.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:15faec4adfff450819f3aee0e2e02c812de6edb88203aa58807955db2003472a", size = 184795, upload-time = "2026-07-06T21:33:06.699Z" },
- { url = "https://files.pythonhosted.org/packages/84/4c/82f132cb4418ee6d953d982b19191e87e2a6372c8a4ce36e50b69d6ade4a/cffi-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:716ff8ec22f20b4d988b12884086bcef0fc99737043e503f7a3935a6be99b1ea", size = 184746, upload-time = "2026-07-06T21:33:08.071Z" },
- { url = "https://files.pythonhosted.org/packages/a0/1c/4ed5a0e5bdca6cbc275556de3328dd1b76fd0c11cc13c88fe66d1d8715f2/cffi-2.1.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:63960549e4f8dc41e31accb97b975abaecfc44c03e396c093a6436763c2ea7db", size = 214747, upload-time = "2026-07-06T21:33:09.671Z" },
- { url = "https://files.pythonhosted.org/packages/3a/a6/e879bb68cc23a2bc9ba8f4b7d8019f0c2694bad2ab6c4a3701d429439f58/cffi-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f", size = 222392, upload-time = "2026-07-06T21:33:10.896Z" },
- { url = "https://files.pythonhosted.org/packages/88/f6/01890cfd63c08f8eb96a8319b0443690197d240a8bd6346048cf7bde9190/cffi-2.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3b926723c13eba9f81d2ef3820d63aeceec3b2d4639906047bf675cb8a7a500d", size = 210285, upload-time = "2026-07-06T21:33:12.251Z" },
- { url = "https://files.pythonhosted.org/packages/a6/cf/2b684132056f438567b61e19d690dd31cd0921ace051e0a458be6074369e/cffi-2.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:47ff3a8bfd8cb9da1af7524b965127095055654c177fcfc7578debcb015eecd0", size = 208801, upload-time = "2026-07-06T21:33:13.617Z" },
- { url = "https://files.pythonhosted.org/packages/6f/08/f2e7d62c460faae0926f2d6e423694aa409ced3bc1fe2927a0a6e5f05416/cffi-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:799416bae98336e400981ff6e532d67d5c709cfb30afb79865a1315f94b0e224", size = 221808, upload-time = "2026-07-06T21:33:15.466Z" },
- { url = "https://files.pythonhosted.org/packages/38/37/04f54b8e63a02f3d908332c9effbf8c366167c6f733ed8a3d4f79b7e2a1e/cffi-2.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:961be50688f7fba2fa65f63712d3b9b341a22311f5253460ce933f52f0de1c8c", size = 225241, upload-time = "2026-07-06T21:33:16.869Z" },
- { url = "https://files.pythonhosted.org/packages/a9/d6/c72eecca433cd3e681c65ed313ab4835d9d4a379704d0f628a6a05f51c2e/cffi-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf5c6cf48238b0eb4c086978c492ad1cbc22373fc5b2d7353b3a598ce6db887a", size = 223588, upload-time = "2026-07-06T21:33:18.239Z" },
- { url = "https://files.pythonhosted.org/packages/c6/4b/e706f67279140f92939da3475ad610df18bfd52d50f14953a8e5fede71d5/cffi-2.1.0-cp313-cp313-win32.whl", hash = "sha256:db3eb7d46527159a878ec3460e9d40615bc25ba337d477db681aea6e4f05c5d2", size = 175248, upload-time = "2026-07-06T21:33:19.799Z" },
- { url = "https://files.pythonhosted.org/packages/5a/47/59eb7975cb0e4ef0afa764ea945b29a5bb4537a9f771cb7d6c8a5dd74c95/cffi-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:8e74a6135550c4748af665b1b1118b6aab33b1fc6a16f9aff630af107c3b4512", size = 185717, upload-time = "2026-07-06T21:33:21.47Z" },
- { url = "https://files.pythonhosted.org/packages/5a/af/34fee85c48f8d94efc8597bc09470c9dd274c145f1c12e0fbc6ab6d38d74/cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f", size = 180114, upload-time = "2026-07-06T21:33:22.515Z" },
+sdist = { url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be", size = 530807, upload-time = "2026-08-03T21:21:18.939Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/10/69/43965eccfdead3b9220015fd1320e117be8c6ed01a62ffab76eeb752f5d5/cffi-2.1.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0", size = 184821, upload-time = "2026-08-03T21:19:44.887Z" },
+ { url = "https://files.pythonhosted.org/packages/54/7d/16e5a096677b5e313ca80cd5e5170efa3ea44624a82bb111925522da64b1/cffi-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf", size = 184719, upload-time = "2026-08-03T21:19:46.129Z" },
+ { url = "https://files.pythonhosted.org/packages/56/e6/8941622732edec876dd17d0453dce07317ae96db34f2ec1436c9d3785986/cffi-2.1.1-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a", size = 214799, upload-time = "2026-08-03T21:19:47.218Z" },
+ { url = "https://files.pythonhosted.org/packages/44/de/f98430906df1545ffde0d543dd124a7a439bc2cd32b36b9c53f805df7333/cffi-2.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890", size = 222389, upload-time = "2026-08-03T21:19:48.331Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/5b/717f1526b9957b34456313c31645c5b82b8fb5c3fe9e4752999be7128bfc/cffi-2.1.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50", size = 210249, upload-time = "2026-08-03T21:19:49.543Z" },
+ { url = "https://files.pythonhosted.org/packages/64/b3/f8aa4f3e34986c7e4ec45072d1b1b9dd295b6b18007b45518d79726dd725/cffi-2.1.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e", size = 208775, upload-time = "2026-08-03T21:19:50.918Z" },
+ { url = "https://files.pythonhosted.org/packages/b1/db/dceb9dd5b231e1da801793f8acc9f3c52a7e1afe40bb1aae37e02b0faad5/cffi-2.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf", size = 221822, upload-time = "2026-08-03T21:19:52.054Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/d2/6cd24ae3be000a634109c247d1475d62e5616d0dc78c82770942ec384248/cffi-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517", size = 225232, upload-time = "2026-08-03T21:19:53.109Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/52/3fa190537004dd7f0ab860a6dc7c0175b8667f68d1e618a46f5498d30250/cffi-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735", size = 223597, upload-time = "2026-08-03T21:19:54.515Z" },
+ { url = "https://files.pythonhosted.org/packages/80/fb/0bb75b7039588c074b37ae99f40d9bfddf990ecb2fbc346ebccd2e56b9be/cffi-2.1.1-cp312-cp312-win32.whl", hash = "sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e", size = 175292, upload-time = "2026-08-03T21:19:55.566Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/79/615cc094e2fb508cade7de88d3b4f6c4ec2bab695c97bce9153dc65aadf5/cffi-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a", size = 185919, upload-time = "2026-08-03T21:19:56.89Z" },
+ { url = "https://files.pythonhosted.org/packages/70/c6/d0ea84713fe46b243a436a18fcd47d639732747e21635c8a27191b06dc30/cffi-2.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80", size = 180093, upload-time = "2026-08-03T21:19:58.155Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/f4/035513d4117049066b4779dc3b7c0c0fdad175fa13731c9f4003f1cd1478/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e", size = 194248, upload-time = "2026-08-03T21:19:59.399Z" },
+ { url = "https://files.pythonhosted.org/packages/76/af/2aeb4dbb5fc41a04161ae9ff1518de7cec08e164f44a8ce6a4cf7fd2cd1d/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c", size = 196908, upload-time = "2026-08-03T21:20:00.746Z" },
+ { url = "https://files.pythonhosted.org/packages/a7/46/2e5fdde8555706dd98139a910ca11be02809f3f605ce956f655d0214e100/cffi-2.1.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6", size = 184805, upload-time = "2026-08-03T21:20:02.02Z" },
+ { url = "https://files.pythonhosted.org/packages/55/41/4c7042f317b9217502988f0873af87e16ad606dc20f84e546e3e6ce9764c/cffi-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971", size = 184764, upload-time = "2026-08-03T21:20:03.141Z" },
+ { url = "https://files.pythonhosted.org/packages/43/1f/1c3d90d91811c8f86ced9ed637956c54bfe5b79ca98fe976d7f8c8979f6b/cffi-2.1.1-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c", size = 214722, upload-time = "2026-08-03T21:20:04.377Z" },
+ { url = "https://files.pythonhosted.org/packages/37/6f/3b5ce4c3b2192d250f04908f2bfd91ef34552ec8f7716a5d4abdb8d67bb2/cffi-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125", size = 222369, upload-time = "2026-08-03T21:20:05.544Z" },
+ { url = "https://files.pythonhosted.org/packages/02/10/4b3c75dde3d9663c9e02ba05c2668b954f671d4bbe346413ca8c696b295a/cffi-2.1.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264", size = 210175, upload-time = "2026-08-03T21:20:06.75Z" },
+ { url = "https://files.pythonhosted.org/packages/df/62/14f74b9543e605d17701dc797b815958b8bb70b7624ce1b832ddad48ed6c/cffi-2.1.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3", size = 208670, upload-time = "2026-08-03T21:20:08.04Z" },
+ { url = "https://files.pythonhosted.org/packages/95/95/86342356ff5953b3fb06f7ef7c5bee212d45e770abc7218d451b9148313c/cffi-2.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2", size = 221824, upload-time = "2026-08-03T21:20:09.274Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/ff/7b3429ff53aafe931ed8a5fc69f481bbef7ba6de87ddcbb63d08f483f613/cffi-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b", size = 225148, upload-time = "2026-08-03T21:20:10.7Z" },
+ { url = "https://files.pythonhosted.org/packages/34/34/a95870b9221e09cf4f2ce3178b1a210abdfe63a1bd357da940418d7b8d15/cffi-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7", size = 223564, upload-time = "2026-08-03T21:20:12.165Z" },
+ { url = "https://files.pythonhosted.org/packages/70/ea/839b50531021a647fb5e929f72cf97bc1ff702b5472166164b5b6e76b851/cffi-2.1.1-cp313-cp313-win32.whl", hash = "sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac", size = 175263, upload-time = "2026-08-03T21:20:13.559Z" },
+ { url = "https://files.pythonhosted.org/packages/60/a6/8b149b2c3f2e11aaa1618ef64500b45f50f22c57a977a4dff1aff1f91042/cffi-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d", size = 185688, upload-time = "2026-08-03T21:20:14.69Z" },
+ { url = "https://files.pythonhosted.org/packages/01/9a/11f687cb39d6a3504060d5242f04f48c735afb4d3d533958a20594890cb2/cffi-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973", size = 180078, upload-time = "2026-08-03T21:20:15.917Z" },
]
[[package]]
@@ -817,21 +817,21 @@ wheels = [
[[package]]
name = "faiss-cpu"
-version = "1.14.3"
+version = "1.15.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "numpy" },
{ name = "packaging" },
]
wheels = [
- { url = "https://files.pythonhosted.org/packages/83/b0/48c083d01b7b68c463c1d56507147a9d733f791e1c469a77215a872a9fb5/faiss_cpu-1.14.3-cp310-abi3-macosx_14_0_arm64.whl", hash = "sha256:a9369863290a3f0e033757e4c10577b6ef7431f1cede394dabd0a137e4e2ed45", size = 4768290, upload-time = "2026-06-13T02:19:03.427Z" },
- { url = "https://files.pythonhosted.org/packages/ab/34/6b04ef5bae3eada6b5a9457d7875cce041c040d53c890815cbd1e9821c65/faiss_cpu-1.14.3-cp310-abi3-macosx_15_0_x86_64.whl", hash = "sha256:f9d0e84d909194f63f027bbd3c1e35e905e48c9345c2db6e6f24da09a6bc5906", size = 6925734, upload-time = "2026-06-13T02:19:05.232Z" },
- { url = "https://files.pythonhosted.org/packages/7c/8a/b451af4b3c6dd18749ecfb58ccb68503b77e49c9aa4a89d950e9d521e058/faiss_cpu-1.14.3-cp310-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d734cfa9ac90b6a5dfed3a27cb706d05f22824703dafc3969b4e2071877a31c", size = 9661210, upload-time = "2026-06-13T02:19:06.99Z" },
- { url = "https://files.pythonhosted.org/packages/a0/ed/57335bc18c9e18677587bec9bf070c675b29c8e683e13f4def0440731ca0/faiss_cpu-1.14.3-cp310-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8780b526c06e57aad90a8c4655dfba2ff1b3195bd600ff4499752fc45159c9fc", size = 18506292, upload-time = "2026-06-13T02:19:09.621Z" },
- { url = "https://files.pythonhosted.org/packages/e7/d3/c6ca8c44a63b909e78aa8a69e14501c79c89613e62261d58455ea603d710/faiss_cpu-1.14.3-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b28ba083e8c02f2c9be03783402537fd3f00d27e68799c44bf88931500ee12ec", size = 11238800, upload-time = "2026-06-13T02:19:12.821Z" },
- { url = "https://files.pythonhosted.org/packages/93/5f/b405692913a301251749cb175cb3f564ed257fdaa80a22c9a36444d0095d/faiss_cpu-1.14.3-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cdcb90850cb4b7c27d270839b37bcc0dc8d1fb6a62d1e13053e51ac95061ca25", size = 19237637, upload-time = "2026-06-13T02:19:15.531Z" },
- { url = "https://files.pythonhosted.org/packages/59/aa/bfa53255a6aa6e79b2471bb5af895f662feb02b612e1e0f9efc3d893286e/faiss_cpu-1.14.3-cp312-cp312-win_amd64.whl", hash = "sha256:0a5eb27184123c7ac1060c6b862978eabf0e30c1369ccf8bdb1497d35c06ad3d", size = 16164699, upload-time = "2026-06-13T02:19:22.969Z" },
- { url = "https://files.pythonhosted.org/packages/1d/c1/2fb14f58ff74d7a7d6fd13084c016d9b144ce0bcdf77f6526cc2e4828278/faiss_cpu-1.14.3-cp313-cp313-win_amd64.whl", hash = "sha256:ea2340f675db59af8db6da4535b541ce6948d68a008989c656c292c7b0c77127", size = 16162836, upload-time = "2026-06-13T02:19:25.529Z" },
+ { url = "https://files.pythonhosted.org/packages/59/68/20e91694ad9a8b2bb48af956899e52b645cb1501e7e2ec31cb733da4d4c5/faiss_cpu-1.15.0-cp310-abi3-macosx_14_0_arm64.whl", hash = "sha256:50ea471ef1f4f3580eda8ab0ec9727d4bf65fd71c444bf306ce7cdbba8a42b21", size = 4904897, upload-time = "2026-08-03T17:49:37.003Z" },
+ { url = "https://files.pythonhosted.org/packages/d2/cd/ef4cf498977c4a84af7a8920bc97ca49fc19060c8464c63fab58847b4692/faiss_cpu-1.15.0-cp310-abi3-macosx_15_0_x86_64.whl", hash = "sha256:dd383bb1ce06fabcff5785f998f253aa88f88dcbe1fe36c922417cd6666dd896", size = 7087977, upload-time = "2026-08-03T17:49:38.947Z" },
+ { url = "https://files.pythonhosted.org/packages/94/c8/88b072bf55714405d0d7e11c12349510f15a69ae56033b1cd894fb2be7d6/faiss_cpu-1.15.0-cp310-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d0a2d5d33fe023e263d0d355a837f20db67578e3be27fc5f4012a273274abf6", size = 9835009, upload-time = "2026-08-03T17:49:40.8Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/3b/8878dbfc78a0084bbd408b34827a58b530be98132fcf620b7e15f9191614/faiss_cpu-1.15.0-cp310-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ec9b29aae29e428c085c2d49dbb02e4673cdea75db418d420f9e60e0b4184498", size = 18764625, upload-time = "2026-08-03T17:49:43.676Z" },
+ { url = "https://files.pythonhosted.org/packages/db/2a/654116e6ee2808562a6b2a11c396bdb46d45689e3bf7206ee99400589cab/faiss_cpu-1.15.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:30da3029952f0de69f16ce31946fd63fc3e292c867749bbcd2c0a0f09fd06f65", size = 11413863, upload-time = "2026-08-03T17:49:46.471Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/8c/0a0f09659c1972aa83b9820cd3dd7f68f6678cfcfebde542e1c23d7d8663/faiss_cpu-1.15.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:88fbe1acac6978869063cb2f9477f85718da596a6e0a17751618f9c756bce255", size = 19470092, upload-time = "2026-08-03T17:49:50.253Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/76/021398ec5608314124b554bb025878a86f129bcf3576c293826352d9a783/faiss_cpu-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:5b940897b317febaa761088513a3db164fad3ac71a5e1ed7be9a052c9bf1a447", size = 16251530, upload-time = "2026-08-03T17:50:00.166Z" },
+ { url = "https://files.pythonhosted.org/packages/96/74/4a70395a6e07036628a1bd0b3f709101a6aecfa6a746db13b6e7921cf291/faiss_cpu-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:22dddb013e764aad66dac6cd15b49c7598d60339e0591b73b5e081629419c21b", size = 16251914, upload-time = "2026-08-03T17:50:03.293Z" },
]
[[package]]
@@ -1320,18 +1320,18 @@ wheels = [
[[package]]
name = "hf-xet"
-version = "1.5.2"
+version = "1.6.0"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/63/39/67be8d71f900d9a55761b6022821d6679fb56c64f1b6063d5af2c2606727/hf_xet-1.5.2.tar.gz", hash = "sha256:73044bd31bae33c984af832d19c752a0dffb67518fee9ddbd91d616e1101cf47", size = 903674, upload-time = "2026-07-16T17:29:56.833Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/1b/ab/522a2ab67f27971a9d48ca666d4fca85ef7d5282d142e31fd087e27b1bbe/hf_xet-1.6.0.tar.gz", hash = "sha256:2e58454a340b3556dfa4972d5451aff4fba8dd42a236600ba1a1d2b1514f0fef", size = 920527, upload-time = "2026-08-03T22:33:13.243Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/de/ba/2b70603c7552db82baeb2623e2336898304a17328845151be4fe1f48d420/hf_xet-1.5.2-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:f922b8f5fb84f1dd3d7ab7a1316354a1bca9b1c73ecfc19c76e51a2a49d29799", size = 4033760, upload-time = "2026-07-16T17:29:43.884Z" },
- { url = "https://files.pythonhosted.org/packages/60/ac/b097a86a1e4a6098f3a79382643ab09d5733d87ccc864877ad1e12b49b70/hf_xet-1.5.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:045f84440c55cdeb659cf1a1dd48c77bcd0d2e93632e2fea8f2c3bdee79f38ed", size = 3841438, upload-time = "2026-07-16T17:29:45.539Z" },
- { url = "https://files.pythonhosted.org/packages/d3/35/db860aa3a0780660324a506ad4b3d322ddc6ecbba4b9340aed0942cbf21c/hf_xet-1.5.2-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:db78c39c83d6279daddc98e2238f373ab8980685556d42472b4ec51abcf03e8c", size = 4428006, upload-time = "2026-07-16T17:29:46.996Z" },
- { url = "https://files.pythonhosted.org/packages/af/6b/832dd980af4b0c3ae0660e309285f2ffcdff2faa38129390dbb47aa4a3f9/hf_xet-1.5.2-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7db73c810500c54c6760be8c39d4b2e476974de85424c50063efc22fdda13025", size = 4221099, upload-time = "2026-07-16T17:29:48.525Z" },
- { url = "https://files.pythonhosted.org/packages/9e/05/ae50f0d34e3254e6c3e208beb2519f6b8673016fc4b3643badaf6450d186/hf_xet-1.5.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6395cfe3c9cbead4f16b31808b0e67eac428b66c656f856e99636adaddea878f", size = 4420766, upload-time = "2026-07-16T17:29:50.092Z" },
- { url = "https://files.pythonhosted.org/packages/07/a9/c050bc2743a2bcd68928bfee157b08681667a164a24ec95fbfcfcd717e08/hf_xet-1.5.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cde8cd167126bb6109b2ceb19b844433a4988643e8f3e01dd9dd0e4a34535097", size = 4636716, upload-time = "2026-07-16T17:29:51.62Z" },
- { url = "https://files.pythonhosted.org/packages/e9/f8/68b01c5c2edb56ac9a67b3d076ffddcb90867abaee923923eb34e7a14e76/hf_xet-1.5.2-cp38-abi3-win_amd64.whl", hash = "sha256:ecf63d1cb69a9a7319910f8f83fcf9b46e7a32dfcf4b8f8eeddb55f647306e65", size = 3988373, upload-time = "2026-07-16T17:29:53.395Z" },
- { url = "https://files.pythonhosted.org/packages/39/c6/988383e9dc17294d536fcbcd6fd16eed882e411ad16c954984a53e47b09c/hf_xet-1.5.2-cp38-abi3-win_arm64.whl", hash = "sha256:1da28519496eb7c8094c11e4d25509b4a468457a0302d58136099db2fd9a671d", size = 3816957, upload-time = "2026-07-16T17:29:54.991Z" },
+ { url = "https://files.pythonhosted.org/packages/a2/50/7afa2c9c787405864fc47a0d1bbc02c62e9101947ed43c1f43899fc7d91d/hf_xet-1.6.0-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:633dc0cd71d32da58ab8c03ad38e2fac452c15c2b0a2866ebf6ededfe0a5061d", size = 4071729, upload-time = "2026-08-03T22:33:00.721Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/69/55b8dcf636142ae660fec1869fcac14c4da2e8412e14d6eee1523be77e9f/hf_xet-1.6.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:f0906082d9932ae0c0057fa194041c22b4e2cdb46b2592ef3b91f020d62a081a", size = 3876287, upload-time = "2026-08-03T22:33:02.251Z" },
+ { url = "https://files.pythonhosted.org/packages/67/4e/a28359bf1c1ecf11eba22123168c138698f7cb576ac678f5a2e16cd5da08/hf_xet-1.6.0-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d62671bb130879cef0ee4c9ebe47a14af6c66ec53e6d84dc15936e5ffdfac82f", size = 4464663, upload-time = "2026-08-03T22:33:03.802Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/69/1f0cbc2fb22ae6082d094f743d1b8945a3f36f6089cb95f42b7ee348cda7/hf_xet-1.6.0-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0e6e21fa3cdfcdcd76748564bf593870a5e013f47d97cf10aed63aa222cff5b7", size = 4262538, upload-time = "2026-08-03T22:33:05.287Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/3a/4f4f2301ade26e404462d3336fa11f7958d914cabbabdd6e03c3c5d5658c/hf_xet-1.6.0-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:4fc74352a17015bd0ee90038bc9efe38db894cde45f268b6712b04fce8cd0acb", size = 4460520, upload-time = "2026-08-03T22:33:06.81Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/5f/311725e2a905534dfee2dcb5b08414f249147f1f12252bfc2bd24caa075c/hf_xet-1.6.0-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:8fb4f71cba6129110c3374a33f919001ff130488fc23553698e34cc1c2a1198c", size = 4675937, upload-time = "2026-08-03T22:33:08.616Z" },
+ { url = "https://files.pythonhosted.org/packages/98/b7/8c59a66d15205024662f1d66968136f13893f96df1ddc5087e2e281fc95f/hf_xet-1.6.0-cp38-abi3-win_amd64.whl", hash = "sha256:fb4fadde1b2b70bf4c0c14a6dccbe7194b1c28947fefd5bbe3fed9d940676c3b", size = 4033128, upload-time = "2026-08-03T22:33:10.171Z" },
+ { url = "https://files.pythonhosted.org/packages/73/63/ca511b6f802f28cf3489b280fe77475bcca8de85e81a6299d7916b5b5555/hf_xet-1.6.0-cp38-abi3-win_arm64.whl", hash = "sha256:3dc3e35441ba395006af5aaacc40ef2e603c51ef46c3530b9156185f00935ea3", size = 3859359, upload-time = "2026-08-03T22:33:11.725Z" },
]
[[package]]
@@ -2443,7 +2443,7 @@ wheels = [
[[package]]
name = "openai"
-version = "2.52.0"
+version = "2.53.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -2455,9 +2455,9 @@ dependencies = [
{ name = "tqdm" },
{ name = "typing-extensions" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/bb/5a/c45fa035cd72c70ebe67c6e079e3adf871492382634f69e3dff62c43597d/openai-2.52.0.tar.gz", hash = "sha256:7c736d592f81471ce1f734838390983c4d8c8aecff23dcd36e600a58e5032d9c", size = 1098876, upload-time = "2026-07-31T15:13:03.228Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/ef/cf/36e3e7235fdf6d125c052acc0970924611b17a20a4fe580596faf4566a65/openai-2.53.0.tar.gz", hash = "sha256:baf5802ad08980e1d9d561e1b996e800c8bcd14af5847c6d0e7a5cc59e4d4116", size = 1099435, upload-time = "2026-08-03T21:42:01.664Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/a1/ac/ceb40c995df49533ad4dcff6c37f0d85cf14446a212363fc9d2f927e60b4/openai-2.52.0-py3-none-any.whl", hash = "sha256:f97e231d9a8fa69ab55897df1080f02d99913fb0a30e3ee56ea16a1eb6c2d434", size = 1659569, upload-time = "2026-07-31T15:13:01.145Z" },
+ { url = "https://files.pythonhosted.org/packages/78/0f/cc6afea3542a5142c5d8fc8211c5e059a8375105d004a41dfa2c7948dbb0/openai-2.53.0-py3-none-any.whl", hash = "sha256:c694ffc747a3c4d1663ef2b07b811315a476164ee5efa3a993967349ebca7618", size = 1659829, upload-time = "2026-08-03T21:41:59.581Z" },
]
[[package]]
@@ -4349,7 +4349,7 @@ wheels = [
[[package]]
name = "typer"
-version = "0.27.0"
+version = "0.27.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "annotated-doc" },
@@ -4357,9 +4357,9 @@ dependencies = [
{ name = "rich" },
{ name = "shellingham" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/ae/40/4a3db7990d1f62a53182aa96eaef57aeb2886a27f90a195bc66713565d31/typer-0.27.1.tar.gz", hash = "sha256:a79bef8469a79c45498e7b814ecf8d603cc7644e9acbd9e19cac0334240b18df", size = 203994, upload-time = "2026-08-03T14:41:03.438Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" },
+ { url = "https://files.pythonhosted.org/packages/43/89/9518bc0c3929bee36b3a4a8e3daddd6e03f92f9961c66d4983b837160543/typer-0.27.1-py3-none-any.whl", hash = "sha256:53150287edd11baeb4e4722c8e394fcdf8181c0ae89485cba8d25c778d5edd56", size = 122874, upload-time = "2026-08-03T14:41:04.391Z" },
]
[[package]]
From b5329b70e78f38408e34aae3de7483de9e901fc2 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Tue, 4 Aug 2026 09:20:25 +0200
Subject: [PATCH 017/197] LCORE-3291: Set encoding explicitly
---
scripts/latest_tag.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/latest_tag.py b/scripts/latest_tag.py
index aae7dbadb..72c97e08c 100755
--- a/scripts/latest_tag.py
+++ b/scripts/latest_tag.py
@@ -51,7 +51,7 @@ def main() -> None:
print(reason)
if github_output := os.environ.get("GITHUB_OUTPUT"):
- with open(github_output, "a") as f:
+ with open(github_output, "a", encoding="utf-8") as f:
f.write(f"apply_latest={apply_latest}\n")
From 9551365ee6f8317f07453069c840ceb86fd7219d Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Tue, 4 Aug 2026 09:38:33 +0200
Subject: [PATCH 018/197] LCORE-1449: Removed unused type ignore
---
tests/unit/authorization/test_middleware.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tests/unit/authorization/test_middleware.py b/tests/unit/authorization/test_middleware.py
index 373a7e72d..a98c3526b 100644
--- a/tests/unit/authorization/test_middleware.py
+++ b/tests/unit/authorization/test_middleware.py
@@ -118,8 +118,8 @@ def test_noop_auth_modules(
roles_resolver, access_resolver = get_authorization_resolvers()
- assert isinstance(roles_resolver, expected_types[0]) # type: ignore
- assert isinstance(access_resolver, expected_types[1]) # type: ignore
+ assert isinstance(roles_resolver, expected_types[0])
+ assert isinstance(access_resolver, expected_types[1])
@pytest.mark.parametrize(
"empty_rules", ["role_rules", "access_rules", "both_rules"]
@@ -321,7 +321,7 @@ async def test_request_state_handling(
mock_request,
]
- await _perform_authorization_check(Action.QUERY, args, kwargs) # type: ignore
+ await _perform_authorization_check(Action.QUERY, args, kwargs)
if request_location != "none":
assert mock_request.state.authorized_actions == {Action.QUERY}
From 680502a0a013e8b11f045e01bd7abad90ef0460a Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Tue, 4 Aug 2026 10:14:29 +0200
Subject: [PATCH 019/197] LCORE-3407: Fixed types in unit test
---
tests/unit/utils/test_models_dumper.py | 32 +++++++++++++-------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/tests/unit/utils/test_models_dumper.py b/tests/unit/utils/test_models_dumper.py
index 07a903131..f572109b1 100644
--- a/tests/unit/utils/test_models_dumper.py
+++ b/tests/unit/utils/test_models_dumper.py
@@ -9155,7 +9155,7 @@ def test_dump_models(tmpdir: Path) -> None:
assert schemas is not None
# list of schemas expected in a dump
- expected_schemas = (
+ expected_schemas = [
"A2AStateConfiguration",
"APIKeyTokenConfiguration",
"AbstractErrorResponse",
@@ -9368,12 +9368,12 @@ def test_dump_models(tmpdir: Path) -> None:
"VectorStoreResponse",
"VectorStoreUpdateRequest",
"VectorStoresListResponse",
- )
+ ]
for expected_schema in expected_schemas:
assert expected_schema in schemas
-def check_json_file_content(filename: str, expected_schemas: list[str]) -> None:
+def check_json_file_content(filename: Path, expected_schemas: list[str]) -> None:
"""Check the content of provided JSON file with OpenAPI-compatible schema."""
with open(filename, "r", encoding="utf-8") as fin:
# schema should be stored in JSON format
@@ -9405,7 +9405,7 @@ def test_dump_models_group_requests(tmpdir: Path) -> None:
dump_models_group(group, filename)
# list of schemas expected in a dump
- expected_schemas = (
+ expected_schemas = [
"ConversationUpdateRequest",
"FeedbackRequest",
"FeedbackStatusUpdateRequest",
@@ -9425,7 +9425,7 @@ def test_dump_models_group_requests(tmpdir: Path) -> None:
"VectorStoreCreateRequest",
"VectorStoreFileCreateRequest",
"VectorStoreUpdateRequest",
- )
+ ]
check_json_file_content(filename, expected_schemas)
@@ -9436,7 +9436,7 @@ def test_dump_models_group_successful_responses(tmpdir: Path) -> None:
dump_models_group(group, filename)
# list of schemas expected in a dump
- expected_schemas = (
+ expected_schemas = [
"AuthorizedResponse",
"ConfigurationResponse",
"ConversationDeleteResponse",
@@ -9477,7 +9477,7 @@ def test_dump_models_group_successful_responses(tmpdir: Path) -> None:
"VectorStoreFilesListResponse",
"VectorStoreResponse",
"VectorStoresListResponse",
- )
+ ]
check_json_file_content(filename, expected_schemas)
@@ -9488,7 +9488,7 @@ def test_dump_models_group_error_responses(tmpdir: Path) -> None:
dump_models_group(group, filename)
# list of schemas expected in a dump
- expected_schemas = (
+ expected_schemas = [
"AbstractErrorResponse",
"BadRequestResponse",
"ConflictResponse",
@@ -9502,7 +9502,7 @@ def test_dump_models_group_error_responses(tmpdir: Path) -> None:
"ServiceUnavailableResponse",
"UnauthorizedResponse",
"UnprocessableEntityResponse",
- )
+ ]
check_json_file_content(filename, expected_schemas)
@@ -9513,7 +9513,7 @@ def test_dump_models_group_common(tmpdir: Path) -> None:
dump_models_group(group, filename)
# list of schemas expected in a dump
- expected_schemas = (
+ expected_schemas = [
"Attachment",
"ConversationData",
"ConversationDetails",
@@ -9535,7 +9535,7 @@ def test_dump_models_group_common(tmpdir: Path) -> None:
"Transcript",
"TranscriptMetadata",
"TurnSummary",
- )
+ ]
check_json_file_content(filename, expected_schemas)
@@ -9546,7 +9546,7 @@ def test_dump_models_group_agent(tmpdir: Path) -> None:
dump_models_group(group, filename)
# list of schemas expected in a dump
- expected_schemas = (
+ expected_schemas = [
"EndEventData",
"EndStreamPayload",
"ErrorEventData",
@@ -9561,7 +9561,7 @@ def test_dump_models_group_agent(tmpdir: Path) -> None:
"ToolCallStreamPayload",
"ToolResultStreamPayload",
"TurnCompleteStreamPayload",
- )
+ ]
check_json_file_content(filename, expected_schemas)
@@ -9572,10 +9572,10 @@ def test_dump_models_common_responses(tmpdir: Path) -> None:
dump_models_group(group, filename)
# list of schemas expected in a dump
- expected_schemas = (
+ expected_schemas = [
"InputToolMCP",
"ResponsesApiParams",
- )
+ ]
check_json_file_content(filename, expected_schemas)
@@ -9586,7 +9586,7 @@ def test_dump_models_conversation_summary(tmpdir: Path) -> None:
dump_models_group(group, filename)
# list of schemas expected in a dump
- expected_schemas = ("ConversationSummary",)
+ expected_schemas = ["ConversationSummary"]
check_json_file_content(filename, expected_schemas)
From 6f5a7f56d9821f6c61e832bd95518745667b698e Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Tue, 4 Aug 2026 14:19:44 +0200
Subject: [PATCH 020/197] LCORE-2922: Konflux package bump-up: anyio
---
.konflux/requirements.hashes.wheel.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.konflux/requirements.hashes.wheel.txt b/.konflux/requirements.hashes.wheel.txt
index dac4d632a..e9c8934a9 100644
--- a/.konflux/requirements.hashes.wheel.txt
+++ b/.konflux/requirements.hashes.wheel.txt
@@ -20,8 +20,8 @@ annotated-types==0.7.0 \
--hash=sha256:d31d6f386f3ecd6cdca12274844b969c3f9c90d15ebef7774f2eb34857108758
anthropic==0.117.0 \
--hash=sha256:090da100887647422594995b93d51c3139ec58dcd29ac4357a382fee1bb13645
-anyio==4.14.1 \
- --hash=sha256:7b1919965ee5094a3cf8b0c371749b59b5835293055e51ab23a4a45bca1d3fab
+anyio==4.14.2 \
+ --hash=sha256:910fa689d2615586a8c10cd10caaa20a6613e5eda16c3844eeb2b0886d37c8d3
argcomplete==3.7.0 \
--hash=sha256:5cc89c09cbdd234b8bef7fcf3576221b903aad46acd66e34387e32c9000f4963
asyncpg==0.31.0 \
From 68a0b99b80b5a1391cd8c0743fa8ef9f14aab15c Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Tue, 4 Aug 2026 14:22:26 +0200
Subject: [PATCH 021/197] Updated pull request template
---
.github/PULL_REQUEST_TEMPLATE.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index a8cb3b673..d0532db13 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -12,7 +12,8 @@
- [ ] Documentation Update
- [ ] Configuration Update
- [ ] Bump-up service version
-- [ ] Bump-up dependent library
+- [ ] Bump-up dependent library [`pyproject.toml` + `uv.lock`]
+- [ ] Bump-up dependent library [`requirements.*.txt` for Konflux]
- [ ] Bump-up library or tool used for development (does not change the final image)
- [ ] CI configuration change
- [ ] Konflux configuration change
From fcff6a59a97cfdb98cbffd8f8e84166eaae77cf8 Mon Sep 17 00:00:00 2001
From: Stephanie
Date: Tue, 4 Aug 2026 11:05:00 -0400
Subject: [PATCH 022/197] address review addess
Signed-off-by: Stephanie
---
README.md | 6 +-
docs/user_doc/skills_guide.md | 8 +--
.../api/responses/successful/catalog.py | 3 +-
src/models/common/__init__.py | 2 +-
src/utils/pydantic_ai_helpers.py | 8 +--
.../features/http_401_unauthorized.feature | 17 +++++
tests/e2e/features/rbac.feature | 6 ++
tests/e2e/features/skills.feature | 63 +++----------------
tests/unit/app/endpoints/test_skills.py | 22 ++++++-
9 files changed, 64 insertions(+), 71 deletions(-)
diff --git a/README.md b/README.md
index 6f0168dd8..0933934bc 100644
--- a/README.md
+++ b/README.md
@@ -1280,11 +1280,11 @@ This is distinct from the `list_skills` tool that the agent itself may
invoke during a `/v1/query` or `/v1/streaming_query` turn.
If [authentication](#authentication) is enabled, include the appropriate
-credentials (e.g. `-H "Authorization: Bearer "`); otherwise the
-request returns `401`/`403`.
+credentials; otherwise the request returns `401`/`403`.
```bash
-curl http://localhost:8080/v1/skills
+curl -H "Authorization: Bearer " \
+ http://localhost:8080/v1/skills
```
**Response Body:**
diff --git a/docs/user_doc/skills_guide.md b/docs/user_doc/skills_guide.md
index 7e1776879..30b080293 100644
--- a/docs/user_doc/skills_guide.md
+++ b/docs/user_doc/skills_guide.md
@@ -212,12 +212,12 @@ See [examples/skills/](../examples/skills/) for complete working examples.
`GET /v1/skills` returns the name and description of every skill loaded
from the configured `skills.paths`, without going through an LLM/agent
-turn. If authentication is enabled, include the appropriate credentials
-(e.g. `-H "Authorization: Bearer "`); otherwise the request
-returns `401`/`403`:
+turn. If authentication is enabled, include the appropriate credentials;
+otherwise the request returns `401`/`403`:
```bash
-curl http://localhost:8080/v1/skills
+curl -H "Authorization: Bearer " \
+ http://localhost:8080/v1/skills
```
```json
diff --git a/src/models/api/responses/successful/catalog.py b/src/models/api/responses/successful/catalog.py
index 2c4df4bf5..072472bae 100644
--- a/src/models/api/responses/successful/catalog.py
+++ b/src/models/api/responses/successful/catalog.py
@@ -5,10 +5,11 @@
from pydantic import Field
from models.api.responses.successful.bases import AbstractSuccessfulResponse
-from models.common.skills import SkillMetadata
from models.common import CatalogModel, CatalogShield
+from models.common.skills import SkillMetadata
from models.common.tools import CatalogTool
+
class SkillsResponse(AbstractSuccessfulResponse):
"""Model representing a response to skills request.
diff --git a/src/models/common/__init__.py b/src/models/common/__init__.py
index 4f5e87896..6db7467b0 100644
--- a/src/models/common/__init__.py
+++ b/src/models/common/__init__.py
@@ -19,8 +19,8 @@
ShieldModerationResult,
)
from models.common.query import Attachment, SolrVectorSearchRequest
-from models.common.skills import SkillMetadata
from models.common.shields import CatalogShield
+from models.common.skills import SkillMetadata
from models.common.transcripts import Transcript, TranscriptMetadata
from models.common.turn_summary import (
MCPListToolsSummary,
diff --git a/src/utils/pydantic_ai_helpers.py b/src/utils/pydantic_ai_helpers.py
index b1f003fcc..39faf79f2 100644
--- a/src/utils/pydantic_ai_helpers.py
+++ b/src/utils/pydantic_ai_helpers.py
@@ -14,10 +14,6 @@
from configuration import AppConfig
from models.common.responses.responses_api_params import ResponsesApiParams
from models.common.skills import SkillMetadata
-from models.config import SkillsConfiguration
-from pydantic_ai_lightspeed.llamastack import (
- LlamaStackResponsesModel,
-)
from models.common.tools import CatalogTool, CatalogToolParameter
from models.config import (
QuestionValidityConfig,
@@ -27,9 +23,7 @@
)
from pydantic_ai_lightspeed.capabilities import QuestionValidity
from pydantic_ai_lightspeed.capabilities.redaction import PiiRedactionCapability
-from pydantic_ai_lightspeed.llamastack import (
- OgxResponsesModel,
-)
+from pydantic_ai_lightspeed.llamastack import OgxResponsesModel
from utils.shields import get_shields_for_request
_AGENT_SKILLS_PROVIDER_ID: Final[str] = "agent-skills"
diff --git a/tests/e2e/features/http_401_unauthorized.feature b/tests/e2e/features/http_401_unauthorized.feature
index d33076277..f1cb2f7ec 100644
--- a/tests/e2e/features/http_401_unauthorized.feature
+++ b/tests/e2e/features/http_401_unauthorized.feature
@@ -124,6 +124,23 @@ Feature: HTTP 401 Unauthorized
}
"""
+ # --- skills ---
+
+ Scenario: Skills list returns 401 when not authenticated
+ Given The service uses the lightspeed-stack-auth-noop-token.yaml configuration
+ And The service is restarted
+ When I access REST API endpoint "skills" using HTTP GET method
+ Then The status code of the response is 401
+ And The body of the response is the following
+ """
+ {
+ "detail": {
+ "response": "Missing or invalid credentials provided by client",
+ "cause": "No Authorization header found"
+ }
+ }
+ """
+
# --- prompts ---
Scenario: Prompts list returns 401 when not authenticated
diff --git a/tests/e2e/features/rbac.feature b/tests/e2e/features/rbac.feature
index 07d711ddb..517dcd404 100644
--- a/tests/e2e/features/rbac.feature
+++ b/tests/e2e/features/rbac.feature
@@ -101,6 +101,12 @@ Feature: Role-Based Access Control (RBAC)
Then The status code of the response is 403
And The body of the response contains does not have permission
+ Scenario: Query-only user cannot list skills - returns 403
+ And I authenticate as "query_only" user
+ When I access REST API endpoint "skills" using HTTP GET method
+ Then The status code of the response is 403
+ And The body of the response contains does not have permission
+
# ============================================
# No Role - Minimal Access (everyone role only)
# ============================================
diff --git a/tests/e2e/features/skills.feature b/tests/e2e/features/skills.feature
index 776676ecb..593db6a26 100644
--- a/tests/e2e/features/skills.feature
+++ b/tests/e2e/features/skills.feature
@@ -178,61 +178,16 @@ Feature: Agent skills tests
}
"""
- # --- GET /v1/skills endpoint ---
-
- @SkillsConfig
- Scenario: GET /v1/skills returns metadata for configured skills
- Given The service uses the lightspeed-stack-skills.yaml configuration
- And The service is restarted
- When I access REST API endpoint "skills" using HTTP GET method
- Then The status code of the response is 200
- And The body of the response is the following
- """
- {
- "skills": [
- {
- "name": "echo",
- "description": "Echo back the user's input exactly as provided. Use when a user asks to echo, repeat, or mirror text."
- }
- ]
- }
- """
-
- Scenario: GET /v1/skills returns an empty list when no skills are configured
- Given The service uses the lightspeed-stack.yaml configuration
- And The service is restarted
- When I access REST API endpoint "skills" using HTTP GET method
- Then The status code of the response is 200
- And The body of the response is the following
- """
- {
- "skills": []
- }
- """
-
- @SkillsMultiConfig
- Scenario: GET /v1/skills discovers all skills in a skills directory
- Given The service uses the lightspeed-stack-skills-directory.yaml configuration
- And The service is restarted
- When I access REST API endpoint "skills" using HTTP GET method
- Then The status code of the response is 200
- And The body of the response is the following
- """
- {
- "skills": [
- {
- "name": "echo",
- "description": "Echo back the user's input exactly as provided. Use when a user asks to echo, repeat, or mirror text."
- },
- {
- "name": "summarize",
- "description": "Summarize text into a concise single-sentence overview. Use when a user asks to summarize, condense, or shorten text."
- }
- ]
- }
- """
-
# --- Skill discovery ---
+ #
+ # Note: plain GET /v1/skills happy-path coverage (configured skills, empty
+ # list, and multi-skill directory discovery) lives in
+ # tests/integration/endpoints/test_skills_integration.py instead of here.
+ # That endpoint only reads local skill directories and returns a typed
+ # response with no LLM/agent turn involved, so it doesn't need the full e2e
+ # stack. See tests/e2e/features/http_401_unauthorized.feature and
+ # tests/e2e/features/rbac.feature for the /v1/skills auth-failure (401/403)
+ # coverage.
@SkillsConfig
Scenario: LLM can discover skills via list_skills tool using query endpoint
diff --git a/tests/unit/app/endpoints/test_skills.py b/tests/unit/app/endpoints/test_skills.py
index 5a5b65c87..294f6e6db 100644
--- a/tests/unit/app/endpoints/test_skills.py
+++ b/tests/unit/app/endpoints/test_skills.py
@@ -3,11 +3,12 @@
from pathlib import Path
import pytest
-from fastapi import Request
+from fastapi import HTTPException, Request, status
from pytest_mock import MockerFixture
from app.endpoints.skills import skills_endpoint_handler
from authentication.interface import AuthTuple
+from configuration import AppConfig
from models.api.responses.successful import SkillsResponse
from models.config import SkillsConfiguration
from tests.unit.utils.auth_helpers import mock_authorization_resolvers
@@ -15,6 +16,25 @@
MOCK_AUTH: AuthTuple = ("mock_user_id", "mock_username", True, "mock_token")
+@pytest.mark.asyncio
+async def test_skills_endpoint_handler_configuration_not_loaded(
+ mocker: MockerFixture,
+) -> None:
+ """Test that the skills endpoint returns 500 when configuration is not loaded."""
+ mock_authorization_resolvers(mocker)
+
+ mock_config = AppConfig()
+ mock_config._configuration = None # pylint: disable=protected-access
+ mocker.patch("app.endpoints.skills.configuration", mock_config)
+
+ request = Request(scope={"type": "http"})
+
+ with pytest.raises(HTTPException) as exc_info:
+ await skills_endpoint_handler(request=request, auth=MOCK_AUTH)
+ assert exc_info.value.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
+ assert exc_info.value.detail["response"] == "Configuration is not loaded" # type: ignore
+
+
@pytest.mark.asyncio
async def test_skills_loaded(
mocker: MockerFixture,
From 8eb6623873aef27ac7a94ee7d7c6016f97b037c0 Mon Sep 17 00:00:00 2001
From: Jordan Dubrick
Date: Tue, 4 Aug 2026 14:26:29 -0400
Subject: [PATCH 023/197] add integration tests for saved prompts
Signed-off-by: Jordan Dubrick
---
.../test_saved_prompts_integration.py | 268 ++++++++++++++++++
1 file changed, 268 insertions(+)
create mode 100644 tests/integration/endpoints/test_saved_prompts_integration.py
diff --git a/tests/integration/endpoints/test_saved_prompts_integration.py b/tests/integration/endpoints/test_saved_prompts_integration.py
new file mode 100644
index 000000000..e59230758
--- /dev/null
+++ b/tests/integration/endpoints/test_saved_prompts_integration.py
@@ -0,0 +1,268 @@
+"""Integration tests for the /v1/saved-prompts REST API endpoints."""
+
+import pytest
+from fastapi import HTTPException, Request, status
+from sqlalchemy.orm import Session
+
+from app.endpoints.saved_prompts import (
+ create_saved_prompts_handler,
+ delete_saved_prompts_handler,
+ get_saved_prompts_config_handler,
+ list_saved_prompts_handler,
+)
+from authentication.interface import AuthTuple
+from configuration import AppConfig
+from models.api.requests import SavedPromptCreateRequest
+from models.api.responses.successful import SavedPromptResponse
+from tests.integration.conftest import (
+ TEST_NON_EXISTENT_ID,
+ TEST_OTHER_USER_ID,
+)
+
+
+@pytest.fixture(name="other_auth")
+def other_auth_fixture() -> AuthTuple:
+ """Auth tuple for a different user than noop default auth."""
+ return (TEST_OTHER_USER_ID, "other-user", True, "test_token")
+
+
+async def create_prompt_via_handler(
+ request: Request,
+ auth: AuthTuple,
+ name: str,
+ content: str,
+) -> SavedPromptResponse:
+ """Create a saved prompt through the real create handler.
+
+ Parameters:
+ request: FastAPI request for authorization middleware.
+ auth: Authenticated user tuple.
+ name: Prompt display name.
+ content: Prompt body.
+
+ Returns:
+ SavedPromptResponse from the create handler.
+ """
+ return await create_saved_prompts_handler(
+ request=request,
+ body=SavedPromptCreateRequest(name=name, content=content),
+ auth=auth,
+ )
+
+
+@pytest.mark.asyncio
+async def test_get_saved_prompts_config_returns_limits(
+ test_config: AppConfig,
+ test_request: Request,
+ test_auth: AuthTuple,
+) -> None:
+ """Config endpoint returns saved-prompts limits from loaded configuration."""
+ expected = test_config.configuration.saved_prompts
+
+ response = await get_saved_prompts_config_handler(
+ auth=test_auth,
+ request=test_request,
+ )
+
+ assert response.max_prompts_per_user == expected.max_prompts_per_user
+ assert response.max_display_name_length == expected.max_display_name_length
+ assert response.max_content_length == expected.max_content_length
+
+
+@pytest.mark.asyncio
+async def test_list_saved_prompts_empty_for_new_user(
+ test_config: AppConfig,
+ test_request: Request,
+ test_auth: AuthTuple,
+ patch_db_session: Session,
+) -> None:
+ """List returns an empty prompts array when the user has no saved prompts."""
+ _ = test_config
+ _ = patch_db_session
+
+ response = await list_saved_prompts_handler(
+ auth=test_auth,
+ request=test_request,
+ )
+
+ assert response.prompts == []
+
+
+@pytest.mark.asyncio
+async def test_create_saved_prompt_persists_and_is_listable(
+ test_config: AppConfig,
+ test_request: Request,
+ test_auth: AuthTuple,
+ patch_db_session: Session,
+) -> None:
+ """Create returns prompt fields and the owning user can list it."""
+ _ = test_config
+ _ = patch_db_session
+
+ created = await create_prompt_via_handler(
+ request=test_request,
+ auth=test_auth,
+ name="Deploy to staging",
+ content="Help me write a deployment checklist",
+ )
+
+ assert created.id
+ assert created.name == "Deploy to staging"
+ assert created.content == "Help me write a deployment checklist"
+ assert created.created_at is not None
+ assert created.updated_at is not None
+
+ listed = await list_saved_prompts_handler(
+ auth=test_auth,
+ request=test_request,
+ )
+ assert len(listed.prompts) == 1
+ assert listed.prompts[0].id == created.id
+ assert listed.prompts[0].name == "Deploy to staging"
+
+
+@pytest.mark.asyncio
+async def test_list_saved_prompts_isolates_users(
+ test_config: AppConfig,
+ test_request: Request,
+ test_auth: AuthTuple,
+ other_auth: AuthTuple,
+ patch_db_session: Session,
+) -> None:
+ """List returns only the caller's prompts."""
+ _ = test_config
+ _ = patch_db_session
+
+ owned = await create_prompt_via_handler(
+ request=test_request,
+ auth=test_auth,
+ name="owned-prompt",
+ content="owned body",
+ )
+ other = await create_prompt_via_handler(
+ request=test_request,
+ auth=other_auth,
+ name="other-user-prompt",
+ content="should not appear",
+ )
+
+ listed = await list_saved_prompts_handler(
+ auth=test_auth,
+ request=test_request,
+ )
+
+ ids = [p.id for p in listed.prompts]
+ assert owned.id in ids
+ assert other.id not in ids
+
+
+@pytest.mark.asyncio
+async def test_create_saved_prompt_returns_422_when_limit_exceeded(
+ test_config: AppConfig,
+ test_request: Request,
+ test_auth: AuthTuple,
+ patch_db_session: Session,
+) -> None:
+ """Create returns 422 after the configured per-user maximum is reached."""
+ _ = patch_db_session
+ test_config.configuration.saved_prompts.max_prompts_per_user = 1
+
+ await create_prompt_via_handler(
+ request=test_request,
+ auth=test_auth,
+ name="one",
+ content="body one",
+ )
+
+ with pytest.raises(HTTPException) as exc_info:
+ await create_prompt_via_handler(
+ request=test_request,
+ auth=test_auth,
+ name="two",
+ content="body two",
+ )
+
+ assert exc_info.value.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT
+
+
+@pytest.mark.asyncio
+async def test_delete_own_saved_prompt_removes_it_from_list(
+ test_config: AppConfig,
+ test_request: Request,
+ test_auth: AuthTuple,
+ patch_db_session: Session,
+) -> None:
+ """Deleting an owned prompt returns deleted=True and removes it from list."""
+ _ = test_config
+ _ = patch_db_session
+
+ created = await create_prompt_via_handler(
+ request=test_request,
+ auth=test_auth,
+ name="to-delete",
+ content="temporary",
+ )
+
+ deleted = await delete_saved_prompts_handler(
+ request=test_request,
+ prompt_id=created.id,
+ auth=test_auth,
+ )
+ assert deleted.deleted is True
+ assert deleted.prompt_id == created.id
+
+ listed = await list_saved_prompts_handler(
+ auth=test_auth,
+ request=test_request,
+ )
+ assert listed.prompts == []
+
+
+@pytest.mark.asyncio
+async def test_delete_missing_saved_prompt_returns_deleted_false(
+ test_config: AppConfig,
+ test_request: Request,
+ test_auth: AuthTuple,
+ patch_db_session: Session,
+) -> None:
+ """Deleting a non-existent valid id returns deleted=False (idempotent)."""
+ _ = test_config
+ _ = patch_db_session
+
+ deleted = await delete_saved_prompts_handler(
+ request=test_request,
+ prompt_id=TEST_NON_EXISTENT_ID,
+ auth=test_auth,
+ )
+
+ assert deleted.deleted is False
+ assert deleted.prompt_id == TEST_NON_EXISTENT_ID
+
+
+@pytest.mark.asyncio
+async def test_delete_other_users_saved_prompt_returns_403(
+ test_config: AppConfig,
+ test_request: Request,
+ test_auth: AuthTuple,
+ other_auth: AuthTuple,
+ patch_db_session: Session,
+) -> None:
+ """Deleting another user's prompt raises HTTP 403."""
+ _ = test_config
+ _ = patch_db_session
+
+ other_prompt = await create_prompt_via_handler(
+ request=test_request,
+ auth=other_auth,
+ name="owned-by-other",
+ content="secret",
+ )
+
+ with pytest.raises(HTTPException) as exc_info:
+ await delete_saved_prompts_handler(
+ request=test_request,
+ prompt_id=other_prompt.id,
+ auth=test_auth,
+ )
+
+ assert exc_info.value.status_code == status.HTTP_403_FORBIDDEN
From c62182444080693ed274966d7f23147b5bf630d6 Mon Sep 17 00:00:00 2001
From: Jordan Dubrick
Date: Tue, 4 Aug 2026 14:52:35 -0400
Subject: [PATCH 024/197] address coderabbit comments
Signed-off-by: Jordan Dubrick
---
.../endpoints/test_saved_prompts_integration.py | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/tests/integration/endpoints/test_saved_prompts_integration.py b/tests/integration/endpoints/test_saved_prompts_integration.py
index e59230758..9cce36ddf 100644
--- a/tests/integration/endpoints/test_saved_prompts_integration.py
+++ b/tests/integration/endpoints/test_saved_prompts_integration.py
@@ -161,6 +161,7 @@ async def test_create_saved_prompt_returns_422_when_limit_exceeded(
test_config: AppConfig,
test_request: Request,
test_auth: AuthTuple,
+ other_auth: AuthTuple,
patch_db_session: Session,
) -> None:
"""Create returns 422 after the configured per-user maximum is reached."""
@@ -174,6 +175,14 @@ async def test_create_saved_prompt_returns_422_when_limit_exceeded(
content="body one",
)
+ other_created = await create_prompt_via_handler(
+ request=test_request,
+ auth=other_auth,
+ name="other-user-one",
+ content="other user body",
+ )
+ assert other_created.id
+
with pytest.raises(HTTPException) as exc_info:
await create_prompt_via_handler(
request=test_request,
@@ -266,3 +275,9 @@ async def test_delete_other_users_saved_prompt_returns_403(
)
assert exc_info.value.status_code == status.HTTP_403_FORBIDDEN
+
+ remaining = await list_saved_prompts_handler(
+ auth=other_auth,
+ request=test_request,
+ )
+ assert any(prompt.id == other_prompt.id for prompt in remaining.prompts)
From 279fc221a901be7571504387250b3a7d75545525 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Wed, 5 Aug 2026 08:44:45 +0200
Subject: [PATCH 025/197] LCORE-2922: Updated dependencies
---
uv.lock | 67 ++++++++++++++++++++++++++++++---------------------------
1 file changed, 35 insertions(+), 32 deletions(-)
diff --git a/uv.lock b/uv.lock
index 7d1eeb50f..a153d77ea 100644
--- a/uv.lock
+++ b/uv.lock
@@ -49,14 +49,14 @@ wheels = [
[[package]]
name = "aiofile"
-version = "3.11.1"
+version = "3.12.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "caio" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/48/41/2fea7e193e061ce54eacc3b7bc0e6a99e4fcff43c78cf0a76dd781ed8334/aiofile-3.11.1.tar.gz", hash = "sha256:1f91912c6643d2a4e49ca4ae3514f0bf3867ce948a36d99a6411b8f4755f4cf9", size = 19342, upload-time = "2026-05-16T08:18:33.538Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/14/31/edb06aabd8f8f0b56d659f30800795f40b93cba96be946ce179f6931e3a5/aiofile-3.12.3.tar.gz", hash = "sha256:caa6aa746b5e47e2165f7abd741b6415e49cf4d44fddc0f61844612cc3924d41", size = 21600, upload-time = "2026-08-04T22:59:27.171Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/67/cd/0d76dfc5de72bde52f55f53e925c7d152d9c7906634ec1e0cbc7e8d4ad93/aiofile-3.11.1-py3-none-any.whl", hash = "sha256:ce77d14ac07f77bc2b757834a5c129321f3f705c474593deed5ab209079a52c9", size = 20446, upload-time = "2026-05-16T08:18:32.051Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/79/6e45e778c4c3cab39e0937b007b720c15f76c50c6453d153282d0fcc3588/aiofile-3.12.3-py3-none-any.whl", hash = "sha256:5c1bcc9e929c50834608e8cc1a4cc1d7503eb60c15a535b779fd39e2f372c017", size = 22122, upload-time = "2026-08-04T22:59:25.838Z" },
]
[[package]]
@@ -201,11 +201,11 @@ wheels = [
[[package]]
name = "argcomplete"
-version = "3.7.0"
+version = "3.7.1"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/95/c0/c8e94135e66fabf89a120d9b4b123fe6993506beca6c1938a74c24cfa5fd/argcomplete-3.7.0.tar.gz", hash = "sha256:afde224f753f874807b1dc1414e883ab8fe0cda9c04807b6047dcb8e1ac23913", size = 73284, upload-time = "2026-06-30T22:28:22.249Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/d1/40/8a867253c9b8afa296ac22e426a157eebbe41dcac66f7f50bbbef931afed/argcomplete-3.7.1.tar.gz", hash = "sha256:6926a3a70ae70dce1f3dfb5cf1fc984278cd163e78ec18ad2ed7fa4fabd8f281", size = 74457, upload-time = "2026-08-04T15:03:59.399Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/12/f6/5b8ec087cd9cfa9449491ec83f76fb6b7006b4dff57d2ba8aaab330fe8e4/argcomplete-3.7.0-py3-none-any.whl", hash = "sha256:d8f0f22d2a8a7caa383be1e22b6caf1ecaf0ebd10d8f83cc125e36540c95830c", size = 42575, upload-time = "2026-06-30T22:28:20.547Z" },
+ { url = "https://files.pythonhosted.org/packages/11/56/1935d0692656f0bfc0c2336d4ce599dcf166abe4ec786ce1abdaefa19589/argcomplete-3.7.1-py3-none-any.whl", hash = "sha256:0bed095030f295599b1018a622a53ea22f4f253e134b87be396b51e59ee00954", size = 43301, upload-time = "2026-08-04T15:03:58.02Z" },
]
[[package]]
@@ -434,19 +434,22 @@ wheels = [
[[package]]
name = "caio"
-version = "0.9.25"
+version = "0.12.2"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/92/88/b8527e1b00c1811db339a1df8bd1ae49d146fcea9d6a5c40e3a80aaeb38d/caio-0.9.25.tar.gz", hash = "sha256:16498e7f81d1d0f5a4c0ad3f2540e65fe25691376e0a5bd367f558067113ed10", size = 26781, upload-time = "2025-12-26T15:21:36.501Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/75/c8/82b3c760141a1076408164b03e8789b51809add6aecd48aa9d7651cf6b59/caio-0.12.2.tar.gz", hash = "sha256:87a67c0dccc60e432888bd532ec504b66e124a5d8b391aab894583b55abd39ea", size = 80927, upload-time = "2026-08-04T14:43:33.726Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/d3/25/79c98ebe12df31548ba4eaf44db11b7cad6b3e7b4203718335620939083c/caio-0.9.25-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fb7ff95af4c31ad3f03179149aab61097a71fd85e05f89b4786de0359dffd044", size = 36983, upload-time = "2025-12-26T15:21:36.075Z" },
- { url = "https://files.pythonhosted.org/packages/a3/2b/21288691f16d479945968a0a4f2856818c1c5be56881d51d4dac9b255d26/caio-0.9.25-cp312-cp312-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:97084e4e30dfa598449d874c4d8e0c8d5ea17d2f752ef5e48e150ff9d240cd64", size = 82012, upload-time = "2025-12-26T15:22:20.983Z" },
- { url = "https://files.pythonhosted.org/packages/03/c4/8a1b580875303500a9c12b9e0af58cb82e47f5bcf888c2457742a138273c/caio-0.9.25-cp312-cp312-manylinux_2_34_aarch64.whl", hash = "sha256:4fa69eba47e0f041b9d4f336e2ad40740681c43e686b18b191b6c5f4c5544bfb", size = 81502, upload-time = "2026-03-04T22:08:22.381Z" },
- { url = "https://files.pythonhosted.org/packages/d1/1c/0fe770b8ffc8362c48134d1592d653a81a3d8748d764bec33864db36319d/caio-0.9.25-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:6bebf6f079f1341d19f7386db9b8b1f07e8cc15ae13bfdaff573371ba0575d69", size = 80200, upload-time = "2026-03-04T22:08:23.382Z" },
- { url = "https://files.pythonhosted.org/packages/31/57/5e6ff127e6f62c9f15d989560435c642144aa4210882f9494204bc892305/caio-0.9.25-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d6c2a3411af97762a2b03840c3cec2f7f728921ff8adda53d7ea2315a8563451", size = 36979, upload-time = "2025-12-26T15:21:35.484Z" },
- { url = "https://files.pythonhosted.org/packages/a3/9f/f21af50e72117eb528c422d4276cbac11fb941b1b812b182e0a9c70d19c5/caio-0.9.25-cp313-cp313-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0998210a4d5cd5cb565b32ccfe4e53d67303f868a76f212e002a8554692870e6", size = 81900, upload-time = "2025-12-26T15:22:21.919Z" },
- { url = "https://files.pythonhosted.org/packages/9c/12/c39ae2a4037cb10ad5eb3578eb4d5f8c1a2575c62bba675f3406b7ef0824/caio-0.9.25-cp313-cp313-manylinux_2_34_aarch64.whl", hash = "sha256:1a177d4777141b96f175fe2c37a3d96dec7911ed9ad5f02bac38aaa1c936611f", size = 81523, upload-time = "2026-03-04T22:08:25.187Z" },
- { url = "https://files.pythonhosted.org/packages/22/59/f8f2e950eb4f1a5a3883e198dca514b9d475415cb6cd7b78b9213a0dd45a/caio-0.9.25-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:9ed3cfb28c0e99fec5e208c934e5c157d0866aa9c32aa4dc5e9b6034af6286b7", size = 80243, upload-time = "2026-03-04T22:08:26.449Z" },
- { url = "https://files.pythonhosted.org/packages/86/93/1f76c8d1bafe3b0614e06b2195784a3765bbf7b0a067661af9e2dd47fc33/caio-0.9.25-py3-none-any.whl", hash = "sha256:06c0bb02d6b929119b1cfbe1ca403c768b2013a369e2db46bfa2a5761cf82e40", size = 19087, upload-time = "2025-12-26T15:22:00.221Z" },
+ { url = "https://files.pythonhosted.org/packages/60/bc/b62bf048a6e11870291a24319ed027bdf658df9ba77d1ad762aa138e066b/caio-0.12.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2097cc0d19fa95e8d55aad770597bb0f76e4f70ed48278c965aa7c5b0b8c3bf5", size = 84702, upload-time = "2026-08-04T14:43:03.946Z" },
+ { url = "https://files.pythonhosted.org/packages/f7/be/b40d55d793afcfa5bcdb32ade9289d9588e14e3026c2c87522e303cc6e8c/caio-0.12.2-cp312-cp312-manylinux_2_34_aarch64.whl", hash = "sha256:2122dccbd1959b922543fc9f8a9d2af47bd5b59190d1ece2445d3d1b4d1be45f", size = 198292, upload-time = "2026-08-04T14:43:05.238Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/02/9bd2bca72bfa478337618eae88942c43c891ae225e11baeae275e5e5c6ab/caio-0.12.2-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:107e56554c179749de9440e1b5e5a19813572eebf3166e9dc3e5228b16966beb", size = 196207, upload-time = "2026-08-04T14:43:06.494Z" },
+ { url = "https://files.pythonhosted.org/packages/48/9b/65f95efdd68b50b7a9f2555c93d9edc7da7aa5ae5e153163c41cf6fd5cd9/caio-0.12.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adc7785e61ff7cf372318f67ec65617eaa06975e20da177522665dca8be6ea5d", size = 195748, upload-time = "2026-08-04T14:43:07.893Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/16/6a5c010ca435a5184d11ca350874694ac19db249560126dc8df0f25791ce/caio-0.12.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:07942d3b5999127ecb96256c38d5dbf49ed2864c087ed2a80b783901d0aa3ba1", size = 195835, upload-time = "2026-08-04T14:43:09.19Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/9b/31f0b49a2542ffa2f9d6140267e2b568e722a1feeb05cfbffea97666c62b/caio-0.12.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:40ebea9ebe3a3a66ae85fa00d4112d163654a33c82dcf9b26a99f7d30de13317", size = 84656, upload-time = "2026-08-04T14:43:10.513Z" },
+ { url = "https://files.pythonhosted.org/packages/99/bc/62568d688af9712a34fe3f958d7a98c53bb2017e263260cd5deae67a90e9/caio-0.12.2-cp313-cp313-manylinux_2_34_aarch64.whl", hash = "sha256:6003ec389a68d5ec8f089df82b2dc8915293dd630a4d11322d7e3455045981fd", size = 198443, upload-time = "2026-08-04T14:43:11.767Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/e4/5ed627860285612e5307f06c109913c5918c947fbc223b55599e484c64b0/caio-0.12.2-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:eee9376d0e2af25b6defc5bce39f6efa90521c803aaf12eba931bd898a397cfc", size = 196356, upload-time = "2026-08-04T14:43:13.206Z" },
+ { url = "https://files.pythonhosted.org/packages/81/e2/2a8cfc6ba3ef3f19e7c778e9fb6f98600f0971cca78bbdfc23a413a66349/caio-0.12.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:78e3ccafc98e009fcb00a97ad441585551e52c0ae7ecc50427a3ccd9b11502fd", size = 195893, upload-time = "2026-08-04T14:43:14.649Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/87/77c40fb2301d0b5bb27c2e79ae42fce718ed75396d5fe3e1c09d8e1400b1/caio-0.12.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f2355db8917f5a0f3638bf332fe0d87549c80e978fca01db84a8a14b9df56a05", size = 195969, upload-time = "2026-08-04T14:43:15.946Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/b5/0ceca97eb546fe6bbace3399c8b11dfc503efcc7509d708a7a3f09ab50e9/caio-0.12.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8054cba5e7ee623bea34946e2b59eb7c7c2be8872d0a5d12215d6ff564938d5f", size = 78621, upload-time = "2026-08-04T14:43:17.316Z" },
+ { url = "https://files.pythonhosted.org/packages/61/8a/71b0144f783468ba9f1bbf8a2f8e45c7d85ae31ec192f10650aa46f31702/caio-0.12.2-py3-none-any.whl", hash = "sha256:5233e797c9fe2b541914b1bc2e2df82677e2206b537e44e252188f3c2cbb0ea9", size = 62548, upload-time = "2026-08-04T14:43:32.394Z" },
]
[[package]]
@@ -2674,11 +2677,11 @@ wheels = [
[[package]]
name = "packaging"
-version = "26.2"
+version = "26.3"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
+ { url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" },
]
[[package]]
@@ -3129,14 +3132,14 @@ email = [
[[package]]
name = "pydantic-ai"
-version = "2.23.0"
+version = "2.24.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic-ai-slim", extra = ["anthropic", "cli", "evals", "google", "logfire", "mcp", "openai", "retries", "web"] },
]
-sdist = { url = "https://files.pythonhosted.org/packages/1c/73/8dbd43b74f31c187a57fc2b7ae35d2596893b8f386abebadc2d136e62e7e/pydantic_ai-2.23.0.tar.gz", hash = "sha256:3da15a28e171cbb4548f3fffbd098dd9df44888c800dd7e48633795e18525a07", size = 19369, upload-time = "2026-08-04T01:58:18.18Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/8f/43/d36321d72c526471cd1c02987d1f520c366ea209fbba47f8b4d6b07038af/pydantic_ai-2.24.0.tar.gz", hash = "sha256:3a869db582b216d1b7549e20f9af1bee1c89671d702e8a8a7480894eb2cc516c", size = 19368, upload-time = "2026-08-05T02:30:06.052Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/3d/af/965fb83595ab34f5c0b6363323ac15c9aa478fc5de7cfc3360386eed7bd0/pydantic_ai-2.23.0-py3-none-any.whl", hash = "sha256:a9042f5880522565c36e716a983c196d57cc9e2c40e8fd1188ee40802fc8d104", size = 7740, upload-time = "2026-08-04T01:58:08.868Z" },
+ { url = "https://files.pythonhosted.org/packages/a7/51/e08738bce3d6c310077a3d925b946fbc8cf96b22e0858013afa71810fee5/pydantic_ai-2.24.0-py3-none-any.whl", hash = "sha256:7cc0b980a2769a308c0529bf2e2086fca72e674e7c1d4a15be96c9e911112ac3", size = 7740, upload-time = "2026-08-05T02:29:58.138Z" },
]
[[package]]
@@ -3155,7 +3158,7 @@ wheels = [
[[package]]
name = "pydantic-ai-slim"
-version = "2.23.0"
+version = "2.24.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -3167,9 +3170,9 @@ dependencies = [
{ name = "pydantic-graph" },
{ name = "typing-inspection" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/0d/9f/53b19efefa041c1080f7c4ad41679a9293cce64f1265168a98cbe06a0ab7/pydantic_ai_slim-2.23.0.tar.gz", hash = "sha256:d16dcbfb2bfea0ee162bf0f499442fab5a4d69b41e4c54f3b694c2e90b983768", size = 965485, upload-time = "2026-08-04T01:58:20.668Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/64/fd/875459f2ed354401760a8e2d427894ee906a0f90a9e7c27e7d8a2fd1b024/pydantic_ai_slim-2.24.0.tar.gz", hash = "sha256:56f21fa0944da4c38b56cfdb3aec0777d8d5cd451c18651ca58faaec485ee004", size = 972138, upload-time = "2026-08-05T02:30:07.899Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/9e/6f/539a255524178a8421d582271a8d7f8667b036f02b4ddc4f20abcc63888b/pydantic_ai_slim-2.23.0-py3-none-any.whl", hash = "sha256:a2fa3e56408bbf1b83900e3dd4ad9b137297742f450863c2f0f9a03a547d0e33", size = 1157486, upload-time = "2026-08-04T01:58:12.356Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/1a/6d9643f06c960eb9e943e081c4790ed2842dcb4ccf47e5a07788e097f6c7/pydantic_ai_slim-2.24.0-py3-none-any.whl", hash = "sha256:934552227426c89edc51742c4827dd416ddfccb6d76536ddd8e5be7d9d403aa5", size = 1165666, upload-time = "2026-08-05T02:30:00.812Z" },
]
[package.optional-dependencies]
@@ -3255,7 +3258,7 @@ wheels = [
[[package]]
name = "pydantic-evals"
-version = "2.23.0"
+version = "2.24.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -3265,14 +3268,14 @@ dependencies = [
{ name = "pyyaml" },
{ name = "rich" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/ae/4e/ac3bcbbefe683991e8cbd3f69c624c2d550002e9f33fe03ba9e69309ef94/pydantic_evals-2.23.0.tar.gz", hash = "sha256:3f5e16708976c165ae23109f55143fa3d68a3f569b35bc70ca7c54cf737df63e", size = 85391, upload-time = "2026-08-04T01:58:21.933Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/3a/a8/9db0909b4e3bcccbb8a6a560bf18e1fe4b576fa34286fd8630e985b5b1c5/pydantic_evals-2.24.0.tar.gz", hash = "sha256:0ff5fd9ed6502645236bcce6eec2a7ee39b1e174347335f472905a4e85f7c9f3", size = 85393, upload-time = "2026-08-05T02:30:09.723Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/45/72/569511b3de588615a9151b727dedc181d2d54d5434d55b768dc26fa20ab0/pydantic_evals-2.23.0-py3-none-any.whl", hash = "sha256:8cde69fc2e126b20372488187b016f329fab710bd325d10dc4083a9e19ff04b2", size = 100540, upload-time = "2026-08-04T01:58:14.431Z" },
+ { url = "https://files.pythonhosted.org/packages/41/20/bf5ea1048958c8d692a3d02a8bdac1b8d20bbd7b41945dcba4e5e33f85bf/pydantic_evals-2.24.0-py3-none-any.whl", hash = "sha256:5a751012040c235ee1b8b8e25fc5e31a50f8be397ccfe3193ed323ee85d622ee", size = 100539, upload-time = "2026-08-05T02:30:02.526Z" },
]
[[package]]
name = "pydantic-graph"
-version = "2.23.0"
+version = "2.24.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -3281,9 +3284,9 @@ dependencies = [
{ name = "pydantic" },
{ name = "typing-inspection" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/09/fc/273bac7d14fb62c060e0c20c51a9cc60e9e90a96d992fd20e77abf4b6ac1/pydantic_graph-2.23.0.tar.gz", hash = "sha256:54c9939f47fd8a268c96320d7d90e7cef037cbfd2625a675dc4028c1377f70ab", size = 45179, upload-time = "2026-08-04T01:58:23.085Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/c6/37/1ace6e245823b2f0387e9f28390e5f1309686b2dc17a799e3a530f986c53/pydantic_graph-2.24.0.tar.gz", hash = "sha256:04546807cdc5c36793088a3c42dcffd74825e192b06cafd7d43f0726dc8a302e", size = 45179, upload-time = "2026-08-05T02:30:10.773Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/0d/c4/875cf853d205dc55422bd44ff0fbfac82e6e34ff7693df016fc3a4088d32/pydantic_graph-2.23.0-py3-none-any.whl", hash = "sha256:b0f12b4f72adb2a5522b5962c95e1a7b140cb3f631a628036f935e291a9e50ba", size = 52662, upload-time = "2026-08-04T01:58:15.858Z" },
+ { url = "https://files.pythonhosted.org/packages/54/a3/0d6eadc5caeb536198f998fd21bd5ade05459edd58057ff4c0322a8ef773/pydantic_graph-2.24.0-py3-none-any.whl", hash = "sha256:be32705d3e92fad0c3149f9b4b8708fd2583e1aa02c36c26556538f8ecc1c8de", size = 52661, upload-time = "2026-08-05T02:30:03.821Z" },
]
[[package]]
From 1e2cf7a2f891be748754aec42516499a26554e07 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Wed, 5 Aug 2026 08:50:56 +0200
Subject: [PATCH 026/197] LCORE-3410: Optional type in
llama_stack_configuration.py
---
src/llama_stack_configuration.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/llama_stack_configuration.py b/src/llama_stack_configuration.py
index 766f04fb4..62e76ec4b 100644
--- a/src/llama_stack_configuration.py
+++ b/src/llama_stack_configuration.py
@@ -516,8 +516,8 @@ def enrich_byok_rag(ls_config: dict[str, Any], byok_rag: list[dict[str, Any]]) -
def _vector_store_provider_by_id(
- providers: list[dict[str, Any]], provider_id: str | None
-) -> dict[str, Any] | None:
+ providers: list[dict[str, Any]], provider_id: Optional[str]
+) -> Optional[dict[str, Any]]:
"""Return the provider entry matching ``provider_id``.
Parameters:
From 68ae3e285fe915579e3cedc3a7186dd2945e314d Mon Sep 17 00:00:00 2001
From: Andrej Simurka
Date: Wed, 5 Aug 2026 09:15:13 +0200
Subject: [PATCH 027/197] Added explicit model registration for vertexai
---
examples/vertexai-run.yaml | 4 ++++
tests/e2e/configs/run-vertexai.yaml | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/examples/vertexai-run.yaml b/examples/vertexai-run.yaml
index 69f0a8a28..266bd778d 100644
--- a/examples/vertexai-run.yaml
+++ b/examples/vertexai-run.yaml
@@ -97,6 +97,10 @@ storage:
backend: sql_default
registered_resources:
models:
+ - model_id: google/gemini-2.5-flash
+ provider_id: google-vertex
+ model_type: llm
+ provider_model_id: google/gemini-2.5-flash
- model_id: all-mpnet-base-v2
model_type: embedding
provider_id: sentence-transformers
diff --git a/tests/e2e/configs/run-vertexai.yaml b/tests/e2e/configs/run-vertexai.yaml
index 341413097..1caf7648b 100644
--- a/tests/e2e/configs/run-vertexai.yaml
+++ b/tests/e2e/configs/run-vertexai.yaml
@@ -98,6 +98,10 @@ storage:
backend: sql_default
registered_resources:
models:
+ - model_id: google/gemini-2.5-flash
+ provider_id: google-vertex
+ model_type: llm
+ provider_model_id: google/gemini-2.5-flash
- model_id: all-mpnet-base-v2
model_type: embedding
provider_id: sentence-transformers
From c4073dc4928ef71d1c7fd7f0636ebe030d28b4ca Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Wed, 5 Aug 2026 13:28:26 +0200
Subject: [PATCH 028/197] LCORE-3292: Fixed too long line
---
scripts/vulnerability_report.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/vulnerability_report.py b/scripts/vulnerability_report.py
index eea3b1471..daae6ce9d 100644
--- a/scripts/vulnerability_report.py
+++ b/scripts/vulnerability_report.py
@@ -140,7 +140,8 @@ def check_args(args: Namespace) -> None:
Validate command-line argument consistency.
- Ensures that if graph generation is enabled, at least one output format (SVG or PNG) is specified.
+ Ensures that if graph generation is enabled on command line, at least one output format
+ (SVG or PNG) is specified.
Raises:
ValueError: If graph generation is requested but neither SVG nor PNG output is selected.
From 90872d445ae740fb2df72440024f400082aa972b Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Wed, 5 Aug 2026 13:31:34 +0200
Subject: [PATCH 029/197] LCORE-1555: CVE in NLTK
---
.konflux/requirements.hashes.wheel.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.konflux/requirements.hashes.wheel.txt b/.konflux/requirements.hashes.wheel.txt
index e9c8934a9..c165d5202 100644
--- a/.konflux/requirements.hashes.wheel.txt
+++ b/.konflux/requirements.hashes.wheel.txt
@@ -213,8 +213,8 @@ narwhals==2.23.0 \
--hash=sha256:c1627216d19dd2e8ba31484f558b450424cb253bcb73950922a0cf133b57ea77
networkx==3.6.1 \
--hash=sha256:56b687ad58bed743066f1b7d5e6f56a72d2f193c8eaf35064abaedda4fba3745
-nltk==3.9.4 \
- --hash=sha256:99935c670d486819ac6b9c78b2b36b811bdb8e0720414ee3f3663d8ff521bd62
+nltk==3.10.0 \
+ --hash=sha256:a15da2911adca5c7b4574b902f6b344f3f65db72ded7f79b30617bbe7100d318
numpy==2.3.5 \
--hash=sha256:927205c8882f7a53543a8fc5b13fcb05771d6bfff35e06daf8030e57549cc7be \
--hash=sha256:a08c6c26c26d7530d09ac93bc177593958c2e3ce4a9b5750c14a80329cca157c
From b0813e7a88a3ed0d582299f32192e214811c55e7 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Wed, 5 Aug 2026 13:50:26 +0200
Subject: [PATCH 030/197] Transitive deps
---
.konflux/requirements.hashes.wheel.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.konflux/requirements.hashes.wheel.txt b/.konflux/requirements.hashes.wheel.txt
index c165d5202..53692dfc8 100644
--- a/.konflux/requirements.hashes.wheel.txt
+++ b/.konflux/requirements.hashes.wheel.txt
@@ -62,6 +62,8 @@ cryptography==49.0.0 \
--hash=sha256:44e7dda87cce4e64a4eada2469ade616471772ee8203d7331967ef7ba2fee2bd
datasets==5.0.0 \
--hash=sha256:0fbc08ef020b03a22d91ad38b3b22091a1e18c1335f2963d357ea540bfb032e7
+defusedxml==0.7.1 \
+ --hash=sha256:884a1483dffbab373933eb9604e1ebb2a6d5e794b1c467e83ddd453a9d48b1c6
dill==0.4.1 \
--hash=sha256:8aa45e639751fc9610ff6aa53229cd95c66142cb2372fa4b530985c0d6a445ce
distro==1.9.0 \
From 87c4785fdba5d7bcb7af25a7b7501f9d633a6faa Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Wed, 5 Aug 2026 14:16:12 +0200
Subject: [PATCH 031/197] Konflux pipelines
---
.tekton/lightspeed-stack-0-7-pull-request.yaml | 2 +-
.tekton/lightspeed-stack-0-7-push.yaml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.tekton/lightspeed-stack-0-7-pull-request.yaml b/.tekton/lightspeed-stack-0-7-pull-request.yaml
index edec4f6f5..e27eea079 100644
--- a/.tekton/lightspeed-stack-0-7-pull-request.yaml
+++ b/.tekton/lightspeed-stack-0-7-pull-request.yaml
@@ -53,7 +53,7 @@ spec:
],
"requirements_build_files": ["requirements-build.txt"],
"binary": {
- "packages": "a2a-sdk,accelerate,aiofile,aiohappyeyeballs,aiohttp,aiosignal,aiosqlite,annotated-doc,annotated-types,anthropic,anyio,argcomplete,asyncpg,attrs,authlib,autoevals,azure-core,azure-identity,beartype,cachetools,caio,certifi,cffi,chardet,charset-normalizer,chevron,click,cryptography,datasets,dill,distro,dnspython,docstring-parser,durationpy,einops,email-validator,emoji,exceptiongroup,executing,faiss-cpu,fastapi,fastmcp-slim,fastuuid,filelock,fire,frozenlist,fsspec,genai-prices,google-api-core,google-auth,google-cloud-core,google-cloud-storage,google-crc32c,google-genai,google-resumable-media,googleapis-common-protos,greenlet,griffelib,grpc-google-iam-v1,grpcio,grpcio-status,h11,hf-xet,httpcore,httpcore2,httpx,httpx-sse,httpx2,huggingface-hub,idna,importlib-metadata,jaraco-classes,jaraco-context,jaraco-functools,jeepney,jinja2,jiter,joblib,joserfc,jsonpath-ng,jsonschema,jsonschema-specifications,keyring,kubernetes,langdetect,litellm,logfire,logfire-api,markdown-it-py,markupsafe,maturin,mcp,mdurl,more-itertools,mpmath,msal,msal-extensions,multidict,multiprocess,narwhals,networkx,nltk,numpy,oauthlib,ogx,ogx-api,ogx-client,openai,opentelemetry-api,opentelemetry-distro,opentelemetry-exporter-otlp,opentelemetry-exporter-otlp-proto-common,opentelemetry-exporter-otlp-proto-grpc,opentelemetry-exporter-otlp-proto-http,opentelemetry-instrumentation,opentelemetry-instrumentation-httpx,opentelemetry-proto,opentelemetry-sdk,opentelemetry-semantic-conventions,opentelemetry-util-http,oracledb,packaging,pandas,peft,pip,platformdirs,polyleven,prometheus-client,prompt-toolkit,propcache,proto-plus,protobuf,psutil,psycopg2-binary,py-key-value-aio,pyaml,pyarrow,pyasn1,pyasn1-modules,pycparser,pydantic,pydantic-ai,pydantic-ai-slim,pydantic-core,pydantic-evals,pydantic-graph,pydantic-settings,pygments,pyjwt,pyopenssl,pypdf,pyperclip,python-dateutil,python-dotenv,python-multipart,pytz,pyyaml,referencing,regex,requests,requests-oauthlib,rich,rpds-py,safetensors,scikit-learn,scipy,secretstorage,semver,sentence-transformers,sentry-sdk,setuptools,shellingham,six,sniffio,sqlalchemy,sse-starlette,starlette,structlog,sympy,tenacity,termcolor,threadpoolctl,tiktoken,tokenizers,torch,tornado,tqdm,transformers,tree-sitter,triton,trl,truststore,typer,typing-extensions,typing-inspection,urllib3,uv,uv-build,uvicorn,wcwidth,websocket-client,websockets,wrapt,xxhash,yarl,zipp,zstandard",
+ "packages": "a2a-sdk,accelerate,aiofile,aiohappyeyeballs,aiohttp,aiosignal,aiosqlite,annotated-doc,annotated-types,anthropic,anyio,argcomplete,asyncpg,attrs,authlib,autoevals,azure-core,azure-identity,beartype,cachetools,caio,certifi,cffi,chardet,charset-normalizer,chevron,click,cryptography,datasets,defusedxml,dill,distro,dnspython,docstring-parser,durationpy,einops,email-validator,emoji,exceptiongroup,executing,faiss-cpu,fastapi,fastmcp-slim,fastuuid,filelock,fire,frozenlist,fsspec,genai-prices,google-api-core,google-auth,google-cloud-core,google-cloud-storage,google-crc32c,google-genai,google-resumable-media,googleapis-common-protos,greenlet,griffelib,grpc-google-iam-v1,grpcio,grpcio-status,h11,hf-xet,httpcore,httpcore2,httpx,httpx-sse,httpx2,huggingface-hub,idna,importlib-metadata,jaraco-classes,jaraco-context,jaraco-functools,jeepney,jinja2,jiter,joblib,joserfc,jsonpath-ng,jsonschema,jsonschema-specifications,keyring,kubernetes,langdetect,litellm,logfire,logfire-api,markdown-it-py,markupsafe,maturin,mcp,mdurl,more-itertools,mpmath,msal,msal-extensions,multidict,multiprocess,narwhals,networkx,nltk,numpy,oauthlib,ogx,ogx-api,ogx-client,openai,opentelemetry-api,opentelemetry-distro,opentelemetry-exporter-otlp,opentelemetry-exporter-otlp-proto-common,opentelemetry-exporter-otlp-proto-grpc,opentelemetry-exporter-otlp-proto-http,opentelemetry-instrumentation,opentelemetry-instrumentation-httpx,opentelemetry-proto,opentelemetry-sdk,opentelemetry-semantic-conventions,opentelemetry-util-http,oracledb,packaging,pandas,peft,pip,platformdirs,polyleven,prometheus-client,prompt-toolkit,propcache,proto-plus,protobuf,psutil,psycopg2-binary,py-key-value-aio,pyaml,pyarrow,pyasn1,pyasn1-modules,pycparser,pydantic,pydantic-ai,pydantic-ai-slim,pydantic-core,pydantic-evals,pydantic-graph,pydantic-settings,pygments,pyjwt,pyopenssl,pypdf,pyperclip,python-dateutil,python-dotenv,python-multipart,pytz,pyyaml,referencing,regex,requests,requests-oauthlib,rich,rpds-py,safetensors,scikit-learn,scipy,secretstorage,semver,sentence-transformers,sentry-sdk,setuptools,shellingham,six,sniffio,sqlalchemy,sse-starlette,starlette,structlog,sympy,tenacity,termcolor,threadpoolctl,tiktoken,tokenizers,torch,tornado,tqdm,transformers,tree-sitter,triton,trl,truststore,typer,typing-extensions,typing-inspection,urllib3,uv,uv-build,uvicorn,wcwidth,websocket-client,websockets,wrapt,xxhash,yarl,zipp,zstandard",
"os": "linux",
"arch": "x86_64,aarch64",
"py_version": 312
diff --git a/.tekton/lightspeed-stack-0-7-push.yaml b/.tekton/lightspeed-stack-0-7-push.yaml
index d71531d5f..fc1b611d0 100644
--- a/.tekton/lightspeed-stack-0-7-push.yaml
+++ b/.tekton/lightspeed-stack-0-7-push.yaml
@@ -54,7 +54,7 @@ spec:
],
"requirements_build_files": ["requirements-build.txt"],
"binary": {
- "packages": "a2a-sdk,accelerate,aiofile,aiohappyeyeballs,aiohttp,aiosignal,aiosqlite,annotated-doc,annotated-types,anthropic,anyio,argcomplete,asyncpg,attrs,authlib,autoevals,azure-core,azure-identity,beartype,cachetools,caio,certifi,cffi,chardet,charset-normalizer,chevron,click,cryptography,datasets,dill,distro,dnspython,docstring-parser,durationpy,einops,email-validator,emoji,exceptiongroup,executing,faiss-cpu,fastapi,fastmcp-slim,fastuuid,filelock,fire,frozenlist,fsspec,genai-prices,google-api-core,google-auth,google-cloud-core,google-cloud-storage,google-crc32c,google-genai,google-resumable-media,googleapis-common-protos,greenlet,griffelib,grpc-google-iam-v1,grpcio,grpcio-status,h11,hf-xet,httpcore,httpcore2,httpx,httpx-sse,httpx2,huggingface-hub,idna,importlib-metadata,jaraco-classes,jaraco-context,jaraco-functools,jeepney,jinja2,jiter,joblib,joserfc,jsonpath-ng,jsonschema,jsonschema-specifications,keyring,kubernetes,langdetect,litellm,logfire,logfire-api,markdown-it-py,markupsafe,maturin,mcp,mdurl,more-itertools,mpmath,msal,msal-extensions,multidict,multiprocess,narwhals,networkx,nltk,numpy,oauthlib,ogx,ogx-api,ogx-client,openai,opentelemetry-api,opentelemetry-distro,opentelemetry-exporter-otlp,opentelemetry-exporter-otlp-proto-common,opentelemetry-exporter-otlp-proto-grpc,opentelemetry-exporter-otlp-proto-http,opentelemetry-instrumentation,opentelemetry-instrumentation-httpx,opentelemetry-proto,opentelemetry-sdk,opentelemetry-semantic-conventions,opentelemetry-util-http,oracledb,packaging,pandas,peft,pip,platformdirs,polyleven,prometheus-client,prompt-toolkit,propcache,proto-plus,protobuf,psutil,psycopg2-binary,py-key-value-aio,pyaml,pyarrow,pyasn1,pyasn1-modules,pycparser,pydantic,pydantic-ai,pydantic-ai-slim,pydantic-core,pydantic-evals,pydantic-graph,pydantic-settings,pygments,pyjwt,pyopenssl,pypdf,pyperclip,python-dateutil,python-dotenv,python-multipart,pytz,pyyaml,referencing,regex,requests,requests-oauthlib,rich,rpds-py,safetensors,scikit-learn,scipy,secretstorage,semver,sentence-transformers,sentry-sdk,setuptools,shellingham,six,sniffio,sqlalchemy,sse-starlette,starlette,structlog,sympy,tenacity,termcolor,threadpoolctl,tiktoken,tokenizers,torch,tornado,tqdm,transformers,tree-sitter,triton,trl,truststore,typer,typing-extensions,typing-inspection,urllib3,uv,uv-build,uvicorn,wcwidth,websocket-client,websockets,wrapt,xxhash,yarl,zipp,zstandard",
+ "packages": "a2a-sdk,accelerate,aiofile,aiohappyeyeballs,aiohttp,aiosignal,aiosqlite,annotated-doc,annotated-types,anthropic,anyio,argcomplete,asyncpg,attrs,authlib,autoevals,azure-core,azure-identity,beartype,cachetools,caio,certifi,cffi,chardet,charset-normalizer,chevron,click,cryptography,datasets,defusedxml,dill,distro,dnspython,docstring-parser,durationpy,einops,email-validator,emoji,exceptiongroup,executing,faiss-cpu,fastapi,fastmcp-slim,fastuuid,filelock,fire,frozenlist,fsspec,genai-prices,google-api-core,google-auth,google-cloud-core,google-cloud-storage,google-crc32c,google-genai,google-resumable-media,googleapis-common-protos,greenlet,griffelib,grpc-google-iam-v1,grpcio,grpcio-status,h11,hf-xet,httpcore,httpcore2,httpx,httpx-sse,httpx2,huggingface-hub,idna,importlib-metadata,jaraco-classes,jaraco-context,jaraco-functools,jeepney,jinja2,jiter,joblib,joserfc,jsonpath-ng,jsonschema,jsonschema-specifications,keyring,kubernetes,langdetect,litellm,logfire,logfire-api,markdown-it-py,markupsafe,maturin,mcp,mdurl,more-itertools,mpmath,msal,msal-extensions,multidict,multiprocess,narwhals,networkx,nltk,numpy,oauthlib,ogx,ogx-api,ogx-client,openai,opentelemetry-api,opentelemetry-distro,opentelemetry-exporter-otlp,opentelemetry-exporter-otlp-proto-common,opentelemetry-exporter-otlp-proto-grpc,opentelemetry-exporter-otlp-proto-http,opentelemetry-instrumentation,opentelemetry-instrumentation-httpx,opentelemetry-proto,opentelemetry-sdk,opentelemetry-semantic-conventions,opentelemetry-util-http,oracledb,packaging,pandas,peft,pip,platformdirs,polyleven,prometheus-client,prompt-toolkit,propcache,proto-plus,protobuf,psutil,psycopg2-binary,py-key-value-aio,pyaml,pyarrow,pyasn1,pyasn1-modules,pycparser,pydantic,pydantic-ai,pydantic-ai-slim,pydantic-core,pydantic-evals,pydantic-graph,pydantic-settings,pygments,pyjwt,pyopenssl,pypdf,pyperclip,python-dateutil,python-dotenv,python-multipart,pytz,pyyaml,referencing,regex,requests,requests-oauthlib,rich,rpds-py,safetensors,scikit-learn,scipy,secretstorage,semver,sentence-transformers,sentry-sdk,setuptools,shellingham,six,sniffio,sqlalchemy,sse-starlette,starlette,structlog,sympy,tenacity,termcolor,threadpoolctl,tiktoken,tokenizers,torch,tornado,tqdm,transformers,tree-sitter,triton,trl,truststore,typer,typing-extensions,typing-inspection,urllib3,uv,uv-build,uvicorn,wcwidth,websocket-client,websockets,wrapt,xxhash,yarl,zipp,zstandard",
"os": "linux",
"arch": "x86_64,aarch64",
"py_version": 312
From 05f705ff3c704739e52a93f505f19da88fe2bc36 Mon Sep 17 00:00:00 2001
From: Andrej Simurka
Date: Wed, 5 Aug 2026 14:18:57 +0200
Subject: [PATCH 032/197] Fix vertexai and bedrock model paths
---
.github/workflows/e2e_tests_providers.yaml | 14 +++++++-------
examples/vertexai-run.yaml | 6 +++---
tests/e2e/configs/run-bedrock.yaml | 2 +-
tests/e2e/configs/run-vertexai.yaml | 6 +++---
4 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/.github/workflows/e2e_tests_providers.yaml b/.github/workflows/e2e_tests_providers.yaml
index c18935252..344a95254 100644
--- a/.github/workflows/e2e_tests_providers.yaml
+++ b/.github/workflows/e2e_tests_providers.yaml
@@ -15,18 +15,18 @@ jobs:
mode: ["server", "library"]
environment: ["azure", "vertexai", "watsonx", "bedrock"]
# Expected default LLM for Behave (matches tests/e2e/configs/run-.yaml).
- # | environment | model_id | provider_id |
- # |-------------|-------------------------------------|---------------|
- # | azure | gpt-4o-mini | azure |
- # | vertexai | google/gemini-2.5-flash | google-vertex |
- # | watsonx | meta-llama/llama-3-3-70b-instruct | watsonx |
- # | bedrock | deepseek.v3-v1:0 | aws-bedrock |
+ # | environment | model_id | provider_id |
+ # |-------------|--------------------------------------------| --------------|
+ # | azure | gpt-4o-mini | azure |
+ # | vertexai | publishers/google/models/gemini-2.5-flash | google-vertex |
+ # | watsonx | meta-llama/llama-3-3-70b-instruct | watsonx |
+ # | bedrock | deepseek.v3-v1:0 | aws-bedrock |
include:
- environment: azure
e2e_default_model: gpt-4o-mini
e2e_default_provider: azure
- environment: vertexai
- e2e_default_model: google/gemini-2.5-flash
+ e2e_default_model: publishers/google/models/gemini-2.5-flash
e2e_default_provider: google-vertex
- environment: watsonx
e2e_default_model: meta-llama/llama-3-3-70b-instruct
diff --git a/examples/vertexai-run.yaml b/examples/vertexai-run.yaml
index 266bd778d..5e29257c9 100644
--- a/examples/vertexai-run.yaml
+++ b/examples/vertexai-run.yaml
@@ -19,7 +19,7 @@ providers:
config:
project: ${env.VERTEX_AI_PROJECT}
location: ${env.VERTEX_AI_LOCATION}
- allowed_models: ["google/gemini-2.5-flash"]
+ allowed_models: ["publishers/google/models/gemini-2.5-flash"]
- provider_id: openai
provider_type: remote::openai
config:
@@ -97,10 +97,10 @@ storage:
backend: sql_default
registered_resources:
models:
- - model_id: google/gemini-2.5-flash
+ - model_id: publishers/google/models/gemini-2.5-flash
provider_id: google-vertex
model_type: llm
- provider_model_id: google/gemini-2.5-flash
+ provider_model_id: publishers/google/models/gemini-2.5-flash
- model_id: all-mpnet-base-v2
model_type: embedding
provider_id: sentence-transformers
diff --git a/tests/e2e/configs/run-bedrock.yaml b/tests/e2e/configs/run-bedrock.yaml
index 2de83e64d..3448351e4 100644
--- a/tests/e2e/configs/run-bedrock.yaml
+++ b/tests/e2e/configs/run-bedrock.yaml
@@ -97,7 +97,7 @@ storage:
backend: sql_default
registered_resources:
models:
- - model_id: custom-bedrock-model
+ - model_id: deepseek.v3-v1:0
model_type: llm
provider_id: aws-bedrock
provider_model_id: deepseek.v3-v1:0
diff --git a/tests/e2e/configs/run-vertexai.yaml b/tests/e2e/configs/run-vertexai.yaml
index 1caf7648b..ba361be6d 100644
--- a/tests/e2e/configs/run-vertexai.yaml
+++ b/tests/e2e/configs/run-vertexai.yaml
@@ -19,7 +19,7 @@ providers:
config:
project: ${env.VERTEX_AI_PROJECT}
location: ${env.VERTEX_AI_LOCATION}
- allowed_models: ["google/gemini-2.5-flash"]
+ allowed_models: ["publishers/google/models/gemini-2.5-flash"]
- provider_id: openai
provider_type: remote::openai
config:
@@ -98,10 +98,10 @@ storage:
backend: sql_default
registered_resources:
models:
- - model_id: google/gemini-2.5-flash
+ - model_id: publishers/google/models/gemini-2.5-flash
provider_id: google-vertex
model_type: llm
- provider_model_id: google/gemini-2.5-flash
+ provider_model_id: publishers/google/models/gemini-2.5-flash
- model_id: all-mpnet-base-v2
model_type: embedding
provider_id: sentence-transformers
From 1ba9590024ee62d69e7dd7a451b01c12b30d57a2 Mon Sep 17 00:00:00 2001
From: Anik Bhattacharjee
Date: Wed, 5 Aug 2026 11:42:41 -0400
Subject: [PATCH 033/197] LCORE-3424: Add workflow and dependency
troubleshooting guidance to AGENTS.md
Adds two new sections to the development guide to improve developer experience and reduce CI friction:
1. **Workflow Rules** - Proactive CI/quality check requirements
2. **Environment & Dependencies** - Dependency troubleshooting guidance
Analysis of recent development sessions revealed two recurring friction patterns:
- Code changes frequently failed CI (Black, pylint, tests) after PR submission, requiring multiple fix cycles
- Dependency/import issues were difficult to diagnose due to venv/system Python confusion and Makefile hardcoded paths
---
AGENTS.md | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/AGENTS.md b/AGENTS.md
index 413616ffb..8b9f83812 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,5 +1,18 @@
# Lightspeed Core Stack Development Guide
+## Workflow Rules
+
+### CI/Quality Checks Before Completion
+After making code changes, proactively run the full CI/linting pipeline before presenting changes as complete. Do not wait for the user to report CI failures.
+
+**Required checks:**
+- `uv run make format` - Black formatting
+- `uv run make verify` - All linters (pylint, pyright, ruff, docstyle)
+- `uv run make test-unit` - Unit tests
+- OpenAPI schema regeneration if models changed
+
+Only report work as complete after all checks pass.
+
## Project Overview
Lightspeed Core Stack (LCS) is an AI-powered assistant built on FastAPI that provides answers using LLM services, agents, and RAG databases. It integrates with Llama Stack for AI operations.
@@ -10,6 +23,22 @@ Lightspeed Core Stack (LCS) is an AI-powered assistant built on FastAPI that pro
- `uv run make format` - Format code (black + ruff)
- `uv run make verify` - Run all linters (black, pylint, pyright, ruff, docstyle, check-types)
+## Environment & Dependencies
+
+This project uses Python with uv for dependency management. When debugging dependency/import issues, check:
+
+1. **Which Python binary is being invoked** (system vs venv)
+ - Run `which python` to verify the active Python
+ - Check if `.venv/bin/python` is being used
+ - System Python vs venv Python can cause ModuleNotFoundError
+
+2. **Whether `uv sync` was run in the correct environment**
+ - Run `uv sync --group dev` to install all dependencies
+ - Verify packages are installed in `.venv/lib/python*/site-packages/`
+ - Ensure the command was run in the project root directory
+
+Do not suggest generic venv activation without checking these first.
+
## Code Architecture & Patterns
### Project Structure
From 86a6a8aa2eecb5f78dd54c7486ea2ff650b9a384 Mon Sep 17 00:00:00 2001
From: "red-hat-konflux-kflux-prd-rh02[bot]"
<190377777+red-hat-konflux-kflux-prd-rh02[bot]@users.noreply.github.com>
Date: Wed, 5 Aug 2026 16:00:25 +0000
Subject: [PATCH 034/197] Red Hat Konflux kflux-prd-rh02 update
lightspeed-stack-0-8
Signed-off-by: red-hat-konflux-kflux-prd-rh02[bot] <190377777+red-hat-konflux-kflux-prd-rh02[bot]@users.noreply.github.com>
---
.../lightspeed-stack-0-8-pull-request.yaml | 583 ++++++++++++++++++
.tekton/lightspeed-stack-0-8-push.yaml | 580 +++++++++++++++++
2 files changed, 1163 insertions(+)
create mode 100644 .tekton/lightspeed-stack-0-8-pull-request.yaml
create mode 100644 .tekton/lightspeed-stack-0-8-push.yaml
diff --git a/.tekton/lightspeed-stack-0-8-pull-request.yaml b/.tekton/lightspeed-stack-0-8-pull-request.yaml
new file mode 100644
index 000000000..bd21328d7
--- /dev/null
+++ b/.tekton/lightspeed-stack-0-8-pull-request.yaml
@@ -0,0 +1,583 @@
+apiVersion: tekton.dev/v1
+kind: PipelineRun
+metadata:
+ annotations:
+ build.appstudio.openshift.io/repo: https://github.com/lightspeed-core/lightspeed-stack?rev={{revision}}
+ build.appstudio.redhat.com/commit_sha: '{{revision}}'
+ build.appstudio.redhat.com/pull_request_number: '{{pull_request_number}}'
+ build.appstudio.redhat.com/target_branch: '{{target_branch}}'
+ pipelinesascode.tekton.dev/cancel-in-progress: "true"
+ pipelinesascode.tekton.dev/max-keep-runs: "3"
+ pipelinesascode.tekton.dev/on-cel-expression: event == "pull_request" && target_branch
+ == "main"
+ labels:
+ appstudio.openshift.io/application: lightspeed-core-0-8
+ appstudio.openshift.io/component: lightspeed-stack-0-8
+ pipelines.appstudio.openshift.io/type: build
+ name: lightspeed-stack-0-8-on-pull-request
+ namespace: lightspeed-core-tenant
+spec:
+ params:
+ - name: git-url
+ value: '{{source_url}}'
+ - name: revision
+ value: '{{revision}}'
+ - name: output-image
+ value: quay.io/redhat-user-workloads/lightspeed-core-tenant/lightspeed-stack-0-8:on-pr-{{revision}}
+ - name: image-expires-after
+ value: 5d
+ - name: build-platforms
+ value:
+ - linux/x86_64
+ - name: dockerfile
+ value: Containerfile
+ - name: path-context
+ value: .
+ pipelineSpec:
+ description: |
+ This pipeline is ideal for building multi-arch container images from a Containerfile while maintaining trust after pipeline customization.
+
+ _Uses `buildah` to create a multi-platform container image leveraging [trusted artifacts](https://konflux-ci.dev/architecture/ADR/0036-trusted-artifacts.html). It also optionally creates a source image and runs some build-time tests. This pipeline requires that the [multi platform controller](https://github.com/konflux-ci/multi-platform-controller) is deployed and configured on your Konflux instance. Information is shared between tasks using OCI artifacts instead of PVCs. EC will pass the [`trusted_task.trusted`](https://conforma.dev/docs/policy/packages/release_trusted_task.html#trusted_task__trusted) policy as long as all data used to build the artifact is generated from trusted tasks.
+ This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-docker-build-multi-platform-oci-ta?tab=tags)_
+ params:
+ - description: Source Repository URL
+ name: git-url
+ type: string
+ - default: ""
+ description: Revision of the Source Repository
+ name: revision
+ type: string
+ - description: Fully Qualified Output Image
+ name: output-image
+ type: string
+ - default: .
+ description: Path to the source code of an application's component from where
+ to build image.
+ name: path-context
+ type: string
+ - default: Dockerfile
+ description: Path to the Dockerfile inside the context specified by parameter
+ path-context
+ name: dockerfile
+ type: string
+ - default: "false"
+ description: Skip checks against built image
+ name: skip-checks
+ type: string
+ - default: "false"
+ description: Execute the build with network isolation
+ name: hermetic
+ type: string
+ - default: ""
+ description: Build dependencies to be prefetched
+ name: prefetch-input
+ type: string
+ - default: ""
+ description: Image tag expiration time, time values could be something like
+ 1h, 2d, 3w for hours, days, and weeks, respectively.
+ name: image-expires-after
+ type: string
+ - default: "false"
+ description: Build a source image.
+ name: build-source-image
+ type: string
+ - default: "true"
+ description: Add built image into an OCI image index
+ name: build-image-index
+ type: string
+ - default: docker
+ description: The format for the resulting image's mediaType. Valid values are
+ oci or docker.
+ name: buildah-format
+ type: string
+ - default: "false"
+ description: Enable cache proxy configuration
+ name: enable-cache-proxy
+ - default: "true"
+ description: Use the package registry proxy when prefetching dependencies
+ name: enable-package-registry-proxy
+ - default: .
+ description: Target directories in component's source code to scan with SAST
+ tools. Multiple values should be separated with commas.
+ name: sast-target-dirs
+ type: string
+ - default: []
+ description: Array of --build-arg values ("arg=value" strings) for buildah
+ name: build-args
+ type: array
+ - default: ""
+ description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file
+ name: build-args-file
+ type: string
+ - default: "false"
+ description: Whether to enable privileged mode, should be used only with remote
+ VMs
+ name: privileged-nested
+ type: string
+ - default: ""
+ description: Sets the image created time and the SOURCE_DATE_EPOCH build argument.
+ On its own, it does not change file timestamps inside the layers (set rewrite-timestamp
+ to "true" for that). Leave empty to keep the actual build time.
+ name: source-date-epoch
+ type: string
+ - default: "false"
+ description: When "true", clamp file modification times in the image layers
+ to at most source-date-epoch. Does nothing unless source-date-epoch is set.
+ name: rewrite-timestamp
+ type: string
+ - default: "false"
+ description: When "true", omit the build history (history timestamps, layer
+ metadata, etc.) from the resulting image.
+ name: omit-history
+ type: string
+ - default:
+ - linux/x86_64
+ description: List of platforms to build the container images on. The available
+ set of values is determined by the configuration of the multi-platform-controller.
+ name: build-platforms
+ type: array
+ results:
+ - description: ""
+ name: IMAGE_URL
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - description: ""
+ name: IMAGE_DIGEST
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - description: ""
+ name: CHAINS-GIT_URL
+ value: $(tasks.clone-repository.results.url)
+ - description: ""
+ name: CHAINS-GIT_COMMIT
+ value: $(tasks.clone-repository.results.commit)
+ tasks:
+ - name: init
+ params:
+ - name: enable-cache-proxy
+ value: $(params.enable-cache-proxy)
+ taskRef:
+ params:
+ - name: name
+ value: init
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-init:0.4.2@sha256:421003a5c077ecb820460e71637125ec9093d2101c749a32ede28e190283e9db
+ - name: kind
+ value: task
+ resolver: bundles
+ - name: clone-repository
+ params:
+ - name: url
+ value: $(params.git-url)
+ - name: revision
+ value: $(params.revision)
+ - name: ociStorage
+ value: $(params.output-image).git
+ - name: ociArtifactExpiresAfter
+ value: $(params.image-expires-after)
+ runAfter:
+ - init
+ taskRef:
+ params:
+ - name: name
+ value: git-clone-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-git-clone-oci-ta:0.2.4@sha256:df3c42d78223f07b40a84dd29e5c8860d14777ffdf150ea08c738770f51216dc
+ - name: kind
+ value: task
+ resolver: bundles
+ workspaces:
+ - name: basic-auth
+ workspace: git-auth
+ - name: prefetch-dependencies
+ params:
+ - name: input
+ value: $(params.prefetch-input)
+ - name: enable-package-registry-proxy
+ value: $(params.enable-package-registry-proxy)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.clone-repository.results.SOURCE_ARTIFACT)
+ - name: ociStorage
+ value: $(params.output-image).prefetch
+ - name: ociArtifactExpiresAfter
+ value: $(params.image-expires-after)
+ runAfter:
+ - clone-repository
+ taskRef:
+ params:
+ - name: name
+ value: prefetch-dependencies-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-prefetch-dependencies-oci-ta:0.3.2@sha256:389aea03a065e8118d36b7acb85b05cd13f6750e7e10ff8a85f270ee65b0167b
+ - name: kind
+ value: task
+ resolver: bundles
+ workspaces:
+ - name: git-basic-auth
+ workspace: git-auth
+ - name: netrc
+ workspace: netrc
+ - matrix:
+ params:
+ - name: PLATFORM
+ value:
+ - $(params.build-platforms)
+ name: build-images
+ params:
+ - name: IMAGE
+ value: $(params.output-image)
+ - name: DOCKERFILE
+ value: $(params.dockerfile)
+ - name: CONTEXT
+ value: $(params.path-context)
+ - name: HERMETIC
+ value: $(params.hermetic)
+ - name: PREFETCH_INPUT
+ value: $(params.prefetch-input)
+ - name: IMAGE_EXPIRES_AFTER
+ value: $(params.image-expires-after)
+ - name: COMMIT_SHA
+ value: $(tasks.clone-repository.results.commit)
+ - name: BUILD_ARGS
+ value:
+ - $(params.build-args[*])
+ - name: BUILD_ARGS_FILE
+ value: $(params.build-args-file)
+ - name: PRIVILEGED_NESTED
+ value: $(params.privileged-nested)
+ - name: SOURCE_URL
+ value: $(tasks.clone-repository.results.url)
+ - name: BUILDAH_FORMAT
+ value: $(params.buildah-format)
+ - name: HTTP_PROXY
+ value: $(tasks.init.results.http-proxy)
+ - name: NO_PROXY
+ value: $(tasks.init.results.no-proxy)
+ - name: SOURCE_DATE_EPOCH
+ value: $(params.source-date-epoch)
+ - name: REWRITE_TIMESTAMP
+ value: $(params.rewrite-timestamp)
+ - name: OMIT_HISTORY
+ value: $(params.omit-history)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ - name: CACHI2_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ - name: IMAGE_APPEND_PLATFORM
+ value: "true"
+ runAfter:
+ - prefetch-dependencies
+ taskRef:
+ params:
+ - name: name
+ value: buildah-remote-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-buildah-remote-oci-ta:0.10.5@sha256:eb277ec7b44443f0506a60ac940a2e52178d60f17cb0f51a6966daed5b3755de
+ - name: kind
+ value: task
+ resolver: bundles
+ - name: build-image-index
+ params:
+ - name: IMAGE
+ value: $(params.output-image)
+ - name: ALWAYS_BUILD_INDEX
+ value: $(params.build-image-index)
+ - name: IMAGES
+ value:
+ - $(tasks.build-images.results.IMAGE_REF[*])
+ - name: BUILDAH_FORMAT
+ value: $(params.buildah-format)
+ runAfter:
+ - build-images
+ taskRef:
+ params:
+ - name: name
+ value: build-image-index
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-build-image-index:0.3.1@sha256:cc75f64deecccb1b59e96ac1182665a5342d79c9e22eebff63d26b0f00a4319c
+ - name: kind
+ value: task
+ resolver: bundles
+ - name: build-source-image
+ params:
+ - name: BINARY_IMAGE
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: BINARY_IMAGE_DIGEST
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ - name: CACHI2_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: source-build-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-source-build-oci-ta:0.3@sha256:7c5575ac8e292f27f57716c021ab0324460dc958e73946724c588c5228e5f372
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.build-source-image)
+ operator: in
+ values:
+ - "true"
+ - name: deprecated-base-image-check
+ params:
+ - name: IMAGE_URL
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: IMAGE_DIGEST
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: deprecated-image-check
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-deprecated-image-check:0.5@sha256:0ccc688a77e9b7b0b8973c132a1e840844137e77f887be4a0bec8893b0776872
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - matrix:
+ params:
+ - name: image-platform
+ value:
+ - $(params.build-platforms)
+ name: clair-scan
+ params:
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: clair-scan
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-clair-scan:0.3@sha256:f5b4415db9ac1fba3e11d993a617e0b275d1f0ed2fc669b12c400ed848c39174
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - matrix:
+ params:
+ - name: platform
+ value:
+ - $(params.build-platforms)
+ name: ecosystem-cert-preflight-checks
+ params:
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: ecosystem-cert-preflight-checks
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-ecosystem-cert-preflight-checks:0.2@sha256:e438f3104d706f73812994953d3d0a9c62ac8e4a372d86337ff26bbca9902709
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - name: sast-snyk-check
+ params:
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: TARGET_DIRS
+ value: $(params.sast-target-dirs)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ - name: CACHI2_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: sast-snyk-check-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-snyk-check-oci-ta:0.5@sha256:eba24f5d9f4b18aa71e523b9b3dbcf22982aa4b018824260a090b19dfc9abf6f
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - matrix:
+ params:
+ - name: image-arch
+ value:
+ - $(params.build-platforms)
+ name: clamav-scan
+ params:
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: clamav-scan
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-clamav-scan:0.3@sha256:53a02326bfb930ca5ef6bfa7a33acca833d57752f34f3cb79255fe2e25e7d217
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - name: sast-shell-check
+ params:
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: TARGET_DIRS
+ value: $(params.sast-target-dirs)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ - name: CACHI2_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: sast-shell-check-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-shell-check-oci-ta:0.1@sha256:61b27e6ad5daba761d41bb37efb790ed98380603fd4fe2f86d156def5bd72ecc
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - name: sast-unicode-check
+ params:
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: TARGET_DIRS
+ value: $(params.sast-target-dirs)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ - name: CACHI2_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: sast-unicode-check-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-unicode-check-oci-ta:0.4@sha256:eb9d5392f215cb8b52b16382098cac4885b1e6cd989f88ebd83fdb234d283eb9
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - name: apply-tags
+ params:
+ - name: IMAGE_URL
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: IMAGE_DIGEST
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: apply-tags
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-apply-tags:0.3@sha256:3ab844157eccd68e95e4852adc06c3c4ea674edb7865a474b0a898227f2893d6
+ - name: kind
+ value: task
+ resolver: bundles
+ - name: push-dockerfile
+ params:
+ - name: IMAGE
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: IMAGE_DIGEST
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: DOCKERFILE
+ value: $(params.dockerfile)
+ - name: CONTEXT
+ value: $(params.path-context)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: push-dockerfile-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-push-dockerfile-oci-ta:0.3.1@sha256:5a6cbebd89e5bc163b38231859767f7f6a0dd66cf1333699574379f062731183
+ - name: kind
+ value: task
+ resolver: bundles
+ - name: rpms-signature-scan
+ params:
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: rpms-signature-scan
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-rpms-signature-scan:0.2@sha256:ccb77d1bf7627fc6241a59ed42bb6e5707a8682754fe8ae18f2cfdddbcf29275
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ workspaces:
+ - name: git-auth
+ optional: true
+ - name: netrc
+ optional: true
+ taskRunTemplate:
+ serviceAccountName: build-pipeline-lightspeed-stack-0-8
+ workspaces:
+ - name: git-auth
+ secret:
+ secretName: '{{ git_auth_secret }}'
+status: {}
diff --git a/.tekton/lightspeed-stack-0-8-push.yaml b/.tekton/lightspeed-stack-0-8-push.yaml
new file mode 100644
index 000000000..183726ce1
--- /dev/null
+++ b/.tekton/lightspeed-stack-0-8-push.yaml
@@ -0,0 +1,580 @@
+apiVersion: tekton.dev/v1
+kind: PipelineRun
+metadata:
+ annotations:
+ build.appstudio.openshift.io/repo: https://github.com/lightspeed-core/lightspeed-stack?rev={{revision}}
+ build.appstudio.redhat.com/commit_sha: '{{revision}}'
+ build.appstudio.redhat.com/target_branch: '{{target_branch}}'
+ pipelinesascode.tekton.dev/cancel-in-progress: "false"
+ pipelinesascode.tekton.dev/max-keep-runs: "3"
+ pipelinesascode.tekton.dev/on-cel-expression: event == "push" && target_branch
+ == "main"
+ labels:
+ appstudio.openshift.io/application: lightspeed-core-0-8
+ appstudio.openshift.io/component: lightspeed-stack-0-8
+ pipelines.appstudio.openshift.io/type: build
+ name: lightspeed-stack-0-8-on-push
+ namespace: lightspeed-core-tenant
+spec:
+ params:
+ - name: git-url
+ value: '{{source_url}}'
+ - name: revision
+ value: '{{revision}}'
+ - name: output-image
+ value: quay.io/redhat-user-workloads/lightspeed-core-tenant/lightspeed-stack-0-8:{{revision}}
+ - name: build-platforms
+ value:
+ - linux/x86_64
+ - name: dockerfile
+ value: Containerfile
+ - name: path-context
+ value: .
+ pipelineSpec:
+ description: |
+ This pipeline is ideal for building multi-arch container images from a Containerfile while maintaining trust after pipeline customization.
+
+ _Uses `buildah` to create a multi-platform container image leveraging [trusted artifacts](https://konflux-ci.dev/architecture/ADR/0036-trusted-artifacts.html). It also optionally creates a source image and runs some build-time tests. This pipeline requires that the [multi platform controller](https://github.com/konflux-ci/multi-platform-controller) is deployed and configured on your Konflux instance. Information is shared between tasks using OCI artifacts instead of PVCs. EC will pass the [`trusted_task.trusted`](https://conforma.dev/docs/policy/packages/release_trusted_task.html#trusted_task__trusted) policy as long as all data used to build the artifact is generated from trusted tasks.
+ This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-docker-build-multi-platform-oci-ta?tab=tags)_
+ params:
+ - description: Source Repository URL
+ name: git-url
+ type: string
+ - default: ""
+ description: Revision of the Source Repository
+ name: revision
+ type: string
+ - description: Fully Qualified Output Image
+ name: output-image
+ type: string
+ - default: .
+ description: Path to the source code of an application's component from where
+ to build image.
+ name: path-context
+ type: string
+ - default: Dockerfile
+ description: Path to the Dockerfile inside the context specified by parameter
+ path-context
+ name: dockerfile
+ type: string
+ - default: "false"
+ description: Skip checks against built image
+ name: skip-checks
+ type: string
+ - default: "false"
+ description: Execute the build with network isolation
+ name: hermetic
+ type: string
+ - default: ""
+ description: Build dependencies to be prefetched
+ name: prefetch-input
+ type: string
+ - default: ""
+ description: Image tag expiration time, time values could be something like
+ 1h, 2d, 3w for hours, days, and weeks, respectively.
+ name: image-expires-after
+ type: string
+ - default: "false"
+ description: Build a source image.
+ name: build-source-image
+ type: string
+ - default: "true"
+ description: Add built image into an OCI image index
+ name: build-image-index
+ type: string
+ - default: docker
+ description: The format for the resulting image's mediaType. Valid values are
+ oci or docker.
+ name: buildah-format
+ type: string
+ - default: "false"
+ description: Enable cache proxy configuration
+ name: enable-cache-proxy
+ - default: "true"
+ description: Use the package registry proxy when prefetching dependencies
+ name: enable-package-registry-proxy
+ - default: .
+ description: Target directories in component's source code to scan with SAST
+ tools. Multiple values should be separated with commas.
+ name: sast-target-dirs
+ type: string
+ - default: []
+ description: Array of --build-arg values ("arg=value" strings) for buildah
+ name: build-args
+ type: array
+ - default: ""
+ description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file
+ name: build-args-file
+ type: string
+ - default: "false"
+ description: Whether to enable privileged mode, should be used only with remote
+ VMs
+ name: privileged-nested
+ type: string
+ - default: ""
+ description: Sets the image created time and the SOURCE_DATE_EPOCH build argument.
+ On its own, it does not change file timestamps inside the layers (set rewrite-timestamp
+ to "true" for that). Leave empty to keep the actual build time.
+ name: source-date-epoch
+ type: string
+ - default: "false"
+ description: When "true", clamp file modification times in the image layers
+ to at most source-date-epoch. Does nothing unless source-date-epoch is set.
+ name: rewrite-timestamp
+ type: string
+ - default: "false"
+ description: When "true", omit the build history (history timestamps, layer
+ metadata, etc.) from the resulting image.
+ name: omit-history
+ type: string
+ - default:
+ - linux/x86_64
+ description: List of platforms to build the container images on. The available
+ set of values is determined by the configuration of the multi-platform-controller.
+ name: build-platforms
+ type: array
+ results:
+ - description: ""
+ name: IMAGE_URL
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - description: ""
+ name: IMAGE_DIGEST
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - description: ""
+ name: CHAINS-GIT_URL
+ value: $(tasks.clone-repository.results.url)
+ - description: ""
+ name: CHAINS-GIT_COMMIT
+ value: $(tasks.clone-repository.results.commit)
+ tasks:
+ - name: init
+ params:
+ - name: enable-cache-proxy
+ value: $(params.enable-cache-proxy)
+ taskRef:
+ params:
+ - name: name
+ value: init
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-init:0.4.2@sha256:421003a5c077ecb820460e71637125ec9093d2101c749a32ede28e190283e9db
+ - name: kind
+ value: task
+ resolver: bundles
+ - name: clone-repository
+ params:
+ - name: url
+ value: $(params.git-url)
+ - name: revision
+ value: $(params.revision)
+ - name: ociStorage
+ value: $(params.output-image).git
+ - name: ociArtifactExpiresAfter
+ value: $(params.image-expires-after)
+ runAfter:
+ - init
+ taskRef:
+ params:
+ - name: name
+ value: git-clone-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-git-clone-oci-ta:0.2.4@sha256:df3c42d78223f07b40a84dd29e5c8860d14777ffdf150ea08c738770f51216dc
+ - name: kind
+ value: task
+ resolver: bundles
+ workspaces:
+ - name: basic-auth
+ workspace: git-auth
+ - name: prefetch-dependencies
+ params:
+ - name: input
+ value: $(params.prefetch-input)
+ - name: enable-package-registry-proxy
+ value: $(params.enable-package-registry-proxy)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.clone-repository.results.SOURCE_ARTIFACT)
+ - name: ociStorage
+ value: $(params.output-image).prefetch
+ - name: ociArtifactExpiresAfter
+ value: $(params.image-expires-after)
+ runAfter:
+ - clone-repository
+ taskRef:
+ params:
+ - name: name
+ value: prefetch-dependencies-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-prefetch-dependencies-oci-ta:0.3.2@sha256:389aea03a065e8118d36b7acb85b05cd13f6750e7e10ff8a85f270ee65b0167b
+ - name: kind
+ value: task
+ resolver: bundles
+ workspaces:
+ - name: git-basic-auth
+ workspace: git-auth
+ - name: netrc
+ workspace: netrc
+ - matrix:
+ params:
+ - name: PLATFORM
+ value:
+ - $(params.build-platforms)
+ name: build-images
+ params:
+ - name: IMAGE
+ value: $(params.output-image)
+ - name: DOCKERFILE
+ value: $(params.dockerfile)
+ - name: CONTEXT
+ value: $(params.path-context)
+ - name: HERMETIC
+ value: $(params.hermetic)
+ - name: PREFETCH_INPUT
+ value: $(params.prefetch-input)
+ - name: IMAGE_EXPIRES_AFTER
+ value: $(params.image-expires-after)
+ - name: COMMIT_SHA
+ value: $(tasks.clone-repository.results.commit)
+ - name: BUILD_ARGS
+ value:
+ - $(params.build-args[*])
+ - name: BUILD_ARGS_FILE
+ value: $(params.build-args-file)
+ - name: PRIVILEGED_NESTED
+ value: $(params.privileged-nested)
+ - name: SOURCE_URL
+ value: $(tasks.clone-repository.results.url)
+ - name: BUILDAH_FORMAT
+ value: $(params.buildah-format)
+ - name: HTTP_PROXY
+ value: $(tasks.init.results.http-proxy)
+ - name: NO_PROXY
+ value: $(tasks.init.results.no-proxy)
+ - name: SOURCE_DATE_EPOCH
+ value: $(params.source-date-epoch)
+ - name: REWRITE_TIMESTAMP
+ value: $(params.rewrite-timestamp)
+ - name: OMIT_HISTORY
+ value: $(params.omit-history)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ - name: CACHI2_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ - name: IMAGE_APPEND_PLATFORM
+ value: "true"
+ runAfter:
+ - prefetch-dependencies
+ taskRef:
+ params:
+ - name: name
+ value: buildah-remote-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-buildah-remote-oci-ta:0.10.5@sha256:eb277ec7b44443f0506a60ac940a2e52178d60f17cb0f51a6966daed5b3755de
+ - name: kind
+ value: task
+ resolver: bundles
+ - name: build-image-index
+ params:
+ - name: IMAGE
+ value: $(params.output-image)
+ - name: ALWAYS_BUILD_INDEX
+ value: $(params.build-image-index)
+ - name: IMAGES
+ value:
+ - $(tasks.build-images.results.IMAGE_REF[*])
+ - name: BUILDAH_FORMAT
+ value: $(params.buildah-format)
+ runAfter:
+ - build-images
+ taskRef:
+ params:
+ - name: name
+ value: build-image-index
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-build-image-index:0.3.1@sha256:cc75f64deecccb1b59e96ac1182665a5342d79c9e22eebff63d26b0f00a4319c
+ - name: kind
+ value: task
+ resolver: bundles
+ - name: build-source-image
+ params:
+ - name: BINARY_IMAGE
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: BINARY_IMAGE_DIGEST
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ - name: CACHI2_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: source-build-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-source-build-oci-ta:0.3@sha256:7c5575ac8e292f27f57716c021ab0324460dc958e73946724c588c5228e5f372
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.build-source-image)
+ operator: in
+ values:
+ - "true"
+ - name: deprecated-base-image-check
+ params:
+ - name: IMAGE_URL
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: IMAGE_DIGEST
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: deprecated-image-check
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-deprecated-image-check:0.5@sha256:0ccc688a77e9b7b0b8973c132a1e840844137e77f887be4a0bec8893b0776872
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - matrix:
+ params:
+ - name: image-platform
+ value:
+ - $(params.build-platforms)
+ name: clair-scan
+ params:
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: clair-scan
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-clair-scan:0.3@sha256:f5b4415db9ac1fba3e11d993a617e0b275d1f0ed2fc669b12c400ed848c39174
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - matrix:
+ params:
+ - name: platform
+ value:
+ - $(params.build-platforms)
+ name: ecosystem-cert-preflight-checks
+ params:
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: ecosystem-cert-preflight-checks
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-ecosystem-cert-preflight-checks:0.2@sha256:e438f3104d706f73812994953d3d0a9c62ac8e4a372d86337ff26bbca9902709
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - name: sast-snyk-check
+ params:
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: TARGET_DIRS
+ value: $(params.sast-target-dirs)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ - name: CACHI2_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: sast-snyk-check-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-snyk-check-oci-ta:0.5@sha256:eba24f5d9f4b18aa71e523b9b3dbcf22982aa4b018824260a090b19dfc9abf6f
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - matrix:
+ params:
+ - name: image-arch
+ value:
+ - $(params.build-platforms)
+ name: clamav-scan
+ params:
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: clamav-scan
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-clamav-scan:0.3@sha256:53a02326bfb930ca5ef6bfa7a33acca833d57752f34f3cb79255fe2e25e7d217
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - name: sast-shell-check
+ params:
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: TARGET_DIRS
+ value: $(params.sast-target-dirs)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ - name: CACHI2_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: sast-shell-check-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-shell-check-oci-ta:0.1@sha256:61b27e6ad5daba761d41bb37efb790ed98380603fd4fe2f86d156def5bd72ecc
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - name: sast-unicode-check
+ params:
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: TARGET_DIRS
+ value: $(params.sast-target-dirs)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ - name: CACHI2_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: sast-unicode-check-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-unicode-check-oci-ta:0.4@sha256:eb9d5392f215cb8b52b16382098cac4885b1e6cd989f88ebd83fdb234d283eb9
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - name: apply-tags
+ params:
+ - name: IMAGE_URL
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: IMAGE_DIGEST
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: apply-tags
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-apply-tags:0.3@sha256:3ab844157eccd68e95e4852adc06c3c4ea674edb7865a474b0a898227f2893d6
+ - name: kind
+ value: task
+ resolver: bundles
+ - name: push-dockerfile
+ params:
+ - name: IMAGE
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: IMAGE_DIGEST
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: DOCKERFILE
+ value: $(params.dockerfile)
+ - name: CONTEXT
+ value: $(params.path-context)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: push-dockerfile-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-push-dockerfile-oci-ta:0.3.1@sha256:5a6cbebd89e5bc163b38231859767f7f6a0dd66cf1333699574379f062731183
+ - name: kind
+ value: task
+ resolver: bundles
+ - name: rpms-signature-scan
+ params:
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: rpms-signature-scan
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-rpms-signature-scan:0.2@sha256:ccb77d1bf7627fc6241a59ed42bb6e5707a8682754fe8ae18f2cfdddbcf29275
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ workspaces:
+ - name: git-auth
+ optional: true
+ - name: netrc
+ optional: true
+ taskRunTemplate:
+ serviceAccountName: build-pipeline-lightspeed-stack-0-8
+ workspaces:
+ - name: git-auth
+ secret:
+ secretName: '{{ git_auth_secret }}'
+status: {}
From 7894002bb8b30c851cc14983e8e55009aeedc9bb Mon Sep 17 00:00:00 2001
From: Maysun J Faisal
Date: Fri, 31 Jul 2026 18:42:33 -0400
Subject: [PATCH 035/197] RHIDP-14130: fix OKP citation URLs and add
configurable search mode
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Build correct citation URLs for OKP documents in both offline
(localhost) and online (docs.redhat.com) modes for rag.inline
and rag.tool paths
- Add search_mode field to OkpConfiguration for operator-level
default (keyword/hybrid/semantic)
- Fix lexical→keyword mode translation so BM25 search works
without an embedding model (air-gapped support)
Co-Authored-By: Claude Opus 4.6
---
src/constants.py | 2 +
src/models/common/query.py | 7 +-
src/models/config.py | 10 +
src/utils/agents/tool_processor.py | 13 +-
src/utils/responses.py | 35 ++-
src/utils/vector_search.py | 5 +-
.../unit/utils/agents/test_tool_processor.py | 59 +++++
tests/unit/utils/test_responses.py | 232 ++++++++++++++++++
tests/unit/utils/test_vector_search.py | 65 ++++-
9 files changed, 419 insertions(+), 9 deletions(-)
diff --git a/src/constants.py b/src/constants.py
index e32927e79..80335834a 100644
--- a/src/constants.py
+++ b/src/constants.py
@@ -235,6 +235,8 @@
SOLR_VECTOR_SEARCH_DEFAULT_K: Final[int] = 5
SOLR_VECTOR_SEARCH_DEFAULT_SCORE_THRESHOLD: Final[float] = 0.3
SOLR_VECTOR_SEARCH_DEFAULT_MODE: Final[str] = "hybrid"
+# LCORE exposes "lexical" but Llama Stack dispatch recognizes "keyword"
+SOLR_SEARCH_MODE_MAP: Final[dict[str, str]] = {"lexical": "keyword"}
# Internal Solr filter always applied to restrict results to chunk documents
SOLR_CHUNK_FILTER_QUERY: Final[str] = "is_chunk:true"
diff --git a/src/models/common/query.py b/src/models/common/query.py
index e062881f9..c340b76ea 100644
--- a/src/models/common/query.py
+++ b/src/models/common/query.py
@@ -144,13 +144,14 @@ class SolrVectorSearchRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
- mode: Optional[Literal["semantic", "hybrid", "lexical"]] = Field(
+ mode: Optional[Literal["semantic", "hybrid", "lexical", "keyword"]] = Field(
None,
description=(
"Solr vector_io search mode. When omitted, the server default "
- f"({SOLR_VECTOR_SEARCH_DEFAULT_MODE!r}) is used."
+ f"({SOLR_VECTOR_SEARCH_DEFAULT_MODE!r}) is used. "
+ "'keyword' and 'lexical' both use BM25 text search."
),
- examples=["hybrid", "semantic", "lexical"],
+ examples=["hybrid", "semantic", "keyword", "lexical"],
)
filters: Optional[dict[str, Any]] = Field(
None,
diff --git a/src/models/config.py b/src/models/config.py
index 941507ce1..0e8814636 100644
--- a/src/models/config.py
+++ b/src/models/config.py
@@ -2555,6 +2555,16 @@ class OkpConfiguration(ConfigurationBase):
"Use Solr boolean syntax, e.g. 'product:ansible AND product:*openshift*'.",
)
+ search_mode: Optional[Literal["semantic", "hybrid", "keyword"]] = Field(
+ default=None,
+ title="OKP search mode",
+ description="Default Solr search mode for OKP queries. "
+ "'keyword' uses BM25 text search (no embedding model needed). "
+ "'hybrid' combines vector + keyword search. "
+ "'semantic' uses pure vector search. "
+ "When unset, falls back to the global default ('hybrid').",
+ )
+
class RerankerConfiguration(ConfigurationBase):
"""Reranker configuration for RAG chunk reranking."""
diff --git a/src/utils/agents/tool_processor.py b/src/utils/agents/tool_processor.py
index bb12a4e5e..6be085daa 100644
--- a/src/utils/agents/tool_processor.py
+++ b/src/utils/agents/tool_processor.py
@@ -17,6 +17,7 @@
)
from pydantic_ai.native_tools import FileSearchTool, MCPServerTool, WebSearchTool
+import constants
from constants import DEFAULT_RAG_TOOL
from log import get_logger
from models.common.agents import AgentTurnAccumulator
@@ -28,7 +29,7 @@
ToolInfoSummary,
ToolResultSummary,
)
-from utils.responses import resolve_source_for_result
+from utils.responses import _build_okp_doc_url, resolve_source_for_result
logger = get_logger(__name__)
@@ -286,9 +287,17 @@ def build_referenced_document(
Referenced document when metadata is present, otherwise None.
"""
attributes = result.attributes or {}
+ resolved_source = resolve_source_for_result(
+ attributes, vector_store_ids, rag_id_mapping
+ )
doc_url = _file_search_attribute_url(attributes)
doc_title = _file_search_attribute_str(attributes, "title")
+
+ # OKP/Solr chunks need URL construction with the OKP base URL
+ if resolved_source == constants.OKP_RAG_ID:
+ doc_url = _build_okp_doc_url(attributes)
+
if not (doc_title or doc_url):
return None
@@ -298,7 +307,7 @@ def build_referenced_document(
return ReferencedDocument(
doc_url=AnyUrl(doc_url) if doc_url else None,
doc_title=doc_title,
- source=resolve_source_for_result(attributes, vector_store_ids, rag_id_mapping),
+ source=resolved_source,
document_id=doc_id,
)
diff --git a/src/utils/responses.py b/src/utils/responses.py
index 9ea71f247..95e231038 100644
--- a/src/utils/responses.py
+++ b/src/utils/responses.py
@@ -5,6 +5,7 @@
import json
from collections.abc import Mapping, Sequence
from typing import Any, Optional, cast
+from urllib.parse import urljoin
from fastapi import HTTPException
from ogx_api import OpenAIResponseObject
@@ -850,6 +851,33 @@ def apply_mcp_headers_to_explicit_tools(
return out
+def _build_okp_doc_url(attributes: dict[str, Any]) -> Optional[str]:
+ """Build a full OKP document URL from file_search result attributes.
+
+ Uses the ``offline`` flag from OKP configuration to choose between
+ ``source_path`` (disconnected clusters) and ``reference_url`` (online).
+ The chosen relative path is joined with the OKP base URL.
+
+ Args:
+ attributes: Metadata dict from a file_search result chunk.
+
+ Returns:
+ Fully-qualified document URL, or None if no usable path is found.
+ """
+ offline = configuration.okp.offline
+ if offline:
+ reference = attributes.get("source_path") or attributes.get("doc_id")
+ else:
+ reference = attributes.get("reference_url") or attributes.get("doc_id")
+
+ if not reference:
+ return None
+
+ rhokp = configuration.okp.rhokp_url
+ base_url = str(rhokp) if rhokp is not None else constants.RH_SERVER_OKP_DEFAULT_URL
+ return urljoin(base_url, str(reference))
+
+
def parse_referenced_documents( # pylint: disable=too-many-locals
response: Optional[ResponseObject],
vector_store_ids: Optional[list[str]] = None,
@@ -899,9 +927,12 @@ def parse_referenced_documents( # pylint: disable=too-many-locals
doc_title = attributes.get("title")
doc_id = attributes.get("document_id") or attributes.get("doc_id")
+ # OKP/Solr chunks use reference_url/source_path instead
+ if not doc_url and resolved_source == constants.OKP_RAG_ID:
+ doc_url = _build_okp_doc_url(attributes)
+
if doc_title or doc_url:
- # Treat empty string as None for URL to satisfy Optional[AnyUrl]
- final_url = doc_url or None
+ final_url: Any = doc_url or None
if (final_url, doc_title) not in seen_docs:
documents.append(
ReferencedDocument(
diff --git a/src/utils/vector_search.py b/src/utils/vector_search.py
index 9cf4ffff4..aa26b6030 100644
--- a/src/utils/vector_search.py
+++ b/src/utils/vector_search.py
@@ -121,8 +121,11 @@ def _build_query_params(
resolved_mode = (
solr.mode
if solr is not None and solr.mode is not None
- else constants.SOLR_VECTOR_SEARCH_DEFAULT_MODE
+ else (
+ configuration.okp.search_mode or constants.SOLR_VECTOR_SEARCH_DEFAULT_MODE
+ )
)
+ resolved_mode = constants.SOLR_SEARCH_MODE_MAP.get(resolved_mode, resolved_mode)
params: dict[str, Any] = {
"k": k if k is not None else constants.SOLR_VECTOR_SEARCH_DEFAULT_K,
"score_threshold": constants.SOLR_VECTOR_SEARCH_DEFAULT_SCORE_THRESHOLD,
diff --git a/tests/unit/utils/agents/test_tool_processor.py b/tests/unit/utils/agents/test_tool_processor.py
index 2fb83a9cf..bd77cf93d 100644
--- a/tests/unit/utils/agents/test_tool_processor.py
+++ b/tests/unit/utils/agents/test_tool_processor.py
@@ -343,6 +343,65 @@ def test_title_only_document(self) -> None:
assert doc.doc_url is None
assert doc.doc_title == "Title Only"
+ def test_okp_online_builds_full_url(self, mocker: MockerFixture) -> None:
+ """Test OKP online mode joins reference_url with OKP base URL."""
+ mock_config = mocker.patch("utils.responses.configuration")
+ mock_config.okp.offline = False
+ mock_config.okp.rhokp_url = AnyUrl("https://docs.example.com/")
+
+ result = _file_search_result(
+ attributes={
+ "reference_url": "/en/docs/guide/index",
+ "source_path": "/en/docs/guide/index",
+ "title": "OKP Guide",
+ "source": "okp",
+ }
+ )
+
+ doc = build_referenced_document(result, ["portal-rag"], {"portal-rag": "okp"})
+
+ assert doc is not None
+ assert str(doc.doc_url) == "https://docs.example.com/en/docs/guide/index"
+ assert doc.source == "okp"
+
+ def test_okp_offline_builds_url_from_source_path(
+ self, mocker: MockerFixture
+ ) -> None:
+ """Test OKP offline mode uses source_path with OKP base URL."""
+ mock_config = mocker.patch("utils.responses.configuration")
+ mock_config.okp.offline = True
+ mock_config.okp.rhokp_url = AnyUrl("http://localhost:8081/")
+
+ result = _file_search_result(
+ attributes={
+ "reference_url": "https://docs.redhat.com/en/docs/guide/index",
+ "source_path": "/en/docs/guide/index",
+ "title": "OKP Guide",
+ "source": "okp",
+ }
+ )
+
+ doc = build_referenced_document(result, ["portal-rag"], {"portal-rag": "okp"})
+
+ assert doc is not None
+ assert str(doc.doc_url) == "http://localhost:8081/en/docs/guide/index"
+ assert doc.source == "okp"
+
+ def test_non_okp_source_uses_reference_url_directly(self) -> None:
+ """Test non-OKP sources still use reference_url from attribute keys."""
+ result = _file_search_result(
+ attributes={
+ "reference_url": "https://example.com/doc",
+ "title": "Non-OKP Doc",
+ }
+ )
+
+ doc = build_referenced_document(result, ["vs-001"], {"vs-001": "other"})
+
+ assert doc is not None
+ assert str(doc.doc_url) == "https://example.com/doc"
+ assert doc.source == "other"
+
class TestReferencedDocumentsFromFileSearchResults:
"""Tests for referenced_documents_from_file_search_results."""
diff --git a/tests/unit/utils/test_responses.py b/tests/unit/utils/test_responses.py
index 9e8c752e4..a4a66fda7 100644
--- a/tests/unit/utils/test_responses.py
+++ b/tests/unit/utils/test_responses.py
@@ -69,6 +69,7 @@
from utils.query import normalize_vertex_ai_model_id
from utils.responses import (
_build_chunk_attributes,
+ _build_okp_doc_url,
_merge_tools,
build_mcp_tool_call_from_arguments_done,
build_tool_call_summary,
@@ -3146,6 +3147,237 @@ def test_multiple_stores_source_is_none(self, mocker: MockerFixture) -> None:
assert docs[0].source is None
+class TestBuildOkpDocUrl:
+ """Tests for _build_okp_doc_url OKP URL construction."""
+
+ def test_online_mode_uses_reference_url(self, mocker: MockerFixture) -> None:
+ """Test that online mode (offline=False) uses reference_url."""
+ mock_okp = mocker.Mock()
+ mock_okp.offline = False
+ mock_okp.rhokp_url = "https://docs.openshift.com"
+ mock_config = mocker.Mock()
+ mock_config.okp = mock_okp
+ mocker.patch("utils.responses.configuration", mock_config)
+
+ url = _build_okp_doc_url(
+ {
+ "reference_url": "/docs/pipelines/config.html",
+ "source_path": "pipelines/config.html",
+ }
+ )
+ assert url == "https://docs.openshift.com/docs/pipelines/config.html"
+
+ def test_offline_mode_uses_source_path(self, mocker: MockerFixture) -> None:
+ """Test that offline mode (offline=True) uses source_path."""
+ mock_okp = mocker.Mock()
+ mock_okp.offline = True
+ mock_okp.rhokp_url = "https://docs.openshift.com"
+ mock_config = mocker.Mock()
+ mock_config.okp = mock_okp
+ mocker.patch("utils.responses.configuration", mock_config)
+
+ url = _build_okp_doc_url(
+ {
+ "reference_url": "/docs/pipelines/config.html",
+ "source_path": "pipelines/config.html",
+ }
+ )
+ assert url == "https://docs.openshift.com/pipelines/config.html"
+
+ def test_online_falls_back_to_doc_id(self, mocker: MockerFixture) -> None:
+ """Test online mode falls back to doc_id when reference_url is absent."""
+ mock_okp = mocker.Mock()
+ mock_okp.offline = False
+ mock_okp.rhokp_url = "https://docs.openshift.com"
+ mock_config = mocker.Mock()
+ mock_config.okp = mock_okp
+ mocker.patch("utils.responses.configuration", mock_config)
+
+ url = _build_okp_doc_url({"doc_id": "some-doc-id"})
+ assert url == "https://docs.openshift.com/some-doc-id"
+
+ def test_offline_falls_back_to_doc_id(self, mocker: MockerFixture) -> None:
+ """Test offline mode falls back to doc_id when source_path is absent."""
+ mock_okp = mocker.Mock()
+ mock_okp.offline = True
+ mock_okp.rhokp_url = "https://docs.openshift.com"
+ mock_config = mocker.Mock()
+ mock_config.okp = mock_okp
+ mocker.patch("utils.responses.configuration", mock_config)
+
+ url = _build_okp_doc_url({"doc_id": "some-doc-id"})
+ assert url == "https://docs.openshift.com/some-doc-id"
+
+ def test_returns_none_when_no_reference(self, mocker: MockerFixture) -> None:
+ """Test returns None when no reference_url, source_path, or doc_id."""
+ mock_okp = mocker.Mock()
+ mock_okp.offline = False
+ mock_okp.rhokp_url = "https://docs.openshift.com"
+ mock_config = mocker.Mock()
+ mock_config.okp = mock_okp
+ mocker.patch("utils.responses.configuration", mock_config)
+
+ url = _build_okp_doc_url({"title": "Some Doc"})
+ assert url is None
+
+ def test_uses_default_url_when_rhokp_url_is_none(
+ self, mocker: MockerFixture
+ ) -> None:
+ """Test uses RH_SERVER_OKP_DEFAULT_URL when rhokp_url is not configured."""
+ mock_okp = mocker.Mock()
+ mock_okp.offline = False
+ mock_okp.rhokp_url = None
+ mock_config = mocker.Mock()
+ mock_config.okp = mock_okp
+ mocker.patch("utils.responses.configuration", mock_config)
+
+ url = _build_okp_doc_url({"reference_url": "/docs/page.html"})
+ assert url == "http://localhost:8081/docs/page.html"
+
+
+class TestParseReferencedDocumentsOkp:
+ """Tests for parse_referenced_documents with OKP/Solr file_search results."""
+
+ def test_okp_online_builds_full_url(self, mocker: MockerFixture) -> None:
+ """Test OKP result builds full URL from reference_url in online mode."""
+ mock_okp = mocker.Mock()
+ mock_okp.offline = False
+ mock_okp.rhokp_url = "https://docs.openshift.com"
+ mock_config = mocker.Mock()
+ mock_config.okp = mock_okp
+ mocker.patch("utils.responses.configuration", mock_config)
+
+ mock_result = mocker.Mock()
+ mock_result.attributes = {
+ "reference_url": "/docs/pipelines/config.html",
+ "source_path": "pipelines/config.html",
+ "title": "Pipeline Config",
+ "doc_id": "doc-001",
+ "source": "okp",
+ }
+
+ mock_output = mocker.Mock()
+ mock_output.type = "file_search_call"
+ mock_output.results = [mock_result]
+
+ mock_response = mocker.Mock()
+ mock_response.output = [mock_output]
+
+ docs = parse_referenced_documents(
+ mock_response,
+ vector_store_ids=["portal-rag"],
+ rag_id_mapping={"portal-rag": "okp"},
+ )
+
+ assert len(docs) == 1
+ assert (
+ str(docs[0].doc_url)
+ == "https://docs.openshift.com/docs/pipelines/config.html"
+ )
+ assert docs[0].doc_title == "Pipeline Config"
+ assert docs[0].source == "okp"
+
+ def test_okp_offline_builds_url_from_source_path(
+ self, mocker: MockerFixture
+ ) -> None:
+ """Test OKP result builds URL from source_path in offline mode."""
+ mock_okp = mocker.Mock()
+ mock_okp.offline = True
+ mock_okp.rhokp_url = "https://docs.openshift.com"
+ mock_config = mocker.Mock()
+ mock_config.okp = mock_okp
+ mocker.patch("utils.responses.configuration", mock_config)
+
+ mock_result = mocker.Mock()
+ mock_result.attributes = {
+ "reference_url": "/docs/pipelines/config.html",
+ "source_path": "pipelines/config.html",
+ "title": "Pipeline Config",
+ "doc_id": "doc-001",
+ "source": "okp",
+ }
+
+ mock_output = mocker.Mock()
+ mock_output.type = "file_search_call"
+ mock_output.results = [mock_result]
+
+ mock_response = mocker.Mock()
+ mock_response.output = [mock_output]
+
+ docs = parse_referenced_documents(
+ mock_response,
+ vector_store_ids=["portal-rag"],
+ rag_id_mapping={"portal-rag": "okp"},
+ )
+
+ assert len(docs) == 1
+ assert (
+ str(docs[0].doc_url) == "https://docs.openshift.com/pipelines/config.html"
+ )
+ assert docs[0].source == "okp"
+
+ def test_okp_multistore_detected_via_source_attribute(
+ self, mocker: MockerFixture
+ ) -> None:
+ """Test OKP detected in multi-store scenario via source attribute."""
+ mock_okp = mocker.Mock()
+ mock_okp.offline = False
+ mock_okp.rhokp_url = "https://docs.openshift.com"
+ mock_config = mocker.Mock()
+ mock_config.okp = mock_okp
+ mocker.patch("utils.responses.configuration", mock_config)
+
+ mock_result = mocker.Mock()
+ mock_result.attributes = {
+ "reference_url": "/docs/builds.html",
+ "title": "Builds",
+ "source": "okp",
+ }
+
+ mock_output = mocker.Mock()
+ mock_output.type = "file_search_call"
+ mock_output.results = [mock_result]
+
+ mock_response = mocker.Mock()
+ mock_response.output = [mock_output]
+
+ docs = parse_referenced_documents(
+ mock_response,
+ vector_store_ids=["portal-rag", "byok-store"],
+ rag_id_mapping={"portal-rag": "okp", "byok-store": "my-docs"},
+ )
+
+ assert len(docs) == 1
+ assert str(docs[0].doc_url) == "https://docs.openshift.com/docs/builds.html"
+ assert docs[0].source == "okp"
+
+ def test_non_okp_result_unaffected(self, mocker: MockerFixture) -> None:
+ """Test non-OKP results still use existing doc_url/url attribute lookup."""
+ mock_result = mocker.Mock()
+ mock_result.attributes = {
+ "url": "https://example.com/byok-doc",
+ "title": "BYOK Doc",
+ "document_id": "byok-001",
+ }
+
+ mock_output = mocker.Mock()
+ mock_output.type = "file_search_call"
+ mock_output.results = [mock_result]
+
+ mock_response = mocker.Mock()
+ mock_response.output = [mock_output]
+
+ docs = parse_referenced_documents(
+ mock_response,
+ vector_store_ids=["byok-store"],
+ rag_id_mapping={"byok-store": "my-docs"},
+ )
+
+ assert len(docs) == 1
+ assert str(docs[0].doc_url) == "https://example.com/byok-doc"
+ assert docs[0].source == "my-docs"
+
+
class TestGetRAGToolsWithConfig:
"""Tests for get_rag_tools with configuration checks."""
diff --git a/tests/unit/utils/test_vector_search.py b/tests/unit/utils/test_vector_search.py
index e53be0148..12058b7bc 100644
--- a/tests/unit/utils/test_vector_search.py
+++ b/tests/unit/utils/test_vector_search.py
@@ -162,7 +162,16 @@ def test_custom_mode(self) -> None:
solr = SolrVectorSearchRequest(mode="lexical")
params = _build_query_params(solr=solr)
- assert params["mode"] == "lexical"
+ # "lexical" is translated to "keyword" for Llama Stack dispatch
+ assert params["mode"] == "keyword"
+ assert "solr" not in params
+
+ def test_keyword_mode_direct(self) -> None:
+ """Request mode 'keyword' is passed through unchanged."""
+ solr = SolrVectorSearchRequest(mode="keyword")
+ params = _build_query_params(solr=solr)
+
+ assert params["mode"] == "keyword"
assert "solr" not in params
def test_mode_with_solr_filters(self) -> None:
@@ -186,6 +195,60 @@ def test_mode_with_only_filters(self) -> None:
assert params["mode"] == constants.SOLR_VECTOR_SEARCH_DEFAULT_MODE
assert params["solr"] == {"fq": ["product:*openshift*"]}
+ def test_config_search_mode_keyword(self, mocker: MockerFixture) -> None:
+ """OKP config search_mode is used when no per-request mode is set."""
+ config_mock = mocker.Mock(spec=AppConfig)
+ config_mock.okp.search_mode = "keyword"
+ mocker.patch("utils.vector_search.configuration", config_mock)
+
+ params = _build_query_params()
+
+ assert params["mode"] == "keyword"
+
+ def test_config_search_mode_semantic(self, mocker: MockerFixture) -> None:
+ """OKP config search_mode 'semantic' is used as default."""
+ config_mock = mocker.Mock(spec=AppConfig)
+ config_mock.okp.search_mode = "semantic"
+ mocker.patch("utils.vector_search.configuration", config_mock)
+
+ params = _build_query_params()
+
+ assert params["mode"] == "semantic"
+
+ def test_per_request_mode_overrides_config(self, mocker: MockerFixture) -> None:
+ """Per-request solr mode takes precedence over OKP config default."""
+ config_mock = mocker.Mock(spec=AppConfig)
+ config_mock.okp.search_mode = "keyword"
+ mocker.patch("utils.vector_search.configuration", config_mock)
+
+ solr = SolrVectorSearchRequest(mode="semantic")
+ params = _build_query_params(solr=solr)
+
+ assert params["mode"] == "semantic"
+
+ def test_no_config_no_request_mode_uses_global_default(
+ self, mocker: MockerFixture
+ ) -> None:
+ """Without config or per-request mode, global default is used."""
+ config_mock = mocker.Mock(spec=AppConfig)
+ config_mock.okp.search_mode = None
+ mocker.patch("utils.vector_search.configuration", config_mock)
+
+ params = _build_query_params()
+
+ assert params["mode"] == constants.SOLR_VECTOR_SEARCH_DEFAULT_MODE
+
+ def test_lexical_config_translated_to_keyword(self, mocker: MockerFixture) -> None:
+ """Per-request 'lexical' is translated to 'keyword' even with config set."""
+ config_mock = mocker.Mock(spec=AppConfig)
+ config_mock.okp.search_mode = "hybrid"
+ mocker.patch("utils.vector_search.configuration", config_mock)
+
+ solr = SolrVectorSearchRequest(mode="lexical")
+ params = _build_query_params(solr=solr)
+
+ assert params["mode"] == "keyword"
+
class TestExtractByokRagChunks:
"""Tests for _extract_byok_rag_chunks function."""
From 618c34d4d60026bb4f4616ca89f6e104423eee31 Mon Sep 17 00:00:00 2001
From: Jordan Dubrick
Date: Wed, 5 Aug 2026 16:37:47 -0400
Subject: [PATCH 036/197] fix: update embedding model handling to work with ogx
Signed-off-by: Jordan Dubrick
---
src/llama_stack_configuration.py | 33 ++++++----
tests/unit/test_llama_stack_configuration.py | 68 ++++++++++++++++++--
tests/unit/test_llama_stack_synthesize.py | 2 +-
3 files changed, 83 insertions(+), 20 deletions(-)
diff --git a/src/llama_stack_configuration.py b/src/llama_stack_configuration.py
index 62e76ec4b..6ec0671ae 100644
--- a/src/llama_stack_configuration.py
+++ b/src/llama_stack_configuration.py
@@ -250,7 +250,8 @@ def construct_vector_stores_section(
list[dict[str, Any]]: The `vector_stores` list where each entry is a mapping with keys:
- `vector_store_id`: identifier of the vector store (for Llama Stack config)
- `provider_id`: provider identifier prefixed with `"byok_"`
- - `embedding_model`: name of the embedding model
+ - `embedding_model`: registered OGX model id
+ (``sentence-transformers/byok__embedding``), not the load path
- `embedding_dimension`: embedding vector dimensionality
"""
output = []
@@ -280,12 +281,13 @@ def construct_vector_stores_section(
continue
existing_store_ids.add(vector_db_id)
added += 1
- embedding_model = brag.get("embedding_model", constants.DEFAULT_EMBEDDING_MODEL)
+ # OGX registers BYOK embeddings as sentence-transformers/byok__embedding
+ # (see construct_models_section). Lookups must use that id, not the load path.
output.append(
{
"vector_store_id": vector_db_id,
"provider_id": f"byok_{rag_id}",
- "embedding_model": embedding_model,
+ "embedding_model": f"sentence-transformers/byok_{rag_id}_embedding",
"embedding_dimension": brag.get("embedding_dimension"),
}
)
@@ -544,10 +546,12 @@ def _upsert_vsprov_embedding_model(
embedding_model: str,
embedding_dimension: int,
) -> None:
- """Register an embedding model if provider_model_id is not already present.
+ """Register a vsprov embedding model alias if that model_id is not present.
- Dedupes against BYOK/baseline rows by ``provider_model_id`` (after stripping
- a leading ``sentence-transformers/`` prefix).
+ Dedupes by ``model_id`` (``vsprov__embedding``), not by load
+ path. BYOK and ``vector_store`` often share the same
+ ``provider_model_id``; both aliases must be registered so
+ ``default_embedding_model`` can resolve.
Parameters:
ls_config: Llama Stack configuration modified in place.
@@ -557,12 +561,13 @@ def _upsert_vsprov_embedding_model(
validated ``vector_store.providers`` entries).
"""
models = ls_config.setdefault("registered_resources", {}).setdefault("models", [])
- provider_model_id = embedding_model.removeprefix("sentence-transformers/")
- if any(model.get("provider_model_id") == provider_model_id for model in models):
+ model_id = f"vsprov_{provider_id}_embedding"
+ if any(model.get("model_id") == model_id for model in models):
return
+ provider_model_id = embedding_model.removeprefix("sentence-transformers/")
models.append(
{
- "model_id": f"vsprov_{provider_id}_embedding",
+ "model_id": model_id,
"model_type": "embedding",
"provider_id": "sentence-transformers",
"provider_model_id": provider_model_id,
@@ -655,12 +660,14 @@ def _apply_vector_stores_defaults(
if not isinstance(vector_stores, dict):
vector_stores = {}
ls_config["vector_stores"] = vector_stores
- vector_stores["default_provider_id"] = str(designated["id"]).strip()
- emb = designated.get("embedding_model")
- if emb:
+ provider_id = str(designated["id"]).strip()
+ vector_stores["default_provider_id"] = provider_id
+ # Match _upsert_vsprov_embedding_model model_id; OGX validates
+ # provider_id/model_id against registered models, not the load path.
+ if designated.get("embedding_model"):
vector_stores["default_embedding_model"] = {
"provider_id": "sentence-transformers",
- "model_id": emb,
+ "model_id": f"vsprov_{provider_id}_embedding",
}
diff --git a/tests/unit/test_llama_stack_configuration.py b/tests/unit/test_llama_stack_configuration.py
index 74bd9d3fa..0f619af9c 100644
--- a/tests/unit/test_llama_stack_configuration.py
+++ b/tests/unit/test_llama_stack_configuration.py
@@ -151,7 +151,7 @@ def test_construct_vector_stores_section_adds_new() -> None:
assert len(output) == 1
assert output[0]["vector_store_id"] == "store1"
assert output[0]["provider_id"] == "byok_rag1"
- assert output[0]["embedding_model"] == "test-model"
+ assert output[0]["embedding_model"] == "sentence-transformers/byok_rag1_embedding"
assert output[0]["embedding_dimension"] == 512
@@ -234,7 +234,7 @@ def test_construct_vector_stores_section_skips_duplicate_within_byok() -> None:
]
output = construct_vector_stores_section(ls_config, byok_rag)
assert len(output) == 1
- assert output[0]["embedding_model"] == "model-a"
+ assert output[0]["embedding_model"] == "sentence-transformers/byok_rag1_embedding"
# =============================================================================
@@ -557,6 +557,26 @@ def test_construct_models_section_strips_prefix() -> None:
assert output[0]["provider_model_id"] == "/usr/path/model"
+def test_byok_vector_store_uses_registered_embedding_id_not_load_path() -> None:
+ """BYOK store lookup id matches registered model; path stays on provider_model_id."""
+ ls_config: dict[str, Any] = {}
+ byok_rag = [
+ {
+ "rag_id": "rhdh-docs",
+ "vector_db_id": "vs_abc",
+ "embedding_model": "sentence-transformers//rag-content/embeddings_model",
+ "embedding_dimension": 768,
+ },
+ ]
+ stores = construct_vector_stores_section(ls_config, byok_rag)
+ models = construct_models_section(ls_config, byok_rag)
+ assert stores[0]["embedding_model"] == (
+ "sentence-transformers/byok_rhdh-docs_embedding"
+ )
+ assert models[0]["model_id"] == "byok_rhdh-docs_embedding"
+ assert models[0]["provider_model_id"] == "/rag-content/embeddings_model"
+
+
def test_construct_storage_backends_section_raises_on_missing_rag_id() -> None:
"""Test raises ValueError when rag_id is missing from a BYOK RAG entry."""
ls_config: dict[str, Any] = {}
@@ -938,7 +958,7 @@ def test_enrich_vector_store_faiss_appends() -> None:
)
assert ls_config["vector_stores"]["default_provider_id"] == "notebooks"
assert ls_config["vector_stores"]["default_embedding_model"]["model_id"] == (
- "/rag-content/embeddings_model"
+ "vsprov_notebooks_embedding"
)
assert (
ls_config["vector_stores"]["annotation_prompt_params"]["enable_annotations"]
@@ -1084,7 +1104,7 @@ def test_enrich_vector_store_multiple_entries() -> None:
assert "vsprov_nb-pg_storage" not in ls_config["storage"]["backends"]
assert ls_config["vector_stores"]["default_provider_id"] == "notebooks"
assert ls_config["vector_stores"]["default_embedding_model"]["model_id"] == (
- "/emb-faiss"
+ "vsprov_notebooks_embedding"
)
assert (
ls_config["vector_stores"]["annotation_prompt_params"]["enable_annotations"]
@@ -1110,8 +1130,8 @@ def test_enrich_vector_store_noop_without_entries() -> None:
assert ls_config["vector_stores"]["default_provider_id"] == "faiss"
-def test_enrich_vector_store_dedupes_embedding_model() -> None:
- """Same provider_model_id as an existing model does not add a second row."""
+def test_enrich_vector_store_registers_alias_when_load_path_shared_with_byok() -> None:
+ """Shared provider_model_id with BYOK still registers vsprov_* for defaults."""
ls_config: dict[str, Any] = {
"providers": {},
"storage": {"backends": {}},
@@ -1144,7 +1164,43 @@ def test_enrich_vector_store_dedupes_embedding_model() -> None:
],
},
)
+ model_ids = {m["model_id"] for m in ls_config["registered_resources"]["models"]}
+ assert model_ids == {
+ "byok_rhdh-docs_embedding",
+ "vsprov_notebooks_embedding",
+ }
+ assert ls_config["vector_stores"]["default_embedding_model"]["model_id"] == (
+ "vsprov_notebooks_embedding"
+ )
+
+
+def test_enrich_vector_store_dedupes_same_vsprov_model_id() -> None:
+ """Re-enriching the same vector_store provider does not duplicate its model."""
+ ls_config: dict[str, Any] = {
+ "providers": {},
+ "storage": {"backends": {}},
+ "registered_resources": {"models": [], "vector_stores": []},
+ "vector_stores": {},
+ }
+ vector_store = {
+ "default_provider": "notebooks",
+ "providers": [
+ {
+ "id": "notebooks",
+ "type": "faiss",
+ "embedding_model": "/rag-content/embeddings_model",
+ "embedding_dimension": 768,
+ "config": {"path": "/tmp/n.db"},
+ }
+ ],
+ }
+ enrich_vector_store(ls_config, vector_store)
+ enrich_vector_store(ls_config, vector_store)
assert len(ls_config["registered_resources"]["models"]) == 1
+ assert (
+ ls_config["registered_resources"]["models"][0]["model_id"]
+ == "vsprov_notebooks_embedding"
+ )
def test_enrich_vector_store_skips_embedding_without_dimension() -> None:
diff --git a/tests/unit/test_llama_stack_synthesize.py b/tests/unit/test_llama_stack_synthesize.py
index c03fb604c..15927ae99 100644
--- a/tests/unit/test_llama_stack_synthesize.py
+++ b/tests/unit/test_llama_stack_synthesize.py
@@ -655,7 +655,7 @@ def test_synthesize_includes_vector_store() -> None:
assert "notebooks" in ids
assert result["vector_stores"]["default_provider_id"] == "notebooks"
assert result["vector_stores"]["default_embedding_model"]["model_id"] == (
- "/rag-content/embeddings_model"
+ "vsprov_notebooks_embedding"
)
From 4ec9bf7fe61982417f37af78739450124fbfd31f Mon Sep 17 00:00:00 2001
From: Jordan Dubrick
Date: Wed, 5 Aug 2026 16:50:39 -0400
Subject: [PATCH 037/197] address coderabbit review
Signed-off-by: Jordan Dubrick
---
src/llama_stack_configuration.py | 43 ++++++-----
tests/unit/test_llama_stack_configuration.py | 77 ++++++++++++++++++++
2 files changed, 100 insertions(+), 20 deletions(-)
diff --git a/src/llama_stack_configuration.py b/src/llama_stack_configuration.py
index 6ec0671ae..7d6692285 100644
--- a/src/llama_stack_configuration.py
+++ b/src/llama_stack_configuration.py
@@ -338,14 +338,16 @@ def construct_models_section(
provider_model_id = embedding_model
provider_model_id = provider_model_id.removeprefix("sentence-transformers/")
- # Skip if embedding model already registered
- existing_model_ids = [m.get("provider_model_id") for m in output]
- if provider_model_id in existing_model_ids:
+ # Dedupe by generated model_id (not load path). Vector stores look up
+ # sentence-transformers/byok__embedding; shared paths still need
+ # one alias per rag_id.
+ model_id = f"byok_{rag_id}_embedding"
+ if any(model.get("model_id") == model_id for model in output):
continue
output.append(
{
- "model_id": f"byok_{rag_id}_embedding",
+ "model_id": model_id,
"model_type": "embedding",
"provider_id": "sentence-transformers",
"provider_model_id": provider_model_id,
@@ -546,12 +548,12 @@ def _upsert_vsprov_embedding_model(
embedding_model: str,
embedding_dimension: int,
) -> None:
- """Register a vsprov embedding model alias if that model_id is not present.
+ """Register or refresh a vsprov embedding model alias by model_id.
- Dedupes by ``model_id`` (``vsprov__embedding``), not by load
- path. BYOK and ``vector_store`` often share the same
- ``provider_model_id``; both aliases must be registered so
- ``default_embedding_model`` can resolve.
+ Uses ``model_id`` ``vsprov__embedding`` (not load path) so
+ BYOK and ``vector_store`` can share a ``provider_model_id`` and both
+ resolve. Re-enrichment updates path and metadata when the same
+ ``model_id`` already exists.
Parameters:
ls_config: Llama Stack configuration modified in place.
@@ -562,18 +564,19 @@ def _upsert_vsprov_embedding_model(
"""
models = ls_config.setdefault("registered_resources", {}).setdefault("models", [])
model_id = f"vsprov_{provider_id}_embedding"
- if any(model.get("model_id") == model_id for model in models):
- return
provider_model_id = embedding_model.removeprefix("sentence-transformers/")
- models.append(
- {
- "model_id": model_id,
- "model_type": "embedding",
- "provider_id": "sentence-transformers",
- "provider_model_id": provider_model_id,
- "metadata": {"embedding_dimension": embedding_dimension},
- }
- )
+ entry = {
+ "model_id": model_id,
+ "model_type": "embedding",
+ "provider_id": "sentence-transformers",
+ "provider_model_id": provider_model_id,
+ "metadata": {"embedding_dimension": embedding_dimension},
+ }
+ for index, model in enumerate(models):
+ if model.get("model_id") == model_id:
+ models[index] = entry
+ return
+ models.append(entry)
def _vsprov_fields_and_backend(
diff --git a/tests/unit/test_llama_stack_configuration.py b/tests/unit/test_llama_stack_configuration.py
index 0f619af9c..3655eef08 100644
--- a/tests/unit/test_llama_stack_configuration.py
+++ b/tests/unit/test_llama_stack_configuration.py
@@ -577,6 +577,38 @@ def test_byok_vector_store_uses_registered_embedding_id_not_load_path() -> None:
assert models[0]["provider_model_id"] == "/rag-content/embeddings_model"
+def test_construct_models_section_registers_alias_per_rag_id_for_shared_path() -> None:
+ """Two BYOK entries sharing a load path each get a byok__embedding alias."""
+ ls_config: dict[str, Any] = {}
+ byok_rag = [
+ {
+ "rag_id": "docs-a",
+ "vector_db_id": "vs_a",
+ "embedding_model": "/rag-content/embeddings_model",
+ "embedding_dimension": 768,
+ },
+ {
+ "rag_id": "docs-b",
+ "vector_db_id": "vs_b",
+ "embedding_model": "/rag-content/embeddings_model",
+ "embedding_dimension": 768,
+ },
+ ]
+ models = construct_models_section(ls_config, byok_rag)
+ stores = construct_vector_stores_section(ls_config, byok_rag)
+ assert {m["model_id"] for m in models} == {
+ "byok_docs-a_embedding",
+ "byok_docs-b_embedding",
+ }
+ assert all(
+ m["provider_model_id"] == "/rag-content/embeddings_model" for m in models
+ )
+ assert {s["embedding_model"] for s in stores} == {
+ "sentence-transformers/byok_docs-a_embedding",
+ "sentence-transformers/byok_docs-b_embedding",
+ }
+
+
def test_construct_storage_backends_section_raises_on_missing_rag_id() -> None:
"""Test raises ValueError when rag_id is missing from a BYOK RAG entry."""
ls_config: dict[str, Any] = {}
@@ -1203,6 +1235,51 @@ def test_enrich_vector_store_dedupes_same_vsprov_model_id() -> None:
)
+def test_enrich_vector_store_updates_vsprov_alias_on_path_change() -> None:
+ """Re-enrichment with a new embedding path refreshes the vsprov_* model row."""
+ ls_config: dict[str, Any] = {
+ "providers": {},
+ "storage": {"backends": {}},
+ "registered_resources": {"models": [], "vector_stores": []},
+ "vector_stores": {},
+ }
+ enrich_vector_store(
+ ls_config,
+ {
+ "default_provider": "notebooks",
+ "providers": [
+ {
+ "id": "notebooks",
+ "type": "faiss",
+ "embedding_model": "/old/embeddings_model",
+ "embedding_dimension": 768,
+ "config": {"path": "/tmp/n.db"},
+ }
+ ],
+ },
+ )
+ enrich_vector_store(
+ ls_config,
+ {
+ "default_provider": "notebooks",
+ "providers": [
+ {
+ "id": "notebooks",
+ "type": "faiss",
+ "embedding_model": "/new/embeddings_model",
+ "embedding_dimension": 384,
+ "config": {"path": "/tmp/n.db"},
+ }
+ ],
+ },
+ )
+ models = ls_config["registered_resources"]["models"]
+ assert len(models) == 1
+ assert models[0]["model_id"] == "vsprov_notebooks_embedding"
+ assert models[0]["provider_model_id"] == "/new/embeddings_model"
+ assert models[0]["metadata"]["embedding_dimension"] == 384
+
+
def test_enrich_vector_store_skips_embedding_without_dimension() -> None:
"""embedding_model without embedding_dimension does not register a model."""
ls_config: dict[str, Any] = {
From efdc479c3b86316d1ed935ae9420bf8f296480b0 Mon Sep 17 00:00:00 2001
From: Maysun J Faisal
Date: Wed, 5 Aug 2026 17:31:37 -0400
Subject: [PATCH 038/197] RHIDP-16060: update providers submodule and fix ogx
model registration
- Update providers submodule to upstream main (faf6a89) which includes
merged PR #160: Solr vector_io provider migrated to ogx imports
- Add SOLR_EMBEDDING_MODEL_ID constant to prevent double-prefixing
- Use constant in llama_stack_configuration.py for model/vector store registration
---
providers | 2 +-
src/constants.py | 1 +
src/llama_stack_configuration.py | 9 ++-------
3 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/providers b/providers
index 778596236..faf6a89a3 160000
--- a/providers
+++ b/providers
@@ -1 +1 @@
-Subproject commit 778596236bb94d942d9f0b43f5c660d96532fb6f
+Subproject commit faf6a89a3ad7856e2e7a934324f31d146108acdb
diff --git a/src/constants.py b/src/constants.py
index 80335834a..93006b24b 100644
--- a/src/constants.py
+++ b/src/constants.py
@@ -254,6 +254,7 @@
"sentence-transformers/ibm-granite/granite-embedding-30m-english"
)
SOLR_DEFAULT_EMBEDDING_DIMENSION: Final[int] = 384
+SOLR_EMBEDDING_MODEL_ID: Final[str] = "sentence-transformers/solr_embedding"
# Default score multiplier for BYOK RAG vector stores
DEFAULT_SCORE_MULTIPLIER: Final[float] = 1.0
diff --git a/src/llama_stack_configuration.py b/src/llama_stack_configuration.py
index 62e76ec4b..e19e5d281 100644
--- a/src/llama_stack_configuration.py
+++ b/src/llama_stack_configuration.py
@@ -878,16 +878,11 @@ def enrich_solr( # pylint: disable=too-many-locals
for vs in ls_config["registered_resources"]["vector_stores"]
]
if constants.SOLR_DEFAULT_VECTOR_STORE_ID not in existing_stores:
- # Build environment variable expression
- embedding_model_env = (
- f"${{env.SOLR_EMBEDDING_MODEL:={constants.SOLR_DEFAULT_EMBEDDING_MODEL}}}"
- )
-
ls_config["registered_resources"]["vector_stores"].append(
{
"vector_store_id": constants.SOLR_DEFAULT_VECTOR_STORE_ID,
"provider_id": constants.SOLR_PROVIDER_ID,
- "embedding_model": embedding_model_env,
+ "embedding_model": constants.SOLR_EMBEDDING_MODEL_ID,
"embedding_dimension": constants.SOLR_DEFAULT_EMBEDDING_DIMENSION,
}
)
@@ -913,7 +908,7 @@ def enrich_solr( # pylint: disable=too-many-locals
ls_config["registered_resources"]["models"].append(
{
- "model_id": "solr_embedding",
+ "model_id": constants.SOLR_EMBEDDING_MODEL_ID,
"model_type": "embedding",
"provider_id": "sentence-transformers",
"provider_model_id": provider_model_env,
From 80cad86c345226e84c0fa4542837bda563c68c5f Mon Sep 17 00:00:00 2001
From: Maysun J Faisal
Date: Wed, 5 Aug 2026 18:27:17 -0400
Subject: [PATCH 039/197] RHIDP-16060: update Containerfile providers pin to
include ogx migration
Update LIGHTSPEED_PROVIDERS_COMMIT from 8cd1b3d (PR #118) to faf6a89
(PR #160 merge) so default builds include the Solr ogx provider migration.
Co-Authored-By: Claude Opus 4.6
---
deploy/lightspeed-stack/Containerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/deploy/lightspeed-stack/Containerfile b/deploy/lightspeed-stack/Containerfile
index 8108557a9..31a8e0331 100644
--- a/deploy/lightspeed-stack/Containerfile
+++ b/deploy/lightspeed-stack/Containerfile
@@ -36,7 +36,7 @@ COPY ${LSC_SOURCE_DIR}/pyproject.toml ${LSC_SOURCE_DIR}/LICENSE ${LSC_SOURCE_DIR
# lightspeed-providers:
# Fully hermetic — uses prefetched artifact or pinned commit from GitHub
-ARG LIGHTSPEED_PROVIDERS_COMMIT=8cd1b3d3bdd841ea99d31b334ae00a275581661c
+ARG LIGHTSPEED_PROVIDERS_COMMIT=faf6a89a3ad7856e2e7a934324f31d146108acdb
RUN set -eux; \
ZIP_PATH="/tmp/lightspeed-providers.zip"; \
EXTRACT_DIR="/tmp/providers"; \
From 88bc6c983c685a8511be0e8b3004a0001d9f8585 Mon Sep 17 00:00:00 2001
From: Maysun J Faisal
Date: Wed, 5 Aug 2026 18:36:28 -0400
Subject: [PATCH 040/197] RHIDP-16060: update OpenAPI schema and fix tests for
OKP search_mode
Regenerate openapi.json to include search_mode field on OkpConfiguration.
Fix test_dump_configuration expectations for search_mode: None.
Fix test_enrich_solr_adds_embedding_model for sentence-transformers/ prefix.
Co-Authored-By: Claude Opus 4.6
---
docs/devel_doc/openapi.json | 23 +++++++++++++++++--
.../models/config/test_dump_configuration.py | 10 ++++++++
tests/unit/test_llama_stack_configuration.py | 2 +-
3 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/docs/devel_doc/openapi.json b/docs/devel_doc/openapi.json
index 073109e41..ecf3bb767 100644
--- a/docs/devel_doc/openapi.json
+++ b/docs/devel_doc/openapi.json
@@ -15950,6 +15950,23 @@
],
"title": "OKP chunk filter query",
"description": "Additional OKP filter query applied to every OKP search request. Use Solr boolean syntax, e.g. 'product:ansible AND product:*openshift*'."
+ },
+ "search_mode": {
+ "anyOf": [
+ {
+ "type": "string",
+ "enum": [
+ "semantic",
+ "hybrid",
+ "keyword"
+ ]
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "title": "OKP search mode",
+ "description": "Default Solr search mode for OKP queries. 'keyword' uses BM25 text search (no embedding model needed). 'hybrid' combines vector + keyword search. 'semantic' uses pure vector search. When unset, falls back to the global default ('hybrid')."
}
},
"additionalProperties": false,
@@ -21277,7 +21294,8 @@
"enum": [
"semantic",
"hybrid",
- "lexical"
+ "lexical",
+ "keyword"
]
},
{
@@ -21285,10 +21303,11 @@
}
],
"title": "Mode",
- "description": "Solr vector_io search mode. When omitted, the server default ('hybrid') is used.",
+ "description": "Solr vector_io search mode. When omitted, the server default ('hybrid') is used. 'keyword' and 'lexical' both use BM25 text search.",
"examples": [
"hybrid",
"semantic",
+ "keyword",
"lexical"
]
},
diff --git a/tests/unit/models/config/test_dump_configuration.py b/tests/unit/models/config/test_dump_configuration.py
index 36dc1011e..45240651d 100644
--- a/tests/unit/models/config/test_dump_configuration.py
+++ b/tests/unit/models/config/test_dump_configuration.py
@@ -248,6 +248,7 @@ def test_dump_configuration_minimal_cfg(tmp_path: Path) -> None:
"rhokp_url": None,
"offline": True,
"chunk_filter_query": None,
+ "search_mode": None,
},
"rlsapi_v1": {
"allow_verbose_infer": False,
@@ -477,6 +478,7 @@ def test_dump_configuration_valid_values(tmp_path: Path) -> None:
"rhokp_url": None,
"offline": True,
"chunk_filter_query": None,
+ "search_mode": None,
},
"rlsapi_v1": {
"allow_verbose_infer": False,
@@ -857,6 +859,7 @@ def test_dump_configuration_with_quota_limiters(tmp_path: Path) -> None:
"rhokp_url": None,
"offline": True,
"chunk_filter_query": None,
+ "search_mode": None,
},
"rlsapi_v1": {
"allow_verbose_infer": False,
@@ -1121,6 +1124,7 @@ def test_dump_configuration_with_quota_limiters_different_values(
"rhokp_url": None,
"offline": True,
"chunk_filter_query": None,
+ "search_mode": None,
},
"rlsapi_v1": {
"allow_verbose_infer": False,
@@ -1418,6 +1422,7 @@ def test_dump_configuration_byok(tmp_path: Path) -> None:
"rhokp_url": None,
"offline": True,
"chunk_filter_query": None,
+ "search_mode": None,
},
"rlsapi_v1": {
"allow_verbose_infer": False,
@@ -1642,6 +1647,7 @@ def test_dump_configuration_pg_namespace(tmp_path: Path) -> None:
"rhokp_url": None,
"offline": True,
"chunk_filter_query": None,
+ "search_mode": None,
},
"rlsapi_v1": {
"allow_verbose_infer": False,
@@ -2026,6 +2032,7 @@ def test_dump_configuration_allow_degraded_mode(tmp_path: Path) -> None:
"rhokp_url": None,
"offline": True,
"chunk_filter_query": None,
+ "search_mode": None,
},
"rlsapi_v1": {
"allow_verbose_infer": False,
@@ -2256,6 +2263,7 @@ def test_dump_configuration_max_retries_settings(tmp_path: Path) -> None:
"rhokp_url": None,
"offline": True,
"chunk_filter_query": None,
+ "search_mode": None,
},
"rlsapi_v1": {
"allow_verbose_infer": False,
@@ -2486,6 +2494,7 @@ def test_dump_configuration_retry_count_settings(tmp_path: Path) -> None:
"rhokp_url": None,
"offline": True,
"chunk_filter_query": None,
+ "search_mode": None,
},
"rlsapi_v1": {
"allow_verbose_infer": False,
@@ -2723,6 +2732,7 @@ def test_dump_configuration_specific_compaction_values(tmp_path: Path) -> None:
"rhokp_url": None,
"offline": True,
"chunk_filter_query": None,
+ "search_mode": None,
},
"rlsapi_v1": {
"allow_verbose_infer": False,
diff --git a/tests/unit/test_llama_stack_configuration.py b/tests/unit/test_llama_stack_configuration.py
index 74bd9d3fa..a0f0bcbbe 100644
--- a/tests/unit/test_llama_stack_configuration.py
+++ b/tests/unit/test_llama_stack_configuration.py
@@ -808,7 +808,7 @@ def test_enrich_solr_adds_embedding_model() -> None:
enrich_solr(ls_config, _OKP_RAG_CONFIG, {})
model_ids = [m["model_id"] for m in ls_config["registered_resources"]["models"]]
- assert "solr_embedding" in model_ids
+ assert "sentence-transformers/solr_embedding" in model_ids
def test_enrich_solr_skips_duplicate_provider() -> None:
From 18c0876dd69b0b99f90afca307de944aa4e8ccd9 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Thu, 6 Aug 2026 09:39:52 +0200
Subject: [PATCH 041/197] LCORE-2922: Updated dependencies
---
uv.lock | 168 ++++++++++++++++++++++++++++----------------------------
1 file changed, 84 insertions(+), 84 deletions(-)
diff --git a/uv.lock b/uv.lock
index a153d77ea..09ea82c2a 100644
--- a/uv.lock
+++ b/uv.lock
@@ -201,11 +201,11 @@ wheels = [
[[package]]
name = "argcomplete"
-version = "3.7.1"
+version = "3.7.2"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/d1/40/8a867253c9b8afa296ac22e426a157eebbe41dcac66f7f50bbbef931afed/argcomplete-3.7.1.tar.gz", hash = "sha256:6926a3a70ae70dce1f3dfb5cf1fc984278cd163e78ec18ad2ed7fa4fabd8f281", size = 74457, upload-time = "2026-08-04T15:03:59.399Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/87/6f/5a73f04007ca950701765949209f068da628bd11f9c2da287278ce91e0ee/argcomplete-3.7.2.tar.gz", hash = "sha256:aad8b69a0b9969edb62db0d1752354c0d50717b10e0cbb00e2a958381b9fc6b9", size = 74473, upload-time = "2026-08-06T04:53:21.662Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/11/56/1935d0692656f0bfc0c2336d4ce599dcf166abe4ec786ce1abdaefa19589/argcomplete-3.7.1-py3-none-any.whl", hash = "sha256:0bed095030f295599b1018a622a53ea22f4f253e134b87be396b51e59ee00954", size = 43301, upload-time = "2026-08-04T15:03:58.02Z" },
+ { url = "https://files.pythonhosted.org/packages/46/bd/551ee6af426af84ca33e02622be722925c196608e9127d731ef17c47f06e/argcomplete-3.7.2-py3-none-any.whl", hash = "sha256:6029205678bdd9c1c728a155f5f9ecf5812393f969eef58807641a2bc2aa5b19", size = 43294, upload-time = "2026-08-06T04:53:20.246Z" },
]
[[package]]
@@ -500,23 +500,23 @@ wheels = [
[[package]]
name = "chardet"
-version = "7.4.3"
+version = "7.5.1"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/19/b6/9df434a8eeba2e6628c465a1dfa31034228ef79b26f76f46278f4ef7e49d/chardet-7.4.3.tar.gz", hash = "sha256:cc1d4eb92a4ec1c2df3b490836ffa46922e599d34ce0bb75cf41fd2bf6303d56", size = 784800, upload-time = "2026-04-13T21:33:39.803Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/56/7c/c9cf52695364a0609829ccc9e88adea553587ef70349314f29ed1b62bcff/chardet-7.5.1.tar.gz", hash = "sha256:0df08f2b2f6ac04b3e7f9e8ad1b1559c2e8497338ff9dfa1e0922335ff9dfe8d", size = 837498, upload-time = "2026-08-06T05:02:11.499Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/61/33/29de185079e6675c3f375546e30a559b7ddc75ce972f18d6e566cd9ea4eb/chardet-7.4.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:75d3c65cc16bddf40b8da1fd25ba84fca5f8070f2b14e86083653c1c85aee971", size = 874870, upload-time = "2026-04-13T21:33:05.977Z" },
- { url = "https://files.pythonhosted.org/packages/9c/2f/4c5af01fd1a7506a1d5375403d68925eac70289229492db5aa68b58103d8/chardet-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:29af5999f654e8729d251f1724a62b538b1262d9292cccaefddf8a02aae1ef6a", size = 854859, upload-time = "2026-04-13T21:33:07.381Z" },
- { url = "https://files.pythonhosted.org/packages/36/21/edb36ad5dfa48d7f8eed97ab43931ecdaa8c15166c21b1d614967e49d681/chardet-7.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:626f00299ad62dfe937058a09572beed442ccc7b58f87aa667949b20fd3db235", size = 875032, upload-time = "2026-04-13T21:33:08.741Z" },
- { url = "https://files.pythonhosted.org/packages/e5/59/a32a241d861cf180853a11c8e5a67641cb1b2af13c3a5ccce83ec07e2c9f/chardet-7.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9a4904dd5f071b7a7d7f50b4a67a86db3c902d243bf31708f1d5cde2f68239cb", size = 888283, upload-time = "2026-04-13T21:33:10.213Z" },
- { url = "https://files.pythonhosted.org/packages/87/2e/e1ee6a77abf3782c00e05b89c4d4328c8353bf9500661c4348df1dd68614/chardet-7.4.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5d2879598bc220689e8ce509fe9c3f37ad2fca53a36be9c9bd91abdd91dd364f", size = 879974, upload-time = "2026-04-13T21:33:11.448Z" },
- { url = "https://files.pythonhosted.org/packages/32/60/fca69c534602a7ced04280c952a246ad1edde2a6ca3a164f65d32ac41fe7/chardet-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:4b2799bd58e7245cfa8d4ab2e8ad1d76a5c3a5b1f32318eb6acca4c69a3e7101", size = 943973, upload-time = "2026-04-13T21:33:12.756Z" },
- { url = "https://files.pythonhosted.org/packages/7c/43/79ac9b4db5bc87020c9dbc419125371d80882d1d197e9c4765ba8682b605/chardet-7.4.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a9e4486df251b8962e86ea9f139ca235aa6e0542a00f7844c9a04160afb99aa9", size = 873769, upload-time = "2026-04-13T21:33:14.002Z" },
- { url = "https://files.pythonhosted.org/packages/55/5f/25bdec773905bff0ff6cf35ca73b17bd05593b4f87bd8c5fa43705f7167d/chardet-7.4.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4fbff1907925b0c5a1064cffb5e040cd5e338585c9c552625f30de6bc2f3107a", size = 853991, upload-time = "2026-04-13T21:33:15.564Z" },
- { url = "https://files.pythonhosted.org/packages/b4/07/a29380ee0b215d23d77733b5ad60c5c0c7969650e080c667acdf9462040d/chardet-7.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:365135eaf37ba65a828f8e668eb0a8c38c479dcbec724dc25f4dfd781049c357", size = 874024, upload-time = "2026-04-13T21:33:16.915Z" },
- { url = "https://files.pythonhosted.org/packages/a8/b1/3338e121cbd4c8a126b8ccb1061170c2ce51a53f678c502793ea49c6fd6d/chardet-7.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfc134b70c846c21ead8e43ada3ae1a805fff732f6922f8abcf2ff27b8f6493d", size = 887410, upload-time = "2026-04-13T21:33:18.368Z" },
- { url = "https://files.pythonhosted.org/packages/63/1c/44a9a9e0c59c185a5d307ceaeee8768afa1558f0a24f7a4b5fa11b67586b/chardet-7.4.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9acd9988a93e09390f3cd231201ea7166c415eb8da1b735928990ffc05cb9fbb", size = 879269, upload-time = "2026-04-13T21:33:20.377Z" },
- { url = "https://files.pythonhosted.org/packages/1b/b3/5d0e77ea774bd3224321c248880ea0c0379000ac5c2bb6d77609549de247/chardet-7.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:e1b98790c284ff813f18f7cf7de5f05ea2435a080030c7f1a8318f3a4f80b131", size = 944155, upload-time = "2026-04-13T21:33:21.694Z" },
- { url = "https://files.pythonhosted.org/packages/8c/6c/0a40afdb50a0fe041ab95553b835a8160b6cf0e81edf2ae2fe9f5224cbf9/chardet-7.4.3-py3-none-any.whl", hash = "sha256:1173b74051570cf08099d7429d92e4882d375ad4217f92a6e5240ccfb26f231e", size = 626562, upload-time = "2026-04-13T21:33:38.559Z" },
+ { url = "https://files.pythonhosted.org/packages/29/95/60f047ece9faf585d6f625adea8786bb15a453fbf183e77a5762c8755c86/chardet-7.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3eb37b2c0aa67bfb1112aa90bfdd95cd3b4006fe051a2ea4872c3c6ba9cf855b", size = 939537, upload-time = "2026-08-06T05:01:34.127Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/8e/847935c588455b0d82fa57a5a8ced4c73a928e30f2012639228e566e3283/chardet-7.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8a001a8f030625b705d9a4e68116e573462bd38192cc6c1bfa318b45606747ac", size = 922039, upload-time = "2026-08-06T05:01:35.929Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/9f/841f7d9f1ff7b99ef2a7e7596b14199dbfe289a11b39c7f98cfb23d0c55a/chardet-7.5.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:54bae16fc5b7ea39956ee737dd09b5f5438deafa9f565ac27c882992c3965b88", size = 945557, upload-time = "2026-08-06T05:01:37.696Z" },
+ { url = "https://files.pythonhosted.org/packages/10/56/89866e9995fdb2c8e8ff1336c4ecd4c86ba0f7e4622ccfacad2c13b2ba7e/chardet-7.5.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecbe0e0a9fff7825fc48650ef297ede49c71a7abc411a0638416207a70bf78c0", size = 961089, upload-time = "2026-08-06T05:01:39.319Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/fe/f568f20d0cea7f853769d3015915daf8bb8460a4265237a051bb374fdcd0/chardet-7.5.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:469f164a608ccee4a8a2c0c2b4328470df9b07443e8269714f8e8a51f6fdf4c4", size = 950289, upload-time = "2026-08-06T05:01:40.782Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/9a/9e17c1c6fbc65f9cba07951d359a24c8f7b17d3ca26bd54f33fd98b70f2e/chardet-7.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:fad6fbc154113e3b17bb757c34b21477e4b6d69fdd4ce51ff2b3f29a42f08b5b", size = 1036514, upload-time = "2026-08-06T05:01:42.394Z" },
+ { url = "https://files.pythonhosted.org/packages/53/3d/3aed10edee5735bc92cf0bd1a469335f596331b3ffc82bbdd157f8d5135f/chardet-7.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b72b9b95c636d170d9a6284d99be9fd93ca08bb2221385ff1a5b69da98ec4f76", size = 935215, upload-time = "2026-08-06T05:01:44.082Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/e9/bd883f6ed3cb53a66b6752da493ef4b82f6435e7c085e0eee21296a0a31c/chardet-7.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4d30a84ec52c37532ad7978329a41224c454959b22503b8f8ed4df763e6c3ed2", size = 917514, upload-time = "2026-08-06T05:01:46.018Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/d2/1773383d05a6cc1a69ee075cf477942edbb00c90bf8ac9778bce884e4c0a/chardet-7.5.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e6faa6b18c7af2fca8d4cbb51fa035fa47f8f4b68547ae927a1c0be34dfc96fa", size = 944654, upload-time = "2026-08-06T05:01:48.01Z" },
+ { url = "https://files.pythonhosted.org/packages/05/c2/9e5200bd6f8c6a32d0f2bbb6235783b3ca421630cb4f18507d5c9edc07ac/chardet-7.5.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36843a0e9e3196142e317806d5ca29ab0bb714de2315897124a018438cc535a3", size = 959589, upload-time = "2026-08-06T05:01:49.512Z" },
+ { url = "https://files.pythonhosted.org/packages/11/b7/1e49d101a790501e540f9d9b33e52a65ccfcc0c0748220cb3ffb44987823/chardet-7.5.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:59598a8e15769ebe62fd0c153a5e4347a7a126cc7b376a724ff63ad80b890506", size = 949138, upload-time = "2026-08-06T05:01:50.993Z" },
+ { url = "https://files.pythonhosted.org/packages/88/d4/ed3b7e5c882ba24b71df8554840898ebbbbc3a57844d218edd4a1f8770a4/chardet-7.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:71f152d66e7bd1faad615897d34765243cb567ad6aef07bf0d7c0cdd69bf6cce", size = 1034753, upload-time = "2026-08-06T05:01:52.488Z" },
+ { url = "https://files.pythonhosted.org/packages/36/6b/f195e0d66b1e18ccbcc3adc52c1c7e1263203e70b9bbe12c5a4198d1935b/chardet-7.5.1-py3-none-any.whl", hash = "sha256:ba7e9b6c15b4fcdf07ae675e5116dee610425f9ad6955c9bdb6bf99aed2e555d", size = 655022, upload-time = "2026-08-06T05:02:10.071Z" },
]
[[package]]
@@ -662,20 +662,20 @@ wheels = [
[[package]]
name = "cucumber-expressions"
-version = "20.0.0"
+version = "20.1.0"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/a2/a6/eaac4ff3afdc776a4d3e0ef29c79db1c9faf11c423175771e225bcef9c84/cucumber_expressions-20.0.0.tar.gz", hash = "sha256:5cbd4012c66584aa82ada990a6e7cb131274796e132e905d27d95ae9a2ca0f48", size = 13738, upload-time = "2026-06-11T07:13:43.691Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/a3/001d7725688d5f8ae7d73d746457c9d11b851a4bad3a315dc7762144ec96/cucumber_expressions-20.1.0.tar.gz", hash = "sha256:0d216ec26e36c71b3e5643f2e72c41f9b266ef04eaa0c7e47a6e3b2caf523b1a", size = 13826, upload-time = "2026-08-05T20:16:52.542Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/75/24/e403585f201d30ab561d8a971a1adc4de28123fb9bf2f9813650fda8ddb0/cucumber_expressions-20.0.0-py3-none-any.whl", hash = "sha256:8a0434529efd7ca6e2052934ec8d677c7e24edc0fad3b1d1b1bc4bbca5e521f3", size = 20236, upload-time = "2026-06-11T07:13:42.667Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/b1/fba2393968001b2307facb76e0bc47be5c67185df752a8f5b61926d26760/cucumber_expressions-20.1.0-py3-none-any.whl", hash = "sha256:640782ebaef82313dc64e4684d0e5c5efbab0611b23f0cfad64f90c7041cf73d", size = 20230, upload-time = "2026-08-05T20:16:51.565Z" },
]
[[package]]
name = "cucumber-tag-expressions"
-version = "11.0.0"
+version = "11.0.1"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/01/98/69e82d5bfaebde03b205c6722e4ebe52940aad26a3768f3c3d28b1e391f3/cucumber_tag_expressions-11.0.0.tar.gz", hash = "sha256:9739a7b3e04b3ee9f77748d2b48dc9e7ff41b041ed6b651283cfec022f0e6d0b", size = 8442, upload-time = "2026-07-23T10:56:49.869Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/50/e0/c2741558040293465d615a4f2555e9180c54a559119b96ff0251dda5fa90/cucumber_tag_expressions-11.0.1.tar.gz", hash = "sha256:f8304dd16e546517816e62ace6c486575023812f42e8a60526fcec1694016146", size = 8635, upload-time = "2026-08-05T20:33:20.775Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/ed/34/fbd46adb089ec277e9b7da3db479976c228c28407dce15e34554478c8ba9/cucumber_tag_expressions-11.0.0-py3-none-any.whl", hash = "sha256:86ce0647bed1e52d6a634649c31758faa22821531541848f221b1f6c4f75c9f7", size = 9723, upload-time = "2026-07-23T10:56:49.023Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/2a/894aded5804c76cf148965721cb57fed0d923ddb2747a77c9147f20d58a9/cucumber_tag_expressions-11.0.1-py3-none-any.whl", hash = "sha256:8ee5433a3b1ad16ca607c905fa3bb6d85d57f087ba119b14ea5e82cd35ea98c5", size = 9757, upload-time = "2026-08-05T20:33:19.95Z" },
]
[[package]]
@@ -855,7 +855,7 @@ wheels = [
[[package]]
name = "fastmcp-slim"
-version = "3.4.5"
+version = "3.4.6"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "platformdirs" },
@@ -865,9 +865,9 @@ dependencies = [
{ name = "rich" },
{ name = "typing-extensions" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/81/1d/f3e271fbcd01ce01a4cf623b336d8e1305c192aa5d5e8e0223b7167462e9/fastmcp_slim-3.4.5.tar.gz", hash = "sha256:5badc3bceee61f61297eeb9494f499325f3ce1cafabf4611b31f6c3e9d7dff59", size = 591622, upload-time = "2026-07-27T19:15:19.455Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/ca/b6/b5b9e81e67a3f39534881d2af6aa3fbd2dc367eaa070c3c932770a0c062f/fastmcp_slim-3.4.6.tar.gz", hash = "sha256:6a1e6e42c697ba90abcb1be617a26947d07316f13c6fa138ae7b0de24558e32c", size = 594167, upload-time = "2026-08-05T14:54:15.924Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/43/3b/16d8aa8224094519f30b078138e725b8a731bf0a13f1f850e58b5f9b3cc4/fastmcp_slim-3.4.5-py3-none-any.whl", hash = "sha256:bc31217827c4999812543c83ee95ed9a47f3ed1e3fd0bd4f64371e375b748eca", size = 766478, upload-time = "2026-07-27T19:15:18.015Z" },
+ { url = "https://files.pythonhosted.org/packages/11/0b/02c254c46b4323ae5262b76a29af73b50a863efc5739a3454d144d3605ee/fastmcp_slim-3.4.6-py3-none-any.whl", hash = "sha256:3e08e6acb03523a47aa17f4d2ab9943e648a41e20b24084da491a732c46dffdc", size = 769174, upload-time = "2026-08-05T14:54:14.663Z" },
]
[package.optional-dependencies]
@@ -1018,7 +1018,7 @@ wheels = [
[[package]]
name = "google-api-core"
-version = "2.33.0"
+version = "2.34.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "google-auth" },
@@ -1027,9 +1027,9 @@ dependencies = [
{ name = "protobuf" },
{ name = "requests" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/87/62/8fb1fb647d2788c950d69d6a769cd9d55c918ac1fc57be2f90b7e4029787/google_api_core-2.33.0.tar.gz", hash = "sha256:3a36bcc3e319783f4c97da41f6f45ea6ffcaa55848e341de16e09cb70243c2bb", size = 181607, upload-time = "2026-07-22T16:28:28.027Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/7b/7c/9be3903e3d45415e8ca493c75f8990a0f6f579d168015d44c379350d0ab0/google_api_core-2.34.0.tar.gz", hash = "sha256:98a779fe72de956eb1c9c2f47ff4c4432a668ece1a002ec38bed07ec2698ae59", size = 187953, upload-time = "2026-08-06T06:23:58.128Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/89/31/5056a347bb934ea04583c8b27916ef1501729c72638629545bce26ff4223/google_api_core-2.33.0-py3-none-any.whl", hash = "sha256:a2e22a0c1d0f03eafff1858b38cf46f832d5902b0c052235bf0ab8402929fbdc", size = 176462, upload-time = "2026-07-22T16:28:22.447Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/c1/a8a92ae1bc4b1a8f804c776d7d3f0c771b78a62c3ad4df1be41b3fd8c767/google_api_core-2.34.0-py3-none-any.whl", hash = "sha256:cdf9c67e7ca2402d86ccbfde5f2503fc83e3cc3f58cc78456ae96cad24a6d2de", size = 180545, upload-time = "2026-08-06T06:22:47.502Z" },
]
[package.optional-dependencies]
@@ -1040,15 +1040,15 @@ grpc = [
[[package]]
name = "google-auth"
-version = "2.56.2"
+version = "2.56.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cryptography" },
{ name = "pyasn1-modules" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/c7/33/dbc946a407401b975f0719658f18e664ece2109f79ffd1ff3bf226c205f4/google_auth-2.56.2.tar.gz", hash = "sha256:e28f103ca8091fb7012b99c44243d7366c29863713b8e34a220c3322b7a07051", size = 365820, upload-time = "2026-07-21T21:53:28.188Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/db/4c/fa42116a48bab3f7a143cf5042ecff7df9c8b73f8a376203cd534d1dc966/google_auth-2.56.3.tar.gz", hash = "sha256:40e229fc901f0a305b553050e5fce562d509bee0435be053abfa91582b51b90c", size = 367110, upload-time = "2026-08-06T06:24:01.36Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/88/63/50636aae68c9bf17c891c7eb18b49baa9bd6b31d2a97b8de4813a9fc8d1c/google_auth-2.56.2-py3-none-any.whl", hash = "sha256:c8270ea95b2697b74e3d8438ae9c5b898e38b623b915c7b5c5635921e7de68a6", size = 258588, upload-time = "2026-07-21T21:53:26.399Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/b3/6117b2f24065cd7e2c4f140e9a193e215f089ca8ba314cf91eb9d0b7fe0a/google_auth-2.56.3-py3-none-any.whl", hash = "sha256:8ec438808f813ad034535000261eed1067475d229d05bbf4216e78c3f2362e53", size = 259116, upload-time = "2026-08-06T06:22:51.788Z" },
]
[package.optional-dependencies]
@@ -1085,7 +1085,7 @@ wheels = [
[[package]]
name = "google-cloud-bigquery"
-version = "3.42.3"
+version = "3.43.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "google-api-core", extra = ["grpc"] },
@@ -1096,22 +1096,22 @@ dependencies = [
{ name = "python-dateutil" },
{ name = "requests" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/0a/53/6a9c19cde15ffe3f218653e4f11d08b2ef97dad78c07c473bc95f8ce7aa9/google_cloud_bigquery-3.42.3.tar.gz", hash = "sha256:d03f8da5ed94aeae5457f3127216cb385392ba266bede25ea257aeec94512900", size = 518359, upload-time = "2026-07-30T18:15:19.314Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/99/a2/5ee4a9eae62dbd61e59504458d5cf870809f790ed136967d94c294b9a3ba/google_cloud_bigquery-3.43.0.tar.gz", hash = "sha256:e3dc25ab9ac8b2b089408493177d4d4508b098c80c3931786fbc20b075298fe6", size = 519709, upload-time = "2026-08-06T06:24:11.919Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/0a/fe/a862130426b56c062dcbc2fcb5a9e4bec9fea9193821718d718f9f10be61/google_cloud_bigquery-3.42.3-py3-none-any.whl", hash = "sha256:81b9bfa3a5fa098a04351c1a12579d16f28b93b836e4556ef6410a01deebf418", size = 264652, upload-time = "2026-07-30T18:15:17.549Z" },
+ { url = "https://files.pythonhosted.org/packages/67/c0/f491506bdff4d73750f74cf18fea7d6ca409ada2f81c4c4d10a32edf5688/google_cloud_bigquery-3.43.0-py3-none-any.whl", hash = "sha256:a39217f14f215472ce9da816f20ebaf77fdb1db7ccdc8360772d8bf6bafb55c2", size = 265159, upload-time = "2026-08-06T06:23:04.281Z" },
]
[[package]]
name = "google-cloud-core"
-version = "2.6.0"
+version = "2.6.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "google-api-core" },
{ name = "google-auth" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/a8/dd/1eef226e470369b26824a505c34482c0b493bc35fe8e0c6b003b5feca21a/google_cloud_core-2.6.0.tar.gz", hash = "sha256:e76149739f90fac1fc6757c09f47eaccb3145b54adbd7759b0f7c4b235f46c83", size = 36001, upload-time = "2026-05-07T08:04:04.124Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/4a/c6/9d7d9ed6703eb35306ca7bf381fb66ba8d978c61a1b550a2e1730a4c4ce8/google_cloud_core-2.6.1.tar.gz", hash = "sha256:1e044b131f2ae097b92312fa195164b0aeb6dc6a88e00231e1210516314c420c", size = 36017, upload-time = "2026-08-06T06:24:18.211Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/84/4a/98da8930ab109c73d9a5d13782a9ebb81ea8c111f6d534a567b71d23e52b/google_cloud_core-2.6.0-py3-none-any.whl", hash = "sha256:6d63ac8e5eca6d9e4319d0a1e2265fadcd7f1049904378caecfa01cf52dd869e", size = 29390, upload-time = "2026-05-07T08:02:34.672Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/4f/37960d5255988b218c40c9b5a2b731013684294a50735d1dd1ab4894e531/google_cloud_core-2.6.1-py3-none-any.whl", hash = "sha256:2682a8a4474a32f56292fb4bca7fa7e4fb0b4af958f6abfe4bca8d195747fd45", size = 29393, upload-time = "2026-08-06T06:23:11.405Z" },
]
[[package]]
@@ -1133,7 +1133,7 @@ wheels = [
[[package]]
name = "google-cloud-storage"
-version = "3.13.0"
+version = "3.13.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "google-api-core" },
@@ -1143,9 +1143,9 @@ dependencies = [
{ name = "google-resumable-media" },
{ name = "requests" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/e3/25/355ed97c1723c787dfaa888808d55db18371f82c38ff862357b1e902cd19/google_cloud_storage-3.13.0.tar.gz", hash = "sha256:d11d8706ea1520fba0f21043bcb7897caf7015d76ce1ad9a4f60237e4d7a9f6c", size = 17340960, upload-time = "2026-07-13T19:10:07.524Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/ce/7e/73bb7512df1d1aad6ce3f9aed847cd40e0cd400ba4a85d86ab8eb412e9cc/google_cloud_storage-3.13.1.tar.gz", hash = "sha256:a80bf8cac2794808aa61c50c5f769ecbbe2d10331bacd0d69d30e59b14b346b2", size = 17341051, upload-time = "2026-08-06T06:24:42.229Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/81/e8/b3678a0931ee7d4b3fdaf0813e6206d66e0922b2c26d912f308728b5b95a/google_cloud_storage-3.13.0-py3-none-any.whl", hash = "sha256:648af3ef8a6acc674e1359d3c920c67eb89a7a5ab66b336bd3ac43fed6b5ab84", size = 341428, upload-time = "2026-07-13T19:09:52.39Z" },
+ { url = "https://files.pythonhosted.org/packages/06/6f/d69f0e185e08ddb58c323a0a935af2b492907b5de362bc08933b0a3b5644/google_cloud_storage-3.13.1-py3-none-any.whl", hash = "sha256:98208de6c21e85cecd3eb44551894efff33d98365500e178867d4305854a770a", size = 341486, upload-time = "2026-08-06T06:23:36.548Z" },
]
[[package]]
@@ -1168,7 +1168,7 @@ wheels = [
[[package]]
name = "google-genai"
-version = "2.16.0"
+version = "2.17.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -1182,33 +1182,33 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "websockets" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/81/e6/ff83088427072cc9d5d21036788cf0ed08cc4906e4a5810e469553a43185/google_genai-2.16.0.tar.gz", hash = "sha256:c4c2524926001b18073db927a5d75bb7c8be7b5fd13ab507d599f51fff2284c5", size = 647939, upload-time = "2026-07-30T14:34:37.366Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/58/2e/03a0486e192cde27f7ffbb20c63fa934a132396a667b1a0e1b7e5f606ad7/google_genai-2.17.0.tar.gz", hash = "sha256:6b640a2390c82b4a240873eddb9f518c6d2c33244b2de16ed3d14526a6da7f57", size = 648676, upload-time = "2026-08-06T05:10:41.382Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/3b/c6/f111056110030b1a5fb949687d7f93c2b4e8996f6494ae32efb049482796/google_genai-2.16.0-py3-none-any.whl", hash = "sha256:f9eda6a7a3dd4491a0d2253c4bdd4536462d63838ed3f1b0e4fb9a0eb8f43331", size = 1050096, upload-time = "2026-07-30T14:34:35.578Z" },
+ { url = "https://files.pythonhosted.org/packages/b3/37/71e397a5b93d9a3c139e95acdcb00b4169ed59ae20e16616f2875170abb7/google_genai-2.17.0-py3-none-any.whl", hash = "sha256:a4835563c60aee646c9c4b261c507aa4a624710d25017012d20dc65abf3d9a54", size = 1044950, upload-time = "2026-08-06T05:10:39.308Z" },
]
[[package]]
name = "google-resumable-media"
-version = "2.10.0"
+version = "2.10.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "google-crc32c" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/48/f8/1ca5781d6be9cb9f73f7d40f4958c4bd1226a60598e3e39e1d6aaf838c4b/google_resumable_media-2.10.0.tar.gz", hash = "sha256:e324bc9d0fdae4c52a08ae90456edc4e71ece858399e1217ac0eb3a51d6bc6ee", size = 2164570, upload-time = "2026-06-03T16:14:26.103Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/f5/f35505e6091614e285056a495488cb0a9c1a9dcc88a4a3c91bbc5fd4835b/google_resumable_media-2.10.1.tar.gz", hash = "sha256:224975032ddb73f7ed9e2f0f4cc08ed1b06874c52d48cc8533e3eb72980b21a0", size = 2164548, upload-time = "2026-08-06T06:24:50.489Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b0/d8/00c6854ac1512bb9eaf13bd3f8f28222f7674947fc510a4ff7616f2efc80/google_resumable_media-2.10.0-py3-none-any.whl", hash = "sha256:88152884bee37b2bf36a0ab81ad8c7fd12212c9803dd981d77c1b35b02d34e7c", size = 81533, upload-time = "2026-06-03T16:13:12.51Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/ba/77ef49baf338c03a11deadac984e3161b3f2b4fa4bb5aab160e7ca0fd522/google_resumable_media-2.10.1-py3-none-any.whl", hash = "sha256:4e2cbc704207ddc09f23b1f18e8ef4a4ccbfe0f1768b370e5c969704adbd0a1c", size = 81533, upload-time = "2026-08-06T06:23:45.464Z" },
]
[[package]]
name = "googleapis-common-protos"
-version = "1.75.0"
+version = "1.75.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "protobuf" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/b5/c8/f439cffde755cffa462bfbb156278fa6f9d09119719af9814b858fd4f81f/googleapis_common_protos-1.75.0.tar.gz", hash = "sha256:53a062ff3c32552fbd62c11fe23768b78e4ddf0494d5e5fd97d3f4689c75fbbd", size = 151035, upload-time = "2026-05-07T08:04:49.423Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/73/74bcab964c9a7a61f2bb71e8179b0f13e6fa98f7ce00fd168aab291e4a2e/googleapis_common_protos-1.75.1.tar.gz", hash = "sha256:d3042c6c5a2d4e67113104d6b6818b59b6bd92a197f2a91508e801fe815cf071", size = 150967, upload-time = "2026-08-06T06:24:51.972Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/e7/c8/e2645aa8ed02fd4c7a2f59d68783b65b1f3cbdfe39a6308e156509d1fee8/googleapis_common_protos-1.75.0-py3-none-any.whl", hash = "sha256:961ed60399c457ceb0ee8f285a84c870aabc9c6a832b9d37bb281b5bebde43ed", size = 300631, upload-time = "2026-05-07T08:03:30.345Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/51/186c02b8549b69ccda44429cf6ff5081e4b61a602ddfe6a8020d1be31d1b/googleapis_common_protos-1.75.1-py3-none-any.whl", hash = "sha256:28a1934bcd33b9c9da66ac301a0a4227e3367f095a17d0375cb98f0a09d93b79", size = 300626, upload-time = "2026-08-06T06:23:46.696Z" },
]
[package.optional-dependencies]
@@ -1255,16 +1255,16 @@ wheels = [
[[package]]
name = "grpc-google-iam-v1"
-version = "0.14.4"
+version = "0.14.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "googleapis-common-protos", extra = ["grpc"] },
{ name = "grpcio" },
{ name = "protobuf" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/44/4f/d098419ad0bfc06c9ce440575f05aa22d8973b6c276e86ac7890093d3c37/grpc_google_iam_v1-0.14.4.tar.gz", hash = "sha256:392b3796947ed6334e61171d9ab06bf7eb357f554e5fc7556ad7aab6d0e17038", size = 23706, upload-time = "2026-04-01T01:57:49.813Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/d2/d0/fa5bdd5f3f421bb68dc6dc162e9caaf942897ca41ce7255b524723c80f0b/grpc_google_iam_v1-0.14.5.tar.gz", hash = "sha256:07fd3a9fafb586588e771831fbfc8f6597050181d0c3b45e039d18b8fdc1aab5", size = 23736, upload-time = "2026-08-06T06:24:54.489Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/89/22/c2dd50c09bf679bd38173656cd4402d2511e563b33bc88f90009cf50613c/grpc_google_iam_v1-0.14.4-py3-none-any.whl", hash = "sha256:412facc320fcbd94034b4df3d557662051d4d8adfa86e0ddb4dca70a3f739964", size = 32675, upload-time = "2026-04-01T01:57:47.69Z" },
+ { url = "https://files.pythonhosted.org/packages/84/ab/be3ad0d46cffe35fd1e7cc3f9947edd6cb3c552229de3be2742f15f7ea47/grpc_google_iam_v1-0.14.5-py3-none-any.whl", hash = "sha256:0f5e680b20aa0a9441e68c769da04d94d70fca4e43751a82d8abb8aa6a7181ca", size = 32674, upload-time = "2026-08-06T06:23:49.467Z" },
]
[[package]]
@@ -1962,7 +1962,7 @@ wheels = [
[[package]]
name = "logfire"
-version = "4.39.0"
+version = "4.40.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "executing" },
@@ -1973,9 +1973,9 @@ dependencies = [
{ name = "rich" },
{ name = "typing-extensions" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/98/7d/9d04b6c716c7963cc0176b0aafee1b7becd0d3c3b2febe704dc9ae5a4318/logfire-4.39.0.tar.gz", hash = "sha256:7291ae695a145c21b4fa9baea2ffaf42b23c79a08e1f3edcef5a4cad41867a0d", size = 1242395, upload-time = "2026-07-24T18:31:34.698Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/71/1ed06d124bd7905f60004d60cbe14c79bda00f0604bf0cb76214f8c96348/logfire-4.40.0.tar.gz", hash = "sha256:f50f9637f9b5cc3eb5f8526e473effa1992d45056c89adc7c821ee7ab2520c75", size = 1260846, upload-time = "2026-08-05T11:26:59.605Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b0/57/b40307cdfd81d07433ad5ae38de70fe6e543f3fb7e764bdf6944695a386b/logfire-4.39.0-py3-none-any.whl", hash = "sha256:e6046e03ce45098c15a9dbf42ced8b95dfcb60cc1f3600a6250c8f515755be5f", size = 405126, upload-time = "2026-07-24T18:31:30.844Z" },
+ { url = "https://files.pythonhosted.org/packages/e6/65/2ed148a656362ff3b5cce0bfae619cf57ca1df33d0c942b4c1461e57f57c/logfire-4.40.0-py3-none-any.whl", hash = "sha256:0ac2c950968812f27ee68ccec4a362230acffaffb28f04945ee07729d5866fa0", size = 409440, upload-time = "2026-08-05T11:26:56.745Z" },
]
[package.optional-dependencies]
@@ -1985,11 +1985,11 @@ httpx = [
[[package]]
name = "logfire-api"
-version = "4.39.0"
+version = "4.40.0"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/b2/f4/41f8647f6091fb9b9aac5a4b6d164bddb11d55b8369bf38de154ef91b8f4/logfire_api-4.39.0.tar.gz", hash = "sha256:1e885f95c37d58cdb927bbc6baea4f4a7c13066f6b3019758627d4dc442643d0", size = 90619, upload-time = "2026-07-24T18:31:36.165Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/9b/5f/f4d0fb5c29d876c533daf415c0d961e1c4d0284167ed0834644a28581230/logfire_api-4.40.0.tar.gz", hash = "sha256:f4631d5ca6af95e9d4dadc4f63619ebb8f2300eecfca0ca99c84403d6ea605de", size = 90781, upload-time = "2026-08-05T11:27:00.947Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/00/d4/87747d12eaf2d852676fd6535df76df945ef62681f1eb5391b63d1fc05e2/logfire_api-4.39.0-py3-none-any.whl", hash = "sha256:20057bbd2898dec2eed02e2559bd73f4e10bc4b108987821df55e9c762da3ba8", size = 140413, upload-time = "2026-07-24T18:31:32.818Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/be/ebe35d94e7d567b58d79bd7e1085fe85195ad4b8c8df8882a5a46caa4984/logfire_api-4.40.0-py3-none-any.whl", hash = "sha256:f8b7309235a942368b927f00e0a1869ff0820833f264a30e77a35f1da829c130", size = 140593, upload-time = "2026-08-05T11:26:58.395Z" },
]
[[package]]
@@ -2294,7 +2294,7 @@ wheels = [
[[package]]
name = "nltk"
-version = "3.10.1"
+version = "3.10.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
@@ -2303,9 +2303,9 @@ dependencies = [
{ name = "regex" },
{ name = "tqdm" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/4a/65/20fa203b28b258fa1222305593ca281e4ad33729c389676bc0d29a8856fd/nltk-3.10.1.tar.gz", hash = "sha256:86a1b41d9ca0d35a2cb72fa60af4c9aaba9fe405b717161fd94cecd69f467007", size = 3098602, upload-time = "2026-08-01T06:25:20.748Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/16/24d639531e73cbc6884fb251d116dfe469df9c595e0dcf24668c54d0e8d3/nltk-3.10.2.tar.gz", hash = "sha256:fcfd80fb77931868cea8357573c79838b8abc609942ef9914d1c9f6070d4645c", size = 3101716, upload-time = "2026-08-05T09:56:20.657Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/82/47/44ffb39cb0edf6b7164fdd87441044d0a1924f0a2d8470e1ad0f533711e0/nltk-3.10.1-py3-none-any.whl", hash = "sha256:55b8780b6b97732c1c3806d4ae02d46113204b11bfdc19dddb95729f627f8853", size = 1725226, upload-time = "2026-08-01T06:25:08.199Z" },
+ { url = "https://files.pythonhosted.org/packages/1f/2b/bf677eb32ca6684b270c0d19ab133c2271e9f3375997e5a8dd2b08e3152d/nltk-3.10.2-py3-none-any.whl", hash = "sha256:2c7ccacb765c5e26b0cb60fb1b57080af522c6924d12a714a243305ba3637412", size = 1725815, upload-time = "2026-08-05T09:56:09.657Z" },
]
[[package]]
@@ -2920,14 +2920,14 @@ wheels = [
[[package]]
name = "proto-plus"
-version = "1.28.2"
+version = "1.28.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "protobuf" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/73/3e/29e0d6a2c5adde6ab5772253fd16ab346324026b89a66e354689c86d0584/proto_plus-1.28.2.tar.gz", hash = "sha256:26d843eb99c1e32fdf1d20ff0faae56607f7748fe774acf9ecd5cfe6c6472501", size = 58063, upload-time = "2026-07-22T16:28:29.119Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/26/6a/056256feb4bd000869aba5c16cf2aa911572ca2a2feb185f86e457b5171e/proto_plus-1.28.3.tar.gz", hash = "sha256:5f91b30dafa6bb38d432c5557a6ee1d35ffd40b4b1e0e3ca27260448560b91d9", size = 58051, upload-time = "2026-08-06T06:24:55.581Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/9d/84/4e9a53a062d4073c74897a6bd20fff74d55307341b3e85c081002462b3ef/proto_plus-1.28.2-py3-none-any.whl", hash = "sha256:b874236fcac2358f601e4330bcb76cb8b89c851303ccf4078408b3d4774d1c52", size = 50693, upload-time = "2026-07-22T16:28:24.059Z" },
+ { url = "https://files.pythonhosted.org/packages/61/3a/cfee3c50294f55a2f0f9575052dec2c2a48891ad4b1c2a133b05a87026cd/proto_plus-1.28.3-py3-none-any.whl", hash = "sha256:dc76880b8ee951cca002098574376cf71e055f9f16d9ba6570fb8a06f726d281", size = 50795, upload-time = "2026-08-06T06:23:50.653Z" },
]
[[package]]
@@ -3132,14 +3132,14 @@ email = [
[[package]]
name = "pydantic-ai"
-version = "2.24.0"
+version = "2.25.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic-ai-slim", extra = ["anthropic", "cli", "evals", "google", "logfire", "mcp", "openai", "retries", "web"] },
]
-sdist = { url = "https://files.pythonhosted.org/packages/8f/43/d36321d72c526471cd1c02987d1f520c366ea209fbba47f8b4d6b07038af/pydantic_ai-2.24.0.tar.gz", hash = "sha256:3a869db582b216d1b7549e20f9af1bee1c89671d702e8a8a7480894eb2cc516c", size = 19368, upload-time = "2026-08-05T02:30:06.052Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/a7/40/11ab48d76c77ca6a62f19a5bdd79dd80cc723ad244f576b0f6c8dafe4368/pydantic_ai-2.25.0.tar.gz", hash = "sha256:0190165b01d8f101b5c4c5c4e610a088aed6946b220ca6d55474a67d118a4e47", size = 19393, upload-time = "2026-08-06T03:20:30.654Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/a7/51/e08738bce3d6c310077a3d925b946fbc8cf96b22e0858013afa71810fee5/pydantic_ai-2.24.0-py3-none-any.whl", hash = "sha256:7cc0b980a2769a308c0529bf2e2086fca72e674e7c1d4a15be96c9e911112ac3", size = 7740, upload-time = "2026-08-05T02:29:58.138Z" },
+ { url = "https://files.pythonhosted.org/packages/45/5b/98d26f8bf01cbb6ff3f8ff10e972d6ca58523b0b03a20e9c5ab245275db0/pydantic_ai-2.25.0-py3-none-any.whl", hash = "sha256:991490b3ceaa258204bbca7749a1da4786b53b29cc5f09b56cc56604023c0c11", size = 7742, upload-time = "2026-08-06T03:20:21.542Z" },
]
[[package]]
@@ -3158,7 +3158,7 @@ wheels = [
[[package]]
name = "pydantic-ai-slim"
-version = "2.24.0"
+version = "2.25.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -3170,9 +3170,9 @@ dependencies = [
{ name = "pydantic-graph" },
{ name = "typing-inspection" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/64/fd/875459f2ed354401760a8e2d427894ee906a0f90a9e7c27e7d8a2fd1b024/pydantic_ai_slim-2.24.0.tar.gz", hash = "sha256:56f21fa0944da4c38b56cfdb3aec0777d8d5cd451c18651ca58faaec485ee004", size = 972138, upload-time = "2026-08-05T02:30:07.899Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/e1/ec/6e186e59a9beede41a9e347f69bd61a833de724aad8a175da8da088d220a/pydantic_ai_slim-2.25.0.tar.gz", hash = "sha256:4f5a36f29e2b346d4b793bf3b983aba17ec19f24015bb811ee40815e98155417", size = 974671, upload-time = "2026-08-06T03:20:33.01Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/f1/1a/6d9643f06c960eb9e943e081c4790ed2842dcb4ccf47e5a07788e097f6c7/pydantic_ai_slim-2.24.0-py3-none-any.whl", hash = "sha256:934552227426c89edc51742c4827dd416ddfccb6d76536ddd8e5be7d9d403aa5", size = 1165666, upload-time = "2026-08-05T02:30:00.812Z" },
+ { url = "https://files.pythonhosted.org/packages/04/46/e168f03ec04a933b6b0ff3e02c7e608c24da8efb03d0e1f4d0b486bfef09/pydantic_ai_slim-2.25.0-py3-none-any.whl", hash = "sha256:9b69d1af463a63a88ea3c3567b38a09e8208efe73a36c8f5d5d5515939a88acd", size = 1169288, upload-time = "2026-08-06T03:20:24.91Z" },
]
[package.optional-dependencies]
@@ -3258,7 +3258,7 @@ wheels = [
[[package]]
name = "pydantic-evals"
-version = "2.24.0"
+version = "2.25.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -3268,14 +3268,14 @@ dependencies = [
{ name = "pyyaml" },
{ name = "rich" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/3a/a8/9db0909b4e3bcccbb8a6a560bf18e1fe4b576fa34286fd8630e985b5b1c5/pydantic_evals-2.24.0.tar.gz", hash = "sha256:0ff5fd9ed6502645236bcce6eec2a7ee39b1e174347335f472905a4e85f7c9f3", size = 85393, upload-time = "2026-08-05T02:30:09.723Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/37/42/84a86b00c710b84c1cd1afbde43b67888437f5068ab7a887a6400301e6c9/pydantic_evals-2.25.0.tar.gz", hash = "sha256:11780b167271a5a0b6cb51e8972cb8cae9c275358b14fba6a4cf79d8a01d702d", size = 85392, upload-time = "2026-08-06T03:20:34.256Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/41/20/bf5ea1048958c8d692a3d02a8bdac1b8d20bbd7b41945dcba4e5e33f85bf/pydantic_evals-2.24.0-py3-none-any.whl", hash = "sha256:5a751012040c235ee1b8b8e25fc5e31a50f8be397ccfe3193ed323ee85d622ee", size = 100539, upload-time = "2026-08-05T02:30:02.526Z" },
+ { url = "https://files.pythonhosted.org/packages/db/b1/eff104fe60e6ab5b488778e78d7c9bbd481bd3820cda4c6124df949d0c6c/pydantic_evals-2.25.0-py3-none-any.whl", hash = "sha256:54f6df9aa30bbe1597f93e65607ba77d76aef0cd9d6804c9f740d909a55769ab", size = 100539, upload-time = "2026-08-06T03:20:26.69Z" },
]
[[package]]
name = "pydantic-graph"
-version = "2.24.0"
+version = "2.25.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -3284,9 +3284,9 @@ dependencies = [
{ name = "pydantic" },
{ name = "typing-inspection" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/c6/37/1ace6e245823b2f0387e9f28390e5f1309686b2dc17a799e3a530f986c53/pydantic_graph-2.24.0.tar.gz", hash = "sha256:04546807cdc5c36793088a3c42dcffd74825e192b06cafd7d43f0726dc8a302e", size = 45179, upload-time = "2026-08-05T02:30:10.773Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/e9/a0/78b22670f9c9608939a27c9de647dba28b6fca864f8883db30f34832ab9b/pydantic_graph-2.25.0.tar.gz", hash = "sha256:1e1d61556ec0d5fdc02d307380f6ad4ac96d0bba9e5eac0881bae42466d3db8a", size = 45179, upload-time = "2026-08-06T03:20:35.284Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/54/a3/0d6eadc5caeb536198f998fd21bd5ade05459edd58057ff4c0322a8ef773/pydantic_graph-2.24.0-py3-none-any.whl", hash = "sha256:be32705d3e92fad0c3149f9b4b8708fd2583e1aa02c36c26556538f8ecc1c8de", size = 52661, upload-time = "2026-08-05T02:30:03.821Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/45/e3f93b1a33fea3e3989de9491a57a69bd93aae0c5b9137f05113e752a8ef/pydantic_graph-2.25.0-py3-none-any.whl", hash = "sha256:87017851610746f76463b0b1fd257286425f3b4feac1fd17e50b0370ae76c2cf", size = 52661, upload-time = "2026-08-06T03:20:28.332Z" },
]
[[package]]
@@ -4030,28 +4030,28 @@ asyncio = [
[[package]]
name = "sse-starlette"
-version = "3.4.6"
+version = "3.4.8"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
{ name = "starlette" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/6c/10/a34c656829ffc1c4b22ef36d70d9ebb6b99c020e2aeb17cee5485099f028/sse_starlette-3.4.6.tar.gz", hash = "sha256:725f8a1bd6d26ae1b2c9610c0ef5065dfdd496f3988d28adcf8c4b49dc25c627", size = 32542, upload-time = "2026-07-20T14:16:32.201Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/f8/00/b42a44342a054d58cb1115d7c8aa9cb4290dd9442f9c1b91a4b8173dba22/sse_starlette-3.4.8.tar.gz", hash = "sha256:ed89ffbb75cbf78a5fe2f2109cd584792ee7f9dfac96f791db546df8f15f3f9c", size = 32548, upload-time = "2026-08-05T11:19:49.982Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/49/36/e10c1d1b7ca881d2625db2ec28508578499187bb1c389952c398474e1834/sse_starlette-3.4.6-py3-none-any.whl", hash = "sha256:56217ab4c9a9f9c5db7b21e08732d3e7c2b807f45231ad23de0551a24c4a41f6", size = 16516, upload-time = "2026-07-20T14:16:30.978Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/3a/764912c58293d95b6dcdf4cc255f9d10de310580ced547b082eb9d72018c/sse_starlette-3.4.8-py3-none-any.whl", hash = "sha256:6e82314c786709a3cd9520f2285cf9fff90e181e598e8a357b0cf80f66afba0d", size = 16516, upload-time = "2026-08-05T11:19:48.748Z" },
]
[[package]]
name = "starlette"
-version = "1.3.1"
+version = "1.4.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/7c1dc7381d9f8ab7d854328ebfa884e62cb3f3d8549ddfd37c7814f42afa/starlette-1.3.1.tar.gz", hash = "sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0", size = 2703240, upload-time = "2026-06-12T09:23:11.602Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/3c/76d2fd1f1357ed0f0108d8a5aa233dcf16e2946a8559c84912fe08e01ac7/starlette-1.4.1.tar.gz", hash = "sha256:b7332de6e9375593a29ba9eee1e6ecfeb3eb2043e2e19a13b4b71da73ff35540", size = 2709041, upload-time = "2026-08-05T15:17:26.23Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/ec/bb/2799cc2ede3ed41131f8975621e7213dfc7ef4acbbaadfa440f32500c370/starlette-1.3.1-py3-none-any.whl", hash = "sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6", size = 73632, upload-time = "2026-06-12T09:23:10.017Z" },
+ { url = "https://files.pythonhosted.org/packages/75/0a/67e95f21498de41433babf7b1db0eeab449eb58872dfb831b27747a70fd0/starlette-1.4.1-py3-none-any.whl", hash = "sha256:7d078e0fbefae0d2cecfb80a799d6fb84b1c0c6acd4f14ac79d17d0e7ec27f19", size = 74019, upload-time = "2026-08-05T15:17:24.357Z" },
]
[[package]]
From b894105efa386ca234a01b373acfcc8ec48a422e Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Thu, 6 Aug 2026 09:42:50 +0200
Subject: [PATCH 042/197] LCORE-3410: Use Optional type hint
---
src/llama_stack_configuration.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/llama_stack_configuration.py b/src/llama_stack_configuration.py
index 62e76ec4b..60b3f44d1 100644
--- a/src/llama_stack_configuration.py
+++ b/src/llama_stack_configuration.py
@@ -573,7 +573,7 @@ def _upsert_vsprov_embedding_model(
def _vsprov_fields_and_backend(
product_type: str, provider_id: str, cfg: dict[str, Any]
-) -> tuple[dict[str, Any], str, dict[str, Any] | None]:
+) -> tuple[dict[str, Any], str, Optional[dict[str, Any]]]:
"""Build template extra fields and optional faiss storage backend.
Parameters:
@@ -712,7 +712,7 @@ def _enrich_one_vector_store_provider(
def enrich_vector_store(
ls_config: dict[str, Any],
- vector_store: dict[str, Any] | None = None,
+ vector_store: Optional[dict[str, Any]] = None,
) -> None:
"""Enrich LS config with dynamic vector-store provider capacity.
From c4714e5ece84c75a7dbabf8941afd83304b05b3c Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Thu, 6 Aug 2026 09:48:07 +0200
Subject: [PATCH 043/197] LCORE-3121: Minor cleanup
---
scripts/konflux_resolve.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/scripts/konflux_resolve.py b/scripts/konflux_resolve.py
index 9eadda8c1..e42ba7efc 100644
--- a/scripts/konflux_resolve.py
+++ b/scripts/konflux_resolve.py
@@ -67,8 +67,7 @@ def parse_version(
version_str = version_str.strip()
if "+" in version_str:
version_str = version_str.split("+", 1)[0]
- if version_str.endswith(".*"):
- version_str = version_str[:-2]
+ version_str = version_str.removesuffix(".*")
m = _VERSION_RE.match(version_str)
if m is None:
raise ValueError(f"Cannot parse version: {version_str!r}")
From 30a6d65592f8772cbc90cf4309c2fcea38fac067 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Thu, 6 Aug 2026 11:38:56 +0200
Subject: [PATCH 044/197] LCORE-3368: Info about Konflux make targets
---
Makefile | 6 +++---
README.md | 14 ++++++++------
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/Makefile b/Makefile
index 787c5fc71..bd243ee78 100644
--- a/Makefile
+++ b/Makefile
@@ -362,13 +362,13 @@ distribution-archives: ## Generate distribution archives to be uploaded into Pyt
upload-distribution-archives: ## Upload distribution archives into Python registry
uv run python -m twine upload --repository ${PYTHON_REGISTRY} dist/*
-konflux-requirements: ## Generate hermetic requirements.*.txt file for konflux build
+konflux-requirements: ## Generate hermetic requirements.*.txt file for Konflux build
./scripts/konflux_requirements.sh
-konflux-rpm-lock: ## Generate rpm.lock.yaml file for konflux build
+konflux-rpm-lock: ## Generate rpm.lock.yaml file for Konflux build
./scripts/generate-rpm-lock.sh
-konflux-artifacts-lock: ## Regenerate artifacts.lock.yaml file for konflux build
+konflux-artifacts-lock: ## Regenerate artifacts.lock.yaml file for Konflux build
./scripts/generate-artifacts-lock.sh
help: ## Show this help screen
diff --git a/README.md b/README.md
index 556c59a08..c8fbe5f01 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,8 @@ The service includes comprehensive user data collection capabilities for various
* [Architecture](#architecture)
* [Prerequisites](#prerequisites)
* [Installation](#installation)
+ * [Clone the Repository](#clone-the-repository)
+ * [System-Specific Installation](#system-specific-installation)
* [Run LCS locally](#run-lcs-locally)
* [Container Runtime Requirements](#container-runtime-requirements)
* [Configuration](#configuration)
@@ -960,9 +962,9 @@ lint-openapi Lint docs/openapi.json (Spectral OAS ruleset;
verify Run all linters
distribution-archives Generate distribution archives to be uploaded into Python registry
upload-distribution-archives Upload distribution archives into Python registry
-konflux-requirements Generate hermetic requirements.*.txt file for konflux build
-konflux-rpm-lock Generate rpm.lock.yaml file for konflux build
-konflux-artifacts-lock Regenerate artifacts.lock.yaml file for konflux build
+konflux-requirements Generate hermetic requirements.*.txt file for Konflux build
+konflux-rpm-lock Generate rpm.lock.yaml file for Konflux build
+konflux-artifacts-lock Regenerate artifacts.lock.yaml file for Konflux build
help Show this help screen
```
@@ -1451,9 +1453,9 @@ make konflux-requirements
This compiles Python dependencies from `pyproject.toml` using `uv`, splits packages by their source index (PyPI vs Red Hat's internal registry), and generates hermetic requirements files with pinned versions and hashes for Konflux builds.
**Files produced:**
-- `requirements.hashes.source.txt` – PyPI packages with hashes
-- `requirements.hashes.wheel.txt` – Red Hat registry packages with hashes
-- `requirements-build.txt` – Build-time dependencies for source packages
+- `.konflux/requirements.hashes.source.txt` – PyPI packages with hashes
+- `.konflux/requirements.hashes.wheel.txt` – Red Hat registry packages with hashes
+- `.konflux/requirements-build.txt` – Build-time dependencies for source packages
The script also updates the Tekton pipeline configurations (`.tekton/lightspeed-stack-*.yaml`) with the list of pre-built wheel packages.
From ff704f16fb7d121061851537154e5338370b6c03 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Thu, 6 Aug 2026 11:58:05 +0200
Subject: [PATCH 045/197] LCORE-3428: Fixed error introduced by merging old PR
---
tests/unit/models/config/test_vector_store.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/unit/models/config/test_vector_store.py b/tests/unit/models/config/test_vector_store.py
index a5d4917f9..f143d8b83 100644
--- a/tests/unit/models/config/test_vector_store.py
+++ b/tests/unit/models/config/test_vector_store.py
@@ -5,7 +5,7 @@
import pytest
import yaml
-from llama_stack.core.stack import replace_env_vars
+from ogx.core.stack import replace_env_vars
from pydantic import SecretStr, TypeAdapter, ValidationError
from models.config import Configuration, VectorStoreProvider
From efd2119bfc58a19933e88296fa9550d80a7cf0d9 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Thu, 6 Aug 2026 15:24:04 +0200
Subject: [PATCH 046/197] Updated doc (nit)
---
docs/models/successful_responses.json | 30 +++++++++++++++++++++------
docs/models/successful_responses.md | 4 ++--
tests/integration/endpoints/README.md | 3 +++
3 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/docs/models/successful_responses.json b/docs/models/successful_responses.json
index f1dcd79bf..0b931d10f 100644
--- a/docs/models/successful_responses.json
+++ b/docs/models/successful_responses.json
@@ -433,10 +433,19 @@
"title": "PostgreSQL host"
},
"port": {
- "type": "string",
- "nullable": true,
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "integer"
+ },
+ {
+ "type": "null"
+ }
+ ],
"default": null,
- "description": "PostgreSQL port for remote::pgvector. Defaults to ${env.POSTGRES_PORT} when rag_type is remote::pgvector.",
+ "description": "PostgreSQL port for remote::pgvector. Defaults to ${env.POSTGRES_PORT} when rag_type is remote::pgvector. Accepts string placeholders and integer values.",
"title": "PostgreSQL port"
},
"db": {
@@ -3933,10 +3942,19 @@
"title": "PostgreSQL host"
},
"port": {
- "type": "string",
- "nullable": true,
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "integer"
+ },
+ {
+ "type": "null"
+ }
+ ],
"default": null,
- "description": "PostgreSQL port. Defaults to ${env.POSTGRES_PORT}.",
+ "description": "PostgreSQL port. Defaults to ${env.POSTGRES_PORT}. Accepts string placeholders and integer values.",
"title": "PostgreSQL port"
},
"db": {
diff --git a/docs/models/successful_responses.md b/docs/models/successful_responses.md
index 3da2c6735..aef881cfb 100644
--- a/docs/models/successful_responses.md
+++ b/docs/models/successful_responses.md
@@ -200,7 +200,7 @@ BYOK (Bring Your Own Knowledge) RAG configuration.
| db_path | string | Path to RAG database. Required for inline::faiss. |
| score_multiplier | number | Multiplier applied to relevance scores from this vector store. Used to weight results when querying multiple knowledge sources. Values > 1 boost this store's results; values < 1 reduce them. |
| host | string | PostgreSQL host for remote::pgvector. Defaults to ${env.POSTGRES_HOST} when rag_type is remote::pgvector. |
-| port | string | PostgreSQL port for remote::pgvector. Defaults to ${env.POSTGRES_PORT} when rag_type is remote::pgvector. |
+| port | | PostgreSQL port for remote::pgvector. Defaults to ${env.POSTGRES_PORT} when rag_type is remote::pgvector. Accepts string placeholders and integer values. |
| db | string | PostgreSQL database name for remote::pgvector. Defaults to ${env.POSTGRES_DATABASE} when rag_type is remote::pgvector. |
| user | string | PostgreSQL user for remote::pgvector. Defaults to ${env.POSTGRES_USER} when rag_type is remote::pgvector. |
| password | string | PostgreSQL password for remote::pgvector. Defaults to ${env.POSTGRES_PASSWORD} when rag_type is remote::pgvector. |
@@ -1777,7 +1777,7 @@ Storage config for a pgvector dynamic vector-store provider.
| Field | Type | Description |
|-------|------|-------------|
| host | string | PostgreSQL host. Defaults to ${env.POSTGRES_HOST}. |
-| port | string | PostgreSQL port. Defaults to ${env.POSTGRES_PORT}. |
+| port | | PostgreSQL port. Defaults to ${env.POSTGRES_PORT}. Accepts string placeholders and integer values. |
| db | string | PostgreSQL database name. Defaults to ${env.POSTGRES_DATABASE}. |
| user | string | PostgreSQL user. Defaults to ${env.POSTGRES_USER}. |
| password | string | PostgreSQL password. Defaults to ${env.POSTGRES_PASSWORD}. |
diff --git a/tests/integration/endpoints/README.md b/tests/integration/endpoints/README.md
index a5fb2cf10..4e4876188 100644
--- a/tests/integration/endpoints/README.md
+++ b/tests/integration/endpoints/README.md
@@ -42,6 +42,9 @@ Integration tests for the rlsapi v1 /infer endpoint.
## [test_root_endpoint.py](test_root_endpoint.py)
Integration tests for the /root endpoint.
+## [test_saved_prompts_integration.py](test_saved_prompts_integration.py)
+Integration tests for the /v1/saved-prompts REST API endpoints.
+
## [test_stream_interrupt_integration.py](test_stream_interrupt_integration.py)
Integration tests for the streaming query interrupt lifecycle.
From 223fb7f27d000e4bdce1c479d20192831f605d8c Mon Sep 17 00:00:00 2001
From: Maysun J Faisal
Date: Thu, 6 Aug 2026 11:20:00 -0400
Subject: [PATCH 047/197] RHIDP-16060: address CodeRabbit review feedback
- Fix doc_url fallback in tool_processor: preserve existing URL when
_build_okp_doc_url returns None (edge case with no OKP reference fields)
- Update mode field description to document OKP config fallback chain
- Add 'keyword' to deprecated-payload warning message
- Fix docstring header: Args -> Parameters per project convention
- Regenerate OpenAPI schema for updated field description
Co-Authored-By: Claude Opus 4.6
---
docs/devel_doc/openapi.json | 2 +-
src/models/common/query.py | 6 +++---
src/utils/agents/tool_processor.py | 2 +-
src/utils/responses.py | 2 +-
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/docs/devel_doc/openapi.json b/docs/devel_doc/openapi.json
index ecf3bb767..babebc57e 100644
--- a/docs/devel_doc/openapi.json
+++ b/docs/devel_doc/openapi.json
@@ -21303,7 +21303,7 @@
}
],
"title": "Mode",
- "description": "Solr vector_io search mode. When omitted, the server default ('hybrid') is used. 'keyword' and 'lexical' both use BM25 text search.",
+ "description": "Solr vector_io search mode. When omitted, the configured OKP default is used; otherwise 'hybrid' applies. 'keyword' and 'lexical' both use BM25 text search.",
"examples": [
"hybrid",
"semantic",
diff --git a/src/models/common/query.py b/src/models/common/query.py
index c340b76ea..924e8443a 100644
--- a/src/models/common/query.py
+++ b/src/models/common/query.py
@@ -147,8 +147,8 @@ class SolrVectorSearchRequest(BaseModel):
mode: Optional[Literal["semantic", "hybrid", "lexical", "keyword"]] = Field(
None,
description=(
- "Solr vector_io search mode. When omitted, the server default "
- f"({SOLR_VECTOR_SEARCH_DEFAULT_MODE!r}) is used. "
+ "Solr vector_io search mode. When omitted, the configured OKP default "
+ f"is used; otherwise {SOLR_VECTOR_SEARCH_DEFAULT_MODE!r} applies. "
"'keyword' and 'lexical' both use BM25 text search."
),
examples=["hybrid", "semantic", "keyword", "lexical"],
@@ -207,6 +207,6 @@ def coerce_legacy_plain_dict(cls, data: Any) -> Any:
logger.warning(
"Solr inline RAG: sending filter fields at the top level of `solr` without "
"`mode` or `filters` is deprecated and will be removed; use "
- '`{"mode": "", "filters": {...}}` instead.'
+ '`{"mode": "", "filters": {...}}` instead.'
)
return {"mode": None, "filters": data}
diff --git a/src/utils/agents/tool_processor.py b/src/utils/agents/tool_processor.py
index 6be085daa..161cb05a6 100644
--- a/src/utils/agents/tool_processor.py
+++ b/src/utils/agents/tool_processor.py
@@ -296,7 +296,7 @@ def build_referenced_document(
# OKP/Solr chunks need URL construction with the OKP base URL
if resolved_source == constants.OKP_RAG_ID:
- doc_url = _build_okp_doc_url(attributes)
+ doc_url = _build_okp_doc_url(attributes) or doc_url
if not (doc_title or doc_url):
return None
diff --git a/src/utils/responses.py b/src/utils/responses.py
index 95e231038..5915f86f7 100644
--- a/src/utils/responses.py
+++ b/src/utils/responses.py
@@ -858,7 +858,7 @@ def _build_okp_doc_url(attributes: dict[str, Any]) -> Optional[str]:
``source_path`` (disconnected clusters) and ``reference_url`` (online).
The chosen relative path is joined with the OKP base URL.
- Args:
+ Parameters:
attributes: Metadata dict from a file_search result chunk.
Returns:
From b44787c3df53c1c4298ddf22beb88daec2acc2cb Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Thu, 6 Aug 2026 17:20:50 +0200
Subject: [PATCH 048/197] Empty line between section header and paragraph
---
scripts/gen_doc.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/scripts/gen_doc.py b/scripts/gen_doc.py
index 6637a8ec9..2b10eeb47 100755
--- a/scripts/gen_doc.py
+++ b/scripts/gen_doc.py
@@ -44,6 +44,7 @@ def generate_docfile(directory: Path) -> None:
for file in files:
if file.endswith(".py"):
print(f"## [{file}]({file})", file=indexfile)
+ print(file=indexfile)
with open(file, encoding="utf-8") as fin:
source = fin.read()
try:
From f6f060e475d921d2f85ddb293796b2f7a6367d56 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Thu, 6 Aug 2026 17:21:10 +0200
Subject: [PATCH 049/197] Regenerated doc
---
src/README.md | 9 +++++
src/a2a_storage/README.md | 6 +++
src/app/README.md | 4 ++
src/app/endpoints/README.md | 28 +++++++++++++
src/authentication/README.md | 10 +++++
src/authorization/README.md | 4 ++
src/cache/README.md | 9 +++++
src/data/README.md | 1 +
src/metrics/README.md | 3 ++
src/models/README.md | 3 ++
src/models/api/README.md | 1 +
src/models/api/requests/README.md | 11 ++++++
src/models/api/responses/README.md | 2 +
src/models/api/responses/error/README.md | 12 ++++++
src/models/api/responses/successful/README.md | 14 +++++++
src/models/common/README.md | 12 ++++++
src/models/common/agents/README.md | 3 ++
src/models/common/responses/README.md | 5 +++
src/models/database/README.md | 4 ++
src/observability/README.md | 2 +
src/observability/formats/README.md | 3 ++
src/pydantic_ai_lightspeed/README.md | 1 +
.../capabilities/README.md | 2 +
.../capabilities/question_validity/README.md | 2 +
.../capabilities/redaction/README.md | 3 ++
.../llamastack/README.md | 4 ++
src/quota/README.md | 11 ++++++
src/runners/README.md | 3 ++
src/telemetry/README.md | 2 +
src/utils/README.md | 39 +++++++++++++++++++
src/utils/agents/README.md | 5 +++
tests/e2e/features/README.md | 1 +
tests/e2e/features/steps/README.md | 19 +++++++++
tests/e2e/mock_jwks_server/README.md | 2 +
tests/e2e/mock_mcp_server/README.md | 1 +
tests/e2e/mock_tls_inference_server/README.md | 1 +
tests/e2e/proxy/README.md | 3 ++
tests/e2e/utils/README.md | 5 +++
.../integration/container_lifecycle/README.md | 1 +
tests/integration/endpoints/README.md | 19 +++++++++
tests/unit/README.md | 11 ++++++
tests/unit/a2a_storage/README.md | 4 ++
tests/unit/app/README.md | 4 ++
tests/unit/app/endpoints/README.md | 28 +++++++++++++
tests/unit/authentication/README.md | 10 +++++
tests/unit/authorization/README.md | 4 ++
tests/unit/cache/README.md | 6 +++
tests/unit/metrics/README.md | 3 ++
tests/unit/models/README.md | 4 ++
tests/unit/models/config/README.md | 31 +++++++++++++++
tests/unit/models/database/README.md | 2 +
tests/unit/models/requests/README.md | 7 ++++
tests/unit/models/responses/README.md | 8 ++++
tests/unit/models/rlsapi/README.md | 3 ++
tests/unit/observability/README.md | 2 +
tests/unit/observability/formats/README.md | 3 ++
tests/unit/pydantic_ai_lightspeed/README.md | 1 +
.../capabilities/README.md | 1 +
.../capabilities/question_validity/README.md | 2 +
.../capabilities/redaction/README.md | 4 ++
.../llamastack/README.md | 4 ++
tests/unit/quota/README.md | 7 ++++
tests/unit/runners/README.md | 2 +
tests/unit/telemetry/README.md | 3 ++
tests/unit/utils/README.md | 33 ++++++++++++++++
tests/unit/utils/agents/README.md | 3 ++
66 files changed, 460 insertions(+)
diff --git a/src/README.md b/src/README.md
index 5472b7b3a..5fc8b0f16 100644
--- a/src/README.md
+++ b/src/README.md
@@ -1,29 +1,38 @@
# List of source files stored in `src` directory
## [__init__.py](__init__.py)
+
Main classes for the Lightspeed Core Stack REST API service.
## [client.py](client.py)
+
Llama Stack client retrieval class.
## [configuration.py](configuration.py)
+
Configuration loader.
## [constants.py](constants.py)
+
Constants used in business logic.
## [lightspeed_stack.py](lightspeed_stack.py)
+
Entry point to the Lightspeed Core Stack REST API service.
## [llama_stack_configuration.py](llama_stack_configuration.py)
+
Llama Stack configuration enrichment and synthesis.
## [log.py](log.py)
+
Log utilities.
## [sentry.py](sentry.py)
+
Sentry error tracking initialization and configuration.
## [version.py](version.py)
+
Service version that is read by project manager tools.
diff --git a/src/a2a_storage/README.md b/src/a2a_storage/README.md
index 85b946791..5a50bfb29 100644
--- a/src/a2a_storage/README.md
+++ b/src/a2a_storage/README.md
@@ -1,20 +1,26 @@
# List of source files stored in `src/a2a_storage` directory
## [__init__.py](__init__.py)
+
A2A protocol persistent storage components.
## [context_store.py](context_store.py)
+
Abstract base class for A2A context-to-conversation mapping storage.
## [in_memory_context_store.py](in_memory_context_store.py)
+
In-memory implementation of A2A context store.
## [postgres_context_store.py](postgres_context_store.py)
+
PostgreSQL implementation of A2A context store.
## [sqlite_context_store.py](sqlite_context_store.py)
+
SQLite implementation of A2A context store.
## [storage_factory.py](storage_factory.py)
+
Factory for creating A2A storage backends.
diff --git a/src/app/README.md b/src/app/README.md
index 5fd8395fc..db3484aa6 100644
--- a/src/app/README.md
+++ b/src/app/README.md
@@ -1,14 +1,18 @@
# List of source files stored in `src/app` directory
## [__init__.py](__init__.py)
+
REST API service based on FastAPI.
## [database.py](database.py)
+
Database engine management.
## [main.py](main.py)
+
Definition of FastAPI based web service.
## [routers.py](routers.py)
+
REST API routers.
diff --git a/src/app/endpoints/README.md b/src/app/endpoints/README.md
index c1ac3c2eb..477b59762 100644
--- a/src/app/endpoints/README.md
+++ b/src/app/endpoints/README.md
@@ -1,86 +1,114 @@
# List of source files stored in `src/app/endpoints` directory
## [__init__.py](__init__.py)
+
Implementation of all endpoints.
## [a2a.py](a2a.py)
+
Handler for A2A (Agent-to-Agent) protocol endpoints using Responses API.
## [a2a_openapi.py](a2a_openapi.py)
+
OpenAPI-only metadata for A2A JSON-RPC routes.
## [authorized.py](authorized.py)
+
Handler for REST API call to authorized endpoint.
## [config.py](config.py)
+
Handler for REST API call to retrieve service configuration.
## [conversations_v1.py](conversations_v1.py)
+
Handler for REST API calls to manage conversation history using Conversations API.
## [conversations_v2.py](conversations_v2.py)
+
Handler for REST API calls to manage conversation history.
## [feedback.py](feedback.py)
+
Handler for REST API endpoint for user feedback.
## [health.py](health.py)
+
Handlers for health REST API endpoints.
## [info.py](info.py)
+
Handler for REST API call to provide info.
## [mcp_auth.py](mcp_auth.py)
+
Handler for REST API calls related to MCP server authentication.
## [mcp_servers.py](mcp_servers.py)
+
Handler for REST API calls to dynamically manage MCP servers.
## [metrics.py](metrics.py)
+
Handler for REST API call to provide metrics.
## [models.py](models.py)
+
Handler for REST API call to list available models.
## [prompts.py](prompts.py)
+
Handler for REST API calls to manage Llama Stack stored prompt templates.
## [providers.py](providers.py)
+
Handler for REST API calls to list and retrieve available providers.
## [query.py](query.py)
+
Handler for REST API call to provide answer to query using Response API.
## [rags.py](rags.py)
+
Handler for REST API calls to list and retrieve available RAGs.
## [responses.py](responses.py)
+
Handler for REST API call to provide answer using Responses API (LCORE specification).
## [responses_telemetry.py](responses_telemetry.py)
+
Splunk telemetry helpers for the Responses API endpoint.
## [rlsapi_v1.py](rlsapi_v1.py)
+
Handler for RHEL Lightspeed rlsapi v1 REST API endpoints.
## [root.py](root.py)
+
Handler for the / endpoint.
## [saved_prompts.py](saved_prompts.py)
+
Handler for REST API calls to manage saved prompts.
## [shields.py](shields.py)
+
Handler for REST API call to list available shields.
## [stream_interrupt.py](stream_interrupt.py)
+
Endpoint for interrupting in-progress streaming query requests.
## [streaming_query.py](streaming_query.py)
+
Streaming query handler using Responses API.
## [tools.py](tools.py)
+
Handler for REST API call to list available tools from MCP servers.
## [vector_stores.py](vector_stores.py)
+
Handler for REST API calls to manage vector stores and files.
diff --git a/src/authentication/README.md b/src/authentication/README.md
index 230767cfe..00aadbcf4 100644
--- a/src/authentication/README.md
+++ b/src/authentication/README.md
@@ -1,32 +1,42 @@
# List of source files stored in `src/authentication` directory
## [__init__.py](__init__.py)
+
This package contains authentication code and modules.
## [api_key_token.py](api_key_token.py)
+
Authentication flow for FastAPI endpoints with a provided API key.
## [interface.py](interface.py)
+
Abstract base class for all authentication method implementations.
## [jwk_token.py](jwk_token.py)
+
Manage authentication flow for FastAPI endpoints with JWK based JWT auth.
## [k8s.py](k8s.py)
+
Manage authentication flow for FastAPI endpoints with K8S/OCP.
## [noop.py](noop.py)
+
Manage authentication flow for FastAPI endpoints with no-op auth.
## [noop_with_token.py](noop_with_token.py)
+
Manage authentication flow for FastAPI endpoints with no-op auth and provided user token.
## [rh_identity.py](rh_identity.py)
+
Red Hat Identity header authentication for FastAPI endpoints.
## [trusted_proxy.py](trusted_proxy.py)
+
Trusted-proxy authentication module for requests forwarded by a K8s proxy.
## [utils.py](utils.py)
+
Authentication utility functions.
diff --git a/src/authorization/README.md b/src/authorization/README.md
index 414fb905f..300800e06 100644
--- a/src/authorization/README.md
+++ b/src/authorization/README.md
@@ -1,14 +1,18 @@
# List of source files stored in `src/authorization` directory
## [__init__.py](__init__.py)
+
Authorization module for role-based access control.
## [azure_token_manager.py](azure_token_manager.py)
+
Azure Entra ID token manager for Azure OpenAI authentication.
## [middleware.py](middleware.py)
+
Authorization middleware and decorators.
## [resolvers.py](resolvers.py)
+
Authorization resolvers for role evaluation and access control.
diff --git a/src/cache/README.md b/src/cache/README.md
index 022a3f333..1da341bd4 100644
--- a/src/cache/README.md
+++ b/src/cache/README.md
@@ -1,29 +1,38 @@
# List of source files stored in `src/cache` directory
## [__init__.py](__init__.py)
+
Various cache implementations.
## [cache.py](cache.py)
+
Abstract class that is parent for all cache implementations.
## [cache_entry.py](cache_entry.py)
+
Model for conversation history cache entry.
## [cache_error.py](cache_error.py)
+
Any exception that can occur during cache operations.
## [cache_factory.py](cache_factory.py)
+
Cache factory class.
## [in_memory_cache.py](in_memory_cache.py)
+
In-memory cache implementation.
## [noop_cache.py](noop_cache.py)
+
No-operation cache implementation.
## [postgres_cache.py](postgres_cache.py)
+
PostgreSQL cache implementation.
## [sqlite_cache.py](sqlite_cache.py)
+
Cache that uses SQLite to store cached values.
diff --git a/src/data/README.md b/src/data/README.md
index e9db52608..1448c2fd8 100644
--- a/src/data/README.md
+++ b/src/data/README.md
@@ -1,5 +1,6 @@
# List of source files stored in `src/data` directory
## [__init__.py](__init__.py)
+
Package-shipped data files for Lightspeed Core Stack.
diff --git a/src/metrics/README.md b/src/metrics/README.md
index 49a1b604d..ebc2e38c3 100644
--- a/src/metrics/README.md
+++ b/src/metrics/README.md
@@ -1,11 +1,14 @@
# List of source files stored in `src/metrics` directory
## [__init__.py](__init__.py)
+
Metrics module for Lightspeed Core Stack.
## [recording.py](recording.py)
+
Recording helpers for Prometheus metrics.
## [utils.py](utils.py)
+
Utility functions for metrics handling.
diff --git a/src/models/README.md b/src/models/README.md
index a474cc866..bc6ed86f0 100644
--- a/src/models/README.md
+++ b/src/models/README.md
@@ -1,11 +1,14 @@
# List of source files stored in `src/models` directory
## [__init__.py](__init__.py)
+
Pydantic models.
## [compaction.py](compaction.py)
+
Pydantic models for conversation compaction.
## [config.py](config.py)
+
Model with service configuration.
diff --git a/src/models/api/README.md b/src/models/api/README.md
index 58243fa92..1efb6f5fc 100644
--- a/src/models/api/README.md
+++ b/src/models/api/README.md
@@ -1,5 +1,6 @@
# List of source files stored in `src/models/api` directory
## [__init__.py](__init__.py)
+
Typed HTTP API models (OpenAPI-oriented) for FastAPI routes.
diff --git a/src/models/api/requests/README.md b/src/models/api/requests/README.md
index 1f7cef7f6..0935904a6 100644
--- a/src/models/api/requests/README.md
+++ b/src/models/api/requests/README.md
@@ -1,35 +1,46 @@
# List of source files stored in `src/models/api/requests` directory
## [__init__.py](__init__.py)
+
Concrete REST API request models grouped by domain.
## [catalog.py](catalog.py)
+
Request models for catalog-related endpoints.
## [conversations.py](conversations.py)
+
Request models for conversation endpoints.
## [feedback.py](feedback.py)
+
Request models for feedback endpoints.
## [mcp_servers.py](mcp_servers.py)
+
Request models for MCP server registration.
## [prompts.py](prompts.py)
+
Request models for prompt template endpoints.
## [query.py](query.py)
+
Request models for query and streaming interrupt endpoints.
## [responses_openai.py](responses_openai.py)
+
Request model for the OpenAI-compatible Responses API.
## [rlsapi.py](rlsapi.py)
+
Models for rlsapi v1 REST API requests.
## [saved_prompts.py](saved_prompts.py)
+
Request models for saved prompts endpoints.
## [vector_stores.py](vector_stores.py)
+
Request models for vector store and file endpoints.
diff --git a/src/models/api/responses/README.md b/src/models/api/responses/README.md
index dff4ff4c1..c1b6083d2 100644
--- a/src/models/api/responses/README.md
+++ b/src/models/api/responses/README.md
@@ -1,8 +1,10 @@
# List of source files stored in `src/models/api/responses` directory
## [__init__.py](__init__.py)
+
HTTP response models and shared OpenAPI description constants.
## [constants.py](constants.py)
+
OpenAPI description strings and shared example-label lists for API responses.
diff --git a/src/models/api/responses/error/README.md b/src/models/api/responses/error/README.md
index 6dcaa4ca9..35a151eb0 100644
--- a/src/models/api/responses/error/README.md
+++ b/src/models/api/responses/error/README.md
@@ -1,38 +1,50 @@
# List of source files stored in `src/models/api/responses/error` directory
## [__init__.py](__init__.py)
+
Structured HTTP error response models for OpenAPI documentation.
## [bad_request.py](bad_request.py)
+
OpenAPI-aligned error response models: HTTP 400 Bad Request.
## [bases.py](bases.py)
+
Base Pydantic types for OpenAPI-aligned structured API error responses.
## [conflict.py](conflict.py)
+
OpenAPI-aligned error response models: HTTP 409 Conflict.
## [content_too_large.py](content_too_large.py)
+
OpenAPI-aligned error response models: HTTP 413 Payload Too Large.
## [forbidden.py](forbidden.py)
+
OpenAPI-aligned error response models: HTTP 403 Forbidden.
## [internal.py](internal.py)
+
OpenAPI-aligned error response models: HTTP 500 Internal Server Error.
## [not_found.py](not_found.py)
+
OpenAPI-aligned error response models: HTTP 404 Not Found.
## [service_unavailable.py](service_unavailable.py)
+
OpenAPI-aligned error response models: HTTP 503 Service Unavailable.
## [too_many_requests.py](too_many_requests.py)
+
OpenAPI-aligned error response models: HTTP 429 Too Many Requests.
## [unauthorized.py](unauthorized.py)
+
OpenAPI-aligned error response models: HTTP 401 Unauthorized.
## [unprocessable_entity.py](unprocessable_entity.py)
+
OpenAPI-aligned error response models: HTTP 422 Unprocessable Entity.
diff --git a/src/models/api/responses/successful/README.md b/src/models/api/responses/successful/README.md
index ce3d5d0bc..fb3ab3594 100644
--- a/src/models/api/responses/successful/README.md
+++ b/src/models/api/responses/successful/README.md
@@ -1,44 +1,58 @@
# List of source files stored in `src/models/api/responses/successful` directory
## [__init__.py](__init__.py)
+
Concrete successful HTTP response models grouped by domain.
## [bases.py](bases.py)
+
Base classes for successful API response models.
## [catalog.py](catalog.py)
+
Successful response bodies for catalog-style endpoints.
## [configuration.py](configuration.py)
+
Successful response model for the configuration endpoint.
## [conversations.py](conversations.py)
+
Successful responses for conversation CRUD and listing.
## [feedback.py](feedback.py)
+
Successful responses for feedback and feedback status endpoints.
## [mcp_servers.py](mcp_servers.py)
+
Successful responses for MCP server registration and listing.
## [probes.py](probes.py)
+
Successful probe-related API responses (info, readiness, liveness, status, auth).
## [prompts.py](prompts.py)
+
Successful responses for stored prompt templates.
## [query.py](query.py)
+
Successful response models for synchronous query and streaming query documentation.
## [responses_openai.py](responses_openai.py)
+
Successful response model for the OpenAI-compatible Responses API.
## [rlsapi.py](rlsapi.py)
+
Models for rlsapi v1 REST API responses.
## [saved_prompts.py](saved_prompts.py)
+
Successful responses for saved prompts configuration, listing, and delete.
## [vector_stores.py](vector_stores.py)
+
Successful responses for vector stores and vector store files.
diff --git a/src/models/common/README.md b/src/models/common/README.md
index c7aae797a..bc7cf1578 100644
--- a/src/models/common/README.md
+++ b/src/models/common/README.md
@@ -1,38 +1,50 @@
# List of source files stored in `src/models/common` directory
## [__init__.py](__init__.py)
+
Shared Pydantic models and types used across API layers.
## [conversation.py](conversation.py)
+
Conversation list rows, metadata, and simplified turn/message shapes for APIs.
## [feedback.py](feedback.py)
+
Predefined feedback categories for AI response quality signals.
## [health.py](health.py)
+
Health-related shared models for readiness and diagnostics.
## [mcp.py](mcp.py)
+
MCP server metadata models shared by registration and list responses.
## [models.py](models.py)
+
Backend-agnostic model catalog types.
## [moderation.py](moderation.py)
+
Shield moderation outcomes for the responses pipeline.
## [query.py](query.py)
+
Shared query-related request primitives.
## [shields.py](shields.py)
+
Catalog models for the ``/shields`` endpoint.
## [tools.py](tools.py)
+
Backend-agnostic tool listing models.
## [transcripts.py](transcripts.py)
+
Pydantic models for persisted query/response transcript entries.
## [turn_summary.py](turn_summary.py)
+
RAG context, chunks, document refs, tool summaries, and per-turn aggregation.
diff --git a/src/models/common/agents/README.md b/src/models/common/agents/README.md
index 1ddcb18e5..55c1c57ee 100644
--- a/src/models/common/agents/README.md
+++ b/src/models/common/agents/README.md
@@ -1,11 +1,14 @@
# List of source files stored in `src/models/common/agents` directory
## [__init__.py](__init__.py)
+
Streaming payload models and event type exports.
## [stream_payloads.py](stream_payloads.py)
+
Typed JSON bodies for SSE streaming events.
## [turn_accumulator.py](turn_accumulator.py)
+
Mutable per-turn state for agent response processing.
diff --git a/src/models/common/responses/README.md b/src/models/common/responses/README.md
index e7bedc1d6..7988b61a5 100644
--- a/src/models/common/responses/README.md
+++ b/src/models/common/responses/README.md
@@ -1,17 +1,22 @@
# List of source files stored in `src/models/common/responses` directory
## [__init__.py](__init__.py)
+
Shared models for the OpenAI-compatible Responses API pipeline.
## [contexts.py](contexts.py)
+
Context objects for the responses endpoint pipeline and streaming query generators.
## [responses_api_params.py](responses_api_params.py)
+
Request parameter model for Llama Stack responses API calls.
## [responses_conversation_context.py](responses_conversation_context.py)
+
Conversation resolution result model for the OpenAI-compatible responses endpoint.
## [types.py](types.py)
+
Type aliases for OpenAI-compatible Responses API input shapes.
diff --git a/src/models/database/README.md b/src/models/database/README.md
index 813bfaefe..cf76bc700 100644
--- a/src/models/database/README.md
+++ b/src/models/database/README.md
@@ -1,14 +1,18 @@
# List of source files stored in `src/models/database` directory
## [__init__.py](__init__.py)
+
Database models package.
## [base.py](base.py)
+
Base model for SQLAlchemy ORM classes.
## [conversations.py](conversations.py)
+
User conversation models.
## [saved_prompts.py](saved_prompts.py)
+
User saved prompt models.
diff --git a/src/observability/README.md b/src/observability/README.md
index 6a4e966d4..1e1f206ae 100644
--- a/src/observability/README.md
+++ b/src/observability/README.md
@@ -1,8 +1,10 @@
# List of source files stored in `src/observability` directory
## [__init__.py](__init__.py)
+
Observability module for telemetry and event collection.
## [splunk.py](splunk.py)
+
Async Splunk HEC client for sending telemetry events.
diff --git a/src/observability/formats/README.md b/src/observability/formats/README.md
index f51ca05d3..6978956db 100644
--- a/src/observability/formats/README.md
+++ b/src/observability/formats/README.md
@@ -1,11 +1,14 @@
# List of source files stored in `src/observability/formats` directory
## [__init__.py](__init__.py)
+
Event format builders for Splunk telemetry.
## [responses.py](responses.py)
+
Event builders for Responses API Splunk format.
## [rlsapi.py](rlsapi.py)
+
Event builders for rlsapi v1 Splunk format.
diff --git a/src/pydantic_ai_lightspeed/README.md b/src/pydantic_ai_lightspeed/README.md
index b5ec5166e..c997021d3 100644
--- a/src/pydantic_ai_lightspeed/README.md
+++ b/src/pydantic_ai_lightspeed/README.md
@@ -1,5 +1,6 @@
# List of source files stored in `src/pydantic_ai_lightspeed` directory
## [__init__.py](__init__.py)
+
Pydantic AI integrations/extensions for Lightspeed Core Stack.
diff --git a/src/pydantic_ai_lightspeed/capabilities/README.md b/src/pydantic_ai_lightspeed/capabilities/README.md
index 0b6ffc607..c7e5f07be 100644
--- a/src/pydantic_ai_lightspeed/capabilities/README.md
+++ b/src/pydantic_ai_lightspeed/capabilities/README.md
@@ -1,8 +1,10 @@
# List of source files stored in `src/pydantic_ai_lightspeed/capabilities` directory
## [__init__.py](__init__.py)
+
Pluggable capabilities for pydantic-ai agents in Lightspeed.
## [base.py](base.py)
+
Abstract base for safety capabilities with a standalone run interface.
diff --git a/src/pydantic_ai_lightspeed/capabilities/question_validity/README.md b/src/pydantic_ai_lightspeed/capabilities/question_validity/README.md
index d6d9e2768..3e51fc9eb 100644
--- a/src/pydantic_ai_lightspeed/capabilities/question_validity/README.md
+++ b/src/pydantic_ai_lightspeed/capabilities/question_validity/README.md
@@ -1,8 +1,10 @@
# List of source files stored in `src/pydantic_ai_lightspeed/capabilities/question_validity` directory
## [__init__.py](__init__.py)
+
Question validity capability for agent input validation.
## [_capability.py](_capability.py)
+
Question validity capability for filtering off-topic user queries.
diff --git a/src/pydantic_ai_lightspeed/capabilities/redaction/README.md b/src/pydantic_ai_lightspeed/capabilities/redaction/README.md
index 60a374464..ed56a9cfd 100644
--- a/src/pydantic_ai_lightspeed/capabilities/redaction/README.md
+++ b/src/pydantic_ai_lightspeed/capabilities/redaction/README.md
@@ -1,11 +1,14 @@
# List of source files stored in `src/pydantic_ai_lightspeed/capabilities/redaction` directory
## [__init__.py](__init__.py)
+
PII redaction capability for Pydantic AI agents.
## [_capability.py](_capability.py)
+
Pydantic AI capability for PII redaction of model messages.
## [core.py](core.py)
+
Core redaction logic for PII detection and replacement.
diff --git a/src/pydantic_ai_lightspeed/llamastack/README.md b/src/pydantic_ai_lightspeed/llamastack/README.md
index 0ed6b4e07..31d479e46 100644
--- a/src/pydantic_ai_lightspeed/llamastack/README.md
+++ b/src/pydantic_ai_lightspeed/llamastack/README.md
@@ -1,14 +1,18 @@
# List of source files stored in `src/pydantic_ai_lightspeed/llamastack` directory
## [__init__.py](__init__.py)
+
Pydantic AI provider for Llama Stack.
## [_model.py](_model.py)
+
Custom OpenAI Responses model that works around Llama Stack streaming quirks.
## [_provider.py](_provider.py)
+
Llama Stack provider implementation for Pydantic AI.
## [_transport.py](_transport.py)
+
httpx transports for Llama Stack library and server modes.
diff --git a/src/quota/README.md b/src/quota/README.md
index 7b7ed798c..fc7edee27 100644
--- a/src/quota/README.md
+++ b/src/quota/README.md
@@ -1,35 +1,46 @@
# List of source files stored in `src/quota` directory
## [__init__.py](__init__.py)
+
Quota management.
## [cluster_quota_limiter.py](cluster_quota_limiter.py)
+
Simple cluster quota limiter where quota is fixed for the whole cluster.
## [connect_pg.py](connect_pg.py)
+
PostgreSQL connection handler.
## [connect_sqlite.py](connect_sqlite.py)
+
SQLite connection handler.
## [quota_exceed_error.py](quota_exceed_error.py)
+
Any exception that can occur when a user does not have enough tokens available.
## [quota_limiter.py](quota_limiter.py)
+
Abstract class that is the parent for all quota limiter implementations.
## [quota_limiter_factory.py](quota_limiter_factory.py)
+
Quota limiter factory class.
## [revokable_quota_limiter.py](revokable_quota_limiter.py)
+
Simple quota limiter where quota can be revoked.
## [sql.py](sql.py)
+
SQL commands used by quota management package.
## [token_usage_history.py](token_usage_history.py)
+
Class with implementation of storage for token usage history.
## [user_quota_limiter.py](user_quota_limiter.py)
+
Simple user quota limiter where each user has a fixed quota.
diff --git a/src/runners/README.md b/src/runners/README.md
index ec6696921..498c49a95 100644
--- a/src/runners/README.md
+++ b/src/runners/README.md
@@ -1,11 +1,14 @@
# List of source files stored in `src/runners` directory
## [__init__.py](__init__.py)
+
Runners.
## [quota_scheduler.py](quota_scheduler.py)
+
User and cluster quota scheduler runner.
## [uvicorn.py](uvicorn.py)
+
Uvicorn runner.
diff --git a/src/telemetry/README.md b/src/telemetry/README.md
index 316e3c325..ffbf1d88b 100644
--- a/src/telemetry/README.md
+++ b/src/telemetry/README.md
@@ -1,8 +1,10 @@
# List of source files stored in `src/telemetry` directory
## [__init__.py](__init__.py)
+
Telemetry module for configuration snapshot collection.
## [configuration_snapshot.py](configuration_snapshot.py)
+
Configuration snapshot with PII masking for telemetry.
diff --git a/src/utils/README.md b/src/utils/README.md
index 34efddcb3..8beddf44d 100644
--- a/src/utils/README.md
+++ b/src/utils/README.md
@@ -1,119 +1,158 @@
# List of source files stored in `src/utils` directory
## [__init__.py](__init__.py)
+
Utility classes and functions for the Lightspeed Stack core service.
## [builtin_tools.py](builtin_tools.py)
+
Discover builtin file-search tools when that provider is configured.
## [checks.py](checks.py)
+
Checks that are performed to configuration options.
## [common.py](common.py)
+
Common utilities for the project.
## [compaction.py](compaction.py)
+
Conversation compaction — partitioning, summarization, additive fold-up.
## [config_dumper.py](config_dumper.py)
+
Function to dump the configuration schema into OpenAPI-compatible format.
## [connection_decorator.py](connection_decorator.py)
+
Decorator that makes sure the object is 'connected' according to it's connected predicate.
## [conversation_compaction.py](conversation_compaction.py)
+
Runtime integration of conversation compaction into the request flow.
## [conversations.py](conversations.py)
+
Utilities for conversations.
## [degraded_mode.py](degraded_mode.py)
+
Degraded mode state tracking.
## [endpoints.py](endpoints.py)
+
Utility functions for endpoint handlers.
## [json_schema_updater.py](json_schema_updater.py)
+
Function to transform a JSON Schema-like dictionary into an OpenAPI-compatible schema.
## [llama_stack_version.py](llama_stack_version.py)
+
Check if the Llama Stack version is supported by the LCS.
## [markdown_repair.py](markdown_repair.py)
+
Utilities for repairing truncated markdown content.
## [mcp_auth_headers.py](mcp_auth_headers.py)
+
Utilities for resolving MCP server authorization headers.
## [mcp_headers.py](mcp_headers.py)
+
MCP headers handling.
## [mcp_oauth_probe.py](mcp_oauth_probe.py)
+
Probe MCP servers for OAuth and raise 401 with WWW-Authenticate when required.
## [mcp_tools.py](mcp_tools.py)
+
Utilities for discovering tools from remote MCP servers without Llama Stack.
## [model_list.py](model_list.py)
+
Helpers for normalizing OGX ``models.list()`` union responses.
## [models_dumper.py](models_dumper.py)
+
Function to dump the schema of all data models into OpenAPI-compatible format.
## [openapi_schema_dumper.py](openapi_schema_dumper.py)
+
Utility function to dump schema with list of models into OpenAPI-compatible JSON format.
## [prompts.py](prompts.py)
+
Utility functions for system prompts.
## [pydantic_ai_helpers.py](pydantic_ai_helpers.py)
+
Helpers for running Pydantic AI agents against Llama Stack (Responses API compatibility).
## [query.py](query.py)
+
Utility functions for working with queries.
## [quota_utils.py](quota_utils.py)
+
Quota handling helper functions.
## [reranker.py](reranker.py)
+
Reranker utilities for RAG chunk reranking.
## [responses.py](responses.py)
+
Utility functions for processing Responses API output.
## [rh_identity.py](rh_identity.py)
+
Utility functions for extracting RH Identity context for telemetry.
## [saved_prompts.py](saved_prompts.py)
+
Validation helpers and data access for saved prompts.
## [shields.py](shields.py)
+
Utility helpers for shield override validation and moderation.
## [stream_interrupts.py](stream_interrupts.py)
+
Stream interrupt registry and persistence utilities.
## [streaming_sse.py](streaming_sse.py)
+
SSE formatting helpers for streaming query responses.
## [suid.py](suid.py)
+
Session ID utility functions.
## [token_counter.py](token_counter.py)
+
Helper classes to count tokens sent and received by the LLM.
## [token_estimator.py](token_estimator.py)
+
Pre-LLM-call token estimation.
## [tool_formatter.py](tool_formatter.py)
+
Utility functions for formatting and parsing MCP tool descriptions.
## [transcripts.py](transcripts.py)
+
Transcript handling.
## [types.py](types.py)
+
Common types for the project.
## [vector_search.py](vector_search.py)
+
Vector search utilities for query endpoints.
diff --git a/src/utils/agents/README.md b/src/utils/agents/README.md
index 65b247af9..ca09f7b20 100644
--- a/src/utils/agents/README.md
+++ b/src/utils/agents/README.md
@@ -1,17 +1,22 @@
# List of source files stored in `src/utils/agents` directory
## [__init__.py](__init__.py)
+
Agent helpers.
## [error_handler.py](error_handler.py)
+
Error mapping for agent inference failures to structured API error responses.
## [query.py](query.py)
+
Non-streaming agent helpers and shared turn-summary builders for agent runs.
## [streaming.py](streaming.py)
+
Agent streaming helpers for the streaming_query flow.
## [tool_processor.py](tool_processor.py)
+
Process and record pydantic-ai tool parts during agent stream dispatch.
diff --git a/tests/e2e/features/README.md b/tests/e2e/features/README.md
index 33a566064..d9cdf399f 100644
--- a/tests/e2e/features/README.md
+++ b/tests/e2e/features/README.md
@@ -1,5 +1,6 @@
# List of source files stored in `tests/e2e/features` directory
## [environment.py](environment.py)
+
Code to be called before and after certain events during testing.
diff --git a/tests/e2e/features/steps/README.md b/tests/e2e/features/steps/README.md
index 183cdba3c..248940d49 100644
--- a/tests/e2e/features/steps/README.md
+++ b/tests/e2e/features/steps/README.md
@@ -1,59 +1,78 @@
# List of source files stored in `tests/e2e/features/steps` directory
## [__init__.py](__init__.py)
+
Implementation of end-to-end tests steps.
## [auth.py](auth.py)
+
Implementation of common test steps.
## [common.py](common.py)
+
Implementation of common test steps.
## [common_http.py](common_http.py)
+
Common steps for HTTP-related operations.
## [conversation.py](conversation.py)
+
Implementation of common test steps.
## [feedback.py](feedback.py)
+
Implementation of common test steps for the feedback API.
## [health.py](health.py)
+
Implementation of common test steps.
## [info.py](info.py)
+
Implementation of common test steps.
## [llm_query_response.py](llm_query_response.py)
+
LLM query and response steps.
## [models.py](models.py)
+
Steps for /models endpoint.
## [place_holder.py](place_holder.py)
+
Implementation of placeholder test steps.
## [prompts.py](prompts.py)
+
Behave steps for /v1/prompts endpoint end-to-end tests.
## [proxy.py](proxy.py)
+
Step definitions for proxy and TLS networking e2e tests.
## [rbac.py](rbac.py)
+
Step definitions for RBAC E2E tests.
## [responses_steps.py](responses_steps.py)
+
Behave steps for POST /v1/responses (LCORE Responses API) multi-turn tests.
## [rlsapi_v1.py](rlsapi_v1.py)
+
rlsapi v1 endpoint test steps.
## [shields.py](shields.py)
+
Behave steps for temporarily disabling Llama Stack shields in e2e (server mode).
## [tls.py](tls.py)
+
Step definitions for TLS configuration e2e tests.
## [token_counters.py](token_counters.py)
+
Step definitions for token counter validation.
diff --git a/tests/e2e/mock_jwks_server/README.md b/tests/e2e/mock_jwks_server/README.md
index 48d931d68..603424345 100644
--- a/tests/e2e/mock_jwks_server/README.md
+++ b/tests/e2e/mock_jwks_server/README.md
@@ -1,8 +1,10 @@
# List of source files stored in `tests/e2e/mock_jwks_server` directory
## [generate_tokens.py](generate_tokens.py)
+
One-time script to generate JWKS and test tokens.
## [server.py](server.py)
+
Simple mock JWKS server for E2E RBAC tests.
diff --git a/tests/e2e/mock_mcp_server/README.md b/tests/e2e/mock_mcp_server/README.md
index 4236f7a14..6650f7ddc 100644
--- a/tests/e2e/mock_mcp_server/README.md
+++ b/tests/e2e/mock_mcp_server/README.md
@@ -1,5 +1,6 @@
# List of source files stored in `tests/e2e/mock_mcp_server` directory
## [server.py](server.py)
+
Minimal mock MCP server for E2E tests with OAuth support.
diff --git a/tests/e2e/mock_tls_inference_server/README.md b/tests/e2e/mock_tls_inference_server/README.md
index 63094a1af..b165ff9c9 100644
--- a/tests/e2e/mock_tls_inference_server/README.md
+++ b/tests/e2e/mock_tls_inference_server/README.md
@@ -1,5 +1,6 @@
# List of source files stored in `tests/e2e/mock_tls_inference_server` directory
## [server.py](server.py)
+
Mock OpenAI-compatible HTTPS inference server for TLS e2e testing.
diff --git a/tests/e2e/proxy/README.md b/tests/e2e/proxy/README.md
index b3d88d75d..429218ebc 100644
--- a/tests/e2e/proxy/README.md
+++ b/tests/e2e/proxy/README.md
@@ -1,11 +1,14 @@
# List of source files stored in `tests/e2e/proxy` directory
## [__init__.py](__init__.py)
+
Test proxy infrastructure for e2e networking tests.
## [interception_proxy.py](interception_proxy.py)
+
Minimal TLS-intercepting (MITM) proxy for e2e testing.
## [tunnel_proxy.py](tunnel_proxy.py)
+
Minimal HTTP CONNECT tunnel proxy for e2e testing.
diff --git a/tests/e2e/utils/README.md b/tests/e2e/utils/README.md
index 1ae5059af..218d5be7f 100644
--- a/tests/e2e/utils/README.md
+++ b/tests/e2e/utils/README.md
@@ -1,17 +1,22 @@
# List of source files stored in `tests/e2e/utils` directory
## [llama_config_utils.py](llama_config_utils.py)
+
Helpers for reading and updating Llama Stack run.yaml across environments.
## [llama_prow_utils.py](llama_prow_utils.py)
+
Thin Prow/OpenShift wrappers for Llama Stack run.yaml ConfigMap operations.
## [llama_stack_utils.py](llama_stack_utils.py)
+
E2E test utilities for Llama Stack shields.
## [prow_utils.py](prow_utils.py)
+
Prow/OpenShift-specific utility functions for E2E tests.
## [utils.py](utils.py)
+
Unsorted utility functions to be used from other sources and test step definitions.
diff --git a/tests/integration/container_lifecycle/README.md b/tests/integration/container_lifecycle/README.md
index 220b00955..090db711a 100644
--- a/tests/integration/container_lifecycle/README.md
+++ b/tests/integration/container_lifecycle/README.md
@@ -1,5 +1,6 @@
# List of source files stored in `tests/integration/container_lifecycle` directory
## [test_container_lifecycle.py](test_container_lifecycle.py)
+
Integration tests for Llama Stack container lifecycle management.
diff --git a/tests/integration/endpoints/README.md b/tests/integration/endpoints/README.md
index 4e4876188..604a13aaa 100644
--- a/tests/integration/endpoints/README.md
+++ b/tests/integration/endpoints/README.md
@@ -1,59 +1,78 @@
# List of source files stored in `tests/integration/endpoints` directory
## [__init__.py](__init__.py)
+
Integration tests for API endpoints.
## [test_authorized_endpoint.py](test_authorized_endpoint.py)
+
Integration tests for the /authorized endpoint.
## [test_config_integration.py](test_config_integration.py)
+
Integration tests for the /config endpoint.
## [test_conversations_v1_integration.py](test_conversations_v1_integration.py)
+
Integration tests for the /v1/conversations REST API endpoints.
## [test_conversations_v2_integration.py](test_conversations_v2_integration.py)
+
Integration tests for the /v2/conversations REST API endpoints (cache-based).
## [test_health_integration.py](test_health_integration.py)
+
Integration tests for the /health endpoint.
## [test_info_integration.py](test_info_integration.py)
+
Integration tests for the /info endpoint.
## [test_model_list.py](test_model_list.py)
+
Integration tests for the /models endpoint (using Responses API).
## [test_query_byok_integration.py](test_query_byok_integration.py)
+
Integration tests for the /query endpoint BYOK inline and tool RAG functionality.
## [test_query_integration.py](test_query_integration.py)
+
Integration tests for the /query endpoint (using Responses API).
## [test_responses_byok_integration.py](test_responses_byok_integration.py)
+
Integration tests for the /responses endpoint BYOK RAG functionality.
## [test_responses_integration.py](test_responses_integration.py)
+
Integration tests for the /v1/responses endpoint.
## [test_rlsapi_v1_integration.py](test_rlsapi_v1_integration.py)
+
Integration tests for the rlsapi v1 /infer endpoint.
## [test_root_endpoint.py](test_root_endpoint.py)
+
Integration tests for the /root endpoint.
## [test_saved_prompts_integration.py](test_saved_prompts_integration.py)
+
Integration tests for the /v1/saved-prompts REST API endpoints.
## [test_stream_interrupt_integration.py](test_stream_interrupt_integration.py)
+
Integration tests for the streaming query interrupt lifecycle.
## [test_streaming_query_byok_integration.py](test_streaming_query_byok_integration.py)
+
Integration tests for the /streaming_query endpoint BYOK inline and tool RAG functionality.
## [test_streaming_query_integration.py](test_streaming_query_integration.py)
+
Integration tests for the /streaming_query endpoint (using Responses API).
## [test_tools_integration.py](test_tools_integration.py)
+
Integration tests for the /tools endpoint.
diff --git a/tests/unit/README.md b/tests/unit/README.md
index 3f4725c5d..0c0d45eb2 100644
--- a/tests/unit/README.md
+++ b/tests/unit/README.md
@@ -1,35 +1,46 @@
# List of source files stored in `tests/unit` directory
## [__init__.py](__init__.py)
+
Unit tests.
## [conftest.py](conftest.py)
+
Shared pytest fixtures for unit tests.
## [test_client.py](test_client.py)
+
Unit tests for functions defined in src/client.py.
## [test_configuration.py](test_configuration.py)
+
Unit tests for functions defined in src/configuration.py.
## [test_configuration_unknown_fields.py](test_configuration_unknown_fields.py)
+
Test configuration validation for unknown fields.
## [test_degraded_mode.py](test_degraded_mode.py)
+
Unit tests for the degraded mode tracker.
## [test_lightspeed_stack.py](test_lightspeed_stack.py)
+
Unit tests for functions defined in src/lightspeed_stack.py.
## [test_llama_stack_configuration.py](test_llama_stack_configuration.py)
+
Unit tests for src/llama_stack_configuration.py.
## [test_llama_stack_synthesize.py](test_llama_stack_synthesize.py)
+
Unit tests for unified-mode Llama Stack configuration synthesis (LCORE-2336).
## [test_log.py](test_log.py)
+
Unit tests for functions defined in src/log.py.
## [test_sentry.py](test_sentry.py)
+
Unit tests for functions defined in src/sentry.py.
diff --git a/tests/unit/a2a_storage/README.md b/tests/unit/a2a_storage/README.md
index 9fdae62ab..2573ed13a 100644
--- a/tests/unit/a2a_storage/README.md
+++ b/tests/unit/a2a_storage/README.md
@@ -1,14 +1,18 @@
# List of source files stored in `tests/unit/a2a_storage` directory
## [__init__.py](__init__.py)
+
Unit tests for A2A storage module.
## [test_in_memory_context_store.py](test_in_memory_context_store.py)
+
Unit tests for InMemoryA2AContextStore.
## [test_sqlite_context_store.py](test_sqlite_context_store.py)
+
Unit tests for SQLiteA2AContextStore.
## [test_storage_factory.py](test_storage_factory.py)
+
Unit tests for A2AStorageFactory.
diff --git a/tests/unit/app/README.md b/tests/unit/app/README.md
index f06dc9fb7..5fcadf112 100644
--- a/tests/unit/app/README.md
+++ b/tests/unit/app/README.md
@@ -1,14 +1,18 @@
# List of source files stored in `tests/unit/app` directory
## [__init__.py](__init__.py)
+
Init of tests/unit/app.
## [test_database.py](test_database.py)
+
Unit tests for app.database module.
## [test_main_middleware.py](test_main_middleware.py)
+
Unit tests for the pure ASGI middlewares in main.py.
## [test_routers.py](test_routers.py)
+
Unit tests for routers.py.
diff --git a/tests/unit/app/endpoints/README.md b/tests/unit/app/endpoints/README.md
index fec5a5b37..2e75c8c92 100644
--- a/tests/unit/app/endpoints/README.md
+++ b/tests/unit/app/endpoints/README.md
@@ -1,86 +1,114 @@
# List of source files stored in `tests/unit/app/endpoints` directory
## [__init__.py](__init__.py)
+
Unit tests for endpoints implementations.
## [conftest.py](conftest.py)
+
Shared pytest fixtures for endpoint unit tests.
## [test_a2a.py](test_a2a.py)
+
Unit tests for the A2A (Agent-to-Agent) protocol endpoints.
## [test_authorized.py](test_authorized.py)
+
Unit tests for the /authorized REST API endpoint.
## [test_config.py](test_config.py)
+
Unit tests for the /config REST API endpoint.
## [test_conversations.py](test_conversations.py)
+
Unit tests for the /conversations REST API endpoints.
## [test_conversations_v2.py](test_conversations_v2.py)
+
Unit tests for the /conversations REST API endpoints.
## [test_feedback.py](test_feedback.py)
+
Unit tests for the /feedback REST API endpoint.
## [test_health.py](test_health.py)
+
Unit tests for the /health REST API endpoint.
## [test_info.py](test_info.py)
+
Unit tests for the /info REST API endpoint.
## [test_mcp_auth.py](test_mcp_auth.py)
+
Unit tests for MCP auth endpoint.
## [test_mcp_servers.py](test_mcp_servers.py)
+
Unit tests for the MCP servers dynamic registration endpoint.
## [test_metrics.py](test_metrics.py)
+
Unit tests for the /metrics REST API endpoint.
## [test_models.py](test_models.py)
+
Unit tests for the /models REST API endpoint.
## [test_prompts.py](test_prompts.py)
+
Unit tests for the /prompts REST API endpoints.
## [test_providers.py](test_providers.py)
+
Unit tests for the /providers REST API endpoints.
## [test_query.py](test_query.py)
+
Unit tests for the /query (v2) REST API endpoint using Responses API.
## [test_rags.py](test_rags.py)
+
Unit tests for the /rags REST API endpoints.
## [test_responses.py](test_responses.py)
+
Unit tests for the /responses REST API endpoint (LCORE Responses API).
## [test_responses_splunk.py](test_responses_splunk.py)
+
Unit tests for Splunk telemetry in the /responses endpoint.
## [test_rlsapi_v1.py](test_rlsapi_v1.py)
+
Unit tests for the rlsapi v1 /infer REST API endpoint.
## [test_root.py](test_root.py)
+
Unit tests for the / endpoint handler.
## [test_saved_prompts.py](test_saved_prompts.py)
+
Unit tests for the /saved-prompts REST API endpoints.
## [test_shields.py](test_shields.py)
+
Unit tests for the /shields REST API endpoint.
## [test_stream_interrupt.py](test_stream_interrupt.py)
+
Unit tests for streaming query interrupt endpoint.
## [test_streaming_query.py](test_streaming_query.py)
+
Unit tests for the /streaming_query (v2) endpoint using Responses API.
## [test_tools.py](test_tools.py)
+
Unit tests for tools endpoint.
## [test_vector_stores.py](test_vector_stores.py)
+
Unit tests for the /vector-stores REST API endpoints.
diff --git a/tests/unit/authentication/README.md b/tests/unit/authentication/README.md
index 1690e99cb..7968e03a1 100644
--- a/tests/unit/authentication/README.md
+++ b/tests/unit/authentication/README.md
@@ -1,32 +1,42 @@
# List of source files stored in `tests/unit/authentication` directory
## [__init__.py](__init__.py)
+
Authentication unit tests package.
## [test_api_key_token.py](test_api_key_token.py)
+
Unit tests for functions defined in authentication/api_key_token.py
## [test_auth.py](test_auth.py)
+
Unit tests for functions defined in authentication/__init__.py
## [test_jwk_token.py](test_jwk_token.py)
+
Unit tests for functions defined in authentication/jwk_token.py
## [test_k8s.py](test_k8s.py)
+
Unit tests for authentication/k8s module.
## [test_noop.py](test_noop.py)
+
Unit tests for functions defined in authentication/noop.py
## [test_noop_with_token.py](test_noop_with_token.py)
+
Unit tests for functions defined in authentication/noop_with_token.py
## [test_rh_identity.py](test_rh_identity.py)
+
Unit tests for Red Hat Identity authentication module.
## [test_trusted_proxy.py](test_trusted_proxy.py)
+
Unit tests for authentication/trusted_proxy module.
## [test_utils.py](test_utils.py)
+
Unit tests for functions defined in authentication/utils.py
diff --git a/tests/unit/authorization/README.md b/tests/unit/authorization/README.md
index d6395e887..63d648432 100644
--- a/tests/unit/authorization/README.md
+++ b/tests/unit/authorization/README.md
@@ -1,14 +1,18 @@
# List of source files stored in `tests/unit/authorization` directory
## [__init__.py](__init__.py)
+
Unit tests for authorization module.
## [test_azure_token_manager.py](test_azure_token_manager.py)
+
Unit test for Authentication with Azure Entra ID Credentials.
## [test_middleware.py](test_middleware.py)
+
Unit tests for the authorization middleware.
## [test_resolvers.py](test_resolvers.py)
+
Unit tests for the authorization resolvers.
diff --git a/tests/unit/cache/README.md b/tests/unit/cache/README.md
index 5c3ba497e..bbdfc48b6 100644
--- a/tests/unit/cache/README.md
+++ b/tests/unit/cache/README.md
@@ -1,20 +1,26 @@
# List of source files stored in `tests/unit/cache` directory
## [__init__.py](__init__.py)
+
Test cases for conversation history cache implementations.
## [test_cache_factory.py](test_cache_factory.py)
+
Unit tests for CacheFactory class.
## [test_in_memory_cache.py](test_in_memory_cache.py)
+
Unit tests for InMemoryCache class — conversation compaction summaries (LCORE-1571).
## [test_noop_cache.py](test_noop_cache.py)
+
Unit tests for NoopCache class.
## [test_postgres_cache.py](test_postgres_cache.py)
+
Unit tests for PostgreSQL cache implementation.
## [test_sqlite_cache.py](test_sqlite_cache.py)
+
Unit tests for SQLite cache implementation.
diff --git a/tests/unit/metrics/README.md b/tests/unit/metrics/README.md
index 3d9c0e37b..7bf2f7155 100644
--- a/tests/unit/metrics/README.md
+++ b/tests/unit/metrics/README.md
@@ -1,11 +1,14 @@
# List of source files stored in `tests/unit/metrics` directory
## [__init__.py](__init__.py)
+
Unit tests for metrics.
## [test_recording.py](test_recording.py)
+
Unit tests for Prometheus metric recording helpers.
## [test_utis.py](test_utis.py)
+
Unit tests for functions defined in metrics/utils.py
diff --git a/tests/unit/models/README.md b/tests/unit/models/README.md
index 906c006a2..053dfdb8b 100644
--- a/tests/unit/models/README.md
+++ b/tests/unit/models/README.md
@@ -1,14 +1,18 @@
# List of source files stored in `tests/unit/models` directory
## [__init__.py](__init__.py)
+
Unit tests for models.
## [test_compaction.py](test_compaction.py)
+
Unit tests for the ConversationSummary model.
## [test_saved_prompts_config.py](test_saved_prompts_config.py)
+
Unit tests for SavedPromptsConfiguration.
## [test_saved_prompts_list_response.py](test_saved_prompts_list_response.py)
+
Unit tests for saved prompts list response models.
diff --git a/tests/unit/models/config/README.md b/tests/unit/models/config/README.md
index 210e40a87..6bbc662ce 100644
--- a/tests/unit/models/config/README.md
+++ b/tests/unit/models/config/README.md
@@ -1,95 +1,126 @@
# List of source files stored in `tests/unit/models/config` directory
## [__init__.py](__init__.py)
+
Unit tests for models defined in config.py.
## [test_a2a_state_configuration.py](test_a2a_state_configuration.py)
+
Unit tests for A2AStateConfiguration.
## [test_approvals_configuration.py](test_approvals_configuration.py)
+
Unit tests for human-in-the-loop approvals configuration models.
## [test_authentication_configuration.py](test_authentication_configuration.py)
+
Unit tests for AuthenticationConfiguration model.
## [test_byok_rag.py](test_byok_rag.py)
+
Unit tests for ByokRag model.
## [test_compaction_configuration.py](test_compaction_configuration.py)
+
Unit tests for CompactionConfiguration and its placement on Configuration.
## [test_conversation_history.py](test_conversation_history.py)
+
Unit tests for ConversationHistoryConfiguration model.
## [test_cors.py](test_cors.py)
+
Unit tests for CORSConfiguration model.
## [test_customization.py](test_customization.py)
+
Unit tests for Customization model.
## [test_database_configuration.py](test_database_configuration.py)
+
Unit tests for DatabaseConfiguration model.
## [test_dump_configuration.py](test_dump_configuration.py)
+
Unit tests checking ability to dump configuration.
## [test_in_memory_cache_configuration.py](test_in_memory_cache_configuration.py)
+
Unit tests for InMemoryCache model.
## [test_inference_configuration.py](test_inference_configuration.py)
+
Unit tests for InferenceConfiguration model.
## [test_jwt_role_rule.py](test_jwt_role_rule.py)
+
Unit tests for JwtRoleRule model.
## [test_llama_stack_configuration.py](test_llama_stack_configuration.py)
+
Unit tests for LlamaStackConfiguration model.
## [test_model_context_protocol_server.py](test_model_context_protocol_server.py)
+
Unit tests for ModelContextProtocolServer model.
## [test_observability_configuration.py](test_observability_configuration.py)
+
Unit tests for ObservabilityConfiguration model.
## [test_postgresql_database_configuration.py](test_postgresql_database_configuration.py)
+
Unit tests for PostgreSQLDatabaseConfiguration model.
## [test_quota_handlers_config.py](test_quota_handlers_config.py)
+
Unit tests for QuotaHandlersConfiguration model.
## [test_quota_limiter_config.py](test_quota_limiter_config.py)
+
Unit tests for QuotaLimiterConfig model.
## [test_quota_scheduler_config.py](test_quota_scheduler_config.py)
+
Unit tests for QuotaSchedulerConfig model.
## [test_rag_configuration.py](test_rag_configuration.py)
+
Unit tests for RAG and OKP configuration models.
## [test_reranker_configuration.py](test_reranker_configuration.py)
+
Unit tests for RerankerConfiguration model.
## [test_rlsapi_v1_configuration.py](test_rlsapi_v1_configuration.py)
+
Unit tests for RlsapiV1Configuration and related startup validators.
## [test_service_configuration.py](test_service_configuration.py)
+
Unit tests for ServiceConfiguration model.
## [test_shields_configuration.py](test_shields_configuration.py)
+
Unit tests for ShieldConfiguration model and the Configuration.shields list.
## [test_skills_configuration.py](test_skills_configuration.py)
+
Unit tests for SkillsConfiguration model.
## [test_splunk_configuration.py](test_splunk_configuration.py)
+
Unit tests for SplunkConfiguration model.
## [test_tls_configuration.py](test_tls_configuration.py)
+
Unit tests for TLSConfiguration model.
## [test_user_data_collection.py](test_user_data_collection.py)
+
Unit tests for UserDataCollection model.
## [test_vector_store.py](test_vector_store.py)
+
Unit tests for vector_store configuration models.
diff --git a/tests/unit/models/database/README.md b/tests/unit/models/database/README.md
index 694564ced..19fc88f9b 100644
--- a/tests/unit/models/database/README.md
+++ b/tests/unit/models/database/README.md
@@ -1,8 +1,10 @@
# List of source files stored in `tests/unit/models/database` directory
## [__init__.py](__init__.py)
+
Unit tests for database models.
## [test_saved_prompts.py](test_saved_prompts.py)
+
Unit tests for SavedPrompt database model.
diff --git a/tests/unit/models/requests/README.md b/tests/unit/models/requests/README.md
index a07744eb8..d7a74a1ac 100644
--- a/tests/unit/models/requests/README.md
+++ b/tests/unit/models/requests/README.md
@@ -1,23 +1,30 @@
# List of source files stored in `tests/unit/models/requests` directory
## [__init__.py](__init__.py)
+
Unit tests for REST API request models under ``models.api.requests``.
## [test_attachment.py](test_attachment.py)
+
Unit tests for Attachment model.
## [test_feedback_request.py](test_feedback_request.py)
+
Unit tests for FeedbackRequest model.
## [test_feedback_status_update_request.py](test_feedback_status_update_request.py)
+
Unit tests for FeedbackStatusUpdateRequest model.
## [test_query_request.py](test_query_request.py)
+
Unit tests for QueryRequest model.
## [test_responses_request.py](test_responses_request.py)
+
Unit tests for ResponsesRequest body-size validation.
## [test_vector_store_requests.py](test_vector_store_requests.py)
+
Unit tests for Vector Store request models.
diff --git a/tests/unit/models/responses/README.md b/tests/unit/models/responses/README.md
index d196a6b39..192dc8e01 100644
--- a/tests/unit/models/responses/README.md
+++ b/tests/unit/models/responses/README.md
@@ -1,26 +1,34 @@
# List of source files stored in `tests/unit/models/responses` directory
## [__init__.py](__init__.py)
+
Unit tests for models defined in responses.py.
## [test_authorized_response.py](test_authorized_response.py)
+
Unit tests for AuthorizedResponse model.
## [test_error_responses.py](test_error_responses.py)
+
Unit tests for all error response models.
## [test_query_response.py](test_query_response.py)
+
Unit tests for QueryResponse model.
## [test_rag_chunk.py](test_rag_chunk.py)
+
Unit tests for RAGChunk and RAGContext models.
## [test_response_types.py](test_response_types.py)
+
Unit tests for response-related type models defined in models/responses.py.
## [test_successful_responses.py](test_successful_responses.py)
+
Unit tests for all successful response models.
## [test_types.py](test_types.py)
+
Unit tests for response-related type models.
diff --git a/tests/unit/models/rlsapi/README.md b/tests/unit/models/rlsapi/README.md
index 6b801bd57..f7f223736 100644
--- a/tests/unit/models/rlsapi/README.md
+++ b/tests/unit/models/rlsapi/README.md
@@ -1,11 +1,14 @@
# List of source files stored in `tests/unit/models/rlsapi` directory
## [__init__.py](__init__.py)
+
Unit tests for rlsapi v1 models.
## [test_requests.py](test_requests.py)
+
Unit tests for rlsapi v1 request models.
## [test_responses.py](test_responses.py)
+
Unit tests for rlsapi v1 response models.
diff --git a/tests/unit/observability/README.md b/tests/unit/observability/README.md
index b388a94d9..079a420a2 100644
--- a/tests/unit/observability/README.md
+++ b/tests/unit/observability/README.md
@@ -1,8 +1,10 @@
# List of source files stored in `tests/unit/observability` directory
## [__init__.py](__init__.py)
+
Unit tests for observability module.
## [test_splunk.py](test_splunk.py)
+
Unit tests for Splunk HEC client.
diff --git a/tests/unit/observability/formats/README.md b/tests/unit/observability/formats/README.md
index e154a397b..5bad4e904 100644
--- a/tests/unit/observability/formats/README.md
+++ b/tests/unit/observability/formats/README.md
@@ -1,11 +1,14 @@
# List of source files stored in `tests/unit/observability/formats` directory
## [__init__.py](__init__.py)
+
Unit tests for observability event format builders.
## [test_responses.py](test_responses.py)
+
Unit tests for responses event builders.
## [test_rlsapi.py](test_rlsapi.py)
+
Unit tests for rlsapi v1 event builders.
diff --git a/tests/unit/pydantic_ai_lightspeed/README.md b/tests/unit/pydantic_ai_lightspeed/README.md
index b1d77535c..7531a03d9 100644
--- a/tests/unit/pydantic_ai_lightspeed/README.md
+++ b/tests/unit/pydantic_ai_lightspeed/README.md
@@ -1,5 +1,6 @@
# List of source files stored in `tests/unit/pydantic_ai_lightspeed` directory
## [__init__.py](__init__.py)
+
Unit tests for the pydantic_ai_lightspeed package.
diff --git a/tests/unit/pydantic_ai_lightspeed/capabilities/README.md b/tests/unit/pydantic_ai_lightspeed/capabilities/README.md
index eb318efd1..b603ec1a9 100644
--- a/tests/unit/pydantic_ai_lightspeed/capabilities/README.md
+++ b/tests/unit/pydantic_ai_lightspeed/capabilities/README.md
@@ -1,5 +1,6 @@
# List of source files stored in `tests/unit/pydantic_ai_lightspeed/capabilities` directory
## [__init__.py](__init__.py)
+
Unit tests for pydantic_ai_lightspeed capabilities.
diff --git a/tests/unit/pydantic_ai_lightspeed/capabilities/question_validity/README.md b/tests/unit/pydantic_ai_lightspeed/capabilities/question_validity/README.md
index b98e24ca9..6e3ff8979 100644
--- a/tests/unit/pydantic_ai_lightspeed/capabilities/question_validity/README.md
+++ b/tests/unit/pydantic_ai_lightspeed/capabilities/question_validity/README.md
@@ -1,8 +1,10 @@
# List of source files stored in `tests/unit/pydantic_ai_lightspeed/capabilities/question_validity` directory
## [__init__.py](__init__.py)
+
Unit tests for question validity capability.
## [test_capability.py](test_capability.py)
+
Unit tests for pydantic_ai_lightspeed.capabilities.question_validity._capacity module.
diff --git a/tests/unit/pydantic_ai_lightspeed/capabilities/redaction/README.md b/tests/unit/pydantic_ai_lightspeed/capabilities/redaction/README.md
index 134637706..d52381911 100644
--- a/tests/unit/pydantic_ai_lightspeed/capabilities/redaction/README.md
+++ b/tests/unit/pydantic_ai_lightspeed/capabilities/redaction/README.md
@@ -1,14 +1,18 @@
# List of source files stored in `tests/unit/pydantic_ai_lightspeed/capabilities/redaction` directory
## [__init__.py](__init__.py)
+
Tests for pydantic_ai_lightspeed.capabilities.redaction package.
## [test_capability.py](test_capability.py)
+
Unit tests for pydantic_ai_lightspeed.capabilities.redaction.capability module.
## [test_config.py](test_config.py)
+
Unit tests for pydantic_ai_lightspeed.capabilities.redaction.config module.
## [test_core.py](test_core.py)
+
Unit tests for pydantic_ai_lightspeed.capabilities.redaction.core module.
diff --git a/tests/unit/pydantic_ai_lightspeed/llamastack/README.md b/tests/unit/pydantic_ai_lightspeed/llamastack/README.md
index fd0c79b39..4aedd4cd6 100644
--- a/tests/unit/pydantic_ai_lightspeed/llamastack/README.md
+++ b/tests/unit/pydantic_ai_lightspeed/llamastack/README.md
@@ -1,14 +1,18 @@
# List of source files stored in `tests/unit/pydantic_ai_lightspeed/llamastack` directory
## [__init__.py](__init__.py)
+
Unit tests for pydantic_ai_lightspeed.llamastack sub-package.
## [test_model.py](test_model.py)
+
Unit tests for pydantic_ai_lightspeed.llamastack._model module.
## [test_provider.py](test_provider.py)
+
Unit tests for pydantic_ai_lightspeed.llamastack._provider module.
## [test_transport.py](test_transport.py)
+
Unit tests for pydantic_ai_lightspeed.llamastack._transport module.
diff --git a/tests/unit/quota/README.md b/tests/unit/quota/README.md
index fd1febf16..8bc76d7fd 100644
--- a/tests/unit/quota/README.md
+++ b/tests/unit/quota/README.md
@@ -1,23 +1,30 @@
# List of source files stored in `tests/unit/quota` directory
## [__init__.py](__init__.py)
+
Unit tests for quota limiters.
## [test_cluster_quota_limiter.py](test_cluster_quota_limiter.py)
+
Unit tests for ClusterQuotaLimiter class.
## [test_connect_pg.py](test_connect_pg.py)
+
Unit tests for PostgreSQL connection handler.
## [test_connect_sqlite.py](test_connect_sqlite.py)
+
Unit tests for SQLite connection handler.
## [test_quota_exceed_error.py](test_quota_exceed_error.py)
+
Unit tests for QuotaExceedError class.
## [test_quota_limiter_factory.py](test_quota_limiter_factory.py)
+
Unit tests for quota limiter factory class.
## [test_user_quota_limiter.py](test_user_quota_limiter.py)
+
Unit tests for UserQuotaLimiter class.
diff --git a/tests/unit/runners/README.md b/tests/unit/runners/README.md
index 33ffdcab2..92086f296 100644
--- a/tests/unit/runners/README.md
+++ b/tests/unit/runners/README.md
@@ -1,8 +1,10 @@
# List of source files stored in `tests/unit/runners` directory
## [__init__.py](__init__.py)
+
Unit tests for runners.
## [test_uvicorn_runner.py](test_uvicorn_runner.py)
+
Unit tests for the Uvicorn runner implementation.
diff --git a/tests/unit/telemetry/README.md b/tests/unit/telemetry/README.md
index da5049a6d..81860adc4 100644
--- a/tests/unit/telemetry/README.md
+++ b/tests/unit/telemetry/README.md
@@ -1,11 +1,14 @@
# List of source files stored in `tests/unit/telemetry` directory
## [__init__.py](__init__.py)
+
Unit tests for the telemetry module.
## [conftest.py](conftest.py)
+
Shared fixtures for telemetry unit tests.
## [test_configuration_snapshot.py](test_configuration_snapshot.py)
+
Tests for configuration snapshot with PII masking.
diff --git a/tests/unit/utils/README.md b/tests/unit/utils/README.md
index 9a606cde5..55b32396d 100644
--- a/tests/unit/utils/README.md
+++ b/tests/unit/utils/README.md
@@ -1,101 +1,134 @@
# List of source files stored in `tests/unit/utils` directory
## [__init__.py](__init__.py)
+
Init of tests/unit/utils.
## [auth_helpers.py](auth_helpers.py)
+
Helper functions for mocking authorization in tests.
## [test_builtin_tools.py](test_builtin_tools.py)
+
Unit tests for builtin file-search tool discovery.
## [test_checks.py](test_checks.py)
+
Unit tests for functions defined in utils/checks module.
## [test_compaction.py](test_compaction.py)
+
Unit tests for utils/compaction — partitioning, prompt, summarization.
## [test_config_dumper.py](test_config_dumper.py)
+
Unit tests for utils/config_dumper module.
## [test_connection_decorator.py](test_connection_decorator.py)
+
Unit tests for the connection decorator.
## [test_conversation_compaction.py](test_conversation_compaction.py)
+
Unit tests for runtime conversation compaction (LCORE-1572).
## [test_conversations.py](test_conversations.py)
+
Unit tests for conversation utility functions.
## [test_endpoints.py](test_endpoints.py)
+
Unit tests for endpoints utility functions.
## [test_json_schema_updater.py](test_json_schema_updater.py)
+
Unit tests for utils/json_schema_updater module.
## [test_llama_stack_version.py](test_llama_stack_version.py)
+
Unit tests for utility function to check Llama Stack version.
## [test_markdown_repair.py](test_markdown_repair.py)
+
Unit tests for markdown repair utilities.
## [test_mcp_auth_headers.py](test_mcp_auth_headers.py)
+
Unit tests for MCP authorization headers utilities.
## [test_mcp_headers.py](test_mcp_headers.py)
+
Unit tests for MCP headers utility functions.
## [test_mcp_tools.py](test_mcp_tools.py)
+
Unit tests for MCP tool discovery utilities.
## [test_model_list.py](test_model_list.py)
+
Unit tests for utils/model_list.py helpers.
## [test_models_dumper.py](test_models_dumper.py)
+
Unit tests for utils/models_dumper module.
## [test_prompts.py](test_prompts.py)
+
Unit tests for prompts utility functions.
## [test_pydantic_ai.py](test_pydantic_ai.py)
+
Unit tests for utils/pydantic_ai module.
## [test_query.py](test_query.py)
+
Unit tests for utils/query.py functions.
## [test_responses.py](test_responses.py)
+
Unit tests for utils/responses.py functions.
## [test_rh_identity.py](test_rh_identity.py)
+
Unit tests for utils/rh_identity module.
## [test_saved_prompts.py](test_saved_prompts.py)
+
Unit tests for saved prompt validation helpers and data access.
## [test_shields.py](test_shields.py)
+
Unit tests for utils/shields.py functions.
## [test_stream_interrupts.py](test_stream_interrupts.py)
+
Unit tests for stream interrupt registry and persistence utilities.
## [test_streaming_sse.py](test_streaming_sse.py)
+
Unit tests for utils/streaming_sse.py.
## [test_suid.py](test_suid.py)
+
Unit tests for functions defined in utils.suid module.
## [test_token_estimator.py](test_token_estimator.py)
+
Unit tests for utils/token_estimator.
## [test_tool_formatter.py](test_tool_formatter.py)
+
Unit tests for tool_formatter utilities.
## [test_transcripts.py](test_transcripts.py)
+
Unit tests for functions defined in utils.transcripts module.
## [test_types.py](test_types.py)
+
Unit tests for functions and types defined in utils/types.py.
## [test_vector_search.py](test_vector_search.py)
+
Unit tests for vector search utilities.
diff --git a/tests/unit/utils/agents/README.md b/tests/unit/utils/agents/README.md
index cfcb0646f..bd0ce69d0 100644
--- a/tests/unit/utils/agents/README.md
+++ b/tests/unit/utils/agents/README.md
@@ -1,11 +1,14 @@
# List of source files stored in `tests/unit/utils/agents` directory
## [test_query.py](test_query.py)
+
Unit tests for utils.agents.query module.
## [test_streaming.py](test_streaming.py)
+
Unit tests for utils.agents.streaming module.
## [test_tool_processor.py](test_tool_processor.py)
+
Unit tests for utils.agents.tool_processor module.
From be2344d8a31dab1f0da90808c8f083338da9db6f Mon Sep 17 00:00:00 2001
From: Maysun J Faisal
Date: Thu, 6 Aug 2026 12:55:16 -0400
Subject: [PATCH 050/197] RHIDP-16060: propagate search_mode to OGX for
rag.tool keyword search
Wire OKP search_mode from lightspeed-stack.yaml into the OGX top-level
vector_stores.chunk_retrieval_params.default_search_mode config. This
enables rag.tool (file_search) to use keyword/hybrid search instead of
defaulting to vector similarity, which is critical for air-gap
environments without an embedding model.
Co-Authored-By: Claude Opus 4.6
---
src/llama_stack_configuration.py | 23 ++++++-
tests/unit/test_llama_stack_configuration.py | 64 ++++++++++++++++++++
2 files changed, 86 insertions(+), 1 deletion(-)
diff --git a/src/llama_stack_configuration.py b/src/llama_stack_configuration.py
index e19e5d281..6d1fcf0f5 100644
--- a/src/llama_stack_configuration.py
+++ b/src/llama_stack_configuration.py
@@ -767,7 +767,7 @@ def enrich_vector_store(
# =============================================================================
-def enrich_solr( # pylint: disable=too-many-locals
+def enrich_solr( # pylint: disable=too-many-locals,too-many-statements
ls_config: dict[str, Any],
rag_config: dict[str, Any],
okp_config: dict[str, Any],
@@ -919,6 +919,27 @@ def enrich_solr( # pylint: disable=too-many-locals
)
logger.info("Added OKP embedding model to registered_resources.models")
+ # Propagate search_mode to OGX's top-level vector_stores config so that
+ # rag.tool (file_search) uses keyword/hybrid instead of defaulting to
+ # vector similarity — critical for air-gap environments without an
+ # embedding model.
+ okp_search_mode = okp_config.get("search_mode")
+ if okp_search_mode:
+ ogx_mode = constants.SOLR_SEARCH_MODE_MAP.get(okp_search_mode, okp_search_mode)
+ # LCORE uses "semantic"; OGX uses "vector"
+ if ogx_mode == "semantic":
+ ogx_mode = "vector"
+ if "vector_stores" not in ls_config:
+ ls_config["vector_stores"] = {}
+ chunk_params = ls_config["vector_stores"].setdefault(
+ "chunk_retrieval_params", {}
+ )
+ chunk_params["default_search_mode"] = ogx_mode
+ logger.info(
+ "Set vector_stores.chunk_retrieval_params.default_search_mode=%s",
+ ogx_mode,
+ )
+
# =============================================================================
# Synthesis: unified-mode run.yaml generation (LCORE-2336)
diff --git a/tests/unit/test_llama_stack_configuration.py b/tests/unit/test_llama_stack_configuration.py
index a0f0bcbbe..199cd6d68 100644
--- a/tests/unit/test_llama_stack_configuration.py
+++ b/tests/unit/test_llama_stack_configuration.py
@@ -884,6 +884,70 @@ def test_enrich_solr_user_chunk_filter_query_is_conjoined() -> None:
)
+def test_enrich_solr_sets_default_search_mode_keyword() -> None:
+ """Test enrich_solr propagates search_mode keyword to vector_stores config."""
+ ls_config: dict[str, Any] = {}
+ enrich_solr(ls_config, _OKP_RAG_CONFIG, {"search_mode": "keyword"})
+
+ assert (
+ ls_config["vector_stores"]["chunk_retrieval_params"]["default_search_mode"]
+ == "keyword"
+ )
+
+
+def test_enrich_solr_sets_default_search_mode_hybrid() -> None:
+ """Test enrich_solr propagates search_mode hybrid to vector_stores config."""
+ ls_config: dict[str, Any] = {}
+ enrich_solr(ls_config, _OKP_RAG_CONFIG, {"search_mode": "hybrid"})
+
+ assert (
+ ls_config["vector_stores"]["chunk_retrieval_params"]["default_search_mode"]
+ == "hybrid"
+ )
+
+
+def test_enrich_solr_maps_semantic_to_vector() -> None:
+ """Test enrich_solr maps LCORE semantic to OGX vector search mode."""
+ ls_config: dict[str, Any] = {}
+ enrich_solr(ls_config, _OKP_RAG_CONFIG, {"search_mode": "semantic"})
+
+ assert (
+ ls_config["vector_stores"]["chunk_retrieval_params"]["default_search_mode"]
+ == "vector"
+ )
+
+
+def test_enrich_solr_maps_lexical_to_keyword() -> None:
+ """Test enrich_solr maps LCORE lexical to OGX keyword via SOLR_SEARCH_MODE_MAP."""
+ ls_config: dict[str, Any] = {}
+ enrich_solr(ls_config, _OKP_RAG_CONFIG, {"search_mode": "lexical"})
+
+ assert (
+ ls_config["vector_stores"]["chunk_retrieval_params"]["default_search_mode"]
+ == "keyword"
+ )
+
+
+def test_enrich_solr_no_search_mode_skips_vector_stores() -> None:
+ """Test enrich_solr does not set vector_stores when search_mode is absent."""
+ ls_config: dict[str, Any] = {}
+ enrich_solr(ls_config, _OKP_RAG_CONFIG, {})
+
+ assert "vector_stores" not in ls_config
+
+
+def test_enrich_solr_preserves_existing_vector_stores() -> None:
+ """Test enrich_solr preserves existing vector_stores config when adding search_mode."""
+ ls_config: dict[str, Any] = {"vector_stores": {"default_provider_id": "faiss"}}
+ enrich_solr(ls_config, _OKP_RAG_CONFIG, {"search_mode": "keyword"})
+
+ assert ls_config["vector_stores"]["default_provider_id"] == "faiss"
+ assert (
+ ls_config["vector_stores"]["chunk_retrieval_params"]["default_search_mode"]
+ == "keyword"
+ )
+
+
# =============================================================================
# Test enrich_vector_store
# =============================================================================
From 68e0d0c80f0ea7cab899f4a6f1b13cd25f5d6a7e Mon Sep 17 00:00:00 2001
From: Jordan Dubrick
Date: Thu, 6 Aug 2026 14:34:58 -0400
Subject: [PATCH 051/197] fix: set EXTERNAL_PROVIDERS_DIR in image for unified
config
Signed-off-by: Jordan Dubrick
---
deploy/lightspeed-stack/Containerfile | 3 +++
1 file changed, 3 insertions(+)
diff --git a/deploy/lightspeed-stack/Containerfile b/deploy/lightspeed-stack/Containerfile
index 8108557a9..a1592f1f0 100644
--- a/deploy/lightspeed-stack/Containerfile
+++ b/deploy/lightspeed-stack/Containerfile
@@ -132,6 +132,9 @@ ENV PATH="/app-root/.venv/bin:$PATH"
# Library mode: Llama Stack expects external provider configs under a path named providers.d (hardcoded).
# We place them at /app-root/providers.d. YAMLs there reference lightspeed_stack_providers.*, so that package must be on PYTHONPATH.
ENV PYTHONPATH="/app-root"
+# Unified: set the environment variable to mount point of external providers.
+# default_run.yaml sets this to ~/.llama/providers.d if unset.
+ENV EXTERNAL_PROVIDERS_DIR="/app-root/providers.d"
# Copy entrypoint script
COPY ${LSC_SOURCE_DIR}/scripts/entrypoint.sh /app-root/entrypoint.sh
From 8a6d9bb8808c8e21e0e81ab929f750dee8bf8b21 Mon Sep 17 00:00:00 2001
From: Maysun J Faisal
Date: Thu, 6 Aug 2026 15:07:15 -0400
Subject: [PATCH 052/197] RHIDP-16060: fix docstring conventions per CodeRabbit
review
- Use Parameters: instead of Args: in enrich_solr docstring
- Update SolrSearchOptions class docstring to match field description
Co-Authored-By: Claude Opus 4.6
---
src/llama_stack_configuration.py | 2 +-
src/models/common/query.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/llama_stack_configuration.py b/src/llama_stack_configuration.py
index 6d1fcf0f5..01ff4823b 100644
--- a/src/llama_stack_configuration.py
+++ b/src/llama_stack_configuration.py
@@ -774,7 +774,7 @@ def enrich_solr( # pylint: disable=too-many-locals,too-many-statements
) -> None:
"""Enrich Llama Stack config with Solr settings.
- Args:
+ Parameters:
ls_config: Llama Stack configuration dict (modified in place)
rag_config: RAG configuration dict. Used keys:
- inline (list[str]): inline RAG IDs
diff --git a/src/models/common/query.py b/src/models/common/query.py
index 924e8443a..81fb15a17 100644
--- a/src/models/common/query.py
+++ b/src/models/common/query.py
@@ -135,7 +135,7 @@ class SolrVectorSearchRequest(BaseModel):
"""LCORE Solr inline RAG options for vector_io.query (mode and provider filters).
Attributes:
- mode: Solr vector_io search mode. When omitted, the server default (hybrid) is used.
+ mode: Solr vector_io search mode. When omitted, the configured OKP default is used.
filters: Solr provider filter payload passed through as params['solr'].
Legacy clients may send a plain JSON object with filter keys only;
From 9e7ca49aa76514a235c0ab41efa3fe32be3e3218 Mon Sep 17 00:00:00 2001
From: Sergey Yedrikov
Date: Thu, 6 Aug 2026 19:26:32 -0400
Subject: [PATCH 053/197] Set the CPE label to 0.8 [main]
---
deploy/lightspeed-stack/Containerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/deploy/lightspeed-stack/Containerfile b/deploy/lightspeed-stack/Containerfile
index 8108557a9..8c1ef546f 100644
--- a/deploy/lightspeed-stack/Containerfile
+++ b/deploy/lightspeed-stack/Containerfile
@@ -144,7 +144,7 @@ ENTRYPOINT ["/app-root/entrypoint.sh"]
LABEL vendor="Red Hat, Inc." \
name="lightspeed-core/lightspeed-stack-rhel9" \
com.redhat.component="lightspeed-core/lightspeed-stack" \
- cpe="cpe:/a:redhat:lightspeed_core:0.7::el9" \
+ cpe="cpe:/a:redhat:lightspeed_core:0.8::el9" \
io.k8s.display-name="Lightspeed Stack" \
summary="A service that provides a REST API for the Lightspeed Core Stack." \
description="Lightspeed Core Stack (LCS) is an AI-powered assistant that provides answers to product questions using backend LLM services, agents, and RAG databases." \
From 8bbb09b3b926b2c4a05113c0863e615be6429080 Mon Sep 17 00:00:00 2001
From: Andrej Simurka
Date: Thu, 6 Aug 2026 13:10:17 +0200
Subject: [PATCH 054/197] Fix e2e proxy teardown leaving pending asyncio tasks
---
tests/e2e/features/steps/proxy.py | 36 +++++++++++++++++++++++----
tests/e2e/proxy/interception_proxy.py | 4 ++-
tests/e2e/proxy/tunnel_proxy.py | 2 ++
3 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/tests/e2e/features/steps/proxy.py b/tests/e2e/features/steps/proxy.py
index 7755cca91..dad6da620 100644
--- a/tests/e2e/features/steps/proxy.py
+++ b/tests/e2e/features/steps/proxy.py
@@ -286,7 +286,11 @@ def _stop_proxy(context: Context, attr: str, loop_attr: str) -> None:
except Exception:
pass
loop.call_soon_threadsafe(loop.stop)
- time.sleep(0.5)
+ thread = getattr(proxy, "_thread", None)
+ if thread is not None:
+ thread.join(timeout=30)
+ else:
+ time.sleep(0.5)
if hasattr(context, attr):
delattr(context, attr)
if hasattr(context, loop_attr):
@@ -368,10 +372,21 @@ def start_tunnel_proxy(context: Context, port: int) -> None:
def run_proxy() -> None:
asyncio.set_event_loop(loop)
- loop.run_until_complete(proxy.start())
- loop.run_forever()
+ try:
+ loop.run_until_complete(proxy.start())
+ loop.run_forever()
+ finally:
+ # Cancel leftover handler tasks so the loop can close cleanly.
+ if pending := asyncio.all_tasks(loop):
+ for task in pending:
+ task.cancel()
+ loop.run_until_complete(
+ asyncio.gather(*pending, return_exceptions=True)
+ )
+ loop.close()
thread = threading.Thread(target=run_proxy, daemon=True)
+ proxy._thread = thread
thread.start()
time.sleep(1)
@@ -463,10 +478,21 @@ def start_interception_proxy(context: Context, port: int) -> None:
def run_proxy() -> None:
asyncio.set_event_loop(loop)
- loop.run_until_complete(proxy.start())
- loop.run_forever()
+ try:
+ loop.run_until_complete(proxy.start())
+ loop.run_forever()
+ finally:
+ # Cancel leftover handler tasks so the loop can close cleanly.
+ if pending := asyncio.all_tasks(loop):
+ for task in pending:
+ task.cancel()
+ loop.run_until_complete(
+ asyncio.gather(*pending, return_exceptions=True)
+ )
+ loop.close()
thread = threading.Thread(target=run_proxy, daemon=True)
+ proxy._thread = thread
thread.start()
time.sleep(1)
diff --git a/tests/e2e/proxy/interception_proxy.py b/tests/e2e/proxy/interception_proxy.py
index f38a328fa..45e20ecd8 100644
--- a/tests/e2e/proxy/interception_proxy.py
+++ b/tests/e2e/proxy/interception_proxy.py
@@ -25,6 +25,7 @@
import json
import logging
import ssl
+import threading
from pathlib import Path
from typing import Any, Optional
@@ -39,7 +40,7 @@
IN_CLUSTER_CA_CERT_PATH = Path("/tmp/interception-proxy-ca.pem")
-class InterceptionProxy:
+class InterceptionProxy: # pylint: disable=too-many-instance-attributes
"""Async TLS-intercepting proxy for testing.
Attributes:
@@ -64,6 +65,7 @@ def __init__(
self.connect_count = 0
self._server: Optional[asyncio.Server] = None
self._handler_tasks: set[asyncio.Task[Any]] = set()
+ self._thread: Optional[threading.Thread] = None
def _make_server_ssl_context(self, hostname: str) -> ssl.SSLContext:
"""Create an SSL context with a certificate for the given hostname.
diff --git a/tests/e2e/proxy/tunnel_proxy.py b/tests/e2e/proxy/tunnel_proxy.py
index b29c01c24..11920c59d 100644
--- a/tests/e2e/proxy/tunnel_proxy.py
+++ b/tests/e2e/proxy/tunnel_proxy.py
@@ -21,6 +21,7 @@
import asyncio
import json
import logging
+import threading
from typing import Any, Optional
# In-cluster defaults (``python tunnel_proxy.py``).
@@ -48,6 +49,7 @@ def __init__(self, host: str = "127.0.0.1", port: int = 8888) -> None:
self.last_connect_target: Optional[str] = None
self._server: Optional[asyncio.Server] = None
self._handler_tasks: set[asyncio.Task[Any]] = set()
+ self._thread: Optional[threading.Thread] = None
async def _handle_client(
self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter
From 52bf8106537c66fb47ed4e54add270519b5f0cdd Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Fri, 7 Aug 2026 14:09:23 +0200
Subject: [PATCH 055/197] LCORE-2922: Updated dependencies
---
uv.lock | 244 +++++++++++++++++++++++++++++++-------------------------
1 file changed, 134 insertions(+), 110 deletions(-)
diff --git a/uv.lock b/uv.lock
index 09ea82c2a..da2330432 100644
--- a/uv.lock
+++ b/uv.lock
@@ -219,27 +219,46 @@ wheels = [
[[package]]
name = "ast-serialize"
-version = "0.6.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/58/ad/0d70a3a2d6e01968d985415259e8ec7ad3f777903f9b1c1f3c8c44642c60/ast_serialize-0.6.0.tar.gz", hash = "sha256:aadd3ffcf4858c9726bf3515f7b199c7eadbe504f96028e4a87172c0da65a8fe", size = 61489, upload-time = "2026-06-30T20:02:55.555Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/52/19/ac8348ae8711c9b5ae834634f635780cab62a0f5e6f988882e048b89c2ae/ast_serialize-0.6.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:093cb8bb91b720d8523580498d031791bb1bbaa048599c3d21085d380e11a596", size = 1185367, upload-time = "2026-06-30T20:02:30.427Z" },
- { url = "https://files.pythonhosted.org/packages/c1/f6/ec7ec652c51db77c2f61d8573338e13e4704303265ccc658cb4031d9f354/ast_serialize-0.6.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:e61580a69faf47e3689795367ed211f2a10fd741478cc0f36a0f128793360aad", size = 1178657, upload-time = "2026-06-30T20:02:31.964Z" },
- { url = "https://files.pythonhosted.org/packages/6f/02/613a7534a41d0122f37d1e0c64aa8ac78bfb831f8c92f6db057a311abb3c/ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:305802f2ce2a7c4e87835078ea85c58b586ddda8095b92fe2ead9364ae19c80a", size = 1238620, upload-time = "2026-06-30T20:02:33.664Z" },
- { url = "https://files.pythonhosted.org/packages/4d/21/087957bba486242afc52f49b2d9e21c9dad00289356cf9efe67084015a9d/ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c7b8b8f0c42f752ea00b2b7d7c090b3f80d9c1c5c75cadf16423790a0cc74081", size = 1236075, upload-time = "2026-06-30T20:02:34.936Z" },
- { url = "https://files.pythonhosted.org/packages/82/04/78128bbb170071c2c72a210a181f1c00e11cc1cec60a8beef747b07f9201/ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd5b91b9e6f2356ace3a556963b0cd783b395fbbb0bb17b4defc283415466e77", size = 1441348, upload-time = "2026-06-30T20:02:36.245Z" },
- { url = "https://files.pythonhosted.org/packages/64/64/62fb99d6faf199b4c3e5b08a07136e9a0d7664bb249c6de3670e5b63e9b6/ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d6ef91590258ada18909b9caea344dac4de2013906b035473cd674a43f4b790", size = 1258580, upload-time = "2026-06-30T20:02:37.53Z" },
- { url = "https://files.pythonhosted.org/packages/ca/87/b4d6c38e0ccd5e85dc54cecdf933a152c60b28fe5d993a6d8a72fa6d5896/ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcbed41e9386059fc0261d602445ede0976c2ecec2939688bcbcb9ed0b6f28b7", size = 1261693, upload-time = "2026-06-30T20:02:39.123Z" },
- { url = "https://files.pythonhosted.org/packages/0e/4b/3676ca2191f39bafb75f93f99b2f429ec464586158fece2165f3572805dc/ast_serialize-0.6.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:cdc4e6f930b9090c2f92c9036ad12ffb8e6e44d4a5ba06f1458a05d60f203f7b", size = 1252517, upload-time = "2026-06-30T20:02:40.511Z" },
- { url = "https://files.pythonhosted.org/packages/f3/58/494ef8c4b4acb2f4a265ac934caf45f792a08fe27d6b853de35ad991941a/ast_serialize-0.6.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:897ac47b5637be41c0c07061c8a912fafa967ef1dc73fa115e4bfa70882a093b", size = 1304843, upload-time = "2026-06-30T20:02:41.961Z" },
- { url = "https://files.pythonhosted.org/packages/b1/f2/13736d920ab3d49bbee80ef1a277dd7b7aaf3b3545efd9d2a8114fe05525/ast_serialize-0.6.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c4af9a1386166e40ed01464991806f89038a2d89782576c7774876fa77034e32", size = 1413698, upload-time = "2026-06-30T20:02:44.179Z" },
- { url = "https://files.pythonhosted.org/packages/a8/5a/e046f3899e2acba4677d7427b76431443a1aa1a0e583dfb05b55b69d55cf/ast_serialize-0.6.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:c901adbd750029b9ac4ad3d6aa56853e0ad4875119fbf52b7b8298afc223828b", size = 1512209, upload-time = "2026-06-30T20:02:45.584Z" },
- { url = "https://files.pythonhosted.org/packages/cc/c7/e42aaca7bb2d22a7c06d5a8c7930086c5a334e93d716e6fa5e6647a4515f/ast_serialize-0.6.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:3ae22a366b752ab4496191525b78b097b5b72d531752e3c1dd7e383a8f2c8a1a", size = 1508464, upload-time = "2026-06-30T20:02:46.942Z" },
- { url = "https://files.pythonhosted.org/packages/95/93/5524a3dc6c3f593de3228ed9cbef73afa047625b7000ec21b7f58e6eb4d4/ast_serialize-0.6.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4ed29121da8b3fdc291002801a1de0f76248fa07dce89157a5f277842cf6126e", size = 1457164, upload-time = "2026-06-30T20:02:48.294Z" },
- { url = "https://files.pythonhosted.org/packages/4f/c0/36a6ffb4d653cf621427b4c4928671f53ad800c453474de2b82564a44ad9/ast_serialize-0.6.0-cp39-abi3-pyemscripten_2026_0_wasm32.whl", hash = "sha256:b1dac4e09d341c1300ba69cdcbe62867b32a8c75d90db9bf4d083bec3b039f0b", size = 863014, upload-time = "2026-06-30T20:02:49.742Z" },
- { url = "https://files.pythonhosted.org/packages/09/c7/7d5ad8b49e1278e1c2a1e0274bd7850560b3f09313aa00c13bc8d5544792/ast_serialize-0.6.0-cp39-abi3-win32.whl", hash = "sha256:82c312a7844d2fdeb4d5c48bd3d215bf940dafd4704e1a9bcf252a99010a99b1", size = 1063165, upload-time = "2026-06-30T20:02:50.98Z" },
- { url = "https://files.pythonhosted.org/packages/47/ae/6710c14ecb276031cf10249f6adf5a59e2d3fdb3b5183bd59f70524067ee/ast_serialize-0.6.0-cp39-abi3-win_amd64.whl", hash = "sha256:113b58346f9ceb664352032770caca817d4a3c86f611c6088e6ef65ddaa70f0e", size = 1101444, upload-time = "2026-06-30T20:02:52.554Z" },
- { url = "https://files.pythonhosted.org/packages/66/40/c53deb2cd0c9b0fb636d24d9f40924cf2e65028e6b20b10cd5c1eeb2c730/ast_serialize-0.6.0-cp39-abi3-win_arm64.whl", hash = "sha256:ccd132fe8db56f61fe743b1f644d01b8d65b83248a8da506f3132bda86d6ed5e", size = 1072965, upload-time = "2026-06-30T20:02:54.097Z" },
+version = "0.8.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e1/a9/11851c3e02a3fea2ddc9932d1fdc7d2edaeecc0d2e11bc5f2a7fde2b0934/ast_serialize-0.8.0.tar.gz", hash = "sha256:6c37c43e4004dfb42d321ddedc569dc17ff4259296f3af577c9ea46a809bc010", size = 845638, upload-time = "2026-08-07T11:29:02.152Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/4c/11/911210c3c78923273a9211a2b6cfc4c8aa723b30dab3e1c8d19afb983b40/ast_serialize-0.8.0-cp315-abi3.abi3t-macosx_10_12_x86_64.whl", hash = "sha256:86b8a1e6d90467345356098b040150e82fbc26d24a7a202224b13dc1f6264ca0", size = 1177715, upload-time = "2026-08-07T11:28:04.654Z" },
+ { url = "https://files.pythonhosted.org/packages/77/89/6282881c8587606638db153cbe21e1e0c4d1f3970dee1aa0610a1c62a026/ast_serialize-0.8.0-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:39e92ff8e8cb45947fe9007174b2950e1fb098e6abd00266a13cd3bcf6675068", size = 1169347, upload-time = "2026-08-07T11:28:06.1Z" },
+ { url = "https://files.pythonhosted.org/packages/97/78/a9f846a03a340ff3728c915f23338ca742742f3292700559cdb3ad999b1e/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c85d8d18db5b2dfcb3b7e38a4d600ca35504c0ed8a6f75cd1c811e4ffe248a15", size = 1225916, upload-time = "2026-08-07T11:28:07.654Z" },
+ { url = "https://files.pythonhosted.org/packages/c0/15/aba6ef8a988a6eceb6f0359589aac509e29ae2dba67fd9bfd5af0c3f13e7/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9830ff7e764f74d9eefb01170c61a9f0fd2c027dac5fcb72e064decd57d56371", size = 1227135, upload-time = "2026-08-07T11:28:09.504Z" },
+ { url = "https://files.pythonhosted.org/packages/94/29/3f63d696ea7c5b8abadcecc3505be51bd900daaccc522ed8322fa5b05a93/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6479d9722a4cd21b578f5478074c41e6169f04811996ec881655560f703a5bba", size = 1425040, upload-time = "2026-08-07T11:28:11.044Z" },
+ { url = "https://files.pythonhosted.org/packages/e2/5d/0aac338604ff59df5774d4304307898982252f325ff7cafe31d52fedcb65/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a63bed264e818cd83eec11feed0f50aa162542b91132ef58afebc857182763a5", size = 1246278, upload-time = "2026-08-07T11:28:12.519Z" },
+ { url = "https://files.pythonhosted.org/packages/23/ca/9f1ef795bb724719532bd86dbec11e5b66857d3fbe9b6772baec0191a6ed/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d187197d234aa45d6cfa2b096be5f666e8cc2e7eb3722d0ab8926293cf5720c", size = 1250029, upload-time = "2026-08-07T11:28:13.896Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/25/5e061372d2ed953b9ba3b9c4f73de3b8e9234cda3f6c088db4686801d0e1/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_31_riscv64.whl", hash = "sha256:2d39a56282cfcc0d8eeea37267c754be59c98d48505c23b1dae5c6011f3813dd", size = 1243575, upload-time = "2026-08-07T11:28:15.37Z" },
+ { url = "https://files.pythonhosted.org/packages/a8/c1/ae7da218053120635a4ca802366c69f707203641af95372eeb83f70dfd52/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f7cc5f10386994c0f4844f1e6d6a97127e9b478660eb6dec2b257644f0acab64", size = 1294396, upload-time = "2026-08-07T11:28:16.813Z" },
+ { url = "https://files.pythonhosted.org/packages/2e/89/271d1f49c5269fcddcc789ea3f25be401f6723fc1138aeda539f4d05516d/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:6102f2f985c2e542be85cd857678ec9356fefa792b93cadfadd31139f5696f27", size = 1401987, upload-time = "2026-08-07T11:28:18.333Z" },
+ { url = "https://files.pythonhosted.org/packages/55/be/4e7d77fcf571ac7cb5cf7115a20c36642bd7d29473b45dfaaefeb9618f90/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_armv7l.whl", hash = "sha256:3a8660fe66667b76a6e9dccd1d33e66b229fde3b308db991c041609226c005b6", size = 1502904, upload-time = "2026-08-07T11:28:20.039Z" },
+ { url = "https://files.pythonhosted.org/packages/8b/ae/ed1de2db7e019d4236fbc164ffa5ef9a6022a300a342bbf142d21b7c141e/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_i686.whl", hash = "sha256:e7266307e5fba39836edb79def8608887af48820508bff3c5f2941e1e04d1534", size = 1496967, upload-time = "2026-08-07T11:28:21.734Z" },
+ { url = "https://files.pythonhosted.org/packages/92/89/5fea507fae5c5f18b7dc7f95e5c00956574b8c717b8fd2049c504fab0b18/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca7e6fd1ad845d1cc649dc2ecd499db2f8f46af5bf8da7b70dd858774cc038b", size = 1559041, upload-time = "2026-08-07T11:28:23.194Z" },
+ { url = "https://files.pythonhosted.org/packages/42/71/478d69df21b64e064554a68134c94be304270316ca676a94e63c389a636a/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_riscv64.whl", hash = "sha256:2880350b13d3eae69a0d70bc1fb6c9bfaca4dbd0e20ba8cd1aa483080b56ff06", size = 1417367, upload-time = "2026-08-07T11:28:24.601Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/2d/8962dc8d5b3a9dc27b36f9db199afa25264c741505469d9ec10ffbfd2ba7/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:ab0f9a59f7d63d0d441b56b9a818b273705264352d5115cfee12e940e816d958", size = 1446178, upload-time = "2026-08-07T11:28:26.152Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/22/14d2ad4fd1d1bcd0dc687ca268e0630069f45162496260c0efb70ee0ea72/ast_serialize-0.8.0-cp315-abi3.abi3t-win32.whl", hash = "sha256:0485a25ef519c62e749ee3c1ad8070e591b380d67226349eb5a70b228dc1ac4a", size = 1063811, upload-time = "2026-08-07T11:28:27.864Z" },
+ { url = "https://files.pythonhosted.org/packages/18/1d/84a327c0202a41aa5fdba3ade33904d6d8f3b9e6806fa83568d835395850/ast_serialize-0.8.0-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:bd84d60bca7079e741be4ac5dbe237751a59d7f6f9f0126b11880d63822cbe16", size = 1105518, upload-time = "2026-08-07T11:28:29.691Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/92/74556dec52fde85a2ad84ed159991b916241043788609c15d8b77e14570b/ast_serialize-0.8.0-cp315-abi3.abi3t-win_arm64.whl", hash = "sha256:057769b5921336eb2d9124f2a731b42ed05ffdac559b840dbdf6f3937cf153dc", size = 1076319, upload-time = "2026-08-07T11:28:31.282Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/e3/6142e920fec6ef7bccabd8c24ed8ed99f8bdc6cb8b065e1df7c6a3b2d667/ast_serialize-0.8.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:e1bd223df0f6c96b396975fa604cb33bce53d9b4a0185490be4c4a289f7c9c87", size = 1184007, upload-time = "2026-08-07T11:28:34.654Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/e9/6e8be8df02b35d85e2b8809f7f1cfa290bdf5882b55127a539d049482db0/ast_serialize-0.8.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ddd3b61f45c132da66c5476b281891e08c1fd87fbdabe8a6973e1622efc85f06", size = 1177588, upload-time = "2026-08-07T11:28:36.318Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/80/7e0fd2e2e2aba257820db4a8657c4c356844d36b914b20a4af294bcfb902/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f9caa63fad8241257ae401b5ff0a64026c6adb36b8e86cbe8782d9ea505daf6", size = 1234575, upload-time = "2026-08-07T11:28:37.772Z" },
+ { url = "https://files.pythonhosted.org/packages/b0/6a/3bae0af06f9b1bae3001c44d64215f5b567877e7aae9ffd45db11c3a7647/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3926fa117b5e65019853a2969966d11c7175af377a3425991f3fe73784412405", size = 1236015, upload-time = "2026-08-07T11:28:39.14Z" },
+ { url = "https://files.pythonhosted.org/packages/6f/c4/ce2d41a1bc22508e82618901f7e10f2a5e2f9556553fea90624daf9875e2/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:485f1113af805e9e170b95ef993ca3fbd4f89c04bab25c58b4fc632d854801ab", size = 1432808, upload-time = "2026-08-07T11:28:40.664Z" },
+ { url = "https://files.pythonhosted.org/packages/1a/90/f5058f209756dd70e958b7538aaa82d25d24944baf9ec8ae6f27b06fcacc/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ccebbed24f1281062d5852353c72c47502955926cfcb8345ffb3a44d87ff3d3", size = 1256251, upload-time = "2026-08-07T11:28:42.223Z" },
+ { url = "https://files.pythonhosted.org/packages/bf/32/7f77ea87fa0836daab706ed5cb7f903bb25fa26a77439011aee626af11d8/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:252f883290d1cdb728eb7fe1d9a7221b88af5a329aae0bc91ddee4dafb820331", size = 1258574, upload-time = "2026-08-07T11:28:43.751Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/5a/75b82ad2725b5e8e8c742732f9e76c6738a292d0709e1f60d10a973730b4/ast_serialize-0.8.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:96abc072ad29db8d02194afd47d68987322622787daceae82398d7b69f3ba2e6", size = 1254075, upload-time = "2026-08-07T11:28:45.28Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/54/8c20ed4eea805516a3fd23dd4a721ce28c64f50f0e4b359969f60a8c97a6/ast_serialize-0.8.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9118ad3e369727060b2696fc4078f250ecffca4248ba87f537f55cea9f9dce06", size = 1301018, upload-time = "2026-08-07T11:28:46.851Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/5b/9f14430f12fe830b656fb38f8e2e05ee13b02a88967660bef46af0ab22a8/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f359df4bd921918af8bebd142a376c77511d7151cc8ba852760b587b5a4a54f3", size = 1409951, upload-time = "2026-08-07T11:28:48.312Z" },
+ { url = "https://files.pythonhosted.org/packages/2d/3d/084882eca93c842bd4262591a071ec7f825340644035e51501208cc5a8d4/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:e94f9121d13fa36cbf21314783c77d05ae3a0868decd18cf5233fdcc6de49ac8", size = 1509544, upload-time = "2026-08-07T11:28:49.847Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/73/ea84852096c2036c61cc0b2f97b90242207419f534dc671060ee1c8e05cb/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:54f95b486018d262bcb387a9afd96f0da74508b442762b80c769454a6fbb3ee3", size = 1505671, upload-time = "2026-08-07T11:28:51.239Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/88/287b9a5300c1f2f651d259f670931b63110adc265b7613c885b44c5bc53d/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:4c38b915511e32bc718c49dbce98ff9af36bac0ad6a604f58000cd5e3aecdba7", size = 1563685, upload-time = "2026-08-07T11:28:53.112Z" },
+ { url = "https://files.pythonhosted.org/packages/ee/f3/1bc3a79afcf0c2a8d2c37182d0d659d1545a9d7f7f6dc9cf3e63d6c17135/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:9a2ef9cf12f2de4f1028c42c1dd7d775255e0fb3e5bb48896c97e35ef52366fe", size = 1427977, upload-time = "2026-08-07T11:28:54.418Z" },
+ { url = "https://files.pythonhosted.org/packages/5c/cd/440c798957e14e31776bfeb024d8fafe0bb1d5b89c51c2f067e69938f7b0/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6f18048fe9f6dd266bd577cdec48bdcecb74faaa01fe941324435483b013ed2a", size = 1454335, upload-time = "2026-08-07T11:28:55.968Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/4a/587eb36dcc240a54c8660f599464516b469ecad96f0dbdb6bccbedb50745/ast_serialize-0.8.0-cp39-abi3-win32.whl", hash = "sha256:31883542dd6c94d178f5db3d32fbd69c5eb88b3a7c018e7ac8cc0c45195ddbed", size = 1068858, upload-time = "2026-08-07T11:28:57.541Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/a4/3e887bbd92164e183cb6e412c6a3e9198ddd446d7fe405958293ef5ef49c/ast_serialize-0.8.0-cp39-abi3-win_amd64.whl", hash = "sha256:861794565b06337005c1447ef23103a3d5a627d08bdc827870d00d0b28ef5f51", size = 1111839, upload-time = "2026-08-07T11:28:59Z" },
+ { url = "https://files.pythonhosted.org/packages/25/6c/b400476d3ceba681ab929787edc9554f6d88fcc69435eb681b00fc0457a5/ast_serialize-0.8.0-cp39-abi3-win_arm64.whl", hash = "sha256:b2a5978662fd4db463dfb4b974d2b10ac6430b98f5333aabc7051909df3561d0", size = 1083655, upload-time = "2026-08-07T11:29:00.349Z" },
]
[[package]]
@@ -586,41 +605,41 @@ wheels = [
[[package]]
name = "coverage"
-version = "7.15.3"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/f4/45/78dbf9604ee5b3db24efbf26bed1cb58862fb40480cba821963c69348751/coverage-7.15.3.tar.gz", hash = "sha256:ae7ea5a4614acf399ef0483c4cb34f8f8f01df848d8fcbe7d3ce0865733f1c4d", size = 935592, upload-time = "2026-08-02T18:50:17.006Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/d1/6c/bac99d9d4c6abe856e93bf3f5212982ac0bfac126dd4a042753bd53bc5af/coverage-7.15.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:79a3e32e83227d83d9684459ed579769b56c369ac2d7313099b2d9e031d2e10f", size = 222499, upload-time = "2026-08-02T18:48:15.018Z" },
- { url = "https://files.pythonhosted.org/packages/aa/bc/cb9a39b083bc1aa70586482dab25c9be20bab0ec6c155340e50d9066bb1e/coverage-7.15.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:767feb87c5886d781d0a69fafd450a20826ddab7b79bce1665deb64d21441b60", size = 222866, upload-time = "2026-08-02T18:48:16.884Z" },
- { url = "https://files.pythonhosted.org/packages/58/fb/beaa453d62000a0a5b39838bee2a137afe609a50a71f55e83c73461e513b/coverage-7.15.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:50951e37033c40548d777b8a8454a2cd622dba1136780065678dccaec307c47f", size = 254367, upload-time = "2026-08-02T18:48:18.507Z" },
- { url = "https://files.pythonhosted.org/packages/66/64/43e72500ed6815cef189f9193f29d7af4b078830337c95ea976cd0c0d427/coverage-7.15.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:63a4ff67364afb2cac826b8bbd78a5c50ce656a7b7137436b44d7b96a9271088", size = 257103, upload-time = "2026-08-02T18:48:20.172Z" },
- { url = "https://files.pythonhosted.org/packages/66/3a/2893e2937adfe02f45fd38e4a8a0a0d8b7a02ff9e012ac3d009bee3c4f16/coverage-7.15.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e95e42856509675fe26560310313a6117640e96f9a1e19bb3d220116a27c94c", size = 258220, upload-time = "2026-08-02T18:48:21.963Z" },
- { url = "https://files.pythonhosted.org/packages/30/b4/d5e6e2eb1a62961083734291304b1f85df72e2abe95c76eb88a7f472afd0/coverage-7.15.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:abad631cba27094b4631993f4c72e89ac0ca1b3a0236c7abaf8ca79aea619851", size = 260481, upload-time = "2026-08-02T18:48:23.682Z" },
- { url = "https://files.pythonhosted.org/packages/dc/c9/9b72c5c6a9798a9a12cf65f66e077cc1fdd396e61915c862688f9afe1cae/coverage-7.15.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2b0807f1f051dd82a234ad6acdb6f1425baede60be1e84e862496c8cc9262ab9", size = 254749, upload-time = "2026-08-02T18:48:25.32Z" },
- { url = "https://files.pythonhosted.org/packages/92/20/e1c2f759e2dbce559ba85c40c0e4acfecc6cff4b740c294c88e41ccc6111/coverage-7.15.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8d6df7aeb5bc464040bbc9ae173d875785d3677ebc4307817997d622d74225e", size = 256138, upload-time = "2026-08-02T18:48:27.064Z" },
- { url = "https://files.pythonhosted.org/packages/a5/ab/48cc7e760f769e86ae290a125ea6e7209dfbdbbbb7ff4f5d9d1ee7a45d57/coverage-7.15.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:974471c506c9f5758808b47c1ebf7949ecd0848f5c1020e78675fefe5ff46866", size = 254283, upload-time = "2026-08-02T18:48:29.082Z" },
- { url = "https://files.pythonhosted.org/packages/15/26/39529a68154f99b3a1829debd8b25eac384effeec890a293b5bbdcb49186/coverage-7.15.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5cba0c9c13e35c86df7998f1afaf6b1da224a3a39e4da59bdabf60c148046dcb", size = 258352, upload-time = "2026-08-02T18:48:30.892Z" },
- { url = "https://files.pythonhosted.org/packages/91/2f/55b82aa3d8d7dd8023a56e7c5c2a70e39a3c44b3353c6cf3faec9ad51566/coverage-7.15.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:4d608dc36a364dce33acbf4fc3a50f9d2054c945f233bb0a2cdb4b90bfa17646", size = 253852, upload-time = "2026-08-02T18:48:32.934Z" },
- { url = "https://files.pythonhosted.org/packages/6a/6d/839f4045124cd3518ecf2c58967e58a911202834e7c5a03cfdf2ab0b29f6/coverage-7.15.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2395869280554a1941da904423c12660c39f721315e1c02d076a7fe0971382f0", size = 255725, upload-time = "2026-08-02T18:48:34.848Z" },
- { url = "https://files.pythonhosted.org/packages/75/21/d25e3e2a9e327798078c877f469dfb6def860bf6e25036529046227d3e15/coverage-7.15.3-cp312-cp312-win32.whl", hash = "sha256:24f3b21840c3eb76cef3cc70b2bf6649010c64471a84a446538a39306e1ba04d", size = 224566, upload-time = "2026-08-02T18:48:36.661Z" },
- { url = "https://files.pythonhosted.org/packages/b1/0f/df90cc1e8d095ce263968a93e04829821b2afb31ac2752c06a2e0a8e3c13/coverage-7.15.3-cp312-cp312-win_amd64.whl", hash = "sha256:fa7b17902c3c1dd8a7adb52679b7f6340bba08443d710c8838e04db8cf62be2a", size = 225098, upload-time = "2026-08-02T18:48:38.941Z" },
- { url = "https://files.pythonhosted.org/packages/65/c7/ec49e43c58967a07163e2d1c6bbd58112b825b2772ab66784afd6a5400ba/coverage-7.15.3-cp312-cp312-win_arm64.whl", hash = "sha256:fcbe83fb7258eacd293bf5322d88807acb35ed12a5cfa99dd8215c083e3b0235", size = 224485, upload-time = "2026-08-02T18:48:40.682Z" },
- { url = "https://files.pythonhosted.org/packages/68/6e/62ae61e1fc434956bec38ed1d5b1c494f58cf579dbd998e77abffe7b3e6b/coverage-7.15.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1182eed05674c63d40951fae27c43e822749f04d25f75df64c2e4fa3168678de", size = 222522, upload-time = "2026-08-02T18:48:42.476Z" },
- { url = "https://files.pythonhosted.org/packages/13/ff/c74c673d81e0e77b6608c3d21331e3db42e30daeb3c8a0a8860d4c9e2e14/coverage-7.15.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c0c4b0d7c4cd56e470d0c9d8441f42e8a96cdfd95050fec027f1d4dd9f11006c", size = 222894, upload-time = "2026-08-02T18:48:44.274Z" },
- { url = "https://files.pythonhosted.org/packages/a1/91/ccb30f5ffafd7d69d0b18e5162f9b711a5654e807b7b0c13497f0826b33f/coverage-7.15.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5c9fce9f4998b0d50a753da765b9215a14decc7863822c89d72da7a89ca625b3", size = 253890, upload-time = "2026-08-02T18:48:46.097Z" },
- { url = "https://files.pythonhosted.org/packages/29/c6/e92a66cda49a2751b09826d51258f199b92aa0cb005bc5f34e9729a52a9c/coverage-7.15.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7a47e2a0a0ace9241e70ee00e44520f88b843094603dd54303f1bafecd929c30", size = 256484, upload-time = "2026-08-02T18:48:47.846Z" },
- { url = "https://files.pythonhosted.org/packages/96/7a/730929164b457cf25cf76c23898b90f9039a104a647890801b6586797b14/coverage-7.15.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:95bad94f83807ae60ed76f3ac012f69b2605ac9ea81bee959a5a483f7fa09c10", size = 257723, upload-time = "2026-08-02T18:48:49.664Z" },
- { url = "https://files.pythonhosted.org/packages/9e/be/04cb5672cb19f5c389eda81ba22d89807699a949653d3625b0e0fda169da/coverage-7.15.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:228e172a76c428bb17d1ab78a2ff188990b0597e5dbd291f52a4edf7412de049", size = 259854, upload-time = "2026-08-02T18:48:51.413Z" },
- { url = "https://files.pythonhosted.org/packages/96/25/5e7fd6af39f6507071455944b8906dd1fe5b7b6bffb6a163ceb20afa0d13/coverage-7.15.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cea9fb33887c99349996266f1fd60abe5af3577a90633392001d27ef46b4b66e", size = 254085, upload-time = "2026-08-02T18:48:53.158Z" },
- { url = "https://files.pythonhosted.org/packages/23/c8/55e58a853f1e61163a6e755897bd14a059d78411e86560f39d9951c019b5/coverage-7.15.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:81760de3155d7f52c21860c4046628dc6bed182f72e3c028e2b4fd46f65aa040", size = 255850, upload-time = "2026-08-02T18:48:55.031Z" },
- { url = "https://files.pythonhosted.org/packages/be/74/8bcec66dbcf3d22bea2a0b2b77ee2fa6f766a647d0023d4eabbc4f2b2756/coverage-7.15.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b47ea0a1d3a3d089826c6cbfad8429d7d8872e28e86baa95ddef330f6875da21", size = 253818, upload-time = "2026-08-02T18:48:57.163Z" },
- { url = "https://files.pythonhosted.org/packages/ce/06/450b673fdfece0997b4e16a31d6bde6b18889c578f1013ddd34c962ac6f9/coverage-7.15.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5459ba486b2a5d58a6c05254779ecdf525e7f20174d0210ceda75ba40fdb8f2c", size = 257973, upload-time = "2026-08-02T18:48:59.098Z" },
- { url = "https://files.pythonhosted.org/packages/56/fd/3ec7409aec0ddc943132452b65672f065f043b844f1830e1fe173c98b3ab/coverage-7.15.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c59209f80a08dbfcdd5109a80dc623cd3b9d22895c85757d34f57a6e6e95570f", size = 253638, upload-time = "2026-08-02T18:49:01.199Z" },
- { url = "https://files.pythonhosted.org/packages/75/20/30a8dabb194123631c93f860fdd86401ad405d56cfb1841873afbfe4e92b/coverage-7.15.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f863856c1779d4a5bb6a94698a2f9073e09c6706501f76f3e7780e72df97d21c", size = 255407, upload-time = "2026-08-02T18:49:03.143Z" },
- { url = "https://files.pythonhosted.org/packages/13/4d/e14365b1953b43653341412f9088b0d752614c626a73a705ff9af400f3a3/coverage-7.15.3-cp313-cp313-win32.whl", hash = "sha256:00cbdc5e322927dc30c5e42b863819b1bb867cc66f26ab5372c585850876ab93", size = 224575, upload-time = "2026-08-02T18:49:05.011Z" },
- { url = "https://files.pythonhosted.org/packages/1c/64/88f762ea80de2070207246faef514513be874486b2773528f2cc2b4b515c/coverage-7.15.3-cp313-cp313-win_amd64.whl", hash = "sha256:835528518a1d823cf336740324b2f335f7c01e609e74abcb5d5163b3e66661e3", size = 225116, upload-time = "2026-08-02T18:49:06.894Z" },
- { url = "https://files.pythonhosted.org/packages/ab/66/03c34c53a319f522554cd29d4f2e16c5eab61aa4cdcf55753129fd7d926c/coverage-7.15.3-cp313-cp313-win_arm64.whl", hash = "sha256:0d2e1f2cbbf36b842f3e2aff8d118c60d677adb498bc6c7fa9c6838738f82767", size = 224509, upload-time = "2026-08-02T18:49:09.129Z" },
- { url = "https://files.pythonhosted.org/packages/37/e7/7069b3d6c018917f49ba2e1c5fb910e498c7fefa3a1b78cb1b79e61ff45d/coverage-7.15.3-py3-none-any.whl", hash = "sha256:da78fa6fc7dafe4212839173133ee85afcf42c5cd5f3e47fa7c1c210453b445e", size = 214297, upload-time = "2026-08-02T18:50:14.709Z" },
+version = "7.15.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/be/c3/4f2195f512fb172aa425a8803a874b2baa9ba7f80ff7b6080998761fc701/coverage-7.15.4.tar.gz", hash = "sha256:0548198fff07ccf4faf469520bce1c2eceb1ce3e62891921138dec10907f9d00", size = 936952, upload-time = "2026-08-06T13:50:24.442Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1d/48/bc8d4ba7b37551a767bd863f15b3f80182b271c2f55975356f5f7dbe94c2/coverage-7.15.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d4fedd1f7f428f9fe83b1ead5e7cc87a43427be31aadafbac3ac0636dc7abb22", size = 222543, upload-time = "2026-08-06T13:47:37.562Z" },
+ { url = "https://files.pythonhosted.org/packages/20/dd/88d6f83f1fffc974a3691a34a97951c5b12df7512a6782c5963883cbc058/coverage-7.15.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:37e2f0cdf58e2e1fed4e4d5a8f8786ae2f7eb80b478016876667dc4a01d60a97", size = 222905, upload-time = "2026-08-06T13:47:38.927Z" },
+ { url = "https://files.pythonhosted.org/packages/bd/5c/54ee0d4748585bb0acab9891cd8d92f2d3593165b4e59fc9de113bfb3140/coverage-7.15.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:fb55d0e70bb15f2e81477613627286581414693d74ac7963c93a790dd453ca9d", size = 254407, upload-time = "2026-08-06T13:47:40.488Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/3f/f0642a372f494bd0d7dad3b497083b910194a5f1c88be2c94fef707c3b59/coverage-7.15.4-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:899b9da30f3c6c336566e3707495bb23e8302d39d862f01fa78c48b99b9437e2", size = 257145, upload-time = "2026-08-06T13:47:41.931Z" },
+ { url = "https://files.pythonhosted.org/packages/71/17/8b46d0ed68251016002ec972c8fc0119961a765d0984cafb8bf317c43758/coverage-7.15.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d15715e8c46552827e5e4f30a35575a2dbcad14454cf3284c54483946bd16931", size = 258257, upload-time = "2026-08-06T13:47:43.527Z" },
+ { url = "https://files.pythonhosted.org/packages/30/b8/8498a0e72d0adbe15477dd07463d2b3bb2c9f6a4815e8589e50939e2c3ae/coverage-7.15.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:002a438859f7b430bc99afeaf01a6d187dad1d0dc907b64cdeffc632a5db8fd8", size = 260517, upload-time = "2026-08-06T13:47:45.121Z" },
+ { url = "https://files.pythonhosted.org/packages/41/e1/7dce19c3bdb1e3dd63e769508216500edad81bd5f69a26d724e32aceaf78/coverage-7.15.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e4193a04b518f7968f3099755f5509ee7cccc6dc2b92a6b14841934d22e222c9", size = 254785, upload-time = "2026-08-06T13:47:46.541Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/b1/e1494703c675a2561723cd9b89f45c9168782c31280c611b1f767851e57c/coverage-7.15.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e98dcc55d572b38e69d117da7e8e8efb8500f1f5eaf81ecd460a63220790b839", size = 256176, upload-time = "2026-08-06T13:47:48.155Z" },
+ { url = "https://files.pythonhosted.org/packages/73/76/a5629d270fb638a43a4b10466f51e2f49d532c1aa4da2913cbbb150bbe0a/coverage-7.15.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:af6c538498ce66c10d3fd541c2a8d5b03da5850355add34e6cba564210cb9e72", size = 254321, upload-time = "2026-08-06T13:47:49.757Z" },
+ { url = "https://files.pythonhosted.org/packages/ff/4f/9c44447218435d5766b911534f9d798144a5560f85e9a54ebe5f3f5d19f9/coverage-7.15.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1d10025d96ea89fc2f73714dbc4cbd433fe012c1ac9e23f895d7728b238b6e52", size = 258390, upload-time = "2026-08-06T13:47:51.248Z" },
+ { url = "https://files.pythonhosted.org/packages/de/36/c1e127616fb3fa18a9ff71e76c417f2fd7424332a4870015ac224ef4c039/coverage-7.15.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d802e1947603162ded419bff83ac7489820355d2b856dfb09206574e3a37ac0c", size = 253894, upload-time = "2026-08-06T13:47:52.816Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/b9/fdb92c8ae7a8bb9b850cc253b7b3b9c8526f68130002048b5671cd510d09/coverage-7.15.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c2de40895718f91951b86712b4c5b694acaf9a0a49be13874896f599a1eed3f4", size = 255763, upload-time = "2026-08-06T13:47:54.296Z" },
+ { url = "https://files.pythonhosted.org/packages/6f/c0/a7d51b2587c7bdb76e71b0896d2565bf7d60436b5122fc83e511adb1f7cd/coverage-7.15.4-cp312-cp312-win32.whl", hash = "sha256:5c3431b2161279b7db5c2a1aa58ae02e5cb8c3c42d93a5094be3f5537bd5b11b", size = 224597, upload-time = "2026-08-06T13:47:56.074Z" },
+ { url = "https://files.pythonhosted.org/packages/49/b9/5c5f80cc55f5acaaca6dee677626bfcec8c87204a7809b438b08e84f4571/coverage-7.15.4-cp312-cp312-win_amd64.whl", hash = "sha256:6befeab5fb2b51c958ca4ac6c5d141a1e8240f4f76e46350f1911963deda49cd", size = 225135, upload-time = "2026-08-06T13:47:57.52Z" },
+ { url = "https://files.pythonhosted.org/packages/47/e4/2a4561f89ff6bf7c925c287d0f2cce8bdf139c3a33735c87e3203401cf94/coverage-7.15.4-cp312-cp312-win_arm64.whl", hash = "sha256:67bc345491ab55b837277d76f5775d057e8c7f1ac44d890d8c2c82adde258c6f", size = 224515, upload-time = "2026-08-06T13:47:58.977Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/84/651a9310859673aaa3b3203f1aa1641ca60fcf2494683e1c9474c7172780/coverage-7.15.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c705b28feb2775dc82a25f1d473a370bc37ff93f5177f4e29ce2425f560f6921", size = 222565, upload-time = "2026-08-06T13:48:00.796Z" },
+ { url = "https://files.pythonhosted.org/packages/82/f9/4dcf700137e8af550670f4d74d1b63828ce93e1e2b05e5f10710eb2ea987/coverage-7.15.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3ff205ab5e3ecc670f6a4dd19d9cbf12ede53dd41cfc1e15716ec961ea6d314e", size = 222936, upload-time = "2026-08-06T13:48:02.391Z" },
+ { url = "https://files.pythonhosted.org/packages/07/4a/612ff1e780b3fbfd637486f542f84adc5503873d8b5d279dec1ffeef9414/coverage-7.15.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5172326e861a38b48b48befca15e0f477a26b283337a33a739c8fed229934e36", size = 253926, upload-time = "2026-08-06T13:48:04.382Z" },
+ { url = "https://files.pythonhosted.org/packages/b0/04/d1cff1c2ead4708a6a79c01d3736b6a25bd38a36678398f72a8dd33dfad9/coverage-7.15.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:12b59c90084e3234fb11184886bf4a40f4f16a8c8f867be2e087b81f8e8868d4", size = 256523, upload-time = "2026-08-06T13:48:05.996Z" },
+ { url = "https://files.pythonhosted.org/packages/b9/80/d34e13fb4b293cbdb9665838cf5522077b8ad14ef947550631a4bced36a5/coverage-7.15.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349062d66f00b40fa2c1c222438bad25fabf755631b5d82937fe985c8008615c", size = 257759, upload-time = "2026-08-06T13:48:08.036Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/e7/2c5fe7636fdb0732fe0f09f308a5b066864078b7fc61f6678e8478554f2e/coverage-7.15.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4256ced708e598e05209bc1a8ab4074e04a51dba4c62fb45926a229af675ace7", size = 259890, upload-time = "2026-08-06T13:48:09.834Z" },
+ { url = "https://files.pythonhosted.org/packages/92/28/9689f0858dfff59c2ea688938ab9fa2925631235df67126a42b6c5c70ae1/coverage-7.15.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d80f974b20782d9612c8b4c9beeca867074c7cf4079d1419843fa25a26428b25", size = 254121, upload-time = "2026-08-06T13:48:11.459Z" },
+ { url = "https://files.pythonhosted.org/packages/f9/e2/785077c230c157243eb5aa9a26c3be260ecd02001bead54a3cada3df8e03/coverage-7.15.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2e179f19bfe1d31f8eeeaa12990194d761c4f62f0759661000bca6cd8729f40b", size = 255891, upload-time = "2026-08-06T13:48:13.209Z" },
+ { url = "https://files.pythonhosted.org/packages/d4/90/e20371b17b40f912f21305c2db2f30efa3de306f7320fc916804872c85a4/coverage-7.15.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8bc16bb47b7679670eceff71d78bfb7d6e5b143f6c2cd117487ec7c75e0d4b78", size = 253859, upload-time = "2026-08-06T13:48:14.736Z" },
+ { url = "https://files.pythonhosted.org/packages/05/49/25371987ee459a5f67c0427fb75c74f9358e65f2c71fe75bf41c1b6c5fcb/coverage-7.15.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1cd685005cd2c4200adfc14cf39a603b9320efab3f18a8f7f156d20c9cc3345f", size = 258011, upload-time = "2026-08-06T13:48:16.464Z" },
+ { url = "https://files.pythonhosted.org/packages/30/6e/32e67467f6154bf4f1c4f63b05acc5097cba4237d45bbeeea446b52e8ac1/coverage-7.15.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:337399ad2c93b3acd2a937627dae8b3e86b66707cd3d3e856347999aadf1ef8d", size = 253676, upload-time = "2026-08-06T13:48:18.493Z" },
+ { url = "https://files.pythonhosted.org/packages/03/c1/8b24192e89286399765155251f99ee9f070a9d637109018ac23d99b99f6f/coverage-7.15.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:96e257121228ec5cd2bb919276e94ac11074471bc37d68dbae0e8308cce15fff", size = 255453, upload-time = "2026-08-06T13:48:20.057Z" },
+ { url = "https://files.pythonhosted.org/packages/16/6f/8b41ebdf67c87854e17c035336a90f1cfbad0c14c2a584301be6ff148718/coverage-7.15.4-cp313-cp313-win32.whl", hash = "sha256:c65a9e0dfc6143491879da4e13b5e30f8be192055de508d737fb14601edbd22c", size = 224605, upload-time = "2026-08-06T13:48:21.655Z" },
+ { url = "https://files.pythonhosted.org/packages/e0/e2/2946c7f0b42b152ecb21ff1bdad72e3d301e790c0c487e4a86e8c9f69347/coverage-7.15.4-cp313-cp313-win_amd64.whl", hash = "sha256:2ff8f5e9b8f7a94f0c11c45631eee103dbcb7d63274edd12c56efe1be690b3b4", size = 225148, upload-time = "2026-08-06T13:48:23.376Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/83/3f4a69957f48ae7a0aba76c34743f88963d607b19e03f3f8e66f91cae0f9/coverage-7.15.4-cp313-cp313-win_arm64.whl", hash = "sha256:6e0a8a5083b096487d6cfced94cdd514d8f5db6f113610fb36c0620edb1028cf", size = 224536, upload-time = "2026-08-06T13:48:25.117Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/d9/e70c286c979378f061d8266e279b686ab0b0b688e1fe0af864684f23a77d/coverage-7.15.4-py3-none-any.whl", hash = "sha256:964730a1e9de9c0cf11be6a1a3c79ce419c34882842abd256086ba4698705e84", size = 214332, upload-time = "2026-08-06T13:50:22.192Z" },
]
[[package]]
@@ -1405,7 +1424,7 @@ wheels = [
[[package]]
name = "huggingface-hub"
-version = "1.26.0"
+version = "1.26.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
@@ -1418,9 +1437,9 @@ dependencies = [
{ name = "tqdm" },
{ name = "typing-extensions" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/82/db/3582597f8be0d34bd6881365a26d390854f12893eabdd62dd36de9df5a47/huggingface_hub-1.26.0.tar.gz", hash = "sha256:c8cd4e2df1ba9402f77fce9b509ec1d52debb502551789473f34016acc14e361", size = 936665, upload-time = "2026-07-30T14:12:04.156Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/89/64/bfe23dab749cb2342e1e13b61c9e684ce46b4d189c7d433cd26f76f52baf/huggingface_hub-1.26.1.tar.gz", hash = "sha256:7c28860777594ac679233f571552d0e46df34ed4e4239e844190fad3ca05e4cd", size = 936700, upload-time = "2026-08-06T09:42:24.859Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/97/bb/63a644c75b545f3ff394b822e9bd1c4a9586489c618b77a4d8a44a33a23b/huggingface_hub-1.26.0-py3-none-any.whl", hash = "sha256:e8cca670caa5d8dfa7e45bf45e86b466698198cd8150c021bcdb4a86b9252364", size = 780357, upload-time = "2026-07-30T14:12:01.998Z" },
+ { url = "https://files.pythonhosted.org/packages/b4/a7/b519cd01e57b685c5f3e9db02cb1bd7aaade35fb6554e0d36bee6d6aae28/huggingface_hub-1.26.1-py3-none-any.whl", hash = "sha256:d8676e4ec96c1e481a22a93232bd86d73bbac643fb767399aefaeaa503890fb0", size = 780754, upload-time = "2026-08-06T09:42:22.497Z" },
]
[[package]]
@@ -1674,37 +1693,41 @@ sdist = { url = "https://files.pythonhosted.org/packages/0e/72/a3add0e4eec4eb9e2
[[package]]
name = "librt"
-version = "0.13.0"
+version = "0.15.0"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/dc/2f/3908645ddddab7120b46295e541ead308109fa48dbec7d67d7a778870d60/librt-0.13.0.tar.gz", hash = "sha256:1d2a610c14ac0d0750ee0a3ab8548e83155258387891caaca04def4bf7289781", size = 211402, upload-time = "2026-07-08T12:26:29.834Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/f0/f4/b2933ddae222dac338476abb872641169a5cfed2c2bb5444a5b07b32b0c3/librt-0.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30536798f4504c0fad0885b1d371b0539abb081e4570c9d7c641cb51141b49f0", size = 150990, upload-time = "2026-07-08T12:25:02.42Z" },
- { url = "https://files.pythonhosted.org/packages/90/ef/db98f744ca50e6efc9c95c70ee49b77aefac31f6a3fc7c83754a42d6a74f/librt-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:93d24ebb82aa4420b1409c389e7857bc35bd0b668007ac8172427d5c73cc8cc5", size = 155238, upload-time = "2026-07-08T12:25:03.681Z" },
- { url = "https://files.pythonhosted.org/packages/03/e7/a197e7bc72baf2c61ce7fdc6906a5054dc05bd8da0819aa894e4857bf87e/librt-0.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb8a1adce42d8b75485a5d56a9623a50bcab995b6079f1dac59fc44034dd93d9", size = 503073, upload-time = "2026-07-08T12:25:05.049Z" },
- { url = "https://files.pythonhosted.org/packages/f8/e7/7887712e27da7c1ab80fcabb1de6eb24243964f6557cae530d4b70706dbd/librt-0.13.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0763ca2ab66058174f9dee426dc64f5e0a89c24a7df8d3fe3f1836c04e25de4b", size = 496528, upload-time = "2026-07-08T12:25:06.26Z" },
- { url = "https://files.pythonhosted.org/packages/94/f0/f2283385bb6b950b26a1410f4ce51ec27231e0b3a4b925c46366d218b198/librt-0.13.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b222493da6e7b6199db9bd79502436cf5a27da3c1f7fa83c7e285444fc93fd03", size = 531786, upload-time = "2026-07-08T12:25:07.658Z" },
- { url = "https://files.pythonhosted.org/packages/36/11/69ac3b54766ffba5fd7e5acebfb048d66dbe1f9f2d14516c2b3edc59cf87/librt-0.13.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fadc63331f4388c3dc90090448f682a7e9feafc11481391c1e94f2f907a3976e", size = 524393, upload-time = "2026-07-08T12:25:09.121Z" },
- { url = "https://files.pythonhosted.org/packages/61/5f/d72f95fd444a926a3c14b4e24979474116988dd57a45be242077c45d3c22/librt-0.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:70d9c62a4cffd9f23396cd5ef93fc5d11b31596b9b7d6306074abe3d5fcf09bd", size = 543026, upload-time = "2026-07-08T12:25:10.459Z" },
- { url = "https://files.pythonhosted.org/packages/c4/08/dcd9993ad192737a004ba263d549f8ea605b326b952e7d6205c7d4170b76/librt-0.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:66c0e7e6b02a155576df2c77ec933a70b72da726e248c494abf690923e624348", size = 546829, upload-time = "2026-07-08T12:25:11.716Z" },
- { url = "https://files.pythonhosted.org/packages/96/d5/6d9bb2f54e4109a956b7128836529653eb9d740f784bc47ed10a02c1000e/librt-0.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ac04bcd3328eb91d99dfedf6a60d9c1f15d3434e6f6daf922f0420f7d90b85c7", size = 535700, upload-time = "2026-07-08T12:25:13.144Z" },
- { url = "https://files.pythonhosted.org/packages/8c/f2/10946922503858a359492fa27f13e86228bde702116a740ac7b3cd185f24/librt-0.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:db327e7271e653c32040b85ae6188059c924b57d7e1e29f935523fa017cd4e82", size = 573566, upload-time = "2026-07-08T12:25:14.336Z" },
- { url = "https://files.pythonhosted.org/packages/48/a8/94f00e3c99479a18088af3685ea016c42f3c7d5d1964d8dbb40c08d7f1aa/librt-0.13.0-cp312-cp312-win32.whl", hash = "sha256:860bd1d8ba48456ce08feaf8d343a8aaeb2fa086f2bcaa2a923fa3f7a3ff9aa3", size = 106099, upload-time = "2026-07-08T12:25:16.159Z" },
- { url = "https://files.pythonhosted.org/packages/c9/7b/2da9c74c1ed25a89cc4e1c8e007ea2eb4a0f1fafa3e70d757fe3242c5c5c/librt-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:e54a315caf843c8d77e388cadc56ea9ded569935ee2d2347d7ea94992e5aa6fa", size = 126934, upload-time = "2026-07-08T12:25:17.275Z" },
- { url = "https://files.pythonhosted.org/packages/d0/65/aead61bbf3b5358593f9d4779d2a0e88eaf6ec191a6342dde36dd1df6371/librt-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:c718e99a0992127af84385378460db624103b559ab260435abcfe77a4e4ed1c1", size = 112236, upload-time = "2026-07-08T12:25:18.425Z" },
- { url = "https://files.pythonhosted.org/packages/67/3b/18e7b63255297a2bdc9c25c8d6d4ca8eca9f63aceb1252c0f7427ac7099e/librt-0.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a468951af16155824e88bdd8326ebe5bdb371f3ec0ac04642994b98201d914f3", size = 151027, upload-time = "2026-07-08T12:25:19.638Z" },
- { url = "https://files.pythonhosted.org/packages/4d/68/e2248452c00d1a03b45fee1752cdc8f790a476efd2402b75181da88a9e61/librt-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ae01d8512cc17079e53425635327dbf3f7ff57a42c00dec348bf79791c56444c", size = 155152, upload-time = "2026-07-08T12:25:20.851Z" },
- { url = "https://files.pythonhosted.org/packages/0e/16/52b1c99bf19057a062aac39c900cbb81499f6f75d6c537c14463d247ba78/librt-0.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32c26893cd085c1efe83219e78d866da23fb20a066101b8f68210004361d224c", size = 502499, upload-time = "2026-07-08T12:25:22.055Z" },
- { url = "https://files.pythonhosted.org/packages/9f/54/b811151805c795f55e0dedee6ec687b75f9982a8105d240ea3910737a77b/librt-0.13.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5929da1981a46bcf4b28b1b9499905f0ff58e2419da402a048234e9783acbc4b", size = 496108, upload-time = "2026-07-08T12:25:23.296Z" },
- { url = "https://files.pythonhosted.org/packages/8f/f8/094d6b2bd93f3fdaa54db54cc788c4a365333bddad65ab02e04da0b1d004/librt-0.13.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:94b85d664d777bab6c0d709416cb42938251fda9e221b79e3a2215d85df5f4f9", size = 531576, upload-time = "2026-07-08T12:25:24.648Z" },
- { url = "https://files.pythonhosted.org/packages/2e/40/541733d5755824f968f7ec39d78ffbd75d145964157ae5e69a09ec6d7326/librt-0.13.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:531b2df3e9fe96b1fcf73a6d165921e4656be5f58d631d384ebce344298368db", size = 524390, upload-time = "2026-07-08T12:25:25.898Z" },
- { url = "https://files.pythonhosted.org/packages/c6/b5/255673cfdbf5ba663339d36cd863c897289ab4337577e19f9405ce059f36/librt-0.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:109b84a9edf69ad89dc1f66358659e14a031baca95e3e5b0060bd903ede8efd6", size = 543053, upload-time = "2026-07-08T12:25:27.436Z" },
- { url = "https://files.pythonhosted.org/packages/9e/11/ab5005e9c9850710f21e354201bf090646349d3fabf5f951eaf70235729e/librt-0.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1304368a3e7ffc3e9db986796cc5326fdb5943a3567ecc137cff318e4240c0e7", size = 546387, upload-time = "2026-07-08T12:25:28.65Z" },
- { url = "https://files.pythonhosted.org/packages/a2/04/a5d7ce1d1df1afd15ca283dcdf7530ac073e12d69ae8c40879dda96f7868/librt-0.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e4f9b472e7d308d94b62c801982065661158c6ed02790d6c7ddb4337cea0f9c1", size = 535970, upload-time = "2026-07-08T12:25:30.171Z" },
- { url = "https://files.pythonhosted.org/packages/5a/76/927e267a6daa290174ac281b23c9804c8829b042ade9c6f24a065f540958/librt-0.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f836c37478f167a81200d8c8b2c920a22224564bed2c23d7aeec760965c367a", size = 573582, upload-time = "2026-07-08T12:25:31.507Z" },
- { url = "https://files.pythonhosted.org/packages/10/24/b6c5213efe39c19f9e13605644d0cf063b4ddaa33ac2e45b088e23a70e2e/librt-0.13.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:4000d961ff9598ac6ea603c6c836a5ed49bc205ade5fc378b998dfe1e2c36628", size = 82189, upload-time = "2026-07-08T12:25:32.675Z" },
- { url = "https://files.pythonhosted.org/packages/4c/00/d29736be177a906ac0b84a5b04b4fbfa22c776dc2f366de4172b0f968c08/librt-0.13.0-cp313-cp313-win32.whl", hash = "sha256:79e44cff71750d299d61a678e49995b0d5935a9cda238c2574daeca3ba536927", size = 106193, upload-time = "2026-07-08T12:25:33.692Z" },
- { url = "https://files.pythonhosted.org/packages/c8/ac/aff6fb45393cb8912f39dfb156ef6b2d1cadb207ff465fc8f66141054be8/librt-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:54dab44a847d5ad1acd05c8a83fe518ae685516ecf4d3f7cc6e3df2a66767650", size = 126962, upload-time = "2026-07-08T12:25:34.769Z" },
- { url = "https://files.pythonhosted.org/packages/d9/3a/d68cb2b334d53fd30fac81d3a489ce4ba0d9506f4df43fcf676b68352b19/librt-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:d4cb6fbfdf874340ab5e51450753c0f817b6958a3621125ee695bbc3de866566", size = 112127, upload-time = "2026-07-08T12:25:35.981Z" },
+sdist = { url = "https://files.pythonhosted.org/packages/36/9b/356320fbae2ac8467e21c5e73e1389c80468e4998c62cc7d3536cc51b614/librt-0.15.0.tar.gz", hash = "sha256:4e66cbe84437497d951b799d3e1551291b6fb3d643820a7014b3655d57a59162", size = 214338, upload-time = "2026-08-07T10:49:42.663Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ba/39/99c25030e782bdfb7a21be8c05254806a2e4bbb05c8d50c2a2130acbfa05/librt-0.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e87bc679f86a99aa3b26e3c78eeb821a247c9a28eae48eaafcc32c3bf4c3bb9e", size = 151021, upload-time = "2026-08-07T10:47:00.057Z" },
+ { url = "https://files.pythonhosted.org/packages/14/43/f4b1bd1b2888798a1409808889a25ea1ba49eaabce7d681ed27734c2df9d/librt-0.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:71599e011ac880e8e45d46047d714871894c7d4ab6f25626f8d4f89da21f368d", size = 155267, upload-time = "2026-08-07T10:47:01.311Z" },
+ { url = "https://files.pythonhosted.org/packages/0c/db/3ad9c965c72f1e1d6beeec44ec10a54e17be8ae042fbb4baade16cbadced/librt-0.15.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c802434092b769b1d613ed2e13fac15fbfce1934a74bd10283b03c0fae231cd1", size = 503136, upload-time = "2026-08-07T10:47:02.45Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/07/5888a6d76acd62ebce66c61b74d94e9370b9c32929f111e487bb6546f8ed/librt-0.15.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5500eeae393a184d14e1f35645962c27129d20c81afa4069e6ef826ebc2b3aaa", size = 496670, upload-time = "2026-08-07T10:47:03.675Z" },
+ { url = "https://files.pythonhosted.org/packages/29/39/ab57cc2f5b276156da02bb7f5a8921bada1cb1993ffec99acf811c602c23/librt-0.15.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6ecfc32dfb46fb7b565bcd6abf9412acf978775a998273d22888a6d7953730dd", size = 513688, upload-time = "2026-08-07T10:47:04.981Z" },
+ { url = "https://files.pythonhosted.org/packages/a7/b9/bdbb0b648b5c2befb031f4c6f3b1dd857415e8fb492a25a3c764a6681e6c/librt-0.15.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89cc46cfd15022e35084355478c9ac809d90b1152222706ac9a7655ec21df6fa", size = 531904, upload-time = "2026-08-07T10:47:06.211Z" },
+ { url = "https://files.pythonhosted.org/packages/93/26/473c2e4b6c104e9e58e27ce95fc8005c8bd4fc36cae4f254371125a92db8/librt-0.15.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d5f51401d102c885b9ca509e62c79b1dbff286e1b9b047fde6f763780789356d", size = 524427, upload-time = "2026-08-07T10:47:07.592Z" },
+ { url = "https://files.pythonhosted.org/packages/26/60/03b3abb82b41714671b907bf6989b228e31e6a8af52dec82b5b0728dc250/librt-0.15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cc30523e3f1a23fb7511cc659834a0d01a1042bb9de359bc1c131cc4ec6c9656", size = 543155, upload-time = "2026-08-07T10:47:08.866Z" },
+ { url = "https://files.pythonhosted.org/packages/f2/0e/9bb1f0a4affbd0a1888f4f79dc03ed2a299d9a2c26c59ab2a97dcbf11903/librt-0.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:59fe030d8ae4a57e3fb7756bf35a858de74e04066fc8555c53d0af979132af81", size = 546890, upload-time = "2026-08-07T10:47:10.327Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/84/6937a280d461f7de6e031ffb02edc2b7c3c90d49d630565ce8ff27cbc5f2/librt-0.15.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5a6526a2a956bbb1e4ae3568c82e650fc99119c66bb011ea60715744955a2b4d", size = 555163, upload-time = "2026-08-07T10:47:11.798Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/95/2a2853c1ee014bf102116e7f897a04beeaeb2461b45b79af98bdfb95f1ef/librt-0.15.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:85ea21ec6730194d67156b0e0b5430ccb1d61f8b8b907e39b37f9812b74a13f0", size = 535812, upload-time = "2026-08-07T10:47:13.279Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/4c/cf9601c1b4c5f09280acd5d83abdb2e68527a2be8257136eb42304218622/librt-0.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1e47b8ba865d7ede071a91a7163073bbaeb72541f1ef8a07d512c45c7b5007f2", size = 573688, upload-time = "2026-08-07T10:47:14.727Z" },
+ { url = "https://files.pythonhosted.org/packages/47/6d/9ac7cbec46189a7625af4b5acbd25f10d827f4141b2002181848c8418923/librt-0.15.0-cp312-cp312-win32.whl", hash = "sha256:a5207ec414d1c4a2a7231b2086970dc036f94293cdf338190984958a013a42f1", size = 106138, upload-time = "2026-08-07T10:47:15.973Z" },
+ { url = "https://files.pythonhosted.org/packages/38/d0/2ae99c83be86ce23f925ac1aeeedc777e97f427c4a8d190c70d0a16e9a87/librt-0.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:73b30cfa976659b3917c8f6153bdb0591c6a9ec6583599fd24a689b690622022", size = 126974, upload-time = "2026-08-07T10:47:17.049Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/ef/dd24f9635c730b86b87587967dda7516b1845e8b17684603d31607fed598/librt-0.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:a54cf9e0ef47b96af580849db5471142200568ce1e02cbf416addab551369570", size = 112292, upload-time = "2026-08-07T10:47:18.222Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/42/467b53a601b406ccd7b97c1fd54b59cb34f9185ad5ce7e9d5c3c4e8961c8/librt-0.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:db13ca398005abcbe538deda87b686d9bd08b7001cf40c4c06b444960ae10a26", size = 151029, upload-time = "2026-08-07T10:47:19.312Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/e6/36c2299b7a94b84fdd01220d8a777a71be5be0925bb0dbdf71c0a06a34d9/librt-0.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa1f1995789dca3698bc550aaceb09a51bd5df0a057ff84ff15296cd1975b801", size = 155194, upload-time = "2026-08-07T10:47:20.398Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/b6/ed5071f9325845e670bd36012757419767fbf56af77ed483077b9e4db541/librt-0.15.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55456ea87d8df21808446d03817be2f65e20391c1c615d9187440dff28cd08dc", size = 502568, upload-time = "2026-08-07T10:47:21.652Z" },
+ { url = "https://files.pythonhosted.org/packages/7f/81/6450c67c3615d87704bcbc21323fafc69c799b06a044c447529f725d4b01/librt-0.15.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5a86a5a08c2235316bdb359d5dbb6ce0abfca7fac06363103e2c5af571d92f95", size = 496153, upload-time = "2026-08-07T10:47:22.925Z" },
+ { url = "https://files.pythonhosted.org/packages/e1/d6/5f52b722bc75076954b3bfd49be15ea362df4d580c6fb315d0f617100d30/librt-0.15.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e56b6a368529bed262da40ce13f8fef590db0479819cca84f16a1f01ac356d0b", size = 513336, upload-time = "2026-08-07T10:47:24.213Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/e2/c08fd1d36ce63ea5a12b85c5d37f4550b5f86a692167e41e5a74222607ae/librt-0.15.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:234d8d394721fa0d786af15ebf1f3fb7f3ed82fd1cd0cde45c2f247b5d4281d2", size = 531661, upload-time = "2026-08-07T10:47:25.507Z" },
+ { url = "https://files.pythonhosted.org/packages/3f/d8/d9482fcbeb177b9eb87bb3899eeb3b42be690313c652f9e146b1d0681fb2/librt-0.15.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d8363d7accb0286ac3a0e633f396e93800dafb8150494505daf9515bbda591f3", size = 524487, upload-time = "2026-08-07T10:47:26.79Z" },
+ { url = "https://files.pythonhosted.org/packages/10/cc/075171517b41f861753034fbb151b42cfc83bcc853849f24f5e66fd60ccf/librt-0.15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0f0ee3644d951f31055ad07d77d92520e84505dd7a432cc4cd501dd70ee06785", size = 543201, upload-time = "2026-08-07T10:47:27.999Z" },
+ { url = "https://files.pythonhosted.org/packages/b0/03/42c2330f37eeb475b6affeedd06518f60035f323af3a839335e3fc9fef2d/librt-0.15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2cfd1a81a648806e6a7717be4cc4d1bb392fa229752bf8444ba365e381e984d6", size = 546467, upload-time = "2026-08-07T10:47:29.396Z" },
+ { url = "https://files.pythonhosted.org/packages/57/1e/1ad4c5638f7e64d8560328bd25c54b409a661bdb6ff254b38ff90744288d/librt-0.15.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a6cd22c9da0d866558e46a041f1cc0c2bbb26b61b137b2347fa834c332e1d101", size = 555139, upload-time = "2026-08-07T10:47:30.815Z" },
+ { url = "https://files.pythonhosted.org/packages/49/41/39fa7d15db1204cd1cbe6514680fbdc243adf754a0885061308f43afc013/librt-0.15.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:6d5225ef8801e4ea5e482fa9b5dfb891dd9ef6f6d870f1f25d449ca2c70ac218", size = 536050, upload-time = "2026-08-07T10:47:32.222Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/88/c6dcf0dd8e26dc0c9a499a2abab8646c86dcaf9ecea9524cb46d3686331a/librt-0.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d28a05796b99f749bf8794f17ba9ba1612d0076b802e9cfc62c554634e9ce3b", size = 573700, upload-time = "2026-08-07T10:47:33.527Z" },
+ { url = "https://files.pythonhosted.org/packages/1b/9b/ab54c71a7918a7c34fa5327fb61390a77446a07a146fbfb1165250a61035/librt-0.15.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:2067ff438048cead9d223ca5675bae2a25e520a7c3e6c1498bf9c6892d22caab", size = 82194, upload-time = "2026-08-07T10:47:34.835Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/b2/4f9a243bb892395f3becb80789ade13771701091f9f07ab8230247953ba8/librt-0.15.0-cp313-cp313-win32.whl", hash = "sha256:1cd3b721f24c206398b9e26da3c3a9c011e6e89d06f318ba8ebefc30f1003890", size = 106231, upload-time = "2026-08-07T10:47:36.251Z" },
+ { url = "https://files.pythonhosted.org/packages/bf/af/64aff4885a40b93132382f2c314647d722574605416504379184ef3045ea/librt-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:f395a4a9a03ac062dbe9a9f82e0c720502e590a38feee6a757bc82e9c63afbd8", size = 126996, upload-time = "2026-08-07T10:47:37.453Z" },
+ { url = "https://files.pythonhosted.org/packages/27/83/335bccf6c7cb9028cb0b54aead27d9ece3f01f83bc6baa2abace5da655c1/librt-0.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:0a15cb554761247d84a3ec0cbdf4078d70725384f0e4662c0fa3b26266eb60ad", size = 112188, upload-time = "2026-08-07T10:47:38.729Z" },
]
[[package]]
@@ -3132,14 +3155,14 @@ email = [
[[package]]
name = "pydantic-ai"
-version = "2.25.0"
+version = "2.26.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic-ai-slim", extra = ["anthropic", "cli", "evals", "google", "logfire", "mcp", "openai", "retries", "web"] },
]
-sdist = { url = "https://files.pythonhosted.org/packages/a7/40/11ab48d76c77ca6a62f19a5bdd79dd80cc723ad244f576b0f6c8dafe4368/pydantic_ai-2.25.0.tar.gz", hash = "sha256:0190165b01d8f101b5c4c5c4e610a088aed6946b220ca6d55474a67d118a4e47", size = 19393, upload-time = "2026-08-06T03:20:30.654Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/cd/2c/58a3d3d21adc76012cb4c46d4da18c19a60c761cb57e2894729338f4f181/pydantic_ai-2.26.0.tar.gz", hash = "sha256:f04585e1b16047e17bfeda8ce5d5f5b549fa3567a000ee2e1f012ac5cc893ccf", size = 19394, upload-time = "2026-08-07T03:34:17.274Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/45/5b/98d26f8bf01cbb6ff3f8ff10e972d6ca58523b0b03a20e9c5ab245275db0/pydantic_ai-2.25.0-py3-none-any.whl", hash = "sha256:991490b3ceaa258204bbca7749a1da4786b53b29cc5f09b56cc56604023c0c11", size = 7742, upload-time = "2026-08-06T03:20:21.542Z" },
+ { url = "https://files.pythonhosted.org/packages/af/71/1cf95a9336a77964a9e40d8a99f4dafcbcc7b7aefbee9d43c62e11016b9e/pydantic_ai-2.26.0-py3-none-any.whl", hash = "sha256:1d2324407ed6c206b4c21436059c651051b836fa443b14165236ea9e53379c10", size = 7744, upload-time = "2026-08-07T03:34:08.258Z" },
]
[[package]]
@@ -3158,7 +3181,7 @@ wheels = [
[[package]]
name = "pydantic-ai-slim"
-version = "2.25.0"
+version = "2.26.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -3170,9 +3193,9 @@ dependencies = [
{ name = "pydantic-graph" },
{ name = "typing-inspection" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/e1/ec/6e186e59a9beede41a9e347f69bd61a833de724aad8a175da8da088d220a/pydantic_ai_slim-2.25.0.tar.gz", hash = "sha256:4f5a36f29e2b346d4b793bf3b983aba17ec19f24015bb811ee40815e98155417", size = 974671, upload-time = "2026-08-06T03:20:33.01Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/4f/51/dc39f52dd38c8bf7d8ad6601a936d22064c935505a897c1bf5060e278c95/pydantic_ai_slim-2.26.0.tar.gz", hash = "sha256:d41a40a976885d5f9c6848552fcd6732d5daa8294faf4d3e0138fb28118b6734", size = 1004525, upload-time = "2026-08-07T03:34:19.129Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/04/46/e168f03ec04a933b6b0ff3e02c7e608c24da8efb03d0e1f4d0b486bfef09/pydantic_ai_slim-2.25.0-py3-none-any.whl", hash = "sha256:9b69d1af463a63a88ea3c3567b38a09e8208efe73a36c8f5d5d5515939a88acd", size = 1169288, upload-time = "2026-08-06T03:20:24.91Z" },
+ { url = "https://files.pythonhosted.org/packages/9f/ac/e09eb468ccec3180f73828b1e0c59b891cc9ee442be2d28410b02c1d09a3/pydantic_ai_slim-2.26.0-py3-none-any.whl", hash = "sha256:855a23f120328e7a12e8f4371db597d74f65925e20ce335d3a6db81203238f58", size = 1201143, upload-time = "2026-08-07T03:34:11.305Z" },
]
[package.optional-dependencies]
@@ -3258,7 +3281,7 @@ wheels = [
[[package]]
name = "pydantic-evals"
-version = "2.25.0"
+version = "2.26.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -3268,14 +3291,14 @@ dependencies = [
{ name = "pyyaml" },
{ name = "rich" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/37/42/84a86b00c710b84c1cd1afbde43b67888437f5068ab7a887a6400301e6c9/pydantic_evals-2.25.0.tar.gz", hash = "sha256:11780b167271a5a0b6cb51e8972cb8cae9c275358b14fba6a4cf79d8a01d702d", size = 85392, upload-time = "2026-08-06T03:20:34.256Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/88/40/abc913aa36099fb180b906de48ac6101c16b7c90281a4d5a66031931e2d3/pydantic_evals-2.26.0.tar.gz", hash = "sha256:b5bcac364042d18a028b9e747c1f930f171706c23cab50473c769e053b43a4c0", size = 85389, upload-time = "2026-08-07T03:34:20.983Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/db/b1/eff104fe60e6ab5b488778e78d7c9bbd481bd3820cda4c6124df949d0c6c/pydantic_evals-2.25.0-py3-none-any.whl", hash = "sha256:54f6df9aa30bbe1597f93e65607ba77d76aef0cd9d6804c9f740d909a55769ab", size = 100539, upload-time = "2026-08-06T03:20:26.69Z" },
+ { url = "https://files.pythonhosted.org/packages/7c/bb/a9d6700db4152b8442639b1d75249c3543ac4f4c76ba83ac6628c97a1fc2/pydantic_evals-2.26.0-py3-none-any.whl", hash = "sha256:41f92eee7270dbb85e6639082256ff14877c1f0bba0d7dda30e683efb6555e0d", size = 100539, upload-time = "2026-08-07T03:34:13.188Z" },
]
[[package]]
name = "pydantic-graph"
-version = "2.25.0"
+version = "2.26.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -3284,23 +3307,23 @@ dependencies = [
{ name = "pydantic" },
{ name = "typing-inspection" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/e9/a0/78b22670f9c9608939a27c9de647dba28b6fca864f8883db30f34832ab9b/pydantic_graph-2.25.0.tar.gz", hash = "sha256:1e1d61556ec0d5fdc02d307380f6ad4ac96d0bba9e5eac0881bae42466d3db8a", size = 45179, upload-time = "2026-08-06T03:20:35.284Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/39/64/05bf73d982dd778b5613ad224a58ca510aaccf622644d97af93e6006a680/pydantic_graph-2.26.0.tar.gz", hash = "sha256:12d9da6c5a0e2634d89f2795ca15783ee37250fdc295b33b5c14232576dafdac", size = 45181, upload-time = "2026-08-07T03:34:22.049Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/d1/45/e3f93b1a33fea3e3989de9491a57a69bd93aae0c5b9137f05113e752a8ef/pydantic_graph-2.25.0-py3-none-any.whl", hash = "sha256:87017851610746f76463b0b1fd257286425f3b4feac1fd17e50b0370ae76c2cf", size = 52661, upload-time = "2026-08-06T03:20:28.332Z" },
+ { url = "https://files.pythonhosted.org/packages/bb/59/54302729598308ba437e250473c99ef51625e86997f7ae2ba6b61a2ad00f/pydantic_graph-2.26.0-py3-none-any.whl", hash = "sha256:4599a980747588faf17ac56cfa9c10b2a79723a5a20c3c7ee479e8366653097c", size = 52662, upload-time = "2026-08-07T03:34:14.831Z" },
]
[[package]]
name = "pydantic-settings"
-version = "2.14.2"
+version = "2.15.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic" },
{ name = "python-dotenv" },
{ name = "typing-inspection" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/5c/b5/8f48e906c3e0205276e8bd8cb7512217a87b2685304d64be27cad5b3019f/pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f", size = 237700, upload-time = "2026-06-19T13:44:56.324Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/68/ca/31c57507b13119d7d3cfa1576dad2911a4861e3be07b579395f4e9d393f9/pydantic_settings-2.15.0.tar.gz", hash = "sha256:694b793e84f766ba76a90ebdefc01d0a9a045dab0382bee70393da93712ad117", size = 261253, upload-time = "2026-08-07T09:24:57.419Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/77/c1/6e422f34e569cf8e18df68d1939c81c099d2b61e4f7d9621c8a77560799c/pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440", size = 61715, upload-time = "2026-06-19T13:44:55.02Z" },
+ { url = "https://files.pythonhosted.org/packages/30/a4/2bffa9f8e804325a09867f0e9d30795c80ea9f8d62560bd1b6ad6220eb2f/pydantic_settings-2.15.0-py3-none-any.whl", hash = "sha256:0ba092c291c94baceb5eff768aa0d56400a457585bc0175925a5a5510303da42", size = 69413, upload-time = "2026-08-07T09:24:55.839Z" },
]
[[package]]
@@ -3358,11 +3381,11 @@ wheels = [
[[package]]
name = "pypdf"
-version = "6.14.2"
+version = "6.15.0"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/03/72/7dfd5ff1c9c37de97a731701f51af091325f123d9d4270361c9c69e4431f/pypdf-6.14.2.tar.gz", hash = "sha256:7873f502fe4385e79539b21d872392dc0c4e3714327c15881cbc7fbfd1f95b25", size = 6491182, upload-time = "2026-06-23T14:18:30.859Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/17/17/ee75a92718ec7212de831e71454d702225aa5e474a805cce169806044453/pypdf-6.15.0.tar.gz", hash = "sha256:d39c4d955a76409284a905e2d65b40076d77ab76129e0faaeeb6612403ecfc79", size = 6993794, upload-time = "2026-08-06T13:06:49.929Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/49/e6/136aa8993a2ae7214e0b0ef2edaa0d2e08d1d4e4982635b08a835ff31ec8/pypdf-6.14.2-py3-none-any.whl", hash = "sha256:3f07891af76dc002657e04993ab9b4de81de29f9013b9761d0b7968bff12e946", size = 349514, upload-time = "2026-06-23T14:18:28.867Z" },
+ { url = "https://files.pythonhosted.org/packages/af/72/ce3067ac31e214a66388159f8462ddb8c13dd00170f24d555a1f1ae8ee91/pypdf-6.15.0-py3-none-any.whl", hash = "sha256:14e001d6504822cb1ca9c7ed9a69bccb320f59b320730f55af804361abe4d5ee", size = 378123, upload-time = "2026-08-06T13:06:47.709Z" },
]
[[package]]
@@ -3915,22 +3938,23 @@ wheels = [
[[package]]
name = "sentence-transformers"
-version = "5.6.1"
+version = "5.7.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "huggingface-hub" },
{ name = "numpy" },
{ name = "scikit-learn" },
{ name = "scipy" },
+ { name = "tokenizers" },
{ name = "torch", version = "2.11.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "sys_platform == 'darwin'" },
{ name = "torch", version = "2.11.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "sys_platform != 'darwin'" },
{ name = "tqdm" },
{ name = "transformers" },
{ name = "typing-extensions" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/75/80/573ab31b77bdfa8f18051188adff3405e928386287cd6f756eff5777dd82/sentence_transformers-5.6.1.tar.gz", hash = "sha256:16af5d682ef66672b076d58599a23905800e850ec2bfb1865938306bf684ad72", size = 452185, upload-time = "2026-07-23T14:40:41.589Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/9d/59/867381b1414a975da6c9953f48a07c05cb0629305e2d37c9bcc9764367b2/sentence_transformers-5.7.0.tar.gz", hash = "sha256:fd8c8fc35e6323631dff9f3760969ebf7980dc3cfda0ab1354bc6a774cc0e5d8", size = 466382, upload-time = "2026-08-06T12:12:33.371Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/c1/ad/8f73f512dc7ad4031d2b64cbb67f70bdfb355756afbe0db610a5146415c1/sentence_transformers-5.6.1-py3-none-any.whl", hash = "sha256:cefbb17b6325a982a4732c8c49fb013375392687049d1de3d435c4b04060680b", size = 596677, upload-time = "2026-07-23T14:40:40.312Z" },
+ { url = "https://files.pythonhosted.org/packages/e8/c8/f63d99e354532f5b83e735dd1e001bda92495fbfde934f65d924abf2b071/sentence_transformers-5.7.0-py3-none-any.whl", hash = "sha256:b78141da3d8137e70d965866e2ca43190b9266f3d4d8752e250ded75e7136730", size = 611333, upload-time = "2026-08-06T12:12:31.881Z" },
]
[[package]]
From 3ff89978e1ed2f0bfc6431554567032e440f3e42 Mon Sep 17 00:00:00 2001
From: John Boos <45039134+jrobertboos@users.noreply.github.com>
Date: Fri, 7 Aug 2026 17:14:31 -0400
Subject: [PATCH 056/197] LCORE-2952: updated pipelines (#2355)
* updated pipelines
* updated integration tests pipelines
---
.../lightspeed-stack-integration-test.yaml | 14 +-
.../lightspeed-stack-rhelai-test.yaml | 14 +-
.../lightspeed-stack-0-7-pull-request.yaml | 680 ------------------
.tekton/lightspeed-stack-0-7-push.yaml | 677 -----------------
.../lightspeed-stack-0-8-pull-request.yaml | 142 +++-
.tekton/lightspeed-stack-0-8-push.yaml | 149 +++-
6 files changed, 269 insertions(+), 1407 deletions(-)
delete mode 100644 .tekton/lightspeed-stack-0-7-pull-request.yaml
delete mode 100644 .tekton/lightspeed-stack-0-7-push.yaml
diff --git a/.tekton/integration-tests/pipeline/lightspeed-stack-integration-test.yaml b/.tekton/integration-tests/pipeline/lightspeed-stack-integration-test.yaml
index 3919ae64e..3f58d8e58 100644
--- a/.tekton/integration-tests/pipeline/lightspeed-stack-integration-test.yaml
+++ b/.tekton/integration-tests/pipeline/lightspeed-stack-integration-test.yaml
@@ -2,7 +2,7 @@
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
- name: lightspeed-stack-0-7-integration-tests-pipeline
+ name: lightspeed-stack-0-8-integration-tests-pipeline
spec:
description: |
This pipeline automates the process of running end-to-end tests for Lightspeed Stack
@@ -12,7 +12,7 @@ spec:
params:
- name: SNAPSHOT
description: 'The JSON string representing the snapshot of the application under test (includes lightspeed-stack image).'
- default: '{"components": [{"name":"lightspeed-stack-0-7", "containerImage": "quay.io/example/lightspeed-stack-0-7:latest"}]}'
+ default: '{"components": [{"name":"lightspeed-stack-0-8", "containerImage": "quay.io/example/lightspeed-stack-0-8:latest"}]}'
type: string
- name: llama-stack-image
description: 'Llama Stack runs from source on UBI (init container clones repo and installs deps). Kept for logging/backwards compatibility.'
@@ -20,7 +20,7 @@ spec:
type: string
- name: test-name
description: 'The name of the test corresponding to a defined Konflux integration test.'
- default: 'lightspeed-stack-0-7-e2e-tests'
+ default: 'lightspeed-stack-0-8-e2e-tests'
- name: namespace
description: 'Namespace to run tests in'
default: 'lightspeed-stack'
@@ -117,8 +117,8 @@ spec:
description: "commit sha to be used to store artifacts"
script: |
dnf -y install jq
- echo -n "$(jq -r --arg n "lightspeed-stack-0-7" '.components[] | select(.name == $n) | .containerImage // ""' <<< "$SNAPSHOT")" > $(step.results.lightspeed-stack-image.path)
- echo -n "$(jq -r --arg n "lightspeed-stack-0-7" '.components[] | select(.name == $n) | .source.git.revision // "latest"' <<< "$SNAPSHOT")" > $(step.results.commit.path)
+ echo -n "$(jq -r --arg n "lightspeed-stack-0-8" '.components[] | select(.name == $n) | .containerImage // ""' <<< "$SNAPSHOT")" > $(step.results.lightspeed-stack-image.path)
+ echo -n "$(jq -r --arg n "lightspeed-stack-0-8" '.components[] | select(.name == $n) | .source.git.revision // "latest"' <<< "$SNAPSHOT")" > $(step.results.commit.path)
- name: echo-integration-params
description: Echo all params passed to lightspeed-stack-integration-tests for verification before the test runs.
runAfter:
@@ -281,8 +281,8 @@ spec:
tar -xzf oc.tar.gz && chmod +x kubectl oc && mv oc kubectl /usr/local/bin/
echo "[e2e] 4/8 SNAPSHOT (length ${#SNAPSHOT} chars; clone URL fixed — SNAPSHOT is main/upstream, not fork)..."
# Fixed fork + branch: Konflux SNAPSHOT points at main repo/rev, not the PR/fork under test.
- REPO_URL=$(jq -r '.components[] | select(.name == "lightspeed-stack-0-7") | .source.git.url // "https://github.com/lightspeed-core/lightspeed-stack.git"' <<< "$SNAPSHOT")
- REPO_REV=$(jq -r '.components[] | select(.name == "lightspeed-stack-0-7") | .source.git.revision // "main"' <<< "$SNAPSHOT")
+ REPO_URL=$(jq -r '.components[] | select(.name == "lightspeed-stack-0-8") | .source.git.url // "https://github.com/lightspeed-core/lightspeed-stack.git"' <<< "$SNAPSHOT")
+ REPO_REV=$(jq -r '.components[] | select(.name == "lightspeed-stack-0-8") | .source.git.revision // "main"' <<< "$SNAPSHOT")
echo "[e2e] 5/8 Clone $REPO_URL @ $REPO_REV"
git clone -q "$REPO_URL" /workspace/lightspeed-stack
cd /workspace/lightspeed-stack && git fetch origin "$REPO_REV" && git checkout -q "$REPO_REV"
diff --git a/.tekton/integration-tests/pipeline/lightspeed-stack-rhelai-test.yaml b/.tekton/integration-tests/pipeline/lightspeed-stack-rhelai-test.yaml
index b075142c7..0cd3fd698 100644
--- a/.tekton/integration-tests/pipeline/lightspeed-stack-rhelai-test.yaml
+++ b/.tekton/integration-tests/pipeline/lightspeed-stack-rhelai-test.yaml
@@ -2,7 +2,7 @@
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
- name: lightspeed-stack-0-7-rhelai-tests-pipeline
+ name: lightspeed-stack-0-8-rhelai-tests-pipeline
spec:
description: |
This pipeline provisions a RHEL AI instance on AWS (vLLM), an ephemeral
@@ -11,11 +11,11 @@ spec:
params:
- name: SNAPSHOT
description: 'The JSON string representing the snapshot of the application under test.'
- default: '{"components": [{"name":"lightspeed-stack-0-7", "containerImage": "quay.io/example/lightspeed-stack-0-7:latest"}]}'
+ default: '{"components": [{"name":"lightspeed-stack-0-8", "containerImage": "quay.io/example/lightspeed-stack-0-8:latest"}]}'
type: string
- name: test-name
description: 'The name of the test corresponding to a defined Konflux integration test.'
- default: 'lightspeed-stack-0-7-rhelai-tests'
+ default: 'lightspeed-stack-0-8-rhelai-tests'
- name: rhelai-version
description: 'RHEL AI version to provision.'
default: '3.4.0'
@@ -285,8 +285,8 @@ spec:
type: string
script: |
dnf -y install jq
- echo -n "$(jq -r --arg n "lightspeed-stack-0-7" '.components[] | select(.name == $n) | .containerImage // ""' <<< "$SNAPSHOT")" > $(step.results.lightspeed-stack-image.path)
- echo -n "$(jq -r --arg n "lightspeed-stack-0-7" '.components[] | select(.name == $n) | .source.git.revision // "latest"' <<< "$SNAPSHOT")" > $(step.results.commit.path)
+ echo -n "$(jq -r --arg n "lightspeed-stack-0-8" '.components[] | select(.name == $n) | .containerImage // ""' <<< "$SNAPSHOT")" > $(step.results.lightspeed-stack-image.path)
+ echo -n "$(jq -r --arg n "lightspeed-stack-0-8" '.components[] | select(.name == $n) | .source.git.revision // "latest"' <<< "$SNAPSHOT")" > $(step.results.commit.path)
# ── Full E2E tests (runs after both RHEL AI and OpenShift are ready) ──
- name: rhelai-e2e-tests
@@ -406,8 +406,8 @@ spec:
curl -sL -o oc.tar.gz https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/latest-4.19/openshift-client-linux-amd64-rhel9.tar.gz
tar -xzf oc.tar.gz && chmod +x kubectl oc && mv oc kubectl /usr/local/bin/
echo "[e2e] 4/8 VLLM_URL=$VLLM_URL"
- REPO_URL=$(jq -r '.components[] | select(.name == "lightspeed-stack-0-7") | .source.git.url // "https://github.com/lightspeed-core/lightspeed-stack.git"' <<< "$SNAPSHOT")
- REPO_REV=$(jq -r '.components[] | select(.name == "lightspeed-stack-0-7") | .source.git.revision // "main"' <<< "$SNAPSHOT")
+ REPO_URL=$(jq -r '.components[] | select(.name == "lightspeed-stack-0-8") | .source.git.url // "https://github.com/lightspeed-core/lightspeed-stack.git"' <<< "$SNAPSHOT")
+ REPO_REV=$(jq -r '.components[] | select(.name == "lightspeed-stack-0-8") | .source.git.revision // "main"' <<< "$SNAPSHOT")
echo "[e2e] 5/8 Clone $REPO_URL @ $REPO_REV"
git clone -q "$REPO_URL" /workspace/lightspeed-stack
cd /workspace/lightspeed-stack && git fetch origin "$REPO_REV" && git checkout -q "$REPO_REV"
diff --git a/.tekton/lightspeed-stack-0-7-pull-request.yaml b/.tekton/lightspeed-stack-0-7-pull-request.yaml
deleted file mode 100644
index e27eea079..000000000
--- a/.tekton/lightspeed-stack-0-7-pull-request.yaml
+++ /dev/null
@@ -1,680 +0,0 @@
-apiVersion: tekton.dev/v1
-kind: PipelineRun
-metadata:
- annotations:
- build.appstudio.openshift.io/repo: https://github.com/lightspeed-core/lightspeed-stack?rev={{revision}}
- build.appstudio.redhat.com/commit_sha: '{{revision}}'
- build.appstudio.redhat.com/pull_request_number: '{{pull_request_number}}'
- build.appstudio.redhat.com/target_branch: '{{target_branch}}'
- pipelinesascode.tekton.dev/cancel-in-progress: "true"
- pipelinesascode.tekton.dev/max-keep-runs: "3"
- pipelinesascode.tekton.dev/on-cel-expression: event == "pull_request" && target_branch == "main"
- creationTimestamp:
- labels:
- appstudio.openshift.io/application: lightspeed-core-0-7
- appstudio.openshift.io/component: lightspeed-stack-0-7
- pipelines.appstudio.openshift.io/type: build
- name: lightspeed-stack-0-7-on-pull-request
- namespace: lightspeed-core-tenant
-spec:
- params:
- - name: git-url
- value: '{{source_url}}'
- - name: revision
- value: '{{revision}}'
- - name: output-image
- value: quay.io/redhat-user-workloads/lightspeed-core-tenant/lightspeed-stack-0-7:on-pr-{{revision}}
- - name: image-expires-after
- value: 5d
- - name: build-platforms
- value:
- - linux/x86_64
- - linux-c6gd2xlarge/arm64
- - name: build-source-image
- value: 'true'
- - name: prefetch-input
- value: |
- [
- {
- "type": "rpm",
- "path": ".konflux"
- },
- {
- "type": "generic",
- "path": ".konflux"
- },
- {
- "type": "pip",
- "path": ".konflux",
- "requirements_files": [
- "requirements.hashes.wheel.txt",
- "requirements.hashes.source.txt",
- "requirements.hermetic.txt"
- ],
- "requirements_build_files": ["requirements-build.txt"],
- "binary": {
- "packages": "a2a-sdk,accelerate,aiofile,aiohappyeyeballs,aiohttp,aiosignal,aiosqlite,annotated-doc,annotated-types,anthropic,anyio,argcomplete,asyncpg,attrs,authlib,autoevals,azure-core,azure-identity,beartype,cachetools,caio,certifi,cffi,chardet,charset-normalizer,chevron,click,cryptography,datasets,defusedxml,dill,distro,dnspython,docstring-parser,durationpy,einops,email-validator,emoji,exceptiongroup,executing,faiss-cpu,fastapi,fastmcp-slim,fastuuid,filelock,fire,frozenlist,fsspec,genai-prices,google-api-core,google-auth,google-cloud-core,google-cloud-storage,google-crc32c,google-genai,google-resumable-media,googleapis-common-protos,greenlet,griffelib,grpc-google-iam-v1,grpcio,grpcio-status,h11,hf-xet,httpcore,httpcore2,httpx,httpx-sse,httpx2,huggingface-hub,idna,importlib-metadata,jaraco-classes,jaraco-context,jaraco-functools,jeepney,jinja2,jiter,joblib,joserfc,jsonpath-ng,jsonschema,jsonschema-specifications,keyring,kubernetes,langdetect,litellm,logfire,logfire-api,markdown-it-py,markupsafe,maturin,mcp,mdurl,more-itertools,mpmath,msal,msal-extensions,multidict,multiprocess,narwhals,networkx,nltk,numpy,oauthlib,ogx,ogx-api,ogx-client,openai,opentelemetry-api,opentelemetry-distro,opentelemetry-exporter-otlp,opentelemetry-exporter-otlp-proto-common,opentelemetry-exporter-otlp-proto-grpc,opentelemetry-exporter-otlp-proto-http,opentelemetry-instrumentation,opentelemetry-instrumentation-httpx,opentelemetry-proto,opentelemetry-sdk,opentelemetry-semantic-conventions,opentelemetry-util-http,oracledb,packaging,pandas,peft,pip,platformdirs,polyleven,prometheus-client,prompt-toolkit,propcache,proto-plus,protobuf,psutil,psycopg2-binary,py-key-value-aio,pyaml,pyarrow,pyasn1,pyasn1-modules,pycparser,pydantic,pydantic-ai,pydantic-ai-slim,pydantic-core,pydantic-evals,pydantic-graph,pydantic-settings,pygments,pyjwt,pyopenssl,pypdf,pyperclip,python-dateutil,python-dotenv,python-multipart,pytz,pyyaml,referencing,regex,requests,requests-oauthlib,rich,rpds-py,safetensors,scikit-learn,scipy,secretstorage,semver,sentence-transformers,sentry-sdk,setuptools,shellingham,six,sniffio,sqlalchemy,sse-starlette,starlette,structlog,sympy,tenacity,termcolor,threadpoolctl,tiktoken,tokenizers,torch,tornado,tqdm,transformers,tree-sitter,triton,trl,truststore,typer,typing-extensions,typing-inspection,urllib3,uv,uv-build,uvicorn,wcwidth,websocket-client,websockets,wrapt,xxhash,yarl,zipp,zstandard",
- "os": "linux",
- "arch": "x86_64,aarch64",
- "py_version": 312
- }
- }
- ]
- - name: hermetic
- value: 'true'
- - name: dockerfile
- value: deploy/lightspeed-stack/Containerfile
- - name: build-args-file
- value: .konflux/build-args-konflux.conf
- pipelineSpec:
- description: |
- This pipeline is ideal for building multi-arch container images from a Containerfile while maintaining trust after pipeline customization.
-
- _Uses `buildah` to create a multi-platform container image leveraging [trusted artifacts](https://konflux-ci.dev/architecture/ADR/0036-trusted-artifacts.html). It also optionally creates a source image and runs some build-time tests. This pipeline requires that the [multi platform controller](https://github.com/konflux-ci/multi-platform-controller) is deployed and configured on your Konflux instance. Information is shared between tasks using OCI artifacts instead of PVCs. EC will pass the [`trusted_task.trusted`](https://conforma.dev/docs/policy/packages/release_trusted_task.html#trusted_task__trusted) policy as long as all data used to build the artifact is generated from trusted tasks.
- This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-docker-build-multi-platform-oci-ta?tab=tags)_
- params:
- - description: Source Repository URL
- name: git-url
- type: string
- - default: ""
- description: Revision of the Source Repository
- name: revision
- type: string
- - description: Fully Qualified Output Image
- name: output-image
- type: string
- - default: .
- description: Path to the source code of an application's component from where to build image.
- name: path-context
- type: string
- - default: Dockerfile
- description: Path to the Dockerfile inside the context specified by parameter path-context
- name: dockerfile
- type: string
- - default: "false"
- description: Skip checks against built image
- name: skip-checks
- type: string
- - default: "false"
- description: Execute the build with network isolation
- name: hermetic
- type: string
- - default: ""
- description: Build dependencies to be prefetched
- name: prefetch-input
- type: string
- - default: ""
- description: Image tag expiration time, time values could be something like 1h, 2d, 3w for hours, days, and weeks, respectively.
- name: image-expires-after
- type: string
- - default: "false"
- description: Build a source image.
- name: build-source-image
- type: string
- - default: "true"
- description: Add built image into an OCI image index
- name: build-image-index
- type: string
- - default: docker
- description: The format for the resulting image's mediaType. Valid values are oci or docker.
- name: buildah-format
- type: string
- - default: []
- description: Array of --build-arg values ("arg=value" strings) for buildah
- name: build-args
- type: array
- - default: ""
- description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file
- name: build-args-file
- type: string
- - default: "false"
- description: Whether to enable privileged mode, should be used only with remote VMs
- name: privileged-nested
- type: string
- - default:
- - linux/x86_64
- description: List of platforms to build the container images on. The available set of values is determined by the configuration of the multi-platform-controller.
- name: build-platforms
- type: array
- - name: enable-cache-proxy
- default: 'false'
- description: Enable cache proxy configuration
- type: string
- - name: enable-package-registry-proxy
- default: 'true'
- description: Use the package registry proxy when prefetching dependencies
- type: string
- - name: sast-target-dirs
- type: string
- default: .
- description: Target directories to scan with SAST tools. Multiple values should be separated with commas.
- - name: source-date-epoch
- type: string
- default: ''
- description: Sets the image created time and the SOURCE_DATE_EPOCH build argument. On its own, it does not change file timestamps inside the layers (set rewrite-timestamp to "true" for that). Leave empty to keep the actual build time.
- - name: rewrite-timestamp
- type: string
- default: 'false'
- description: When "true", clamp file modification times in the image layers to at most source-date-epoch. Does nothing unless source-date-epoch is set.
- - name: omit-history
- type: string
- default: 'false'
- description: When "true", omit the build history (history timestamps, layer metadata, etc.) from the resulting image.
- results:
- - description: ""
- name: IMAGE_URL
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - description: ""
- name: IMAGE_DIGEST
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - description: ""
- name: CHAINS-GIT_URL
- value: $(tasks.clone-repository.results.url)
- - description: ""
- name: CHAINS-GIT_COMMIT
- value: $(tasks.clone-repository.results.commit)
- tasks:
- - name: init
- params:
- - name: enable-cache-proxy
- value: $(params.enable-cache-proxy)
- taskRef:
- params:
- - name: name
- value: init
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-init:0.4.3@sha256:b8465d543589b1238f6911626657f5766e279a0f33a5f70de68073401e031184
- - name: kind
- value: task
- resolver: bundles
- - name: clone-repository
- params:
- - name: url
- value: $(params.git-url)
- - name: revision
- value: $(params.revision)
- - name: ociStorage
- value: $(params.output-image).git
- - name: ociArtifactExpiresAfter
- value: $(params.image-expires-after)
- runAfter:
- - init
- taskRef:
- params:
- - name: name
- value: git-clone-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-git-clone-oci-ta:0.2.5@sha256:510daad5648d37936b9b2c599a35c8e59b7389de8e1a4e58f6c6d079957d730d
- - name: kind
- value: task
- resolver: bundles
- workspaces:
- - name: basic-auth
- workspace: git-auth
- - name: prefetch-dependencies
- params:
- - name: input
- value: $(params.prefetch-input)
- - name: SOURCE_ARTIFACT
- value: $(tasks.clone-repository.results.SOURCE_ARTIFACT)
- - name: ociStorage
- value: $(params.output-image).prefetch
- - name: ociArtifactExpiresAfter
- value: $(params.image-expires-after)
- - name: enable-package-registry-proxy
- value: $(params.enable-package-registry-proxy)
- runAfter:
- - clone-repository
- taskRef:
- params:
- - name: name
- value: prefetch-dependencies-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-prefetch-dependencies-oci-ta:0.6.0@sha256:01158b939522c276ba36804c2cc7ef641a572fb6c27f001819ea287dd708cd13
- - name: kind
- value: task
- resolver: bundles
- workspaces:
- - name: git-basic-auth
- workspace: git-auth
- - name: netrc
- workspace: netrc
- - matrix:
- params:
- - name: PLATFORM
- value:
- - $(params.build-platforms)
- name: build-images
- params:
- - name: IMAGE
- value: $(params.output-image)
- - name: DOCKERFILE
- value: $(params.dockerfile)
- - name: CONTEXT
- value: $(params.path-context)
- - name: HERMETIC
- value: $(params.hermetic)
- - name: PREFETCH_INPUT
- value: $(params.prefetch-input)
- - name: IMAGE_EXPIRES_AFTER
- value: $(params.image-expires-after)
- - name: COMMIT_SHA
- value: $(tasks.clone-repository.results.commit)
- - name: BUILD_ARGS
- value:
- - $(params.build-args[*])
- - name: BUILD_ARGS_FILE
- value: $(params.build-args-file)
- - name: PRIVILEGED_NESTED
- value: $(params.privileged-nested)
- - name: SOURCE_URL
- value: $(tasks.clone-repository.results.url)
- - name: BUILDAH_FORMAT
- value: $(params.buildah-format)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- - name: CACHI2_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- - name: IMAGE_APPEND_PLATFORM
- value: "true"
- - name: HTTP_PROXY
- value: $(tasks.init.results.http-proxy)
- - name: NO_PROXY
- value: $(tasks.init.results.no-proxy)
- - name: SOURCE_DATE_EPOCH
- value: $(params.source-date-epoch)
- - name: REWRITE_TIMESTAMP
- value: $(params.rewrite-timestamp)
- - name: OMIT_HISTORY
- value: $(params.omit-history)
- runAfter:
- - prefetch-dependencies
- taskRef:
- params:
- - name: name
- value: buildah-remote-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-buildah-remote-oci-ta:0.10.7@sha256:94f129a97242995d647b1d23a5d53e7022e0c3dc00aff764a4da4be263263cbf
- - name: kind
- value: task
- resolver: bundles
- - name: build-image-index
- params:
- - name: IMAGE
- value: $(params.output-image)
- - name: ALWAYS_BUILD_INDEX
- value: $(params.build-image-index)
- - name: IMAGES
- value:
- - $(tasks.build-images.results.IMAGE_REF[*])
- - name: BUILDAH_FORMAT
- value: $(params.buildah-format)
- runAfter:
- - build-images
- taskRef:
- params:
- - name: name
- value: build-image-index
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-build-image-index:0.3.1@sha256:a355355b7fcd0ba8de4ba85a162a2e6893f53236b943f79cb03ae0ae9c5ef53c
- - name: kind
- value: task
- resolver: bundles
- - name: build-source-image
- params:
- - name: BINARY_IMAGE
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: BINARY_IMAGE_DIGEST
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- - name: CACHI2_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: source-build-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-source-build-oci-ta:0.3@sha256:6081c4167e87a9167f7db4cda9ff0110607b7b9fc404c3daa076247475a4affa
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.build-source-image)
- operator: in
- values:
- - "true"
- - name: deprecated-base-image-check
- params:
- - name: IMAGE_URL
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: IMAGE_DIGEST
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: deprecated-image-check
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-deprecated-image-check:0.5@sha256:0ccc688a77e9b7b0b8973c132a1e840844137e77f887be4a0bec8893b0776872
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - matrix:
- params:
- - name: image-platform
- value:
- - $(params.build-platforms)
- name: clair-scan
- params:
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: clair-scan
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-clair-scan:0.3.2@sha256:f5b4415db9ac1fba3e11d993a617e0b275d1f0ed2fc669b12c400ed848c39174
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - matrix:
- params:
- - name: platform
- value:
- - $(params.build-platforms)
- name: ecosystem-cert-preflight-checks
- params:
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: ecosystem-cert-preflight-checks
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-ecosystem-cert-preflight-checks:0.2@sha256:27c9760ad11c74ad010d9615ee15348e3674843166acb7686929b3ef6840416c
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - name: sast-snyk-check
- params:
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- - name: CACHI2_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- - name: ARGS
- value: --project-name=lightspeed-stack --report --org=dca2ca89-7e51-4a3a-b7a5-6ad5633057b8
- - name: TARGET_DIRS
- value: $(params.sast-target-dirs)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: sast-snyk-check-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-snyk-check-oci-ta:0.5@sha256:eba24f5d9f4b18aa71e523b9b3dbcf22982aa4b018824260a090b19dfc9abf6f
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - matrix:
- params:
- - name: image-arch
- value:
- - $(params.build-platforms)
- name: clamav-scan
- params:
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: clamav-scan
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-clamav-scan:0.3.1@sha256:53a02326bfb930ca5ef6bfa7a33acca833d57752f34f3cb79255fe2e25e7d217
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - name: sast-coverity-check
- params:
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: IMAGE
- value: $(params.output-image)
- - name: DOCKERFILE
- value: $(params.dockerfile)
- - name: CONTEXT
- value: $(params.path-context)
- - name: HERMETIC
- value: $(params.hermetic)
- - name: PREFETCH_INPUT
- value: $(params.prefetch-input)
- - name: IMAGE_EXPIRES_AFTER
- value: $(params.image-expires-after)
- - name: COMMIT_SHA
- value: $(tasks.clone-repository.results.commit)
- - name: BUILD_ARGS
- value:
- - $(params.build-args[*])
- - name: BUILD_ARGS_FILE
- value: $(params.build-args-file)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- - name: CACHI2_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- - name: TARGET_DIRS
- value: $(params.sast-target-dirs)
- runAfter:
- - coverity-availability-check
- taskRef:
- params:
- - name: name
- value: sast-coverity-check-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-coverity-check-oci-ta:0.3@sha256:e92d00ed858233d0096627861192d3e4fc013cf1559c0d0b0ea0657d3377ce75
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - input: $(tasks.coverity-availability-check.results.STATUS)
- operator: in
- values:
- - success
- - name: coverity-availability-check
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: coverity-availability-check
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-coverity-availability-check:0.2@sha256:8b501440a960aec446db2ebc6625a49d0317a9fc7bf0f7bd9b18cb63052db7de
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - name: sast-shell-check
- params:
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- - name: CACHI2_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- - name: TARGET_DIRS
- value: $(params.sast-target-dirs)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: sast-shell-check-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-shell-check-oci-ta:0.1@sha256:61b27e6ad5daba761d41bb37efb790ed98380603fd4fe2f86d156def5bd72ecc
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - name: sast-unicode-check
- params:
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- - name: CACHI2_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- - name: TARGET_DIRS
- value: $(params.sast-target-dirs)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: sast-unicode-check-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-unicode-check-oci-ta:0.4@sha256:eb9d5392f215cb8b52b16382098cac4885b1e6cd989f88ebd83fdb234d283eb9
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - name: apply-tags
- params:
- - name: IMAGE_URL
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: IMAGE_DIGEST
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: apply-tags
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-apply-tags:0.3@sha256:6387614ae4f9efa8abb7c4175db0ce5d958bc2b90665b4704880e46fbe0535bf
- - name: kind
- value: task
- resolver: bundles
- - name: push-dockerfile
- params:
- - name: IMAGE
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: IMAGE_DIGEST
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: DOCKERFILE
- value: $(params.dockerfile)
- - name: CONTEXT
- value: $(params.path-context)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: push-dockerfile-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-push-dockerfile-oci-ta:0.3.1@sha256:5393bada94051f02aa971ff773b130928e01ac595b9ce3bbbd69899751ed8222
- - name: kind
- value: task
- resolver: bundles
- - name: rpms-signature-scan
- params:
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: rpms-signature-scan
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-rpms-signature-scan:0.2.1@sha256:ccb77d1bf7627fc6241a59ed42bb6e5707a8682754fe8ae18f2cfdddbcf29275
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- workspaces:
- - name: git-auth
- optional: true
- - name: netrc
- optional: true
- timeouts:
- pipeline: 4h
- tasks: 4h
- taskRunTemplate:
- serviceAccountName: build-pipeline-lightspeed-stack-0-7
- workspaces:
- - name: git-auth
- secret:
- secretName: '{{ git_auth_secret }}'
-status: {}
diff --git a/.tekton/lightspeed-stack-0-7-push.yaml b/.tekton/lightspeed-stack-0-7-push.yaml
deleted file mode 100644
index fc1b611d0..000000000
--- a/.tekton/lightspeed-stack-0-7-push.yaml
+++ /dev/null
@@ -1,677 +0,0 @@
-apiVersion: tekton.dev/v1
-kind: PipelineRun
-metadata:
- annotations:
- # Cross-repo nudge: after each push build, the Konflux nudge controller
- # opens an MR in lscore-deploy (gitlab.cee.redhat.com/rhel-lightspeed/lscore-deploy)
- # to bump the image digest in openshift/lightspeed-stack.yml. See RSPEED-3082.
- build.appstudio.openshift.io/build-nudge-files: "openshift/lightspeed-stack.yml"
- build.appstudio.openshift.io/repo: https://github.com/lightspeed-core/lightspeed-stack?rev={{revision}}
- build.appstudio.redhat.com/commit_sha: '{{revision}}'
- build.appstudio.redhat.com/target_branch: '{{target_branch}}'
- pipelinesascode.tekton.dev/cancel-in-progress: "false"
- pipelinesascode.tekton.dev/max-keep-runs: "3"
- pipelinesascode.tekton.dev/on-cel-expression: event == "push" && target_branch == "main"
- creationTimestamp:
- labels:
- appstudio.openshift.io/application: lightspeed-core-0-7
- appstudio.openshift.io/component: lightspeed-stack-0-7
- pipelines.appstudio.openshift.io/type: build
- name: lightspeed-stack-0-7-on-push
- namespace: lightspeed-core-tenant
-spec:
- params:
- - name: git-url
- value: '{{source_url}}'
- - name: revision
- value: '{{revision}}'
- - name: output-image
- value: quay.io/redhat-user-workloads/lightspeed-core-tenant/lightspeed-stack-0-7:{{revision}}
- - name: build-platforms
- value:
- - linux/x86_64
- - linux-c6gd2xlarge/arm64
- - name: build-source-image
- value: 'true'
- - name: prefetch-input
- value: |
- [
- {
- "type": "rpm",
- "path": ".konflux"
- },
- {
- "type": "generic",
- "path": ".konflux"
- },
- {
- "type": "pip",
- "path": ".konflux",
- "requirements_files": [
- "requirements.hashes.wheel.txt",
- "requirements.hashes.source.txt",
- "requirements.hermetic.txt"
- ],
- "requirements_build_files": ["requirements-build.txt"],
- "binary": {
- "packages": "a2a-sdk,accelerate,aiofile,aiohappyeyeballs,aiohttp,aiosignal,aiosqlite,annotated-doc,annotated-types,anthropic,anyio,argcomplete,asyncpg,attrs,authlib,autoevals,azure-core,azure-identity,beartype,cachetools,caio,certifi,cffi,chardet,charset-normalizer,chevron,click,cryptography,datasets,defusedxml,dill,distro,dnspython,docstring-parser,durationpy,einops,email-validator,emoji,exceptiongroup,executing,faiss-cpu,fastapi,fastmcp-slim,fastuuid,filelock,fire,frozenlist,fsspec,genai-prices,google-api-core,google-auth,google-cloud-core,google-cloud-storage,google-crc32c,google-genai,google-resumable-media,googleapis-common-protos,greenlet,griffelib,grpc-google-iam-v1,grpcio,grpcio-status,h11,hf-xet,httpcore,httpcore2,httpx,httpx-sse,httpx2,huggingface-hub,idna,importlib-metadata,jaraco-classes,jaraco-context,jaraco-functools,jeepney,jinja2,jiter,joblib,joserfc,jsonpath-ng,jsonschema,jsonschema-specifications,keyring,kubernetes,langdetect,litellm,logfire,logfire-api,markdown-it-py,markupsafe,maturin,mcp,mdurl,more-itertools,mpmath,msal,msal-extensions,multidict,multiprocess,narwhals,networkx,nltk,numpy,oauthlib,ogx,ogx-api,ogx-client,openai,opentelemetry-api,opentelemetry-distro,opentelemetry-exporter-otlp,opentelemetry-exporter-otlp-proto-common,opentelemetry-exporter-otlp-proto-grpc,opentelemetry-exporter-otlp-proto-http,opentelemetry-instrumentation,opentelemetry-instrumentation-httpx,opentelemetry-proto,opentelemetry-sdk,opentelemetry-semantic-conventions,opentelemetry-util-http,oracledb,packaging,pandas,peft,pip,platformdirs,polyleven,prometheus-client,prompt-toolkit,propcache,proto-plus,protobuf,psutil,psycopg2-binary,py-key-value-aio,pyaml,pyarrow,pyasn1,pyasn1-modules,pycparser,pydantic,pydantic-ai,pydantic-ai-slim,pydantic-core,pydantic-evals,pydantic-graph,pydantic-settings,pygments,pyjwt,pyopenssl,pypdf,pyperclip,python-dateutil,python-dotenv,python-multipart,pytz,pyyaml,referencing,regex,requests,requests-oauthlib,rich,rpds-py,safetensors,scikit-learn,scipy,secretstorage,semver,sentence-transformers,sentry-sdk,setuptools,shellingham,six,sniffio,sqlalchemy,sse-starlette,starlette,structlog,sympy,tenacity,termcolor,threadpoolctl,tiktoken,tokenizers,torch,tornado,tqdm,transformers,tree-sitter,triton,trl,truststore,typer,typing-extensions,typing-inspection,urllib3,uv,uv-build,uvicorn,wcwidth,websocket-client,websockets,wrapt,xxhash,yarl,zipp,zstandard",
- "os": "linux",
- "arch": "x86_64,aarch64",
- "py_version": 312
- }
- }
- ]
- - name: hermetic
- value: 'true'
- - name: dockerfile
- value: deploy/lightspeed-stack/Containerfile
- - name: build-args-file
- value: .konflux/build-args-konflux.conf
- pipelineSpec:
- description: |
- This pipeline is ideal for building multi-arch container images from a Containerfile while maintaining trust after pipeline customization.
-
- _Uses `buildah` to create a multi-platform container image leveraging [trusted artifacts](https://konflux-ci.dev/architecture/ADR/0036-trusted-artifacts.html). It also optionally creates a source image and runs some build-time tests. This pipeline requires that the [multi platform controller](https://github.com/konflux-ci/multi-platform-controller) is deployed and configured on your Konflux instance. Information is shared between tasks using OCI artifacts instead of PVCs. EC will pass the [`trusted_task.trusted`](https://conforma.dev/docs/policy/packages/release_trusted_task.html#trusted_task__trusted) policy as long as all data used to build the artifact is generated from trusted tasks.
- This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-docker-build-multi-platform-oci-ta?tab=tags)_
- params:
- - description: Source Repository URL
- name: git-url
- type: string
- - default: ""
- description: Revision of the Source Repository
- name: revision
- type: string
- - description: Fully Qualified Output Image
- name: output-image
- type: string
- - default: .
- description: Path to the source code of an application's component from where to build image.
- name: path-context
- type: string
- - default: Dockerfile
- description: Path to the Dockerfile inside the context specified by parameter path-context
- name: dockerfile
- type: string
- - default: "false"
- description: Skip checks against built image
- name: skip-checks
- type: string
- - default: "false"
- description: Execute the build with network isolation
- name: hermetic
- type: string
- - default: ""
- description: Build dependencies to be prefetched
- name: prefetch-input
- type: string
- - default: ""
- description: Image tag expiration time, time values could be something like 1h, 2d, 3w for hours, days, and weeks, respectively.
- name: image-expires-after
- type: string
- - default: "false"
- description: Build a source image.
- name: build-source-image
- type: string
- - default: "true"
- description: Add built image into an OCI image index
- name: build-image-index
- type: string
- - default: docker
- description: The format for the resulting image's mediaType. Valid values are oci or docker.
- name: buildah-format
- type: string
- - default: []
- description: Array of --build-arg values ("arg=value" strings) for buildah
- name: build-args
- type: array
- - default: ""
- description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file
- name: build-args-file
- type: string
- - default: "false"
- description: Whether to enable privileged mode, should be used only with remote VMs
- name: privileged-nested
- type: string
- - default:
- - linux/x86_64
- description: List of platforms to build the container images on. The available set of values is determined by the configuration of the multi-platform-controller.
- name: build-platforms
- type: array
- - name: enable-package-registry-proxy
- default: 'true'
- description: Use the package registry proxy when prefetching dependencies
- type: string
- - name: sast-target-dirs
- type: string
- default: .
- description: Target directories to scan with SAST tools. Multiple values should be separated with commas.
- - name: source-date-epoch
- type: string
- default: ''
- description: Sets the image created time and the SOURCE_DATE_EPOCH build argument. On its own, it does not change file timestamps inside the layers (set rewrite-timestamp to "true" for that). Leave empty to keep the actual build time.
- - name: rewrite-timestamp
- type: string
- default: 'false'
- description: When "true", clamp file modification times in the image layers to at most source-date-epoch. Does nothing unless source-date-epoch is set.
- - name: omit-history
- type: string
- default: 'false'
- description: When "true", omit the build history (history timestamps, layer metadata, etc.) from the resulting image.
- results:
- - description: ""
- name: IMAGE_URL
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - description: ""
- name: IMAGE_DIGEST
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - description: ""
- name: CHAINS-GIT_URL
- value: $(tasks.clone-repository.results.url)
- - description: ""
- name: CHAINS-GIT_COMMIT
- value: $(tasks.clone-repository.results.commit)
- tasks:
- - name: init
- taskRef:
- params:
- - name: name
- value: init
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-init:0.4.3@sha256:b8465d543589b1238f6911626657f5766e279a0f33a5f70de68073401e031184
- - name: kind
- value: task
- resolver: bundles
- - name: clone-repository
- params:
- - name: url
- value: $(params.git-url)
- - name: revision
- value: $(params.revision)
- - name: ociStorage
- value: $(params.output-image).git
- - name: ociArtifactExpiresAfter
- value: $(params.image-expires-after)
- runAfter:
- - init
- taskRef:
- params:
- - name: name
- value: git-clone-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-git-clone-oci-ta:0.2.5@sha256:510daad5648d37936b9b2c599a35c8e59b7389de8e1a4e58f6c6d079957d730d
- - name: kind
- value: task
- resolver: bundles
- workspaces:
- - name: basic-auth
- workspace: git-auth
- - name: prefetch-dependencies
- params:
- - name: input
- value: $(params.prefetch-input)
- - name: SOURCE_ARTIFACT
- value: $(tasks.clone-repository.results.SOURCE_ARTIFACT)
- - name: ociStorage
- value: $(params.output-image).prefetch
- - name: ociArtifactExpiresAfter
- value: $(params.image-expires-after)
- - name: enable-package-registry-proxy
- value: $(params.enable-package-registry-proxy)
- runAfter:
- - clone-repository
- taskRef:
- params:
- - name: name
- value: prefetch-dependencies-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-prefetch-dependencies-oci-ta:0.6.0@sha256:01158b939522c276ba36804c2cc7ef641a572fb6c27f001819ea287dd708cd13
- - name: kind
- value: task
- resolver: bundles
- workspaces:
- - name: git-basic-auth
- workspace: git-auth
- - name: netrc
- workspace: netrc
- - matrix:
- params:
- - name: PLATFORM
- value:
- - $(params.build-platforms)
- name: build-images
- params:
- - name: IMAGE
- value: $(params.output-image)
- - name: DOCKERFILE
- value: $(params.dockerfile)
- - name: CONTEXT
- value: $(params.path-context)
- - name: HERMETIC
- value: $(params.hermetic)
- - name: PREFETCH_INPUT
- value: $(params.prefetch-input)
- - name: IMAGE_EXPIRES_AFTER
- value: $(params.image-expires-after)
- - name: COMMIT_SHA
- value: $(tasks.clone-repository.results.commit)
- - name: BUILD_ARGS
- value:
- - $(params.build-args[*])
- - name: BUILD_ARGS_FILE
- value: $(params.build-args-file)
- - name: PRIVILEGED_NESTED
- value: $(params.privileged-nested)
- - name: SOURCE_URL
- value: $(tasks.clone-repository.results.url)
- - name: BUILDAH_FORMAT
- value: $(params.buildah-format)
- - name: HTTP_PROXY
- value: $(tasks.init.results.http-proxy)
- - name: NO_PROXY
- value: $(tasks.init.results.no-proxy)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- - name: CACHI2_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- - name: IMAGE_APPEND_PLATFORM
- value: "true"
- - name: SOURCE_DATE_EPOCH
- value: $(params.source-date-epoch)
- - name: REWRITE_TIMESTAMP
- value: $(params.rewrite-timestamp)
- - name: OMIT_HISTORY
- value: $(params.omit-history)
- runAfter:
- - prefetch-dependencies
- taskRef:
- params:
- - name: name
- value: buildah-remote-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-buildah-remote-oci-ta:0.10.7@sha256:94f129a97242995d647b1d23a5d53e7022e0c3dc00aff764a4da4be263263cbf
- - name: kind
- value: task
- resolver: bundles
- - name: build-image-index
- params:
- - name: IMAGE
- value: $(params.output-image)
- - name: ALWAYS_BUILD_INDEX
- value: $(params.build-image-index)
- - name: IMAGES
- value:
- - $(tasks.build-images.results.IMAGE_REF[*])
- - name: BUILDAH_FORMAT
- value: $(params.buildah-format)
- runAfter:
- - build-images
- taskRef:
- params:
- - name: name
- value: build-image-index
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-build-image-index:0.3.1@sha256:a355355b7fcd0ba8de4ba85a162a2e6893f53236b943f79cb03ae0ae9c5ef53c
- - name: kind
- value: task
- resolver: bundles
- - name: build-source-image
- params:
- - name: BINARY_IMAGE
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: BINARY_IMAGE_DIGEST
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- - name: CACHI2_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: source-build-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-source-build-oci-ta:0.3@sha256:6081c4167e87a9167f7db4cda9ff0110607b7b9fc404c3daa076247475a4affa
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.build-source-image)
- operator: in
- values:
- - "true"
- - name: deprecated-base-image-check
- params:
- - name: IMAGE_URL
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: IMAGE_DIGEST
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: deprecated-image-check
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-deprecated-image-check:0.5@sha256:0ccc688a77e9b7b0b8973c132a1e840844137e77f887be4a0bec8893b0776872
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - matrix:
- params:
- - name: image-platform
- value:
- - $(params.build-platforms)
- name: clair-scan
- params:
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: clair-scan
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-clair-scan:0.3.2@sha256:f5b4415db9ac1fba3e11d993a617e0b275d1f0ed2fc669b12c400ed848c39174
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - matrix:
- params:
- - name: platform
- value:
- - $(params.build-platforms)
- name: ecosystem-cert-preflight-checks
- params:
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: ecosystem-cert-preflight-checks
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-ecosystem-cert-preflight-checks:0.2@sha256:27c9760ad11c74ad010d9615ee15348e3674843166acb7686929b3ef6840416c
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - name: sast-snyk-check
- params:
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- - name: CACHI2_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- - name: ARGS
- value: --project-name=lightspeed-stack --report --org=dca2ca89-7e51-4a3a-b7a5-6ad5633057b8
- - name: TARGET_DIRS
- value: $(params.sast-target-dirs)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: sast-snyk-check-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-snyk-check-oci-ta:0.5@sha256:eba24f5d9f4b18aa71e523b9b3dbcf22982aa4b018824260a090b19dfc9abf6f
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - matrix:
- params:
- - name: image-arch
- value:
- - $(params.build-platforms)
- name: clamav-scan
- params:
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: clamav-scan
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-clamav-scan:0.3.1@sha256:53a02326bfb930ca5ef6bfa7a33acca833d57752f34f3cb79255fe2e25e7d217
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - name: sast-coverity-check
- params:
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: IMAGE
- value: $(params.output-image)
- - name: DOCKERFILE
- value: $(params.dockerfile)
- - name: CONTEXT
- value: $(params.path-context)
- - name: HERMETIC
- value: $(params.hermetic)
- - name: PREFETCH_INPUT
- value: $(params.prefetch-input)
- - name: IMAGE_EXPIRES_AFTER
- value: $(params.image-expires-after)
- - name: COMMIT_SHA
- value: $(tasks.clone-repository.results.commit)
- - name: BUILD_ARGS
- value:
- - $(params.build-args[*])
- - name: BUILD_ARGS_FILE
- value: $(params.build-args-file)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- - name: CACHI2_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- - name: TARGET_DIRS
- value: $(params.sast-target-dirs)
- runAfter:
- - coverity-availability-check
- taskRef:
- params:
- - name: name
- value: sast-coverity-check-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-coverity-check-oci-ta:0.3@sha256:e92d00ed858233d0096627861192d3e4fc013cf1559c0d0b0ea0657d3377ce75
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - input: $(tasks.coverity-availability-check.results.STATUS)
- operator: in
- values:
- - success
- - name: coverity-availability-check
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: coverity-availability-check
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-coverity-availability-check:0.2@sha256:8b501440a960aec446db2ebc6625a49d0317a9fc7bf0f7bd9b18cb63052db7de
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - name: sast-shell-check
- params:
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- - name: CACHI2_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- - name: TARGET_DIRS
- value: $(params.sast-target-dirs)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: sast-shell-check-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-shell-check-oci-ta:0.1@sha256:61b27e6ad5daba761d41bb37efb790ed98380603fd4fe2f86d156def5bd72ecc
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - name: sast-unicode-check
- params:
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- - name: CACHI2_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- - name: TARGET_DIRS
- value: $(params.sast-target-dirs)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: sast-unicode-check-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-unicode-check-oci-ta:0.4@sha256:eb9d5392f215cb8b52b16382098cac4885b1e6cd989f88ebd83fdb234d283eb9
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- - name: apply-tags
- params:
- - name: IMAGE_URL
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: IMAGE_DIGEST
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: ADDITIONAL_TAGS
- value:
- - $(tasks.clone-repository.results.short-commit)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: apply-tags
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-apply-tags:0.3@sha256:6387614ae4f9efa8abb7c4175db0ce5d958bc2b90665b4704880e46fbe0535bf
- - name: kind
- value: task
- resolver: bundles
- - name: push-dockerfile
- params:
- - name: IMAGE
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: IMAGE_DIGEST
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- - name: DOCKERFILE
- value: $(params.dockerfile)
- - name: CONTEXT
- value: $(params.path-context)
- - name: SOURCE_ARTIFACT
- value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: push-dockerfile-oci-ta
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-push-dockerfile-oci-ta:0.3.1@sha256:5393bada94051f02aa971ff773b130928e01ac595b9ce3bbbd69899751ed8222
- - name: kind
- value: task
- resolver: bundles
- - name: rpms-signature-scan
- params:
- - name: image-url
- value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: image-digest
- value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- runAfter:
- - build-image-index
- taskRef:
- params:
- - name: name
- value: rpms-signature-scan
- - name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-rpms-signature-scan:0.2.1@sha256:ccb77d1bf7627fc6241a59ed42bb6e5707a8682754fe8ae18f2cfdddbcf29275
- - name: kind
- value: task
- resolver: bundles
- when:
- - input: $(params.skip-checks)
- operator: in
- values:
- - "false"
- workspaces:
- - name: git-auth
- optional: true
- - name: netrc
- optional: true
- timeouts:
- pipeline: 4h
- tasks: 4h
- taskRunTemplate:
- serviceAccountName: build-pipeline-lightspeed-stack-0-7
- workspaces:
- - name: git-auth
- secret:
- secretName: '{{ git_auth_secret }}'
-status: {}
diff --git a/.tekton/lightspeed-stack-0-8-pull-request.yaml b/.tekton/lightspeed-stack-0-8-pull-request.yaml
index bd21328d7..3fdd49476 100644
--- a/.tekton/lightspeed-stack-0-8-pull-request.yaml
+++ b/.tekton/lightspeed-stack-0-8-pull-request.yaml
@@ -29,10 +29,43 @@ spec:
- name: build-platforms
value:
- linux/x86_64
+ - linux-c6gd2xlarge/arm64
+ - name: build-source-image
+ value: 'true'
+ - name: prefetch-input
+ value: |
+ [
+ {
+ "type": "rpm",
+ "path": ".konflux"
+ },
+ {
+ "type": "generic",
+ "path": ".konflux"
+ },
+ {
+ "type": "pip",
+ "path": ".konflux",
+ "requirements_files": [
+ "requirements.hashes.wheel.txt",
+ "requirements.hashes.source.txt",
+ "requirements.hermetic.txt"
+ ],
+ "requirements_build_files": ["requirements-build.txt"],
+ "binary": {
+ "packages": "a2a-sdk,accelerate,aiofile,aiohappyeyeballs,aiohttp,aiosignal,aiosqlite,annotated-doc,annotated-types,anthropic,anyio,argcomplete,asyncpg,attrs,authlib,autoevals,azure-core,azure-identity,beartype,cachetools,caio,certifi,cffi,chardet,charset-normalizer,chevron,click,cryptography,datasets,defusedxml,dill,distro,dnspython,docstring-parser,durationpy,einops,email-validator,emoji,exceptiongroup,executing,faiss-cpu,fastapi,fastmcp-slim,fastuuid,filelock,fire,frozenlist,fsspec,genai-prices,google-api-core,google-auth,google-cloud-core,google-cloud-storage,google-crc32c,google-genai,google-resumable-media,googleapis-common-protos,greenlet,griffelib,grpc-google-iam-v1,grpcio,grpcio-status,h11,hf-xet,httpcore,httpcore2,httpx,httpx-sse,httpx2,huggingface-hub,idna,importlib-metadata,jaraco-classes,jaraco-context,jaraco-functools,jeepney,jinja2,jiter,joblib,joserfc,jsonpath-ng,jsonschema,jsonschema-specifications,keyring,kubernetes,langdetect,litellm,logfire,logfire-api,markdown-it-py,markupsafe,maturin,mcp,mdurl,more-itertools,mpmath,msal,msal-extensions,multidict,multiprocess,narwhals,networkx,nltk,numpy,oauthlib,ogx,ogx-api,ogx-client,openai,opentelemetry-api,opentelemetry-distro,opentelemetry-exporter-otlp,opentelemetry-exporter-otlp-proto-common,opentelemetry-exporter-otlp-proto-grpc,opentelemetry-exporter-otlp-proto-http,opentelemetry-instrumentation,opentelemetry-instrumentation-httpx,opentelemetry-proto,opentelemetry-sdk,opentelemetry-semantic-conventions,opentelemetry-util-http,oracledb,packaging,pandas,peft,pip,platformdirs,polyleven,prometheus-client,prompt-toolkit,propcache,proto-plus,protobuf,psutil,psycopg2-binary,py-key-value-aio,pyaml,pyarrow,pyasn1,pyasn1-modules,pycparser,pydantic,pydantic-ai,pydantic-ai-slim,pydantic-core,pydantic-evals,pydantic-graph,pydantic-settings,pygments,pyjwt,pyopenssl,pypdf,pyperclip,python-dateutil,python-dotenv,python-multipart,pytz,pyyaml,referencing,regex,requests,requests-oauthlib,rich,rpds-py,safetensors,scikit-learn,scipy,secretstorage,semver,sentence-transformers,sentry-sdk,setuptools,shellingham,six,sniffio,sqlalchemy,sse-starlette,starlette,structlog,sympy,tenacity,termcolor,threadpoolctl,tiktoken,tokenizers,torch,tornado,tqdm,transformers,tree-sitter,triton,trl,truststore,typer,typing-extensions,typing-inspection,urllib3,uv,uv-build,uvicorn,wcwidth,websocket-client,websockets,wrapt,xxhash,yarl,zipp,zstandard",
+ "os": "linux",
+ "arch": "x86_64,aarch64",
+ "py_version": 312
+ }
+ }
+ ]
+ - name: hermetic
+ value: 'true'
- name: dockerfile
- value: Containerfile
- - name: path-context
- value: .
+ value: deploy/lightspeed-stack/Containerfile
+ - name: build-args-file
+ value: .konflux/build-args-konflux.conf
pipelineSpec:
description: |
This pipeline is ideal for building multi-arch container images from a Containerfile while maintaining trust after pipeline customization.
@@ -159,7 +192,7 @@ spec:
- name: name
value: init
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-init:0.4.2@sha256:421003a5c077ecb820460e71637125ec9093d2101c749a32ede28e190283e9db
+ value: quay.io/konflux-ci/tekton-catalog/task-init:0.4.3@sha256:b8465d543589b1238f6911626657f5766e279a0f33a5f70de68073401e031184
- name: kind
value: task
resolver: bundles
@@ -180,7 +213,7 @@ spec:
- name: name
value: git-clone-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-git-clone-oci-ta:0.2.4@sha256:df3c42d78223f07b40a84dd29e5c8860d14777ffdf150ea08c738770f51216dc
+ value: quay.io/konflux-ci/tekton-catalog/task-git-clone-oci-ta:0.2.5@sha256:510daad5648d37936b9b2c599a35c8e59b7389de8e1a4e58f6c6d079957d730d
- name: kind
value: task
resolver: bundles
@@ -206,7 +239,7 @@ spec:
- name: name
value: prefetch-dependencies-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-prefetch-dependencies-oci-ta:0.3.2@sha256:389aea03a065e8118d36b7acb85b05cd13f6750e7e10ff8a85f270ee65b0167b
+ value: quay.io/konflux-ci/tekton-catalog/task-prefetch-dependencies-oci-ta:0.6.0@sha256:01158b939522c276ba36804c2cc7ef641a572fb6c27f001819ea287dd708cd13
- name: kind
value: task
resolver: bundles
@@ -270,7 +303,7 @@ spec:
- name: name
value: buildah-remote-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-buildah-remote-oci-ta:0.10.5@sha256:eb277ec7b44443f0506a60ac940a2e52178d60f17cb0f51a6966daed5b3755de
+ value: quay.io/konflux-ci/tekton-catalog/task-buildah-remote-oci-ta:0.10.7@sha256:94f129a97242995d647b1d23a5d53e7022e0c3dc00aff764a4da4be263263cbf
- name: kind
value: task
resolver: bundles
@@ -292,7 +325,7 @@ spec:
- name: name
value: build-image-index
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-build-image-index:0.3.1@sha256:cc75f64deecccb1b59e96ac1182665a5342d79c9e22eebff63d26b0f00a4319c
+ value: quay.io/konflux-ci/tekton-catalog/task-build-image-index:0.3.1@sha256:a355355b7fcd0ba8de4ba85a162a2e6893f53236b943f79cb03ae0ae9c5ef53c
- name: kind
value: task
resolver: bundles
@@ -313,7 +346,7 @@ spec:
- name: name
value: source-build-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-source-build-oci-ta:0.3@sha256:7c5575ac8e292f27f57716c021ab0324460dc958e73946724c588c5228e5f372
+ value: quay.io/konflux-ci/tekton-catalog/task-source-build-oci-ta:0.3@sha256:6081c4167e87a9167f7db4cda9ff0110607b7b9fc404c3daa076247475a4affa
- name: kind
value: task
resolver: bundles
@@ -362,7 +395,7 @@ spec:
- name: name
value: clair-scan
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-clair-scan:0.3@sha256:f5b4415db9ac1fba3e11d993a617e0b275d1f0ed2fc669b12c400ed848c39174
+ value: quay.io/konflux-ci/tekton-catalog/task-clair-scan:0.3.2@sha256:f5b4415db9ac1fba3e11d993a617e0b275d1f0ed2fc669b12c400ed848c39174
- name: kind
value: task
resolver: bundles
@@ -387,7 +420,7 @@ spec:
- name: name
value: ecosystem-cert-preflight-checks
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-ecosystem-cert-preflight-checks:0.2@sha256:e438f3104d706f73812994953d3d0a9c62ac8e4a372d86337ff26bbca9902709
+ value: quay.io/konflux-ci/tekton-catalog/task-ecosystem-cert-preflight-checks:0.2@sha256:27c9760ad11c74ad010d9615ee15348e3674843166acb7686929b3ef6840416c
- name: kind
value: task
resolver: bundles
@@ -402,12 +435,14 @@ spec:
value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- name: image-url
value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: TARGET_DIRS
- value: $(params.sast-target-dirs)
- name: SOURCE_ARTIFACT
value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- name: CACHI2_ARTIFACT
value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ - name: ARGS
+ value: --project-name=lightspeed-stack --report --org=dca2ca89-7e51-4a3a-b7a5-6ad5633057b8
+ - name: TARGET_DIRS
+ value: $(params.sast-target-dirs)
runAfter:
- build-image-index
taskRef:
@@ -442,7 +477,7 @@ spec:
- name: name
value: clamav-scan
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-clamav-scan:0.3@sha256:53a02326bfb930ca5ef6bfa7a33acca833d57752f34f3cb79255fe2e25e7d217
+ value: quay.io/konflux-ci/tekton-catalog/task-clamav-scan:0.3.1@sha256:53a02326bfb930ca5ef6bfa7a33acca833d57752f34f3cb79255fe2e25e7d217
- name: kind
value: task
resolver: bundles
@@ -451,18 +486,86 @@ spec:
operator: in
values:
- "false"
- - name: sast-shell-check
+ - name: sast-coverity-check
params:
- name: image-digest
value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- name: image-url
value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: IMAGE
+ value: $(params.output-image)
+ - name: DOCKERFILE
+ value: $(params.dockerfile)
+ - name: CONTEXT
+ value: $(params.path-context)
+ - name: HERMETIC
+ value: $(params.hermetic)
+ - name: PREFETCH_INPUT
+ value: $(params.prefetch-input)
+ - name: IMAGE_EXPIRES_AFTER
+ value: $(params.image-expires-after)
+ - name: COMMIT_SHA
+ value: $(tasks.clone-repository.results.commit)
+ - name: BUILD_ARGS
+ value:
+ - $(params.build-args[*])
+ - name: BUILD_ARGS_FILE
+ value: $(params.build-args-file)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ - name: CACHI2_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- name: TARGET_DIRS
value: $(params.sast-target-dirs)
+ runAfter:
+ - coverity-availability-check
+ taskRef:
+ params:
+ - name: name
+ value: sast-coverity-check-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-coverity-check-oci-ta:0.3@sha256:e92d00ed858233d0096627861192d3e4fc013cf1559c0d0b0ea0657d3377ce75
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - input: $(tasks.coverity-availability-check.results.STATUS)
+ operator: in
+ values:
+ - success
+ - name: coverity-availability-check
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: coverity-availability-check
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-coverity-availability-check:0.2@sha256:8b501440a960aec446db2ebc6625a49d0317a9fc7bf0f7bd9b18cb63052db7de
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - name: sast-shell-check
+ params:
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
- name: SOURCE_ARTIFACT
value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- name: CACHI2_ARTIFACT
value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ - name: TARGET_DIRS
+ value: $(params.sast-target-dirs)
runAfter:
- build-image-index
taskRef:
@@ -520,7 +623,7 @@ spec:
- name: name
value: apply-tags
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-apply-tags:0.3@sha256:3ab844157eccd68e95e4852adc06c3c4ea674edb7865a474b0a898227f2893d6
+ value: quay.io/konflux-ci/tekton-catalog/task-apply-tags:0.3@sha256:6387614ae4f9efa8abb7c4175db0ce5d958bc2b90665b4704880e46fbe0535bf
- name: kind
value: task
resolver: bundles
@@ -543,7 +646,7 @@ spec:
- name: name
value: push-dockerfile-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-push-dockerfile-oci-ta:0.3.1@sha256:5a6cbebd89e5bc163b38231859767f7f6a0dd66cf1333699574379f062731183
+ value: quay.io/konflux-ci/tekton-catalog/task-push-dockerfile-oci-ta:0.3.1@sha256:5393bada94051f02aa971ff773b130928e01ac595b9ce3bbbd69899751ed8222
- name: kind
value: task
resolver: bundles
@@ -560,7 +663,7 @@ spec:
- name: name
value: rpms-signature-scan
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-rpms-signature-scan:0.2@sha256:ccb77d1bf7627fc6241a59ed42bb6e5707a8682754fe8ae18f2cfdddbcf29275
+ value: quay.io/konflux-ci/tekton-catalog/task-rpms-signature-scan:0.2.1@sha256:ccb77d1bf7627fc6241a59ed42bb6e5707a8682754fe8ae18f2cfdddbcf29275
- name: kind
value: task
resolver: bundles
@@ -574,6 +677,9 @@ spec:
optional: true
- name: netrc
optional: true
+ timeouts:
+ pipeline: 4h
+ tasks: 4h
taskRunTemplate:
serviceAccountName: build-pipeline-lightspeed-stack-0-8
workspaces:
diff --git a/.tekton/lightspeed-stack-0-8-push.yaml b/.tekton/lightspeed-stack-0-8-push.yaml
index 183726ce1..359a64293 100644
--- a/.tekton/lightspeed-stack-0-8-push.yaml
+++ b/.tekton/lightspeed-stack-0-8-push.yaml
@@ -2,6 +2,10 @@ apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
annotations:
+ # Cross-repo nudge: after each push build, the Konflux nudge controller
+ # opens an MR in lscore-deploy (gitlab.cee.redhat.com/rhel-lightspeed/lscore-deploy)
+ # to bump the image digest in openshift/lightspeed-stack.yml. See RSPEED-3082.
+ build.appstudio.openshift.io/build-nudge-files: "openshift/lightspeed-stack.yml"
build.appstudio.openshift.io/repo: https://github.com/lightspeed-core/lightspeed-stack?rev={{revision}}
build.appstudio.redhat.com/commit_sha: '{{revision}}'
build.appstudio.redhat.com/target_branch: '{{target_branch}}'
@@ -26,10 +30,43 @@ spec:
- name: build-platforms
value:
- linux/x86_64
+ - linux-c6gd2xlarge/arm64
+ - name: build-source-image
+ value: 'true'
+ - name: prefetch-input
+ value: |
+ [
+ {
+ "type": "rpm",
+ "path": ".konflux"
+ },
+ {
+ "type": "generic",
+ "path": ".konflux"
+ },
+ {
+ "type": "pip",
+ "path": ".konflux",
+ "requirements_files": [
+ "requirements.hashes.wheel.txt",
+ "requirements.hashes.source.txt",
+ "requirements.hermetic.txt"
+ ],
+ "requirements_build_files": ["requirements-build.txt"],
+ "binary": {
+ "packages": "a2a-sdk,accelerate,aiofile,aiohappyeyeballs,aiohttp,aiosignal,aiosqlite,annotated-doc,annotated-types,anthropic,anyio,argcomplete,asyncpg,attrs,authlib,autoevals,azure-core,azure-identity,beartype,cachetools,caio,certifi,cffi,chardet,charset-normalizer,chevron,click,cryptography,datasets,defusedxml,dill,distro,dnspython,docstring-parser,durationpy,einops,email-validator,emoji,exceptiongroup,executing,faiss-cpu,fastapi,fastmcp-slim,fastuuid,filelock,fire,frozenlist,fsspec,genai-prices,google-api-core,google-auth,google-cloud-core,google-cloud-storage,google-crc32c,google-genai,google-resumable-media,googleapis-common-protos,greenlet,griffelib,grpc-google-iam-v1,grpcio,grpcio-status,h11,hf-xet,httpcore,httpcore2,httpx,httpx-sse,httpx2,huggingface-hub,idna,importlib-metadata,jaraco-classes,jaraco-context,jaraco-functools,jeepney,jinja2,jiter,joblib,joserfc,jsonpath-ng,jsonschema,jsonschema-specifications,keyring,kubernetes,langdetect,litellm,logfire,logfire-api,markdown-it-py,markupsafe,maturin,mcp,mdurl,more-itertools,mpmath,msal,msal-extensions,multidict,multiprocess,narwhals,networkx,nltk,numpy,oauthlib,ogx,ogx-api,ogx-client,openai,opentelemetry-api,opentelemetry-distro,opentelemetry-exporter-otlp,opentelemetry-exporter-otlp-proto-common,opentelemetry-exporter-otlp-proto-grpc,opentelemetry-exporter-otlp-proto-http,opentelemetry-instrumentation,opentelemetry-instrumentation-httpx,opentelemetry-proto,opentelemetry-sdk,opentelemetry-semantic-conventions,opentelemetry-util-http,oracledb,packaging,pandas,peft,pip,platformdirs,polyleven,prometheus-client,prompt-toolkit,propcache,proto-plus,protobuf,psutil,psycopg2-binary,py-key-value-aio,pyaml,pyarrow,pyasn1,pyasn1-modules,pycparser,pydantic,pydantic-ai,pydantic-ai-slim,pydantic-core,pydantic-evals,pydantic-graph,pydantic-settings,pygments,pyjwt,pyopenssl,pypdf,pyperclip,python-dateutil,python-dotenv,python-multipart,pytz,pyyaml,referencing,regex,requests,requests-oauthlib,rich,rpds-py,safetensors,scikit-learn,scipy,secretstorage,semver,sentence-transformers,sentry-sdk,setuptools,shellingham,six,sniffio,sqlalchemy,sse-starlette,starlette,structlog,sympy,tenacity,termcolor,threadpoolctl,tiktoken,tokenizers,torch,tornado,tqdm,transformers,tree-sitter,triton,trl,truststore,typer,typing-extensions,typing-inspection,urllib3,uv,uv-build,uvicorn,wcwidth,websocket-client,websockets,wrapt,xxhash,yarl,zipp,zstandard",
+ "os": "linux",
+ "arch": "x86_64,aarch64",
+ "py_version": 312
+ }
+ }
+ ]
+ - name: hermetic
+ value: 'true'
- name: dockerfile
- value: Containerfile
- - name: path-context
- value: .
+ value: deploy/lightspeed-stack/Containerfile
+ - name: build-args-file
+ value: .konflux/build-args-konflux.conf
pipelineSpec:
description: |
This pipeline is ideal for building multi-arch container images from a Containerfile while maintaining trust after pipeline customization.
@@ -156,7 +193,7 @@ spec:
- name: name
value: init
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-init:0.4.2@sha256:421003a5c077ecb820460e71637125ec9093d2101c749a32ede28e190283e9db
+ value: quay.io/konflux-ci/tekton-catalog/task-init:0.4.3@sha256:b8465d543589b1238f6911626657f5766e279a0f33a5f70de68073401e031184
- name: kind
value: task
resolver: bundles
@@ -177,7 +214,7 @@ spec:
- name: name
value: git-clone-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-git-clone-oci-ta:0.2.4@sha256:df3c42d78223f07b40a84dd29e5c8860d14777ffdf150ea08c738770f51216dc
+ value: quay.io/konflux-ci/tekton-catalog/task-git-clone-oci-ta:0.2.5@sha256:510daad5648d37936b9b2c599a35c8e59b7389de8e1a4e58f6c6d079957d730d
- name: kind
value: task
resolver: bundles
@@ -203,7 +240,7 @@ spec:
- name: name
value: prefetch-dependencies-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-prefetch-dependencies-oci-ta:0.3.2@sha256:389aea03a065e8118d36b7acb85b05cd13f6750e7e10ff8a85f270ee65b0167b
+ value: quay.io/konflux-ci/tekton-catalog/task-prefetch-dependencies-oci-ta:0.6.0@sha256:01158b939522c276ba36804c2cc7ef641a572fb6c27f001819ea287dd708cd13
- name: kind
value: task
resolver: bundles
@@ -267,7 +304,7 @@ spec:
- name: name
value: buildah-remote-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-buildah-remote-oci-ta:0.10.5@sha256:eb277ec7b44443f0506a60ac940a2e52178d60f17cb0f51a6966daed5b3755de
+ value: quay.io/konflux-ci/tekton-catalog/task-buildah-remote-oci-ta:0.10.7@sha256:94f129a97242995d647b1d23a5d53e7022e0c3dc00aff764a4da4be263263cbf
- name: kind
value: task
resolver: bundles
@@ -289,7 +326,7 @@ spec:
- name: name
value: build-image-index
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-build-image-index:0.3.1@sha256:cc75f64deecccb1b59e96ac1182665a5342d79c9e22eebff63d26b0f00a4319c
+ value: quay.io/konflux-ci/tekton-catalog/task-build-image-index:0.3.1@sha256:a355355b7fcd0ba8de4ba85a162a2e6893f53236b943f79cb03ae0ae9c5ef53c
- name: kind
value: task
resolver: bundles
@@ -310,7 +347,7 @@ spec:
- name: name
value: source-build-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-source-build-oci-ta:0.3@sha256:7c5575ac8e292f27f57716c021ab0324460dc958e73946724c588c5228e5f372
+ value: quay.io/konflux-ci/tekton-catalog/task-source-build-oci-ta:0.3@sha256:6081c4167e87a9167f7db4cda9ff0110607b7b9fc404c3daa076247475a4affa
- name: kind
value: task
resolver: bundles
@@ -359,7 +396,7 @@ spec:
- name: name
value: clair-scan
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-clair-scan:0.3@sha256:f5b4415db9ac1fba3e11d993a617e0b275d1f0ed2fc669b12c400ed848c39174
+ value: quay.io/konflux-ci/tekton-catalog/task-clair-scan:0.3.2@sha256:f5b4415db9ac1fba3e11d993a617e0b275d1f0ed2fc669b12c400ed848c39174
- name: kind
value: task
resolver: bundles
@@ -384,7 +421,7 @@ spec:
- name: name
value: ecosystem-cert-preflight-checks
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-ecosystem-cert-preflight-checks:0.2@sha256:e438f3104d706f73812994953d3d0a9c62ac8e4a372d86337ff26bbca9902709
+ value: quay.io/konflux-ci/tekton-catalog/task-ecosystem-cert-preflight-checks:0.2@sha256:27c9760ad11c74ad010d9615ee15348e3674843166acb7686929b3ef6840416c
- name: kind
value: task
resolver: bundles
@@ -399,12 +436,14 @@ spec:
value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- name: image-url
value: $(tasks.build-image-index.results.IMAGE_URL)
- - name: TARGET_DIRS
- value: $(params.sast-target-dirs)
- name: SOURCE_ARTIFACT
value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- name: CACHI2_ARTIFACT
value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ - name: ARGS
+ value: --project-name=lightspeed-stack --report --org=dca2ca89-7e51-4a3a-b7a5-6ad5633057b8
+ - name: TARGET_DIRS
+ value: $(params.sast-target-dirs)
runAfter:
- build-image-index
taskRef:
@@ -439,7 +478,7 @@ spec:
- name: name
value: clamav-scan
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-clamav-scan:0.3@sha256:53a02326bfb930ca5ef6bfa7a33acca833d57752f34f3cb79255fe2e25e7d217
+ value: quay.io/konflux-ci/tekton-catalog/task-clamav-scan:0.3.1@sha256:53a02326bfb930ca5ef6bfa7a33acca833d57752f34f3cb79255fe2e25e7d217
- name: kind
value: task
resolver: bundles
@@ -448,18 +487,86 @@ spec:
operator: in
values:
- "false"
- - name: sast-shell-check
+ - name: sast-coverity-check
params:
- name: image-digest
value: $(tasks.build-image-index.results.IMAGE_DIGEST)
- name: image-url
value: $(tasks.build-image-index.results.IMAGE_URL)
+ - name: IMAGE
+ value: $(params.output-image)
+ - name: DOCKERFILE
+ value: $(params.dockerfile)
+ - name: CONTEXT
+ value: $(params.path-context)
+ - name: HERMETIC
+ value: $(params.hermetic)
+ - name: PREFETCH_INPUT
+ value: $(params.prefetch-input)
+ - name: IMAGE_EXPIRES_AFTER
+ value: $(params.image-expires-after)
+ - name: COMMIT_SHA
+ value: $(tasks.clone-repository.results.commit)
+ - name: BUILD_ARGS
+ value:
+ - $(params.build-args[*])
+ - name: BUILD_ARGS_FILE
+ value: $(params.build-args-file)
+ - name: SOURCE_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
+ - name: CACHI2_ARTIFACT
+ value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
- name: TARGET_DIRS
value: $(params.sast-target-dirs)
+ runAfter:
+ - coverity-availability-check
+ taskRef:
+ params:
+ - name: name
+ value: sast-coverity-check-oci-ta
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-coverity-check-oci-ta:0.3@sha256:e92d00ed858233d0096627861192d3e4fc013cf1559c0d0b0ea0657d3377ce75
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - input: $(tasks.coverity-availability-check.results.STATUS)
+ operator: in
+ values:
+ - success
+ - name: coverity-availability-check
+ runAfter:
+ - build-image-index
+ taskRef:
+ params:
+ - name: name
+ value: coverity-availability-check
+ - name: bundle
+ value: quay.io/konflux-ci/tekton-catalog/task-coverity-availability-check:0.2@sha256:8b501440a960aec446db2ebc6625a49d0317a9fc7bf0f7bd9b18cb63052db7de
+ - name: kind
+ value: task
+ resolver: bundles
+ when:
+ - input: $(params.skip-checks)
+ operator: in
+ values:
+ - "false"
+ - name: sast-shell-check
+ params:
+ - name: image-digest
+ value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: image-url
+ value: $(tasks.build-image-index.results.IMAGE_URL)
- name: SOURCE_ARTIFACT
value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT)
- name: CACHI2_ARTIFACT
value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT)
+ - name: TARGET_DIRS
+ value: $(params.sast-target-dirs)
runAfter:
- build-image-index
taskRef:
@@ -510,6 +617,9 @@ spec:
value: $(tasks.build-image-index.results.IMAGE_URL)
- name: IMAGE_DIGEST
value: $(tasks.build-image-index.results.IMAGE_DIGEST)
+ - name: ADDITIONAL_TAGS
+ value:
+ - $(tasks.clone-repository.results.short-commit)
runAfter:
- build-image-index
taskRef:
@@ -517,7 +627,7 @@ spec:
- name: name
value: apply-tags
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-apply-tags:0.3@sha256:3ab844157eccd68e95e4852adc06c3c4ea674edb7865a474b0a898227f2893d6
+ value: quay.io/konflux-ci/tekton-catalog/task-apply-tags:0.3@sha256:6387614ae4f9efa8abb7c4175db0ce5d958bc2b90665b4704880e46fbe0535bf
- name: kind
value: task
resolver: bundles
@@ -540,7 +650,7 @@ spec:
- name: name
value: push-dockerfile-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-push-dockerfile-oci-ta:0.3.1@sha256:5a6cbebd89e5bc163b38231859767f7f6a0dd66cf1333699574379f062731183
+ value: quay.io/konflux-ci/tekton-catalog/task-push-dockerfile-oci-ta:0.3.1@sha256:5393bada94051f02aa971ff773b130928e01ac595b9ce3bbbd69899751ed8222
- name: kind
value: task
resolver: bundles
@@ -557,7 +667,7 @@ spec:
- name: name
value: rpms-signature-scan
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-rpms-signature-scan:0.2@sha256:ccb77d1bf7627fc6241a59ed42bb6e5707a8682754fe8ae18f2cfdddbcf29275
+ value: quay.io/konflux-ci/tekton-catalog/task-rpms-signature-scan:0.2.1@sha256:ccb77d1bf7627fc6241a59ed42bb6e5707a8682754fe8ae18f2cfdddbcf29275
- name: kind
value: task
resolver: bundles
@@ -571,6 +681,9 @@ spec:
optional: true
- name: netrc
optional: true
+ timeouts:
+ pipeline: 4h
+ tasks: 4h
taskRunTemplate:
serviceAccountName: build-pipeline-lightspeed-stack-0-8
workspaces:
From 24501fa1407dda7a039b4e792cae3a481ba6d0d5 Mon Sep 17 00:00:00 2001
From: "red-hat-konflux-kflux-prd-rh02[bot]"
<190377777+red-hat-konflux-kflux-prd-rh02[bot]@users.noreply.github.com>
Date: Sat, 8 Aug 2026 08:02:28 +0000
Subject: [PATCH 057/197] Update Konflux references
Signed-off-by: red-hat-konflux-kflux-prd-rh02 <190377777+red-hat-konflux-kflux-prd-rh02[bot]@users.noreply.github.com>
---
.../lightspeed-stack-0-8-pull-request.yaml | 26 +++++++++----------
.tekton/lightspeed-stack-0-8-push.yaml | 26 +++++++++----------
2 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/.tekton/lightspeed-stack-0-8-pull-request.yaml b/.tekton/lightspeed-stack-0-8-pull-request.yaml
index 3fdd49476..d0cd6b23b 100644
--- a/.tekton/lightspeed-stack-0-8-pull-request.yaml
+++ b/.tekton/lightspeed-stack-0-8-pull-request.yaml
@@ -192,7 +192,7 @@ spec:
- name: name
value: init
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-init:0.4.3@sha256:b8465d543589b1238f6911626657f5766e279a0f33a5f70de68073401e031184
+ value: quay.io/konflux-ci/tekton-catalog/task-init:0.4.3@sha256:15d3d4a7e5c70b068103a9d4c6ba2e049db8896709fc45c0bd4be49c134b0989
- name: kind
value: task
resolver: bundles
@@ -213,7 +213,7 @@ spec:
- name: name
value: git-clone-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-git-clone-oci-ta:0.2.5@sha256:510daad5648d37936b9b2c599a35c8e59b7389de8e1a4e58f6c6d079957d730d
+ value: quay.io/konflux-ci/tekton-catalog/task-git-clone-oci-ta:0.2.5@sha256:799e6093832d194293168240a6e2209479cfaad33de51d57bfcbcfead97ed038
- name: kind
value: task
resolver: bundles
@@ -239,7 +239,7 @@ spec:
- name: name
value: prefetch-dependencies-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-prefetch-dependencies-oci-ta:0.6.0@sha256:01158b939522c276ba36804c2cc7ef641a572fb6c27f001819ea287dd708cd13
+ value: quay.io/konflux-ci/tekton-catalog/task-prefetch-dependencies-oci-ta:0.7.1@sha256:75109b17ba38c211fafe6aa676868e16c00e451db7b61bc939b0e7cd6035900b
- name: kind
value: task
resolver: bundles
@@ -303,7 +303,7 @@ spec:
- name: name
value: buildah-remote-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-buildah-remote-oci-ta:0.10.7@sha256:94f129a97242995d647b1d23a5d53e7022e0c3dc00aff764a4da4be263263cbf
+ value: quay.io/konflux-ci/tekton-catalog/task-buildah-remote-oci-ta:0.11.0@sha256:78529bcd4a665aad693af8b98b2fed223a0b853c4f0cf3a8620eebdd66f517ea
- name: kind
value: task
resolver: bundles
@@ -325,7 +325,7 @@ spec:
- name: name
value: build-image-index
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-build-image-index:0.3.1@sha256:a355355b7fcd0ba8de4ba85a162a2e6893f53236b943f79cb03ae0ae9c5ef53c
+ value: quay.io/konflux-ci/tekton-catalog/task-build-image-index:0.3.1@sha256:b00c9e68e96d41c95c725805e378ccdda44e0a1e55b69eae3f9d1f0ba1a6a493
- name: kind
value: task
resolver: bundles
@@ -346,7 +346,7 @@ spec:
- name: name
value: source-build-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-source-build-oci-ta:0.3@sha256:6081c4167e87a9167f7db4cda9ff0110607b7b9fc404c3daa076247475a4affa
+ value: quay.io/konflux-ci/tekton-catalog/task-source-build-oci-ta:0.3@sha256:93f1df1d3b51b20974ca25e1f75704dcd989c4e088994a34784d8759e46ce49f
- name: kind
value: task
resolver: bundles
@@ -420,7 +420,7 @@ spec:
- name: name
value: ecosystem-cert-preflight-checks
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-ecosystem-cert-preflight-checks:0.2@sha256:27c9760ad11c74ad010d9615ee15348e3674843166acb7686929b3ef6840416c
+ value: quay.io/konflux-ci/tekton-catalog/task-ecosystem-cert-preflight-checks:0.2@sha256:e438f3104d706f73812994953d3d0a9c62ac8e4a372d86337ff26bbca9902709
- name: kind
value: task
resolver: bundles
@@ -450,7 +450,7 @@ spec:
- name: name
value: sast-snyk-check-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-snyk-check-oci-ta:0.5@sha256:eba24f5d9f4b18aa71e523b9b3dbcf22982aa4b018824260a090b19dfc9abf6f
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-snyk-check-oci-ta:0.5@sha256:f4818f8ae1317ea51f0273d48c8a6a4c53ca7bb0674ffbb8afc9d399ac991dc1
- name: kind
value: task
resolver: bundles
@@ -573,7 +573,7 @@ spec:
- name: name
value: sast-shell-check-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-shell-check-oci-ta:0.1@sha256:61b27e6ad5daba761d41bb37efb790ed98380603fd4fe2f86d156def5bd72ecc
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-shell-check-oci-ta:0.1@sha256:d33d800e2fa1c3e5a5a63550bf860d0c1dfc91bf877be7b27eab6e280972cdc8
- name: kind
value: task
resolver: bundles
@@ -601,7 +601,7 @@ spec:
- name: name
value: sast-unicode-check-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-unicode-check-oci-ta:0.4@sha256:eb9d5392f215cb8b52b16382098cac4885b1e6cd989f88ebd83fdb234d283eb9
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-unicode-check-oci-ta:0.4@sha256:f31055c9ebab00f58c2bf3964818d3cf3ab924a4d8b65d8f9c9cb6487b549de2
- name: kind
value: task
resolver: bundles
@@ -623,7 +623,7 @@ spec:
- name: name
value: apply-tags
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-apply-tags:0.3@sha256:6387614ae4f9efa8abb7c4175db0ce5d958bc2b90665b4704880e46fbe0535bf
+ value: quay.io/konflux-ci/tekton-catalog/task-apply-tags:0.3@sha256:da0cff2a36f07087798cd5f577b15f3d9e6dd4d3d08956227b298362e08ecc37
- name: kind
value: task
resolver: bundles
@@ -646,7 +646,7 @@ spec:
- name: name
value: push-dockerfile-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-push-dockerfile-oci-ta:0.3.1@sha256:5393bada94051f02aa971ff773b130928e01ac595b9ce3bbbd69899751ed8222
+ value: quay.io/konflux-ci/tekton-catalog/task-push-dockerfile-oci-ta:0.3.1@sha256:350a144c002df3dd0312be1a2a1ec4d3efd5a78ec3eb57b6157de2fb766b30c9
- name: kind
value: task
resolver: bundles
@@ -663,7 +663,7 @@ spec:
- name: name
value: rpms-signature-scan
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-rpms-signature-scan:0.2.1@sha256:ccb77d1bf7627fc6241a59ed42bb6e5707a8682754fe8ae18f2cfdddbcf29275
+ value: quay.io/konflux-ci/tekton-catalog/task-rpms-signature-scan:0.2.1@sha256:41ff5935eae38c717552af6ef82b01c2ec16e64eb7131a8002d14ff3746f0f35
- name: kind
value: task
resolver: bundles
diff --git a/.tekton/lightspeed-stack-0-8-push.yaml b/.tekton/lightspeed-stack-0-8-push.yaml
index 359a64293..b55335881 100644
--- a/.tekton/lightspeed-stack-0-8-push.yaml
+++ b/.tekton/lightspeed-stack-0-8-push.yaml
@@ -193,7 +193,7 @@ spec:
- name: name
value: init
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-init:0.4.3@sha256:b8465d543589b1238f6911626657f5766e279a0f33a5f70de68073401e031184
+ value: quay.io/konflux-ci/tekton-catalog/task-init:0.4.3@sha256:15d3d4a7e5c70b068103a9d4c6ba2e049db8896709fc45c0bd4be49c134b0989
- name: kind
value: task
resolver: bundles
@@ -214,7 +214,7 @@ spec:
- name: name
value: git-clone-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-git-clone-oci-ta:0.2.5@sha256:510daad5648d37936b9b2c599a35c8e59b7389de8e1a4e58f6c6d079957d730d
+ value: quay.io/konflux-ci/tekton-catalog/task-git-clone-oci-ta:0.2.5@sha256:799e6093832d194293168240a6e2209479cfaad33de51d57bfcbcfead97ed038
- name: kind
value: task
resolver: bundles
@@ -240,7 +240,7 @@ spec:
- name: name
value: prefetch-dependencies-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-prefetch-dependencies-oci-ta:0.6.0@sha256:01158b939522c276ba36804c2cc7ef641a572fb6c27f001819ea287dd708cd13
+ value: quay.io/konflux-ci/tekton-catalog/task-prefetch-dependencies-oci-ta:0.7.1@sha256:75109b17ba38c211fafe6aa676868e16c00e451db7b61bc939b0e7cd6035900b
- name: kind
value: task
resolver: bundles
@@ -304,7 +304,7 @@ spec:
- name: name
value: buildah-remote-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-buildah-remote-oci-ta:0.10.7@sha256:94f129a97242995d647b1d23a5d53e7022e0c3dc00aff764a4da4be263263cbf
+ value: quay.io/konflux-ci/tekton-catalog/task-buildah-remote-oci-ta:0.11.0@sha256:78529bcd4a665aad693af8b98b2fed223a0b853c4f0cf3a8620eebdd66f517ea
- name: kind
value: task
resolver: bundles
@@ -326,7 +326,7 @@ spec:
- name: name
value: build-image-index
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-build-image-index:0.3.1@sha256:a355355b7fcd0ba8de4ba85a162a2e6893f53236b943f79cb03ae0ae9c5ef53c
+ value: quay.io/konflux-ci/tekton-catalog/task-build-image-index:0.3.1@sha256:b00c9e68e96d41c95c725805e378ccdda44e0a1e55b69eae3f9d1f0ba1a6a493
- name: kind
value: task
resolver: bundles
@@ -347,7 +347,7 @@ spec:
- name: name
value: source-build-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-source-build-oci-ta:0.3@sha256:6081c4167e87a9167f7db4cda9ff0110607b7b9fc404c3daa076247475a4affa
+ value: quay.io/konflux-ci/tekton-catalog/task-source-build-oci-ta:0.3@sha256:93f1df1d3b51b20974ca25e1f75704dcd989c4e088994a34784d8759e46ce49f
- name: kind
value: task
resolver: bundles
@@ -421,7 +421,7 @@ spec:
- name: name
value: ecosystem-cert-preflight-checks
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-ecosystem-cert-preflight-checks:0.2@sha256:27c9760ad11c74ad010d9615ee15348e3674843166acb7686929b3ef6840416c
+ value: quay.io/konflux-ci/tekton-catalog/task-ecosystem-cert-preflight-checks:0.2@sha256:e438f3104d706f73812994953d3d0a9c62ac8e4a372d86337ff26bbca9902709
- name: kind
value: task
resolver: bundles
@@ -451,7 +451,7 @@ spec:
- name: name
value: sast-snyk-check-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-snyk-check-oci-ta:0.5@sha256:eba24f5d9f4b18aa71e523b9b3dbcf22982aa4b018824260a090b19dfc9abf6f
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-snyk-check-oci-ta:0.5@sha256:f4818f8ae1317ea51f0273d48c8a6a4c53ca7bb0674ffbb8afc9d399ac991dc1
- name: kind
value: task
resolver: bundles
@@ -574,7 +574,7 @@ spec:
- name: name
value: sast-shell-check-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-shell-check-oci-ta:0.1@sha256:61b27e6ad5daba761d41bb37efb790ed98380603fd4fe2f86d156def5bd72ecc
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-shell-check-oci-ta:0.1@sha256:d33d800e2fa1c3e5a5a63550bf860d0c1dfc91bf877be7b27eab6e280972cdc8
- name: kind
value: task
resolver: bundles
@@ -602,7 +602,7 @@ spec:
- name: name
value: sast-unicode-check-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-sast-unicode-check-oci-ta:0.4@sha256:eb9d5392f215cb8b52b16382098cac4885b1e6cd989f88ebd83fdb234d283eb9
+ value: quay.io/konflux-ci/tekton-catalog/task-sast-unicode-check-oci-ta:0.4@sha256:f31055c9ebab00f58c2bf3964818d3cf3ab924a4d8b65d8f9c9cb6487b549de2
- name: kind
value: task
resolver: bundles
@@ -627,7 +627,7 @@ spec:
- name: name
value: apply-tags
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-apply-tags:0.3@sha256:6387614ae4f9efa8abb7c4175db0ce5d958bc2b90665b4704880e46fbe0535bf
+ value: quay.io/konflux-ci/tekton-catalog/task-apply-tags:0.3@sha256:da0cff2a36f07087798cd5f577b15f3d9e6dd4d3d08956227b298362e08ecc37
- name: kind
value: task
resolver: bundles
@@ -650,7 +650,7 @@ spec:
- name: name
value: push-dockerfile-oci-ta
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-push-dockerfile-oci-ta:0.3.1@sha256:5393bada94051f02aa971ff773b130928e01ac595b9ce3bbbd69899751ed8222
+ value: quay.io/konflux-ci/tekton-catalog/task-push-dockerfile-oci-ta:0.3.1@sha256:350a144c002df3dd0312be1a2a1ec4d3efd5a78ec3eb57b6157de2fb766b30c9
- name: kind
value: task
resolver: bundles
@@ -667,7 +667,7 @@ spec:
- name: name
value: rpms-signature-scan
- name: bundle
- value: quay.io/konflux-ci/tekton-catalog/task-rpms-signature-scan:0.2.1@sha256:ccb77d1bf7627fc6241a59ed42bb6e5707a8682754fe8ae18f2cfdddbcf29275
+ value: quay.io/konflux-ci/tekton-catalog/task-rpms-signature-scan:0.2.1@sha256:41ff5935eae38c717552af6ef82b01c2ec16e64eb7131a8002d14ff3746f0f35
- name: kind
value: task
resolver: bundles
From 77fbd468a5044c38b92c621d56948aff38465481 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Sun, 9 Aug 2026 10:09:50 +0200
Subject: [PATCH 058/197] LCORE-2922: Updated dependencies
---
uv.lock | 115 ++++++++++++++++++++++++++++++--------------------------
1 file changed, 62 insertions(+), 53 deletions(-)
diff --git a/uv.lock b/uv.lock
index da2330432..a08b5b67f 100644
--- a/uv.lock
+++ b/uv.lock
@@ -169,7 +169,7 @@ wheels = [
[[package]]
name = "anthropic"
-version = "0.120.2"
+version = "0.121.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -181,9 +181,9 @@ dependencies = [
{ name = "sniffio" },
{ name = "typing-extensions" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/d7/10/4ca013cb166f226bd89e0aeb0fcaff94f45ddf716d4925ce89475d3c587b/anthropic-0.120.2.tar.gz", hash = "sha256:9722efc10c27a30a69f5338ddacdb35bc6a64297a4e4ba729bf83af873d5fb3a", size = 1008421, upload-time = "2026-07-28T17:38:26.986Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/ca/3cb2c20ee729736fbd4546d5d8b67e818288529fe70cb7a80dbf80aef70b/anthropic-0.121.0.tar.gz", hash = "sha256:e79d6e08ab3376602fc9a70d4d5ea3540817c76cf7e16658bed790834e1833d6", size = 1013292, upload-time = "2026-08-07T17:11:07.241Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/63/af/0f5db57b9397a0f3b7fc204cbef143401a7cadaf982330f97f1ce3d39f34/anthropic-0.120.2-py3-none-any.whl", hash = "sha256:0f0bc2b381dc0eb41c8d886b815d79c2041cd2374f83aed36f574b6dc9c579c1", size = 1022851, upload-time = "2026-07-28T17:38:25.466Z" },
+ { url = "https://files.pythonhosted.org/packages/fa/91/b3d41643f1f639927e8c5fb02c3bd8bffe6f1f29e219b3bd4c61e267b15c/anthropic-0.121.0-py3-none-any.whl", hash = "sha256:6048713fa441e59e1cba8363171cd2a86273b25bd213e9c7ac70a523af88b011", size = 1035493, upload-time = "2026-08-07T17:11:08.508Z" },
]
[[package]]
@@ -1424,7 +1424,7 @@ wheels = [
[[package]]
name = "huggingface-hub"
-version = "1.26.1"
+version = "1.27.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
@@ -1437,9 +1437,9 @@ dependencies = [
{ name = "tqdm" },
{ name = "typing-extensions" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/89/64/bfe23dab749cb2342e1e13b61c9e684ce46b4d189c7d433cd26f76f52baf/huggingface_hub-1.26.1.tar.gz", hash = "sha256:7c28860777594ac679233f571552d0e46df34ed4e4239e844190fad3ca05e4cd", size = 936700, upload-time = "2026-08-06T09:42:24.859Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/3e/9b/ddf3d02a8681f1b9ce52fda03d755dad6b74c4f8172304c4c8d2975450f9/huggingface_hub-1.27.0.tar.gz", hash = "sha256:c1fed40ea82a6b41b477f5243546549b792ae0a93abcea608cff66089bf8f8df", size = 942668, upload-time = "2026-08-07T12:48:05.161Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b4/a7/b519cd01e57b685c5f3e9db02cb1bd7aaade35fb6554e0d36bee6d6aae28/huggingface_hub-1.26.1-py3-none-any.whl", hash = "sha256:d8676e4ec96c1e481a22a93232bd86d73bbac643fb767399aefaeaa503890fb0", size = 780754, upload-time = "2026-08-06T09:42:22.497Z" },
+ { url = "https://files.pythonhosted.org/packages/de/d8/95b735e183957c1f26d94c52977f09d466d55119cbbc1558ea4975e4c216/huggingface_hub-1.27.0-py3-none-any.whl", hash = "sha256:7df6827c2f956c60fbaa64646e979e566db76f619dd0a9729dfb8c5a3eb4f68d", size = 784926, upload-time = "2026-08-07T12:48:02.905Z" },
]
[[package]]
@@ -1957,7 +1957,7 @@ llslibdev = [
[[package]]
name = "litellm"
-version = "1.95.0"
+version = "1.96.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "aiohttp" },
@@ -1969,18 +1969,27 @@ dependencies = [
{ name = "jsonschema" },
{ name = "openai" },
{ name = "pydantic" },
+ { name = "pydantic-settings" },
{ name = "python-dotenv" },
{ name = "tiktoken" },
{ name = "tokenizers" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/0e/96/8cdfb9aaf584b57af35a0423c111a1c1264a78b548cebbb5ed96defacdab/litellm-1.95.0.tar.gz", hash = "sha256:0ef126d52c7a559f8353e50d60fd0d5e7e6c8767ad54df25ddaf79b9edca1afc", size = 17513577, upload-time = "2026-08-02T02:52:49.465Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/d0/92/1171e76f2a4204a65adb5c827475e4f1d30e7c6a89d3d3e944d58b6fd8a6/litellm-1.96.0.tar.gz", hash = "sha256:340a9b04e1bf8486b0b99f3f6a5556aa59c8f9c16b11b362c95eabea1bcf7a9d", size = 17679976, upload-time = "2026-08-09T01:36:56.266Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/33/d0/ad0272853cc450f8bb4a40a93d206e767e18ac2ff3f91870374e1d9fc090/litellm-1.95.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:cb667f84f08520f32b076e03c7a3fa51bf3f7e8b641dade34ab046bf00314d6b", size = 26421359, upload-time = "2026-08-02T02:52:16.048Z" },
- { url = "https://files.pythonhosted.org/packages/02/c1/4301aa8ef6d2fb0e4a2b8dec973d7c4499f680b26d2e1b77643864235a4b/litellm-1.95.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:1bdf7153557cc0851fa9477b137fde476c56d5de92a5778ecfc6c3a75439a4e1", size = 26300401, upload-time = "2026-08-02T02:52:19.501Z" },
- { url = "https://files.pythonhosted.org/packages/7c/3d/6cd087bd541f18d924f17bd8e1bb68a7f9d73d03274c5339f9de563bc992/litellm-1.95.0-cp312-cp312-win_amd64.whl", hash = "sha256:62cc5d834e8223dbd16c9ad0b46c73354b6d67cc7fa0eba2764ce65b3b8c474f", size = 24917446, upload-time = "2026-08-02T02:52:23.119Z" },
- { url = "https://files.pythonhosted.org/packages/fd/47/719785f65b01779cf7568c329430c93b2e7832498deb3deec53bdd106f8d/litellm-1.95.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:9d80a9adc506bfce48145621d6649e3fd428407811eb00211bcce33344054701", size = 26422310, upload-time = "2026-08-02T02:52:26.626Z" },
- { url = "https://files.pythonhosted.org/packages/55/48/06447e1125d7ae31bd24d34d2af2833b15aed79dc5f7e8b45862c1d06af8/litellm-1.95.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:cf014ff515825ad49937b4cdf95616270789311db7841d16702e0a5b1ac5b067", size = 26300935, upload-time = "2026-08-02T02:52:30.032Z" },
- { url = "https://files.pythonhosted.org/packages/45/6f/388f85ebcb4e239dc738cab99307051d5a8a69d907023b0dbb200ee95226/litellm-1.95.0-cp313-cp313-win_amd64.whl", hash = "sha256:c73df441153e585832d4e90e3717d17ae888b269daa71d723336369e81ef884b", size = 24917355, upload-time = "2026-08-02T02:52:33.593Z" },
+ { url = "https://files.pythonhosted.org/packages/14/7b/706a7176b1d38529b62724f97e75c98facecc1ac6a60a196c589f5b84aca/litellm-1.96.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:518b9b71a4d7582a0f54f93a65ae4f715ba41bc4475f4a2b9096742612f05f4d", size = 25932809, upload-time = "2026-08-09T01:35:57.551Z" },
+ { url = "https://files.pythonhosted.org/packages/57/25/ad9b206ad7170018d95bf4fc777c492921d69c3f6d99e8c396612f23dee8/litellm-1.96.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05da78216567c1b0d288ce17a9650d1b4a45b8b06fe23384b2fc5835a375a8fb", size = 25643217, upload-time = "2026-08-09T01:36:01.186Z" },
+ { url = "https://files.pythonhosted.org/packages/11/a2/5f2a03b19d7718e1d01c2c5a764dece7f768e8e7ea08a8412f130e166af8/litellm-1.96.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:61b2b93a24a1733bc718c2255f5c8cf84fb8ef60ab87f544494dd3386b2be04c", size = 26579330, upload-time = "2026-08-09T01:36:04.114Z" },
+ { url = "https://files.pythonhosted.org/packages/78/86/9a6480a10edff9c772c03d718d50bb4bdea25f5a94ffc3aa623a199f506c/litellm-1.96.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:2e72181f99794d5b6ac01ee18b97a31b7eee93321c9e5b5e5caa36d062822fc0", size = 26443987, upload-time = "2026-08-09T01:36:06.557Z" },
+ { url = "https://files.pythonhosted.org/packages/4d/bb/1c08d953f69f977f5d17e0912d9847512a80ecb43b4d5f235ae61610917f/litellm-1.96.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:66b97502d727259f29c486da38921b698a8c816d9eef7d4706a686c63436387a", size = 26653427, upload-time = "2026-08-09T01:36:09.542Z" },
+ { url = "https://files.pythonhosted.org/packages/72/77/64ee801331b13bc138de73b216e031dd90e0b6f9a1ae24d33c134d830227/litellm-1.96.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0fdd57b61b6cdf0562eb6daec1d7f02a57dec34ba8f33cd3080bfb5e1beba02b", size = 26860925, upload-time = "2026-08-09T01:36:12.231Z" },
+ { url = "https://files.pythonhosted.org/packages/8f/54/6f8395af7b1ebc7b16251cfd521f780fe4826dc634a6947d08f50f3a75f8/litellm-1.96.0-cp312-cp312-win_amd64.whl", hash = "sha256:4d4f454a86736915762ad8e67817992f7e3f1c7aed2b42be32ace4e4ecd1d20c", size = 25054400, upload-time = "2026-08-09T01:36:14.9Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/1e/ac71d20d3c5df942d8877b834e5db190b77395317f436e59c77e5c8b0ef3/litellm-1.96.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:baf13fd3176a569b2924e2c4bb4e82da03a11e1a7cf4144ea2d92a1b40d87c17", size = 25933352, upload-time = "2026-08-09T01:36:17.98Z" },
+ { url = "https://files.pythonhosted.org/packages/ed/1e/76c666f9ba4e0a20d8b3fca8f0af369f97d2e2c2a4874b10b4f344c6bed7/litellm-1.96.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:26d2ae2a5f8a839b757cfb7744ffa0c95f225c583984b99352887fcf4e5456ef", size = 25643356, upload-time = "2026-08-09T01:36:20.535Z" },
+ { url = "https://files.pythonhosted.org/packages/56/fc/48cdbdb1fc6d0ec573bb9b1c04fe81528d84886e1cde0100d4c38e0238f1/litellm-1.96.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:887fd96224c2197897b1df309e9e8d984196a3d18472f908a6aa5a371e569b25", size = 26580407, upload-time = "2026-08-09T01:36:23.345Z" },
+ { url = "https://files.pythonhosted.org/packages/cc/48/c1bddb7e7c328816a0136d94afa455279b825d13e1507b669da2e2be78b8/litellm-1.96.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1a75d7718fc72e526501d568c01f50278206106d1db7d77e6c34973e0877a77f", size = 26444531, upload-time = "2026-08-09T01:36:26.24Z" },
+ { url = "https://files.pythonhosted.org/packages/c7/63/0f4109c7e19bb78735e87f9fcca565750d49a71b022941ba89366f764cd5/litellm-1.96.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:217191eeb91561372e1f079f2925a15753f1c41955256e09e11787d7c1dca94b", size = 26653932, upload-time = "2026-08-09T01:36:28.81Z" },
+ { url = "https://files.pythonhosted.org/packages/65/9e/812d87aee7db46f9cde44ce96aec25de90f1c4f356def2bb7f6d1ec0a011/litellm-1.96.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b1cc10ba307cb31e9a799bfcdcfed4cb0a558c5cfb867a970cc6159d6ec649bc", size = 26861204, upload-time = "2026-08-09T01:36:31.467Z" },
+ { url = "https://files.pythonhosted.org/packages/61/80/0d276c052f54386a491571792818d7e24e3bcf2a1fae45f431cdb4b8c15f/litellm-1.96.0-cp313-cp313-win_amd64.whl", hash = "sha256:d64c7746768aa2df6a85d63bb6ea0a092488584131ed5e0d49e52e4088e60d20", size = 25054138, upload-time = "2026-08-09T01:36:34.391Z" },
]
[[package]]
@@ -2818,11 +2827,11 @@ wheels = [
[[package]]
name = "platformdirs"
-version = "4.11.0"
+version = "4.11.1"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/78/9b/560e4be8e26f6fd133a03630a8df0c663b9e8d61b4ade152b72005aec83b/platformdirs-4.11.0.tar.gz", hash = "sha256:0555d18370482847566ffabcaa53ad7c6c1c29f195989ae1ed634a05f76ea1e0", size = 31953, upload-time = "2026-07-21T13:09:36.565Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/36/0a/062135c9a98dac804265073cc3afdbec5ae1aa37980bb354f461bafe81b4/platformdirs-4.11.1.tar.gz", hash = "sha256:bb1af68078f25e2f3e111e2d43b8d536df41b73c8a684b40bb018223b66fae27", size = 32396, upload-time = "2026-08-07T23:06:48.516Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/7d/68/d8d58938dfb1370b266a1a729e6d77a985be23689a0496498ee17b2cbf90/platformdirs-4.11.0-py3-none-any.whl", hash = "sha256:360ccded2b7fce0af0ff80cc8f5942a1c5d99b0e856033acb030bfc634709e74", size = 23247, upload-time = "2026-07-21T13:09:35.422Z" },
+ { url = "https://files.pythonhosted.org/packages/4c/85/9b31b44296cfa3bb56cddb35e6a0f6578bab0b490c0806c0245e32c6110c/platformdirs-4.11.1-py3-none-any.whl", hash = "sha256:2efd27d363e8dd2e661639ffb398865a5e0a46442a11d266bf375a0e0c10e386", size = 23261, upload-time = "2026-08-07T23:06:47.219Z" },
]
[[package]]
@@ -3155,14 +3164,14 @@ email = [
[[package]]
name = "pydantic-ai"
-version = "2.26.0"
+version = "2.27.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic-ai-slim", extra = ["anthropic", "cli", "evals", "google", "logfire", "mcp", "openai", "retries", "web"] },
]
-sdist = { url = "https://files.pythonhosted.org/packages/cd/2c/58a3d3d21adc76012cb4c46d4da18c19a60c761cb57e2894729338f4f181/pydantic_ai-2.26.0.tar.gz", hash = "sha256:f04585e1b16047e17bfeda8ce5d5f5b549fa3567a000ee2e1f012ac5cc893ccf", size = 19394, upload-time = "2026-08-07T03:34:17.274Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/aa/90/db2d663fd9997bda144ced660d94ea1de5eb0030a152227c64ec7c070fcf/pydantic_ai-2.27.0.tar.gz", hash = "sha256:4ea446ddff54253829e791d16031f560cf07b80337e9ccb9b28c0444dd09dad3", size = 19413, upload-time = "2026-08-08T04:02:45.436Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/af/71/1cf95a9336a77964a9e40d8a99f4dafcbcc7b7aefbee9d43c62e11016b9e/pydantic_ai-2.26.0-py3-none-any.whl", hash = "sha256:1d2324407ed6c206b4c21436059c651051b836fa443b14165236ea9e53379c10", size = 7744, upload-time = "2026-08-07T03:34:08.258Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/d6/769e6e766ccdb70372011484b3c25986bbdd7cf5ed6e04fe5c28938bbd1a/pydantic_ai-2.27.0-py3-none-any.whl", hash = "sha256:000b9758e93600c71471b30216771f8e85b0ae47b3a059351cc03d51a66a9967", size = 7758, upload-time = "2026-08-08T04:02:37.059Z" },
]
[[package]]
@@ -3181,7 +3190,7 @@ wheels = [
[[package]]
name = "pydantic-ai-slim"
-version = "2.26.0"
+version = "2.27.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -3193,9 +3202,9 @@ dependencies = [
{ name = "pydantic-graph" },
{ name = "typing-inspection" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/4f/51/dc39f52dd38c8bf7d8ad6601a936d22064c935505a897c1bf5060e278c95/pydantic_ai_slim-2.26.0.tar.gz", hash = "sha256:d41a40a976885d5f9c6848552fcd6732d5daa8294faf4d3e0138fb28118b6734", size = 1004525, upload-time = "2026-08-07T03:34:19.129Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/90/bb/464898fb1259adb9c7c39a583e7d83447182468d4459a4191ada12d4e588/pydantic_ai_slim-2.27.0.tar.gz", hash = "sha256:9f827840e2ef1d2317e071899e640ac32429b3c19d6ce05d972b842c0ae4a206", size = 1016384, upload-time = "2026-08-08T04:02:47.451Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/9f/ac/e09eb468ccec3180f73828b1e0c59b891cc9ee442be2d28410b02c1d09a3/pydantic_ai_slim-2.26.0-py3-none-any.whl", hash = "sha256:855a23f120328e7a12e8f4371db597d74f65925e20ce335d3a6db81203238f58", size = 1201143, upload-time = "2026-08-07T03:34:11.305Z" },
+ { url = "https://files.pythonhosted.org/packages/26/10/512641450549b15dd0b49600f975991a8b0067c921ec9e9b7caa0e89cff0/pydantic_ai_slim-2.27.0-py3-none-any.whl", hash = "sha256:d30cabd5e60680574f46df2b8d8e78eb7a5dd5d0963fc50e26fa802909130219", size = 1216383, upload-time = "2026-08-08T04:02:39.9Z" },
]
[package.optional-dependencies]
@@ -3281,7 +3290,7 @@ wheels = [
[[package]]
name = "pydantic-evals"
-version = "2.26.0"
+version = "2.27.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -3291,14 +3300,14 @@ dependencies = [
{ name = "pyyaml" },
{ name = "rich" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/88/40/abc913aa36099fb180b906de48ac6101c16b7c90281a4d5a66031931e2d3/pydantic_evals-2.26.0.tar.gz", hash = "sha256:b5bcac364042d18a028b9e747c1f930f171706c23cab50473c769e053b43a4c0", size = 85389, upload-time = "2026-08-07T03:34:20.983Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/5e/8a/e44c210fc0eb317729432b9fa64c92111c4e3aecdbf5c1371f7622ba177f/pydantic_evals-2.27.0.tar.gz", hash = "sha256:dc0ea51e921a50b9d20bc7e99ac437de97d30a4a02a7d38a658b6edfe09cf19c", size = 85734, upload-time = "2026-08-08T04:02:48.819Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/7c/bb/a9d6700db4152b8442639b1d75249c3543ac4f4c76ba83ac6628c97a1fc2/pydantic_evals-2.26.0-py3-none-any.whl", hash = "sha256:41f92eee7270dbb85e6639082256ff14877c1f0bba0d7dda30e683efb6555e0d", size = 100539, upload-time = "2026-08-07T03:34:13.188Z" },
+ { url = "https://files.pythonhosted.org/packages/87/19/3937e472ca6d72a139c772b08cc4557b3e0835485a5ec5d07df428e2ab01/pydantic_evals-2.27.0-py3-none-any.whl", hash = "sha256:e97ee1128b50a4296c557a80bb3f0a5f5bdf6e16576ee7a2822d7fc3d28d6e03", size = 100915, upload-time = "2026-08-08T04:02:41.715Z" },
]
[[package]]
name = "pydantic-graph"
-version = "2.26.0"
+version = "2.27.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -3307,9 +3316,9 @@ dependencies = [
{ name = "pydantic" },
{ name = "typing-inspection" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/39/64/05bf73d982dd778b5613ad224a58ca510aaccf622644d97af93e6006a680/pydantic_graph-2.26.0.tar.gz", hash = "sha256:12d9da6c5a0e2634d89f2795ca15783ee37250fdc295b33b5c14232576dafdac", size = 45181, upload-time = "2026-08-07T03:34:22.049Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/80/50/ed9203338db139ef6d3f94814f6d6b2f6bce4042bb2278299b9ccb307a90/pydantic_graph-2.27.0.tar.gz", hash = "sha256:b124bd5d329d0e01d3b8c4070366a71db198ea9befc8453e56275fb1656da78b", size = 45181, upload-time = "2026-08-08T04:02:49.907Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/bb/59/54302729598308ba437e250473c99ef51625e86997f7ae2ba6b61a2ad00f/pydantic_graph-2.26.0-py3-none-any.whl", hash = "sha256:4599a980747588faf17ac56cfa9c10b2a79723a5a20c3c7ee479e8366653097c", size = 52662, upload-time = "2026-08-07T03:34:14.831Z" },
+ { url = "https://files.pythonhosted.org/packages/f9/ce/6ecafa2680d70ce34b8c3fdc1667228896f1cd19df2f236dd7fa54214117/pydantic_graph-2.27.0-py3-none-any.whl", hash = "sha256:f80a9f1cfbd3c07b64b032b45fa0710315d6d7e2ae35afc142d4992d99498a4d", size = 52661, upload-time = "2026-08-08T04:02:43.282Z" },
]
[[package]]
@@ -3809,27 +3818,27 @@ wheels = [
[[package]]
name = "ruff"
-version = "0.16.1"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/70/25/7113f6d5498888c5fb7db34081cba7d5971c4cb1bfb26819966eee68f003/ruff-0.16.1.tar.gz", hash = "sha256:fedad7c801dabd3fb9741d76aca39246e6ddd9ca446a015875207bf19f1e6bc7", size = 4877500, upload-time = "2026-07-30T19:37:01.379Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/1b/bd/694da69368e0973de65df2ddc73ab18d43c469d5963d9b150911de6bc513/ruff-0.16.1-py3-none-linux_armv6l.whl", hash = "sha256:58edb313b88f0c5460a26adf5f39a37a3be789494a15e3e411e35fa78b89f9a0", size = 10839126, upload-time = "2026-07-30T19:36:13.697Z" },
- { url = "https://files.pythonhosted.org/packages/3f/f0/b626e5d5bd0dd9576263658ef12885e2288afd1029a48e26ffed65ec1ac1/ruff-0.16.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fde5a99e2f97479af66edd6622c6d5a2a7592c77cf4153d9e4428f5eeb55b60c", size = 11070253, upload-time = "2026-07-30T19:36:17.14Z" },
- { url = "https://files.pythonhosted.org/packages/83/63/f40acfb6b35b88623e71684942b552c3edd96035f5d98f313815f7b277de/ruff-0.16.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e0d4c20532fca4f7fa609369161d968dd28f65d83dabbd61d8e9c7edbf7001f6", size = 10561425, upload-time = "2026-07-30T19:36:20.04Z" },
- { url = "https://files.pythonhosted.org/packages/aa/dd/14ec0e9c2b4d315547dd38765004b4863e354e1b52cb308272215d9f6f6d/ruff-0.16.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30affbcedf59ad5703d9c91f82266e02b47739f797e1a7b6e158e5526a6dae38", size = 10948879, upload-time = "2026-07-30T19:36:22.476Z" },
- { url = "https://files.pythonhosted.org/packages/33/e9/9d870cbae575030fdef595f04b4b97573c525b5497cce4f4498cf2f85446/ruff-0.16.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24e9c631573cbca9d20f1283f8f479b2afa4a8503504822bd71a293889f16743", size = 10643691, upload-time = "2026-07-30T19:36:24.914Z" },
- { url = "https://files.pythonhosted.org/packages/c4/09/12743d544e2173f53ecd27217c65f90d2bc0f8424a66a60339e56bbc0457/ruff-0.16.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b41bdd48fb420987a9b5212e4957c26ad4abce401fa9ea9d4d85843727945f4f", size = 11435354, upload-time = "2026-07-30T19:36:28.447Z" },
- { url = "https://files.pythonhosted.org/packages/7f/89/a1652b2daee52083c9554a6333b678a8b01d0400f976827bb87857f9449a/ruff-0.16.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b0d1e1393b7648079e13669de1c1f4fde06d4583e84d8fd5c1551e0a77a2aa75", size = 12259033, upload-time = "2026-07-30T19:36:31.326Z" },
- { url = "https://files.pythonhosted.org/packages/16/96/ecdcb8c54ee7b123b487f807eb014e6e019155a0b81dfb669acd52f28ce3/ruff-0.16.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07bf434b1c95f4e093be4532068ef4fcf00924eb2ade8796075980902d6fd54a", size = 11667981, upload-time = "2026-07-30T19:36:34.394Z" },
- { url = "https://files.pythonhosted.org/packages/cd/90/c52e12e0d862e9572f2a33aa227409143520abe53111e9a6babbac7b4af8/ruff-0.16.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39897739f112253ee4fdd2e8aa9a4f9ded99fb2be367d5f31dfa4ded6025584c", size = 11468183, upload-time = "2026-07-30T19:36:37.339Z" },
- { url = "https://files.pythonhosted.org/packages/2c/6b/4ffb7ad1d83eb16cf8cbb3c8815d3f11c88460fd162d4b372a2059be1c2a/ruff-0.16.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:82ae3c0c0d74daf17b968a10b7b3bb3ef297ab7de0c1f749646b25e690ccb150", size = 11470071, upload-time = "2026-07-30T19:36:39.91Z" },
- { url = "https://files.pythonhosted.org/packages/9c/72/32ae7db4c0b5e32ab611787caa19d1546800676d79f7483b7100a3561bf4/ruff-0.16.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4d5f2ed10f8242d83fc08d521301089364e3375375705356f20c0e31606ef3ef", size = 10919503, upload-time = "2026-07-30T19:36:42.65Z" },
- { url = "https://files.pythonhosted.org/packages/f7/ca/3d901ba6ad6fc38da39c3448fc6c59ac945679293a17c3ceb6d6c1cba13e/ruff-0.16.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a4665b309891f83f3e3c25447935f1213e9abbd4b5640af7a1f2def9f8d413c1", size = 10649861, upload-time = "2026-07-30T19:36:45.18Z" },
- { url = "https://files.pythonhosted.org/packages/92/79/894ef1ced26552d5f8c9cf6d85b0687840e1128c55aeab7b9c2d54a0d880/ruff-0.16.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26e9ca5c9bc3971f20d3cf18a957f52ffd6a5f6564ff15c4912a144dcac22494", size = 11148137, upload-time = "2026-07-30T19:36:47.936Z" },
- { url = "https://files.pythonhosted.org/packages/2d/69/3609a09fa1cb46cc28b762363e440a354204e5dff01bd0c8d7437874d6b9/ruff-0.16.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:67e1e1e3fa4f0c82f0e36d4cd61e661f6e7a6196cb1aa92fe0828fa7b8f257cd", size = 11559211, upload-time = "2026-07-30T19:36:50.448Z" },
- { url = "https://files.pythonhosted.org/packages/fc/8a/fb22af2fd78a736e241fabf67e30ce1799a64244026377a49e133af90762/ruff-0.16.1-py3-none-win32.whl", hash = "sha256:d31765e131295b8445caf301e3e8a85b34d1b9b211b4109b7ba457888b051806", size = 10838258, upload-time = "2026-07-30T19:36:53.298Z" },
- { url = "https://files.pythonhosted.org/packages/d4/35/e57fd9fb5d423961df087a00b12d42c0a830288dc2f3b45ecca299158b4f/ruff-0.16.1-py3-none-win_amd64.whl", hash = "sha256:09b05e8b90c2cb06ad63464350e7a45e8e44a2dfe52072ebfba6666ca8d3f596", size = 11961111, upload-time = "2026-07-30T19:36:56.107Z" },
- { url = "https://files.pythonhosted.org/packages/cb/46/240ea004bf6dc4feb40e9832f2205a476a47dd5b8a3f8211a5fc5f95e20e/ruff-0.16.1-py3-none-win_arm64.whl", hash = "sha256:dbaadaac38c70239f056d306b7476f246b0bf000fa6b3876402acbf5b227eaf8", size = 11309414, upload-time = "2026-07-30T19:36:58.79Z" },
+version = "0.16.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/73/e1/4508a569211b35599016e84ba65c1a992b7a4004b4b6c4bea02a851cba1b/ruff-0.16.2.tar.gz", hash = "sha256:c3d7828d12e8927a6fc65fe38e2c2541b9e762d360a1786d752cb1b8883b3c9c", size = 4885811, upload-time = "2026-08-07T13:31:01.432Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/14/57/db19951540f98859c956b50bdb4d31089b4d91e9f15e2968e7d5193806d5/ruff-0.16.2-py3-none-linux_armv6l.whl", hash = "sha256:3c8de4cf2181f01d57946d87d777aa52916976fc09942aed89938fab5e013318", size = 10847925, upload-time = "2026-08-07T13:30:14.468Z" },
+ { url = "https://files.pythonhosted.org/packages/13/5a/995fe85a8470d3e391ac0f7fa8054bb454eaf33ee138196d6172ed1079c0/ruff-0.16.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9a48cc05c6fbc811ca81b5d7ba95375affea6582d1b8024e455e41afbbf55344", size = 11072662, upload-time = "2026-08-07T13:30:18.143Z" },
+ { url = "https://files.pythonhosted.org/packages/32/53/370d767c61c71a971a4ace36703a7ecd8c393956349a7325d7fab2b56827/ruff-0.16.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a2c0d14fcbb26c91f0f867a6dc9bd71bbc30b1b6151829c884f23faeab2e5700", size = 10566771, upload-time = "2026-08-07T13:30:20.899Z" },
+ { url = "https://files.pythonhosted.org/packages/85/d6/9d96948caf5a632be62d62202d5ec914d6856f204fd79eb036e5915e79ea/ruff-0.16.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:335c621622c4650330be50842561c6586ac6971bb8ab5407fe34dcc9efb16bbe", size = 10975825, upload-time = "2026-08-07T13:30:23.517Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/92/ea87129b3414acb0b5770563779c51804d37ac67675c7ba35447ddb14773/ruff-0.16.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20e66910f2c37cc753f9ef6580c914a621b80c4fa3549d3e3521e29d0f5bfc3f", size = 10649437, upload-time = "2026-08-07T13:30:26.097Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/43/f8f291dcd4af5bb7872b74fdfa41a7cd7c856ca1d4069670971cf1b9f5cb/ruff-0.16.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7e36fbfba65510548156902bcf1350a979a958ce0347ce0f90d73894036b39f", size = 11446761, upload-time = "2026-08-07T13:30:28.752Z" },
+ { url = "https://files.pythonhosted.org/packages/71/4a/ef991fb2fcf516ab71f0808adcdd8da5e18c8cde447f4ceaf5f47a5132a5/ruff-0.16.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f0eab35f80df8f134aae5d1630e751901321d317cc8e50dc39e36fa3ed34cd12", size = 12336364, upload-time = "2026-08-07T13:30:31.468Z" },
+ { url = "https://files.pythonhosted.org/packages/f3/24/f615e74f307e6ca0e56a482872477b856c70d530aa356abfb6dfe5ca8a80/ruff-0.16.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40ea8c0594feb894e89c8c61ab9c103d38b0ea72dfde6c594107147ca31b1140", size = 11630720, upload-time = "2026-08-07T13:30:34.426Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/d3/8ef50149e8412a77f7ab409efdef0e2b23803707a3863da4fc64cb23d459/ruff-0.16.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab3d62dde0b19facdd632008cc4827fc28ada7736c6bd35ab6f1050f0bfed53f", size = 11466130, upload-time = "2026-08-07T13:30:36.958Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/a7/a19334985c4dea8c381981fa252cd854c7ee52dc4b1686dc16f4a911c702/ruff-0.16.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:e43e1f5b8388da9eca1b9e88328d47a5cec794633ccf6f7484ac2dd15eee92c0", size = 11523634, upload-time = "2026-08-07T13:30:39.822Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/6c/96d192b0e742412ceda08c0a50f9669b253dde9fd6a60ea1a10c9fa79a63/ruff-0.16.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c24788a980581e1d7ea3a0cbe4344c4fbeb0a6a9b1f4713aa46bb104f8294690", size = 10949807, upload-time = "2026-08-07T13:30:42.745Z" },
+ { url = "https://files.pythonhosted.org/packages/fa/51/e26599ceca11e79ee255c7df515995561edf87e9ca1893284e44d98f5a86/ruff-0.16.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:81806b08329130005dd4a8a8394a0c9da8c6f4cafb16ba438d2a2ee6a18bedf1", size = 10646891, upload-time = "2026-08-07T13:30:45.522Z" },
+ { url = "https://files.pythonhosted.org/packages/68/01/800c4b1f97bc8d7c6029e06b1f20473a3cf1e13c4933d8f3342add83fc55/ruff-0.16.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4ce4e02bad779bef557f541a1b31f20d6abeae1cc05ed1b1ac019d4ffd1044c8", size = 11162063, upload-time = "2026-08-07T13:30:48.131Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/d0/1477ea50fc5a0d4b0b71d1d63d50770bdd794d90b43e37a7618e63ec9894/ruff-0.16.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e0422abdf70070255fc4073ce9dfc814cc03db577013761ddd09bc1e4a9a4fbd", size = 11556038, upload-time = "2026-08-07T13:30:50.686Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/76/a7776f32048d991e16d4fa8ff91790b877342d3596cc3ed04acdbf1aaedc/ruff-0.16.2-py3-none-win32.whl", hash = "sha256:bf3a63d78fb39f4bf5ac8ae52051c5520505301abe19ba4e204c453b3f09bb0b", size = 10872850, upload-time = "2026-08-07T13:30:53.471Z" },
+ { url = "https://files.pythonhosted.org/packages/00/0d/929c800d920e61397d82a01b60bffc68da3052c17d31de59efaad2e4ed75/ruff-0.16.2-py3-none-win_amd64.whl", hash = "sha256:bcabe2f6d0fc7819f1431793005af4e4de7371927d037345bf941252b195b9fa", size = 12023338, upload-time = "2026-08-07T13:30:56.193Z" },
+ { url = "https://files.pythonhosted.org/packages/5b/6c/93e26c22c5f78ff87363e07da49c84955affbeb1098bd1936bf3b3f293bf/ruff-0.16.2-py3-none-win_arm64.whl", hash = "sha256:d614e95cedf38a2053fd351c55b103ba30d017d61688fdbfd40ee0412852a99f", size = 11374065, upload-time = "2026-08-07T13:30:58.775Z" },
]
[[package]]
@@ -4067,15 +4076,15 @@ wheels = [
[[package]]
name = "starlette"
-version = "1.4.1"
+version = "1.6.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/0f/3c/76d2fd1f1357ed0f0108d8a5aa233dcf16e2946a8559c84912fe08e01ac7/starlette-1.4.1.tar.gz", hash = "sha256:b7332de6e9375593a29ba9eee1e6ecfeb3eb2043e2e19a13b4b71da73ff35540", size = 2709041, upload-time = "2026-08-05T15:17:26.23Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/b5/b4/205b0d5241d934e8add0c38aa924c4f9fb7330834ff11e5444db964ec3f9/starlette-1.6.0.tar.gz", hash = "sha256:d4e3ac5e546444960c710297a3c9fc3f7ebae1b7e963f3d36173b49da535be9b", size = 2716969, upload-time = "2026-08-08T18:27:57.512Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/75/0a/67e95f21498de41433babf7b1db0eeab449eb58872dfb831b27747a70fd0/starlette-1.4.1-py3-none-any.whl", hash = "sha256:7d078e0fbefae0d2cecfb80a799d6fb84b1c0c6acd4f14ac79d17d0e7ec27f19", size = 74019, upload-time = "2026-08-05T15:17:24.357Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/cb/6a6a47d5b464bd08695d254f3da6e7986cc70c9fa5d778eda57538edfe56/starlette-1.6.0-py3-none-any.whl", hash = "sha256:a86dd39d14bb45f85a3d18525215a9ef0cfd1f192ac793220e72598c90335f0c", size = 75969, upload-time = "2026-08-08T18:27:56.196Z" },
]
[[package]]
From 0dd0e5a6586b5839fa98c5458b430301a47c3567 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Sun, 9 Aug 2026 10:13:11 +0200
Subject: [PATCH 059/197] Updated docs for models
---
docs/models/common.json | 21 +++
docs/models/common.md | 16 ++
docs/models/common.puml | 4 +
docs/models/common.svg | 175 +++++++++---------
docs/models/responses.puml | 6 +-
docs/models/responses.svg | 249 ++++++++++++++------------
docs/models/successful_responses.json | 54 ++++++
docs/models/successful_responses.md | 3 +
8 files changed, 326 insertions(+), 202 deletions(-)
diff --git a/docs/models/common.json b/docs/models/common.json
index 52e9d5ddf..7648a7ea1 100644
--- a/docs/models/common.json
+++ b/docs/models/common.json
@@ -1385,6 +1385,27 @@
"title": "ShieldModerationPassed",
"type": "object"
},
+ "SkillMetadata": {
+ "description": "Metadata describing a single loaded agent skill.\n\nAttributes:\n name: Unique name of the skill.\n description: Human readable description of what the skill does.",
+ "properties": {
+ "name": {
+ "description": "Unique name of the skill",
+ "title": "Name",
+ "type": "string"
+ },
+ "description": {
+ "description": "Human readable description of what the skill does",
+ "title": "Description",
+ "type": "string"
+ }
+ },
+ "required": [
+ "name",
+ "description"
+ ],
+ "title": "SkillMetadata",
+ "type": "object"
+ },
"SolrVectorSearchRequest": {
"additionalProperties": false,
"description": "LCORE Solr inline RAG options for vector_io.query (mode and provider filters).\n\nAttributes:\n mode: Solr vector_io search mode. When omitted, the server default (hybrid) is used.\n filters: Solr provider filter payload passed through as params['solr'].\n\nLegacy clients may send a plain JSON object with filter keys only;\nthat object is accepted as filters with mode unset (server default applies).",
diff --git a/docs/models/common.md b/docs/models/common.md
index 332d0d70b..1f8b56246 100644
--- a/docs/models/common.md
+++ b/docs/models/common.md
@@ -670,6 +670,22 @@ Shield moderation passed; no refusal.
| decision | string | |
+## SkillMetadata
+
+
+Metadata describing a single loaded agent skill.
+
+Attributes:
+ name: Unique name of the skill.
+ description: Human readable description of what the skill does.
+
+
+| Field | Type | Description |
+|-------|------|-------------|
+| name | string | Unique name of the skill |
+| description | string | Human readable description of what the skill does |
+
+
## SolrVectorSearchRequest
diff --git a/docs/models/common.puml b/docs/models/common.puml
index fd0d03627..a7fd7d100 100644
--- a/docs/models/common.puml
+++ b/docs/models/common.puml
@@ -234,6 +234,10 @@ class "ShieldModerationBlocked" as src.models.common.moderation.ShieldModeration
class "ShieldModerationPassed" as src.models.common.moderation.ShieldModerationPassed {
decision : Literal['passed']
}
+class "SkillMetadata" as src.models.common.skills.SkillMetadata {
+ description : str
+ name : str
+}
class "SolrVectorSearchRequest" as src.models.common.query.SolrVectorSearchRequest {
filters : Optional[dict[str, Any]]
mode : Optional[Literal['semantic', 'hybrid', 'lexical']]
diff --git a/docs/models/common.svg b/docs/models/common.svg
index 94f0fad80..676c1d91b 100644
--- a/docs/models/common.svg
+++ b/docs/models/common.svg
@@ -467,22 +467,33 @@
decision : Literal['passed']
+
+
+
+
+
+ SkillMetadata
+
+ description : str
+ name : str
+
+
-
-
-
- SolrVectorSearchRequest
-
- filters : Optional[dict[str, Any]]
- mode : Optional[Literal['semantic', 'hybrid', 'lexical']]
- model_config
-
- coerce_legacy_plain_dict(data: Any) -> Any
+
+
+
+ SolrVectorSearchRequest
+
+ filters : Optional[dict[str, Any]]
+ mode : Optional[Literal['semantic', 'hybrid', 'lexical']]
+ model_config
+
+ coerce_legacy_plain_dict(data: Any) -> Any
-
+ StartEventData
@@ -493,7 +504,7 @@
-
+ StartStreamPayload
@@ -505,7 +516,7 @@
-
+ StreamPayloadBase
@@ -517,7 +528,7 @@
-
+ TokenChunkData
@@ -528,7 +539,7 @@
-
+ TokenStreamPayload
@@ -541,7 +552,7 @@
-
+ ToolCallStreamPayload
@@ -553,32 +564,32 @@
-
-
-
- ToolCallSummary
-
- args : dict[str, Any]
- id : str
- name : str
- type : str
-
+
+
+
+ ToolCallSummary
+
+ args : dict[str, Any]
+ id : str
+ name : str
+ type : str
+
-
-
-
- ToolInfoSummary
-
- description : Optional[str]
- input_schema : Optional[dict[str, Any]]
- name : str
-
+
+
+
+ ToolInfoSummary
+
+ description : Optional[str]
+ input_schema : Optional[dict[str, Any]]
+ name : str
+
-
+ ToolResultStreamPayload
@@ -590,21 +601,21 @@
-
-
-
- ToolResultSummary
-
- content : str
- id : str
- round : int
- status : str
- type : str
-
+
+
+
+ ToolResultSummary
+
+ content : str
+ id : str
+ round : int
+ status : str
+ type : str
+
-
+ Transcript
@@ -622,7 +633,7 @@
-
+ TranscriptMetadata
@@ -638,7 +649,7 @@
-
+ TurnCompleteStreamPayload
@@ -650,105 +661,105 @@
-
-
-
- TurnSummary
-
- id : str
- llm_response : str
- next_chunk_id : int
- output_items : list[OpenAIResponseOutput]
- partial_tokens : list[str]
- rag_chunks : list[RAGChunk]
- referenced_documents : list[ReferencedDocument]
- token_usage
- tool_calls : list[ToolCallSummary]
- tool_results : list[ToolResultSummary]
-
+
+
+
+ TurnSummary
+
+ id : str
+ llm_response : str
+ next_chunk_id : int
+ output_items : list[OpenAIResponseOutput]
+ partial_tokens : list[str]
+ rag_chunks : list[RAGChunk]
+ referenced_documents : list[ReferencedDocument]
+ token_usage
+ tool_calls : list[ToolCallSummary]
+ tool_results : list[ToolResultSummary]
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+ data
-
+ data
-
+ data
-
+ data
-
+ data
-
+ data
-
+ metadata
-
+
diff --git a/docs/models/responses.puml b/docs/models/responses.puml
index 5c336fe31..602464060 100644
--- a/docs/models/responses.puml
+++ b/docs/models/responses.puml
@@ -27,7 +27,7 @@ class "BadRequestResponse" as src.models.api.responses.error.bad_request.BadRequ
}
class "ConfigurationResponse" as src.models.api.responses.successful.configuration.ConfigurationResponse {
configuration
- model_config : ConfigDict
+ model_config
}
class "ConflictResponse" as src.models.api.responses.error.conflict.ConflictResponse {
description : ClassVar[str]
@@ -298,6 +298,10 @@ class "ShieldsResponse" as src.models.api.responses.successful.catalog.ShieldsRe
model_config : dict
shields : list[CatalogShield]
}
+class "SkillsResponse" as src.models.api.responses.successful.catalog.SkillsResponse {
+ model_config : dict
+ skills : list[SkillMetadata]
+}
class "StatusResponse" as src.models.api.responses.successful.probes.StatusResponse {
functionality : str
model_config : dict
diff --git a/docs/models/responses.svg b/docs/models/responses.svg
index 94262b458..4fb01bca1 100644
--- a/docs/models/responses.svg
+++ b/docs/models/responses.svg
@@ -70,7 +70,7 @@
ConfigurationResponseconfiguration
- model_config : ConfigDict
+ model_config
@@ -629,169 +629,180 @@
shields : list[CatalogShield]
+
+
+
+
+
+ SkillsResponse
+
+ model_config : dict
+ skills : list[SkillMetadata]
+
+
-
-
-
- StatusResponse
-
- functionality : str
- model_config : dict
- status : dict[str, Any]
-
+
+
+
+ StatusResponse
+
+ functionality : str
+ model_config : dict
+ status : dict[str, Any]
+
-
-
-
- StreamingInterruptResponse
-
- interrupted : bool
- message : str
- model_config : dict
- request_id : str
-
+
+
+
+ StreamingInterruptResponse
+
+ interrupted : bool
+ message : str
+ model_config : dict
+ request_id : str
+
-
-
-
- StreamingQueryResponse
-
- model_config : dict
-
- openapi_response() -> dict[str, Any]
+
+
+
+ StreamingQueryResponse
+
+ model_config : dict
+
+ openapi_response() -> dict[str, Any]
-
-
-
- ToolsResponse
-
- model_config : dict
- tools : list[CatalogTool]
-
+
+
+
+ ToolsResponse
+
+ model_config : dict
+ tools : list[CatalogTool]
+
-
-
-
- UnauthorizedResponse
-
- description : ClassVar[str]
- model_config : dict
-
+
+
+
+ UnauthorizedResponse
+
+ description : ClassVar[str]
+ model_config : dict
+
-
-
-
- UnprocessableEntityResponse
-
- description : ClassVar[str]
- model_config : dict
-
+
+
+
+ UnprocessableEntityResponse
+
+ description : ClassVar[str]
+ model_config : dict
+
-
-
-
- VectorStoreDeleteResponse
-
- model_config : dict
- resource_name : ClassVar[str]
- vector_store_id : str
-
+
+
+
+ VectorStoreDeleteResponse
+
+ model_config : dict
+ resource_name : ClassVar[str]
+ vector_store_id : str
+
-
-
-
- VectorStoreFileDeleteResponse
-
- file_id : str
- model_config : dict
- resource_name : ClassVar[str]
-
+
+
+
+ VectorStoreFileDeleteResponse
+
+ file_id : str
+ model_config : dict
+ resource_name : ClassVar[str]
+
-
-
-
- VectorStoreFileResponse
-
- attributes : Optional[dict[str, str | float | bool]]
- id : str
- last_error : Optional[str]
- model_config : dict
- object : str
- status : str
- vector_store_id : str
-
+
+
+
+ VectorStoreFileResponse
+
+ attributes : Optional[dict[str, str | float | bool]]
+ id : str
+ last_error : Optional[str]
+ model_config : dict
+ object : str
+ status : str
+ vector_store_id : str
+
-
-
-
- VectorStoreFilesListResponse
-
- data : list[VectorStoreFileResponse]
- model_config : dict
- object : str
-
+
+
+
+ VectorStoreFilesListResponse
+
+ data : list[VectorStoreFileResponse]
+ model_config : dict
+ object : str
+
-
-
-
- VectorStoreResponse
-
- created_at : int
- expires_at : Optional[int]
- id : str
- last_active_at : Optional[int]
- metadata : Optional[dict[str, Any]]
- model_config : dict
- name : str
- status : str
- usage_bytes : int
-
+
+
+
+ VectorStoreResponse
+
+ created_at : int
+ expires_at : Optional[int]
+ id : str
+ last_active_at : Optional[int]
+ metadata : Optional[dict[str, Any]]
+ model_config : dict
+ name : str
+ status : str
+ usage_bytes : int
+
-
-
-
- VectorStoresListResponse
-
- data : list[VectorStoreResponse]
- model_config : dict
- object : str
-
+
+
+
+ VectorStoresListResponse
+
+ data : list[VectorStoreResponse]
+ model_config : dict
+ object : str
+
-
+ detail
-
+ data
-
+
diff --git a/docs/models/successful_responses.json b/docs/models/successful_responses.json
index 0b931d10f..d37c7a886 100644
--- a/docs/models/successful_responses.json
+++ b/docs/models/successful_responses.json
@@ -104,6 +104,7 @@
"feedback",
"get_models",
"get_tools",
+ "get_skills",
"get_shields",
"list_providers",
"get_provider",
@@ -5896,6 +5897,27 @@
"title": "ShieldsResponse",
"type": "object"
},
+ "SkillMetadata": {
+ "description": "Metadata describing a single loaded agent skill.\n\nAttributes:\n name: Unique name of the skill.\n description: Human readable description of what the skill does.",
+ "properties": {
+ "name": {
+ "description": "Unique name of the skill",
+ "title": "Name",
+ "type": "string"
+ },
+ "description": {
+ "description": "Human readable description of what the skill does",
+ "title": "Description",
+ "type": "string"
+ }
+ },
+ "required": [
+ "name",
+ "description"
+ ],
+ "title": "SkillMetadata",
+ "type": "object"
+ },
"SkillsConfiguration": {
"additionalProperties": false,
"description": "Agent skills configuration.\n\nSpecifies paths to skill directories. Skill metadata (name, description)\nis read from SKILL.md frontmatter at startup.\n\nEach path can point to either:\n- A directory containing a SKILL.md file (single skill)\n- A directory containing subdirectories with SKILL.md files (multiple skills)\n\nPaths are validated at startup to ensure they exist and contain valid SKILL.md files.",
@@ -5913,6 +5935,38 @@
"title": "SkillsConfiguration",
"type": "object"
},
+ "SkillsResponse": {
+ "description": "Model representing a response to skills request.\n\nAttributes:\n skills: List of loaded skills with metadata (name and description).",
+ "examples": [
+ {
+ "skills": [
+ {
+ "description": "Review code for quality and security",
+ "name": "code-review"
+ },
+ {
+ "description": "Troubleshoot OpenShift cluster issues",
+ "name": "openshift-troubleshooting"
+ }
+ ]
+ }
+ ],
+ "properties": {
+ "skills": {
+ "description": "List of loaded skills with metadata",
+ "items": {
+ "$ref": "`#/components/schemas/`SkillMetadata"
+ },
+ "title": "Skills",
+ "type": "array"
+ }
+ },
+ "required": [
+ "skills"
+ ],
+ "title": "SkillsResponse",
+ "type": "object"
+ },
"SplunkConfiguration": {
"additionalProperties": false,
"description": "Splunk HEC (HTTP Event Collector) configuration.\n\nSplunk HEC allows sending events directly to Splunk over HTTP/HTTPS.\nThis configuration is used to send telemetry events for inference\nrequests to the corporate Splunk deployment.\n\nUseful resources:\n\n - [Splunk HEC Docs](https://docs.splunk.com/Documentation/SplunkCloud)\n - [About HEC](https://docs.splunk.com/Documentation/Splunk/latest/Data)",
diff --git a/docs/models/successful_responses.md b/docs/models/successful_responses.md
index 37797dad0..1322be546 100644
--- a/docs/models/successful_responses.md
+++ b/docs/models/successful_responses.md
@@ -2576,6 +2576,9 @@ Paths are validated at startup to ensure they exist and contain valid SKILL.md f
Model representing a response to skills request.
+Attributes:
+ skills: List of loaded skills with metadata (name and description).
+
| Field | Type | Description |
|-------|------|-------------|
From 30cc11ef0874959caa087308b3eefe2d6bbb973e Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Sun, 9 Aug 2026 10:13:19 +0200
Subject: [PATCH 060/197] Updated devel documentation
---
src/app/endpoints/README.md | 4 ++++
src/models/common/README.md | 4 ++++
tests/integration/endpoints/README.md | 4 ++++
tests/unit/app/endpoints/README.md | 4 ++++
4 files changed, 16 insertions(+)
diff --git a/src/app/endpoints/README.md b/src/app/endpoints/README.md
index 477b59762..d4984fea7 100644
--- a/src/app/endpoints/README.md
+++ b/src/app/endpoints/README.md
@@ -96,6 +96,10 @@ Handler for REST API calls to manage saved prompts.
Handler for REST API call to list available shields.
+## [skills.py](skills.py)
+
+Handler for REST API call to list loaded agent skills.
+
## [stream_interrupt.py](stream_interrupt.py)
Endpoint for interrupting in-progress streaming query requests.
diff --git a/src/models/common/README.md b/src/models/common/README.md
index bc7cf1578..9e513deb5 100644
--- a/src/models/common/README.md
+++ b/src/models/common/README.md
@@ -36,6 +36,10 @@ Shared query-related request primitives.
Catalog models for the ``/shields`` endpoint.
+## [skills.py](skills.py)
+
+Metadata models for agent skills shared across the skills endpoint and helpers.
+
## [tools.py](tools.py)
Backend-agnostic tool listing models.
diff --git a/tests/integration/endpoints/README.md b/tests/integration/endpoints/README.md
index 604a13aaa..f12fb8872 100644
--- a/tests/integration/endpoints/README.md
+++ b/tests/integration/endpoints/README.md
@@ -60,6 +60,10 @@ Integration tests for the /root endpoint.
Integration tests for the /v1/saved-prompts REST API endpoints.
+## [test_skills_integration.py](test_skills_integration.py)
+
+Integration tests for the /v1/skills endpoint.
+
## [test_stream_interrupt_integration.py](test_stream_interrupt_integration.py)
Integration tests for the streaming query interrupt lifecycle.
diff --git a/tests/unit/app/endpoints/README.md b/tests/unit/app/endpoints/README.md
index 2e75c8c92..71655b2fe 100644
--- a/tests/unit/app/endpoints/README.md
+++ b/tests/unit/app/endpoints/README.md
@@ -96,6 +96,10 @@ Unit tests for the /saved-prompts REST API endpoints.
Unit tests for the /shields REST API endpoint.
+## [test_skills.py](test_skills.py)
+
+Unit tests for skills endpoint.
+
## [test_stream_interrupt.py](test_stream_interrupt.py)
Unit tests for streaming query interrupt endpoint.
From cd5f5d3314bf723557b5c8d338336f5d00a1a7fa Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Sun, 9 Aug 2026 10:25:15 +0200
Subject: [PATCH 061/197] LCORE-3473: Added new requests model
---
src/utils/models_dumper.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/utils/models_dumper.py b/src/utils/models_dumper.py
index c0a98b32f..0c77346ed 100644
--- a/src/utils/models_dumper.py
+++ b/src/utils/models_dumper.py
@@ -33,6 +33,7 @@
r.RlsapiV1InferRequest,
r.RlsapiV1SystemInfo,
r.RlsapiV1Terminal,
+ r.SavedPromptCreateRequest,
r.StreamingInterruptRequest,
r.VectorStoreCreateRequest,
r.VectorStoreFileCreateRequest,
From 422591f5c0df7416dd3270f5970f591c00f6ec32 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Sun, 9 Aug 2026 10:25:26 +0200
Subject: [PATCH 062/197] Updated unit tests accordingly
---
tests/unit/utils/test_models_dumper.py | 1090 +++++++++++++++++++++---
1 file changed, 988 insertions(+), 102 deletions(-)
diff --git a/tests/unit/utils/test_models_dumper.py b/tests/unit/utils/test_models_dumper.py
index da55ab76d..c808f4ed3 100644
--- a/tests/unit/utils/test_models_dumper.py
+++ b/tests/unit/utils/test_models_dumper.py
@@ -161,7 +161,8 @@ def test_dump_models(tmpdir: Path) -> None:
"read_vector_stores",
"manage_files",
"manage_prompts",
- "read_prompts"
+ "read_prompts",
+ "manage_saved_prompts"
],
"title": "Action",
"type": "string"
@@ -203,7 +204,7 @@ def test_dump_models(tmpdir: Path) -> None:
},
"Attachment": {
"additionalProperties": false,
- "description": "Model representing an attachment that can be sent from the UI as part of query.\n\nA list of attachments can be an optional part of 'query' request.\n\nAttributes:\n attachment_type: The attachment type, like \"log\", \"configuration\" etc.\n content_type: The content type as defined in MIME standard\n content: The actual attachment content",
+ "description": "Model representing an attachment that can be sent from the UI as part of query.\n\nA list of attachments can be an optional part of 'query' request.\n\nAttributes:\n attachment_type: The attachment type, like \"log\", \"configuration\", \"image\" etc.\n content_type: The content type as defined in MIME standard\n content: The actual attachment content (text or base64-encoded image data)",
"examples": [
{
"attachment_type": "log",
@@ -219,13 +220,19 @@ def test_dump_models(tmpdir: Path) -> None:
"attachment_type": "configuration",
"content": "foo: bar",
"content_type": "application/yaml"
+ },
+ {
+ "attachment_type": "image",
+ "content": "",
+ "content_type": "image/png"
}
],
"properties": {
"attachment_type": {
- "description": "The attachment type, like 'log', 'configuration' etc.",
+ "description": "The attachment type, like 'log', 'configuration', 'image' etc.",
"examples": [
- "log"
+ "log",
+ "image"
],
"title": "Attachment Type",
"type": "string"
@@ -233,13 +240,15 @@ def test_dump_models(tmpdir: Path) -> None:
"content_type": {
"description": "The content type as defined in MIME standard",
"examples": [
- "text/plain"
+ "text/plain",
+ "image/jpeg",
+ "image/png"
],
"title": "Content Type",
"type": "string"
},
"content": {
- "description": "The actual attachment content",
+ "description": "The actual attachment content (text or base64-encoded image data)",
"examples": [
"warning: quota exceeded"
],
@@ -632,6 +641,182 @@ def test_dump_models(tmpdir: Path) -> None:
"title": "CORSConfiguration",
"type": "object"
},
+ "CatalogModel": {
+ "description": "Normalized model entry used by ``/models`` and internal model resolution.\n\nUnifies OpenAI-style, Anthropic, and Google ``models.list()`` payloads into\none catalog shape.",
+ "properties": {
+ "identifier": {
+ "description": "Model identifier",
+ "title": "Identifier",
+ "type": "string"
+ },
+ "metadata": {
+ "additionalProperties": true,
+ "description": "Provider-specific metadata excluding core catalog fields",
+ "title": "Metadata",
+ "type": "object"
+ },
+ "api_model_type": {
+ "description": "API model type (typically mirrors model_type)",
+ "title": "Api Model Type",
+ "type": "string"
+ },
+ "provider_id": {
+ "description": "Provider identifier",
+ "title": "Provider Id",
+ "type": "string"
+ },
+ "type": {
+ "default": "model",
+ "description": "Object type, always 'model'",
+ "title": "Type",
+ "type": "string"
+ },
+ "provider_resource_id": {
+ "default": "",
+ "description": "Provider-native resource identifier for the model",
+ "title": "Provider Resource Id",
+ "type": "string"
+ },
+ "model_type": {
+ "description": "Model type such as 'llm' or 'embedding'",
+ "title": "Model Type",
+ "type": "string"
+ }
+ },
+ "required": [
+ "identifier",
+ "api_model_type",
+ "provider_id",
+ "model_type"
+ ],
+ "title": "CatalogModel",
+ "type": "object"
+ },
+ "CatalogShield": {
+ "description": "Shield entry in the ``/shields`` catalog response.\n\nAttributes:\n name: Unique, user-facing name identifying this shield instance.\n provider_id: Shield provider / type discriminator.\n type: Catalog entry type; always shield.\n config: Type-specific shield configuration.",
+ "properties": {
+ "name": {
+ "description": "Unique, user-facing name of the shield instance",
+ "title": "Name",
+ "type": "string"
+ },
+ "provider_id": {
+ "description": "Shield provider / type discriminator",
+ "enum": [
+ "question_validity",
+ "redaction"
+ ],
+ "title": "Provider Id",
+ "type": "string"
+ },
+ "type": {
+ "const": "shield",
+ "default": "shield",
+ "description": "Catalog entry type; always shield",
+ "title": "Type",
+ "type": "string"
+ },
+ "config": {
+ "additionalProperties": true,
+ "description": "Type-specific shield configuration",
+ "title": "Config",
+ "type": "object"
+ }
+ },
+ "required": [
+ "name",
+ "provider_id",
+ "config"
+ ],
+ "title": "CatalogShield",
+ "type": "object"
+ },
+ "CatalogTool": {
+ "description": "Tool entry in the ``/tools`` catalog response.",
+ "properties": {
+ "identifier": {
+ "title": "Identifier",
+ "type": "string"
+ },
+ "description": {
+ "title": "Description",
+ "type": "string"
+ },
+ "parameters": {
+ "items": {
+ "$ref": "`#/components/schemas/`CatalogToolParameter"
+ },
+ "title": "Parameters",
+ "type": "array"
+ },
+ "provider_id": {
+ "title": "Provider Id",
+ "type": "string"
+ },
+ "toolgroup_id": {
+ "title": "Toolgroup Id",
+ "type": "string"
+ },
+ "server_source": {
+ "title": "Server Source",
+ "type": "string"
+ },
+ "type": {
+ "default": "tool",
+ "title": "Type",
+ "type": "string"
+ }
+ },
+ "required": [
+ "identifier",
+ "description",
+ "parameters",
+ "provider_id",
+ "toolgroup_id",
+ "server_source"
+ ],
+ "title": "CatalogTool",
+ "type": "object"
+ },
+ "CatalogToolParameter": {
+ "description": "Parameter entry for a tool in the ``/tools`` catalog response.",
+ "properties": {
+ "name": {
+ "title": "Name",
+ "type": "string"
+ },
+ "description": {
+ "title": "Description",
+ "type": "string"
+ },
+ "parameter_type": {
+ "title": "Parameter Type",
+ "type": "string"
+ },
+ "required": {
+ "default": false,
+ "title": "Required",
+ "type": "boolean"
+ },
+ "default": {
+ "anyOf": [
+ {},
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Default"
+ }
+ },
+ "required": [
+ "name",
+ "description",
+ "parameter_type"
+ ],
+ "title": "CatalogToolParameter",
+ "type": "object"
+ },
"CompactionConfiguration": {
"additionalProperties": false,
"description": "Configuration for conversation history compaction.\n\nCompaction summarizes older conversation turns when their estimated\ntoken count approaches the context window limit, keeping the\nconversation usable instead of failing with HTTP 413. The\nconfiguration here controls when compaction triggers and how much\nrecent context is preserved verbatim.\n\nAttributes:\n enabled: Master switch. When False, compaction never triggers\n and other fields are inert.\n threshold_ratio: Trigger compaction when estimated input tokens\n exceed this fraction of the model's context window\n (clamped to 0.0..1.0).\n token_floor: Minimum estimated token count before compaction\n can trigger, regardless of threshold_ratio. Prevents\n triggering on very small context windows.\n buffer_turns: Initial number of recent turns to keep verbatim.\n The runtime applies a degrading guard \u2014 if these turns\n exceed the available budget, it reduces buffer_turns by\n one repeatedly until the budget fits, down to zero.\n buffer_max_ratio: Hard cap on the fraction of the context\n window the buffer zone may occupy, regardless of\n buffer_turns.",
@@ -767,6 +952,11 @@ def test_dump_models(tmpdir: Path) -> None:
"title": "BYOK RAG configuration",
"type": "array"
},
+ "vector_store": {
+ "$ref": "`#/components/schemas/`VectorStoreConfiguration",
+ "description": "Dynamic vector-store provider capacity for runtime POST /v1/vector-stores creates. Not the same as byok_rag (static registered corpora). When providers is non-empty, default_provider is required and must match one of providers[].id. Applied in unified synthesis only.",
+ "title": "Vector store configuration"
+ },
"a2a_state": {
"$ref": "`#/components/schemas/`A2AStateConfiguration",
"description": "Configuration for A2A protocol persistent state storage.",
@@ -806,6 +996,11 @@ def test_dump_models(tmpdir: Path) -> None:
"description": "Splunk HEC configuration for sending telemetry events.",
"title": "Splunk configuration"
},
+ "observability": {
+ "$ref": "`#/components/schemas/`ObservabilityConfiguration",
+ "description": "OpenTelemetry and observability configuration collected from OTEL_* environment variables.",
+ "title": "Observability configuration"
+ },
"deployment_environment": {
"default": "development",
"description": "Deployment environment name (e.g., 'development', 'staging', 'production'). Used in telemetry events.",
@@ -844,6 +1039,28 @@ def test_dump_models(tmpdir: Path) -> None:
"$ref": "`#/components/schemas/`SavedPromptsConfiguration",
"description": "Configuration for saved prompts feature limits including maximum prompts per user, display name length, and content length.",
"title": "Saved prompts configuration"
+ },
+ "shields": {
+ "description": "List of pydantic-ai-lightspeed agent guardrail shields (question validity and PII redaction). Each entry has a unique 'name', a 'provider_id' ('question_validity' or 'redaction'), and a type-specific 'config'.",
+ "items": {
+ "discriminator": {
+ "mapping": {
+ "question_validity": "`#/components/schemas/`QuestionValidityShieldConfiguration",
+ "redaction": "`#/components/schemas/`RedactionShieldConfiguration"
+ },
+ "propertyName": "provider_id"
+ },
+ "oneOf": [
+ {
+ "$ref": "`#/components/schemas/`QuestionValidityShieldConfiguration"
+ },
+ {
+ "$ref": "`#/components/schemas/`RedactionShieldConfiguration"
+ }
+ ]
+ },
+ "title": "Shields configuration",
+ "type": "array"
}
},
"required": [
@@ -899,6 +1116,15 @@ def test_dump_models(tmpdir: Path) -> None:
}
],
"name": "lightspeed-stack",
+ "observability": {
+ "otel": {
+ "OTEL_EXPORTER_OTLP_ENDPOINT": "",
+ "OTEL_EXPORTER_OTLP_HEADERS": "api-key=[REDACTED]",
+ "OTEL_EXPORTER_OTLP_PROTOCOL": "",
+ "OTEL_SDK_DISABLED": "true",
+ "OTEL_SERVICE_NAME": ""
+ }
+ },
"quota_handlers": {
"enable_token_history": false,
"limiters": [],
@@ -1765,6 +1991,67 @@ def test_dump_models(tmpdir: Path) -> None:
"title": "ErrorStreamPayload",
"type": "object"
},
+ "FaissVectorStoreProvider": {
+ "additionalProperties": false,
+ "description": "Dynamic FAISS vector-store provider (runtime create capacity).",
+ "properties": {
+ "id": {
+ "description": "Llama Stack vector_io provider_id. Surrounding whitespace is stripped before validation and emission.",
+ "minLength": 1,
+ "title": "Provider ID",
+ "type": "string"
+ },
+ "embedding_model": {
+ "description": "Embedding model identification used for stores created against this provider.",
+ "minLength": 1,
+ "title": "Embedding model",
+ "type": "string"
+ },
+ "embedding_dimension": {
+ "description": "Dimensionality of embedding vectors for this provider.",
+ "minimum": 0,
+ "title": "Embedding dimension",
+ "type": "integer"
+ },
+ "type": {
+ "const": "faiss",
+ "default": "faiss",
+ "description": "Product type for this dynamic vector-store provider.",
+ "title": "Provider type",
+ "type": "string"
+ },
+ "config": {
+ "$ref": "`#/components/schemas/`FaissVectorStoreProviderConfig",
+ "description": "FAISS storage settings for this provider.",
+ "title": "Storage config"
+ }
+ },
+ "required": [
+ "id",
+ "embedding_model",
+ "embedding_dimension",
+ "config"
+ ],
+ "title": "FaissVectorStoreProvider",
+ "type": "object"
+ },
+ "FaissVectorStoreProviderConfig": {
+ "additionalProperties": false,
+ "description": "Storage config for a FAISS dynamic vector-store provider.",
+ "properties": {
+ "path": {
+ "description": "On-disk FAISS/SQLite path for this provider.",
+ "minLength": 1,
+ "title": "DB path",
+ "type": "string"
+ }
+ },
+ "required": [
+ "path"
+ ],
+ "title": "FaissVectorStoreProviderConfig",
+ "type": "object"
+ },
"FeedbackCategory": {
"description": "Enum representing predefined feedback categories for AI responses.\n\nThese categories help provide structured feedback about AI inference quality\nwhen users provide negative feedback (thumbs down). Multiple categories can\nbe selected to provide comprehensive feedback about response issues.",
"enum": [
@@ -2053,6 +2340,13 @@ def test_dump_models(tmpdir: Path) -> None:
},
"label": "conversation delete"
},
+ {
+ "detail": {
+ "cause": "User 6789 does not have permission to delete saved prompt with ID abc123",
+ "response": "User does not have permission to perform this action"
+ },
+ "label": "saved prompt delete"
+ },
{
"detail": {
"cause": "User 6789 is not authorized to access this endpoint.",
@@ -3194,8 +3488,7 @@ def test_dump_models(tmpdir: Path) -> None:
"models": {
"description": "List of models available",
"items": {
- "additionalProperties": true,
- "type": "object"
+ "$ref": "`#/components/schemas/`CatalogModel"
},
"title": "Models",
"type": "array"
@@ -3272,13 +3565,6 @@ def test_dump_models(tmpdir: Path) -> None:
"response": "Prompt not found"
},
"label": "prompt"
- },
- {
- "detail": {
- "cause": "Saved Prompt with ID 123e4567-e89b-12d3-a456-426614174000 does not exist",
- "response": "Saved Prompt not found"
- },
- "label": "saved prompt"
}
],
"properties": {
@@ -3299,6 +3585,22 @@ def test_dump_models(tmpdir: Path) -> None:
"title": "NotFoundResponse",
"type": "object"
},
+ "ObservabilityConfiguration": {
+ "additionalProperties": false,
+ "description": "OpenTelemetry observability configuration.\n\nThis configuration is automatically populated from OTEL_* environment variables\nto provide visibility into the active tracing setup.\n\nAttributes:\n otel: Dictionary of OTEL_* environment variables with secrets redacted.",
+ "properties": {
+ "otel": {
+ "additionalProperties": {
+ "type": "string"
+ },
+ "description": "Active OpenTelemetry configuration from OTEL_* environment variables",
+ "title": "OpenTelemetry configuration",
+ "type": "object"
+ }
+ },
+ "title": "ObservabilityConfiguration",
+ "type": "object"
+ },
"OkpConfiguration": {
"additionalProperties": false,
"description": "OKP (Offline Knowledge Portal) provider configuration.\n\nControls provider-specific behaviour for the OKP vector store.\nOnly relevant when ``\"okp\"`` is listed in ``rag.inline`` or ``rag.tool``.",
@@ -3363,6 +3665,7 @@ def test_dump_models(tmpdir: Path) -> None:
"type": "object"
},
"OpenAIResponseAnnotationContainerFileCitation": {
+ "description": "Container file citation annotation referencing a file within a container.",
"properties": {
"type": {
"const": "container_file_citation",
@@ -3432,6 +3735,7 @@ def test_dump_models(tmpdir: Path) -> None:
"type": "object"
},
"OpenAIResponseAnnotationFilePath": {
+ "description": "File path annotation referencing a generated file in response content.",
"properties": {
"type": {
"const": "file_path",
@@ -3774,6 +4078,7 @@ def test_dump_models(tmpdir: Path) -> None:
"type": "object"
},
"OpenAIResponseInputToolChoiceMode": {
+ "description": "Enumeration of simple tool choice modes for response generation.",
"enum": [
"auto",
"required",
@@ -4105,6 +4410,7 @@ def test_dump_models(tmpdir: Path) -> None:
"type": "object"
},
"OpenAIResponseOutputMessageContentOutputText": {
+ "description": "Text content within an output message of an OpenAI response.",
"properties": {
"text": {
"title": "Text",
@@ -4354,72 +4660,168 @@ def test_dump_models(tmpdir: Path) -> None:
"title": "OpenAIResponseOutputMessageMCPListTools",
"type": "object"
},
- "OpenAIResponseOutputMessageWebSearchToolCall": {
- "description": "Web search tool call output message for OpenAI responses.\n\n:param id: Unique identifier for this tool call\n:param status: Current status of the web search operation\n:param type: Tool call type identifier, always \"web_search_call\"",
+ "OpenAIResponseOutputMessageReasoningContent": {
+ "description": "Reasoning text from the model.",
"properties": {
- "id": {
- "title": "Id",
- "type": "string"
- },
- "status": {
- "title": "Status",
+ "text": {
+ "description": "The reasoning text content from the model.",
+ "title": "Text",
"type": "string"
},
"type": {
- "const": "web_search_call",
- "default": "web_search_call",
+ "const": "reasoning_text",
+ "default": "reasoning_text",
+ "description": "The type identifier, always 'reasoning_text'.",
"title": "Type",
"type": "string"
}
},
"required": [
- "id",
- "status"
+ "text"
],
- "title": "OpenAIResponseOutputMessageWebSearchToolCall",
+ "title": "OpenAIResponseOutputMessageReasoningContent",
"type": "object"
},
- "OpenAIResponsePrompt": {
- "description": "OpenAI compatible Prompt object that is used in OpenAI responses.\n\n:param id: Unique identifier of the prompt template\n:param variables: Dictionary of variable names to OpenAIResponseInputMessageContent structure for template substitution. The substitution values can either be strings, or other Response input types\nlike images or files.\n:param version: Version number of the prompt to use (defaults to latest if not specified)",
+ "OpenAIResponseOutputMessageReasoningItem": {
+ "description": "Reasoning output from the model, representing the model's thinking process.",
"properties": {
"id": {
+ "description": "Unique identifier for the reasoning output item.",
"title": "Id",
"type": "string"
},
- "variables": {
- "type": "object",
+ "summary": {
+ "description": "Summary of the reasoning output.",
+ "items": {
+ "$ref": "`#/components/schemas/`OpenAIResponseOutputMessageReasoningSummary"
+ },
+ "title": "Summary",
+ "type": "array"
+ },
+ "type": {
+ "const": "reasoning",
+ "default": "reasoning",
+ "description": "The type identifier, always 'reasoning'.",
+ "title": "Type",
+ "type": "string"
+ },
+ "content": {
+ "type": "array",
"nullable": true,
"default": null,
- "title": "Variables"
+ "description": "The reasoning content from the model.",
+ "title": "Content"
},
- "version": {
+ "status": {
"type": "string",
"nullable": true,
"default": null,
- "title": "Version"
+ "description": "The status of the reasoning output.",
+ "title": "Status"
}
},
"required": [
- "id"
+ "id",
+ "summary"
],
- "title": "OpenAIResponsePrompt",
+ "title": "OpenAIResponseOutputMessageReasoningItem",
"type": "object"
},
- "OpenAIResponseReasoning": {
- "description": "Configuration for reasoning effort in OpenAI responses.\n\nControls how much reasoning the model performs before generating a response.\n\n:param effort: The effort level for reasoning. \"low\" favors speed and economical token usage,\n \"high\" favors more complete reasoning, \"medium\" is a balance between the two.",
+ "OpenAIResponseOutputMessageReasoningSummary": {
+ "description": "A summary of reasoning output from the model.",
"properties": {
- "effort": {
- "type": "string",
- "nullable": true,
- "default": null,
- "title": "Effort"
+ "text": {
+ "description": "The summary text of the reasoning output.",
+ "title": "Text",
+ "type": "string"
+ },
+ "type": {
+ "const": "summary_text",
+ "default": "summary_text",
+ "description": "The type identifier, always 'summary_text'.",
+ "title": "Type",
+ "type": "string"
}
},
- "title": "OpenAIResponseReasoning",
+ "required": [
+ "text"
+ ],
+ "title": "OpenAIResponseOutputMessageReasoningSummary",
"type": "object"
},
- "OpenAIResponseText": {
- "description": "Text response configuration for OpenAI responses.\n\n:param format: (Optional) Text format configuration specifying output format requirements",
+ "OpenAIResponseOutputMessageWebSearchToolCall": {
+ "description": "Web search tool call output message for OpenAI responses.\n\n:param id: Unique identifier for this tool call\n:param status: Current status of the web search operation\n:param type: Tool call type identifier, always \"web_search_call\"",
+ "properties": {
+ "id": {
+ "title": "Id",
+ "type": "string"
+ },
+ "status": {
+ "title": "Status",
+ "type": "string"
+ },
+ "type": {
+ "const": "web_search_call",
+ "default": "web_search_call",
+ "title": "Type",
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "status"
+ ],
+ "title": "OpenAIResponseOutputMessageWebSearchToolCall",
+ "type": "object"
+ },
+ "OpenAIResponsePrompt": {
+ "description": "OpenAI compatible Prompt object that is used in OpenAI responses.\n\n:param id: Unique identifier of the prompt template\n:param variables: Dictionary of variable names to OpenAIResponseInputMessageContent structure for template substitution. The substitution values can either be strings, or other Response input types\nlike images or files.\n:param version: Version number of the prompt to use (defaults to latest if not specified)",
+ "properties": {
+ "id": {
+ "title": "Id",
+ "type": "string"
+ },
+ "variables": {
+ "type": "object",
+ "nullable": true,
+ "default": null,
+ "title": "Variables"
+ },
+ "version": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "title": "Version"
+ }
+ },
+ "required": [
+ "id"
+ ],
+ "title": "OpenAIResponsePrompt",
+ "type": "object"
+ },
+ "OpenAIResponseReasoning": {
+ "description": "Configuration for reasoning effort in OpenAI responses.\n\nControls how much reasoning the model performs before generating a response.\n\n:param effort: The effort level for reasoning. \"low\" favors speed and economical token usage,\n \"high\" favors more complete reasoning, \"medium\" is a balance between the two.",
+ "properties": {
+ "effort": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "title": "Effort"
+ },
+ "summary": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Summary mode for reasoning output. One of 'auto', 'concise', or 'detailed'.",
+ "title": "Summary"
+ }
+ },
+ "title": "OpenAIResponseReasoning",
+ "type": "object"
+ },
+ "OpenAIResponseText": {
+ "description": "Text response configuration for OpenAI responses.\n\n:param format: (Optional) Text format configuration specifying output format requirements\n:param verbosity: (Optional) Controls response verbosity level",
"properties": {
"format": {
"anyOf": [
@@ -4431,6 +4833,12 @@ def test_dump_models(tmpdir: Path) -> None:
}
],
"default": null
+ },
+ "verbosity": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "title": "Verbosity"
}
},
"title": "OpenAIResponseText",
@@ -4641,6 +5049,102 @@ def test_dump_models(tmpdir: Path) -> None:
"title": "OpenAITopLogProb",
"type": "object"
},
+ "PgvectorVectorStoreProvider": {
+ "additionalProperties": false,
+ "description": "Dynamic pgvector vector-store provider (runtime create capacity).",
+ "properties": {
+ "id": {
+ "description": "Llama Stack vector_io provider_id. Surrounding whitespace is stripped before validation and emission.",
+ "minLength": 1,
+ "title": "Provider ID",
+ "type": "string"
+ },
+ "embedding_model": {
+ "description": "Embedding model identification used for stores created against this provider.",
+ "minLength": 1,
+ "title": "Embedding model",
+ "type": "string"
+ },
+ "embedding_dimension": {
+ "description": "Dimensionality of embedding vectors for this provider.",
+ "minimum": 0,
+ "title": "Embedding dimension",
+ "type": "integer"
+ },
+ "type": {
+ "const": "pgvector",
+ "default": "pgvector",
+ "description": "Product type for this dynamic vector-store provider.",
+ "title": "Provider type",
+ "type": "string"
+ },
+ "config": {
+ "$ref": "`#/components/schemas/`PgvectorVectorStoreProviderConfig",
+ "description": "pgvector connection settings for this provider.",
+ "title": "Storage config"
+ }
+ },
+ "required": [
+ "id",
+ "embedding_model",
+ "embedding_dimension",
+ "config"
+ ],
+ "title": "PgvectorVectorStoreProvider",
+ "type": "object"
+ },
+ "PgvectorVectorStoreProviderConfig": {
+ "additionalProperties": false,
+ "description": "Storage config for a pgvector dynamic vector-store provider.",
+ "properties": {
+ "host": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "PostgreSQL host. Defaults to ${env.POSTGRES_HOST}.",
+ "title": "PostgreSQL host"
+ },
+ "port": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "integer"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "description": "PostgreSQL port. Defaults to ${env.POSTGRES_PORT}. Accepts string placeholders and integer values.",
+ "title": "PostgreSQL port"
+ },
+ "db": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "PostgreSQL database name. Defaults to ${env.POSTGRES_DATABASE}.",
+ "title": "PostgreSQL database"
+ },
+ "user": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "PostgreSQL user. Defaults to ${env.POSTGRES_USER}.",
+ "title": "PostgreSQL user"
+ },
+ "password": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "PostgreSQL password. Defaults to ${env.POSTGRES_PASSWORD}.",
+ "title": "PostgreSQL password"
+ }
+ },
+ "title": "PgvectorVectorStoreProviderConfig",
+ "type": "object"
+ },
"PostgreSQLDatabaseConfiguration": {
"additionalProperties": false,
"description": "PostgreSQL database configuration.\n\nPostgreSQL database is used by Lightspeed Core Stack service for storing\ninformation about conversation IDs. It can also be leveraged to store\nconversation history and information about quota usage.\n\nUseful resources:\n\n- [Psycopg: connection classes](https://www.psycopg.org/psycopg3/docs/api/connections.html)\n- [PostgreSQL connection strings](https://www.connectionstrings.com/postgresql/)\n- [How to Use PostgreSQL in Python](https://www.freecodecamp.org/news/postgresql-in-python/)",
@@ -5130,7 +5634,7 @@ def test_dump_models(tmpdir: Path) -> None:
},
"QueryRequest": {
"additionalProperties": false,
- "description": "Model representing a request for the LLM (Language Model).\n\nAttributes:\n query: The query string.\n conversation_id: The optional conversation ID (UUID).\n provider: The optional provider.\n model: The optional model.\n system_prompt: The optional system prompt.\n attachments: The optional attachments.\n no_tools: Whether to bypass all tools and MCP servers (default: False).\n generate_topic_summary: Whether to generate topic summary for new conversations.\n media_type: The optional media type for response format (application/json or text/plain).\n vector_store_ids: The optional list of specific vector store IDs to query for RAG.\n shield_ids: The optional list of safety shield IDs to apply.\n solr: Optional Solr inline RAG options (mode, filters) or legacy filter-only dict.",
+ "description": "Model representing a request for the LLM (Language Model).\n\nAttributes:\n query: The query string.\n conversation_id: The optional conversation ID (UUID).\n provider: The optional provider.\n model: The optional model.\n system_prompt: The optional system prompt.\n attachments: The optional attachments.\n no_tools: Whether to bypass all tools and MCP servers (default: False).\n generate_topic_summary: Whether to generate topic summary for new conversations.\n media_type: The optional media type for response format (application/json or text/plain).\n vector_store_ids: The optional list of specific vector store IDs to query for RAG.\n shield_ids: The optional list of configured shield names to apply.\n solr: Optional Solr inline RAG options (mode, filters) or legacy filter-only dict.",
"examples": [
{
"attachments": [
@@ -5287,10 +5791,10 @@ def test_dump_models(tmpdir: Path) -> None:
"type": "array",
"nullable": true,
"default": null,
- "description": "Optional list of safety shield IDs to apply. If None, all configured shields are used. ",
+ "description": "Optional list of configured shield names to apply. If None, all configured shields are used.",
"examples": [
- "llama-guard",
- "custom-shield"
+ "topic-guard",
+ "pii-redaction"
],
"title": "Shield Ids"
},
@@ -5481,6 +5985,63 @@ def test_dump_models(tmpdir: Path) -> None:
"title": "QueryResponse",
"type": "object"
},
+ "QuestionValidityConfig": {
+ "additionalProperties": false,
+ "description": "Configuration for the question validity guardrail.",
+ "properties": {
+ "model_id": {
+ "description": "The model_id to use for the guard",
+ "title": "Model id",
+ "type": "string"
+ },
+ "model_prompt": {
+ "default": "\nInstructions:\n- You are a question classifying tool\n- You are an expert in kubernetes and openshift\n- Your job is to determine where or a user's question is related to kubernetes and/or openshift technologies and to provide a one-word response.\n- If a question appears to be related to kubernetes or openshift technologies, answer with the word ${allowed}, otherwise answer with the word ${rejected}.\n- Do not explain your answer, just provide the one-word response. Do not give any other response.\n- If the given question is an empty string, answer with the word ${rejected}\n\n\nExample Question:\nWhy is the sky blue?\nExample Response:\n${rejected}\n\nExample Question:\nWhy is the grass green?\nExample Response:\n${rejected}\n\nExample Question:\nWhy is sand yellow?\nExample Response:\n${rejected}\n\nExample Question:\nCan you help configure my cluster to automatically scale?\nExample Response:\n${allowed}\n\nQuestion:\n${message}\nResponse:\n",
+ "description": "The default prompt sent to the LLM used to validate the Users' question.",
+ "title": "Model prompt",
+ "type": "string"
+ },
+ "invalid_question_response": {
+ "default": "\nHi, I'm the OpenShift Lightspeed assistant, I can help you with questions about OpenShift, \nplease ask me a question related to OpenShift.\n",
+ "description": "The default response when the Users' question is determined to be invalid.",
+ "title": "Invalid question response",
+ "type": "string"
+ }
+ },
+ "required": [
+ "model_id"
+ ],
+ "title": "QuestionValidityConfig",
+ "type": "object"
+ },
+ "QuestionValidityShieldConfiguration": {
+ "additionalProperties": false,
+ "description": "Configuration for a named question-validity guardrail shield.\n\nAttributes:\n name: Unique, user-facing name identifying this shield instance.\n provider_id: Discriminator identifying this as a question-validity shield.\n config: Question-validity-specific configuration.",
+ "properties": {
+ "name": {
+ "description": "Unique, user-facing name identifying this shield instance.",
+ "title": "Shield name",
+ "type": "string"
+ },
+ "provider_id": {
+ "const": "question_validity",
+ "description": "Discriminator identifying this as a question-validity shield.",
+ "title": "Shield provider id",
+ "type": "string"
+ },
+ "config": {
+ "$ref": "`#/components/schemas/`QuestionValidityConfig",
+ "description": "Question-validity-specific configuration for this shield.",
+ "title": "Shield configuration"
+ }
+ },
+ "required": [
+ "name",
+ "provider_id",
+ "config"
+ ],
+ "title": "QuestionValidityShieldConfiguration",
+ "type": "object"
+ },
"QuotaExceededResponse": {
"description": "429 Too Many Requests - Quota limit exceeded.",
"examples": [
@@ -5896,7 +6457,7 @@ def test_dump_models(tmpdir: Path) -> None:
},
"RagConfiguration": {
"additionalProperties": false,
- "description": "RAG strategy configuration.\n\nControls which RAG sources are used for inline and tool-based retrieval.\n\nEach strategy lists RAG IDs to include. The special ID ``\"okp\"`` defined in constants,\nactivates the OKP provider; all other IDs refer to entries in ``byok_rag``.\n\nBackward compatibility:\n - ``inline`` defaults to ``[]`` (no inline RAG).\n - ``tool`` defaults to ``[]`` (no tool RAG).\n\nIf no RAG strategy is defined (inline and tool are empty),\nthe RAG tool will register all stores available to llama-stack.",
+ "description": "RAG strategy configuration.\n\nControls which RAG sources are used for inline and tool-based retrieval.\n\nEach strategy lists RAG IDs to include. The special ID ``\"okp\"`` defined in constants,\nactivates the OKP provider; all other IDs refer to entries in ``byok_rag``.\n\nBoth ``inline`` and ``tool`` default to ``[]`` (disabled).\nEach must be explicitly configured to activate its respective RAG strategy.",
"properties": {
"inline": {
"description": "RAG IDs whose sources are injected as context before the LLM call. Use 'okp' to enable OKP inline RAG. Empty by default (no inline RAG).",
@@ -5907,7 +6468,7 @@ def test_dump_models(tmpdir: Path) -> None:
"type": "array"
},
"tool": {
- "description": "RAG IDs made available to the LLM as a file_search tool. Use 'okp' to include the OKP vector store. When omitted, all registered BYOK vector stores are used (backward compatibility).",
+ "description": "RAG IDs made available to the LLM as a file_search tool. Use 'okp' to include the OKP vector store. When omitted, tool RAG is disabled.",
"items": {
"type": "string"
},
@@ -6000,6 +6561,86 @@ def test_dump_models(tmpdir: Path) -> None:
"title": "ReadinessResponse",
"type": "object"
},
+ "RedactionConfig": {
+ "additionalProperties": false,
+ "description": "Configuration for PII redaction with regex-based rules.\n\nRules are validated and compiled at construction time. Invalid\nregex patterns raise a ``ValueError`` immediately.\n\nAttributes:\n rules: Ordered list of redaction rules applied sequentially.\n case_sensitive: When False, patterns are compiled with\n ``re.IGNORECASE``. Defaults to False.",
+ "properties": {
+ "rules": {
+ "description": "Ordered list of PII redaction rules",
+ "items": {
+ "$ref": "`#/components/schemas/`RedactionRule"
+ },
+ "title": "Redaction rules",
+ "type": "array"
+ },
+ "case_sensitive": {
+ "default": false,
+ "description": "When False, patterns are compiled with re.IGNORECASE",
+ "title": "Case sensitive",
+ "type": "boolean"
+ }
+ },
+ "title": "RedactionConfig",
+ "type": "object"
+ },
+ "RedactionRule": {
+ "additionalProperties": false,
+ "description": "A single regex-based redaction rule.\n\nAttributes:\n pattern: Raw regex pattern string to match sensitive data.\n replacement: Text to substitute for each match.\n case_sensitive: Per-rule override for case sensitivity.\n When None, the global ``RedactionConfig.case_sensitive``\n flag applies.",
+ "properties": {
+ "pattern": {
+ "description": "Regex pattern to match sensitive data",
+ "title": "Pattern",
+ "type": "string"
+ },
+ "replacement": {
+ "description": "Replacement string for matched text",
+ "title": "Replacement",
+ "type": "string"
+ },
+ "case_sensitive": {
+ "type": "boolean",
+ "nullable": true,
+ "default": null,
+ "description": "Per-rule case sensitivity override. When None, the global config flag applies.",
+ "title": "Case sensitive"
+ }
+ },
+ "required": [
+ "pattern",
+ "replacement"
+ ],
+ "title": "RedactionRule",
+ "type": "object"
+ },
+ "RedactionShieldConfiguration": {
+ "additionalProperties": false,
+ "description": "Configuration for a named PII-redaction guardrail shield.\n\nAttributes:\n name: Unique, user-facing name identifying this shield instance.\n provider_id: Discriminator identifying this as a redaction shield.\n config: Redaction-specific configuration.",
+ "properties": {
+ "name": {
+ "description": "Unique, user-facing name identifying this shield instance.",
+ "title": "Shield name",
+ "type": "string"
+ },
+ "provider_id": {
+ "const": "redaction",
+ "description": "Discriminator identifying this as a redaction shield.",
+ "title": "Shield provider id",
+ "type": "string"
+ },
+ "config": {
+ "$ref": "`#/components/schemas/`RedactionConfig",
+ "description": "Redaction-specific configuration for this shield.",
+ "title": "Shield configuration"
+ }
+ },
+ "required": [
+ "name",
+ "provider_id",
+ "config"
+ ],
+ "title": "RedactionShieldConfiguration",
+ "type": "object"
+ },
"ReferencedDocument": {
"description": "Model representing a document referenced in generating a response.\n\nAttributes:\n doc_url: Url to the referenced doc.\n doc_title: Title of the referenced doc.\n document_id: Document ID for preserving identity during deduplication.",
"properties": {
@@ -6096,6 +6737,9 @@ def test_dump_models(tmpdir: Path) -> None:
},
{
"$ref": "`#/components/schemas/`OpenAIResponseMCPApprovalResponse"
+ },
+ {
+ "$ref": "`#/components/schemas/`OpenAIResponseOutputMessageReasoningItem"
}
]
},
@@ -6314,7 +6958,7 @@ def test_dump_models(tmpdir: Path) -> None:
},
"ResponsesRequest": {
"additionalProperties": false,
- "description": "Model representing a request for the Responses API following LCORE specification.\n\nAttributes:\n input: Input text or structured input items containing the query.\n model: Model identifier in format \"provider/model\". Auto-selected if not provided.\n conversation: Conversation ID linking to an existing conversation. Accepts both\n OpenAI and LCORE formats. Mutually exclusive with previous_response_id.\n include: Explicitly specify output item types that are excluded by default but\n should be included in the response.\n instructions: System instructions or guidelines provided to the model (acts as\n the system prompt).\n max_infer_iters: Maximum number of inference iterations the model can perform.\n max_output_tokens: Maximum number of tokens allowed in the response.\n max_tool_calls: Maximum number of tool calls allowed in a single response.\n metadata: Custom metadata dictionary with key-value pairs for tracking or logging.\n parallel_tool_calls: Whether the model can make multiple tool calls in parallel.\n previous_response_id: Identifier of the previous response in a multi-turn\n conversation. Mutually exclusive with conversation.\n prompt: Prompt object containing a template with variables for dynamic\n substitution.\n reasoning: Reasoning configuration for the response.\n safety_identifier: Safety identifier for the response.\n store: Whether to store the response in conversation history. Defaults to True.\n stream: Whether to stream the response as it is generated. Defaults to False.\n temperature: Sampling temperature controlling randomness (typically 0.0\u20132.0).\n text: Text response configuration specifying output format constraints (JSON\n schema, JSON object, or plain text).\n tool_choice: Tool selection strategy (\"auto\", \"required\", \"none\", or specific\n tool configuration).\n tools: List of tools available to the model (file search, web search, function\n calls, MCP tools). Defaults to all tools available to the model.\n generate_topic_summary: LCORE-specific flag indicating whether to generate a\n topic summary for new conversations. Defaults to True.\n shield_ids: LCORE-specific list of safety shield IDs to apply. If None, all\n configured shields are used.\n solr: Optional Solr inline RAG options (mode, filters) or legacy filter-only dict.",
+ "description": "Model representing a request for the Responses API following LCORE specification.\n\nAttributes:\n input: Input text or structured input items containing the query.\n model: Model identifier in format \"provider/model\". Auto-selected if not provided.\n conversation: Conversation ID linking to an existing conversation. Accepts both\n OpenAI and LCORE formats. Mutually exclusive with previous_response_id.\n include: Explicitly specify output item types that are excluded by default but\n should be included in the response.\n instructions: System instructions or guidelines provided to the model (acts as\n the system prompt).\n max_infer_iters: Maximum number of inference iterations the model can perform.\n max_output_tokens: Maximum number of tokens allowed in the response.\n max_tool_calls: Maximum number of tool calls allowed in a single response.\n metadata: Custom metadata dictionary with key-value pairs for tracking or logging.\n parallel_tool_calls: Whether the model can make multiple tool calls in parallel.\n previous_response_id: Identifier of the previous response in a multi-turn\n conversation. Mutually exclusive with conversation.\n prompt: Prompt object containing a template with variables for dynamic\n substitution.\n reasoning: Reasoning configuration for the response.\n safety_identifier: Safety identifier for the response.\n store: Whether to store the response in conversation history. Defaults to True.\n stream: Whether to stream the response as it is generated. Defaults to False.\n temperature: Sampling temperature controlling randomness (typically 0.0\u20132.0).\n text: Text response configuration specifying output format constraints (JSON\n schema, JSON object, or plain text).\n tool_choice: Tool selection strategy (\"auto\", \"required\", \"none\", or specific\n tool configuration).\n tools: List of tools available to the model (file search, web search, function\n calls, MCP tools). Defaults to all tools available to the model.\n generate_topic_summary: LCORE-specific flag indicating whether to generate a\n topic summary for new conversations. Defaults to True.\n shield_ids: LCORE-specific list of configured shield names to apply.\n If None, all configured shields are used.\n solr: Optional Solr inline RAG options (mode, filters) or legacy filter-only dict.",
"examples": [
{
"generate_topic_summary": true,
@@ -6624,6 +7268,7 @@ def test_dump_models(tmpdir: Path) -> None:
"mcp_call": "`#/components/schemas/`OpenAIResponseOutputMessageMCPCall",
"mcp_list_tools": "`#/components/schemas/`OpenAIResponseOutputMessageMCPListTools",
"message": "`#/components/schemas/`OpenAIResponseMessage",
+ "reasoning": "`#/components/schemas/`OpenAIResponseOutputMessageReasoningItem",
"web_search_call": "`#/components/schemas/`OpenAIResponseOutputMessageWebSearchToolCall"
},
"propertyName": "type"
@@ -6649,6 +7294,9 @@ def test_dump_models(tmpdir: Path) -> None:
},
{
"$ref": "`#/components/schemas/`OpenAIResponseMCPApprovalRequest"
+ },
+ {
+ "$ref": "`#/components/schemas/`OpenAIResponseOutputMessageReasoningItem"
}
]
},
@@ -7189,37 +7837,221 @@ def test_dump_models(tmpdir: Path) -> None:
"title": "SQLiteDatabaseConfiguration",
"type": "object"
},
+ "SavedPromptCreateRequest": {
+ "additionalProperties": false,
+ "description": "Request body to create a user-scoped saved prompt.\n\nLength and emptiness limits are enforced by the endpoint using configured\nsaved-prompts limits, not by static field constraints here.\n\nAttributes:\n name: Display name of the saved prompt.\n content: Prompt body text.",
+ "examples": [
+ {
+ "content": "Help me write a deployment checklist\u2026",
+ "name": "Deploy to staging"
+ }
+ ],
+ "properties": {
+ "name": {
+ "description": "Display name of the saved prompt",
+ "examples": [
+ "Deploy to staging"
+ ],
+ "title": "Name",
+ "type": "string"
+ },
+ "content": {
+ "description": "Prompt body text",
+ "examples": [
+ "Help me write a deployment checklist\u2026"
+ ],
+ "title": "Content",
+ "type": "string"
+ }
+ },
+ "required": [
+ "name",
+ "content"
+ ],
+ "title": "SavedPromptCreateRequest",
+ "type": "object"
+ },
+ "SavedPromptDeleteResponse": {
+ "description": "Result of deleting a saved prompt (always HTTP 200).\n\nAttributes:\n prompt_id: Saved prompt identifier that was passed to delete.\n deleted: Whether the prompt was deleted successfully.\n response: Human-readable outcome of the delete operation.",
+ "examples": [
+ {
+ "label": "deleted",
+ "value": {
+ "deleted": true,
+ "prompt_id": "abc123",
+ "response": "Saved prompt deleted successfully"
+ }
+ },
+ {
+ "label": "not found",
+ "value": {
+ "deleted": false,
+ "prompt_id": "abc123",
+ "response": "Saved prompt not found"
+ }
+ }
+ ],
+ "properties": {
+ "deleted": {
+ "description": "Whether the deletion was successful.",
+ "examples": [
+ true,
+ false
+ ],
+ "title": "Deleted",
+ "type": "boolean"
+ },
+ "prompt_id": {
+ "description": "Saved prompt identifier that was passed to delete.",
+ "examples": [
+ "abc123"
+ ],
+ "title": "Prompt Id",
+ "type": "string"
+ }
+ },
+ "required": [
+ "deleted",
+ "prompt_id"
+ ],
+ "title": "SavedPromptDeleteResponse",
+ "type": "object"
+ },
+ "SavedPromptResponse": {
+ "additionalProperties": false,
+ "description": "Single saved prompt returned to an authenticated user.\n\nAttributes:\n id: Unique identifier of the saved prompt.\n name: Display name of the saved prompt.\n content: Prompt body text.\n created_at: When the prompt was created.\n updated_at: When the prompt was last updated.",
+ "examples": [
+ {
+ "content": "Help me write a deployment checklist\u2026",
+ "created_at": "2026-07-22T16:00:00+00:00",
+ "id": "abc123",
+ "name": "Deploy to staging",
+ "updated_at": "2026-07-22T16:00:00+00:00"
+ }
+ ],
+ "properties": {
+ "id": {
+ "description": "Unique identifier of the saved prompt",
+ "examples": [
+ "abc123"
+ ],
+ "title": "Id",
+ "type": "string"
+ },
+ "name": {
+ "description": "Display name of the saved prompt",
+ "examples": [
+ "Deploy to staging"
+ ],
+ "title": "Name",
+ "type": "string"
+ },
+ "content": {
+ "description": "Prompt body text",
+ "examples": [
+ "Help me write a deployment checklist\u2026"
+ ],
+ "title": "Content",
+ "type": "string"
+ },
+ "created_at": {
+ "description": "When the prompt was created",
+ "examples": [
+ "2026-07-22T16:00:00+00:00"
+ ],
+ "format": "date-time",
+ "title": "Created At",
+ "type": "string"
+ },
+ "updated_at": {
+ "description": "When the prompt was last updated",
+ "examples": [
+ "2026-07-22T16:00:00+00:00"
+ ],
+ "format": "date-time",
+ "title": "Updated At",
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "name",
+ "content",
+ "created_at",
+ "updated_at"
+ ],
+ "title": "SavedPromptResponse",
+ "type": "object"
+ },
"SavedPromptsConfiguration": {
"additionalProperties": false,
- "description": "Configuration for saved prompts feature limits.\n\nControls the maximum number of prompts a user can save, the maximum\ndisplay name (title) length, and the maximum prompt content length.\nAll fields are optional and default to values defined in constants.\n\nAttributes:\n max_prompts_per_user: Maximum number of saved prompts allowed per user.\n max_display_name_length: Maximum character length for the prompt display name.\n max_content_length: Maximum character length for the prompt content body.",
+ "description": "Configuration for saved prompts feature limits.\n\nControls the maximum number of prompts a user can save, the maximum\ndisplay name (title) length, and the maximum prompt content length.\nOmitted fields use the defaults defined in constants.\n\nAttributes:\n max_prompts_per_user: Maximum number of saved prompts allowed per user.\n max_display_name_length: Maximum character length for the prompt display name.\n max_content_length: Maximum character length for the prompt content body.",
"properties": {
"max_prompts_per_user": {
- "type": "integer",
- "nullable": true,
- "default": null,
+ "default": 50,
"description": "Maximum number of saved prompts a user can create. Defaults to 50. Cannot exceed 200.",
- "title": "Max prompts per user"
+ "minimum": 0,
+ "maximum": 200,
+ "title": "Max prompts per user",
+ "type": "integer"
},
"max_display_name_length": {
- "type": "integer",
- "nullable": true,
- "default": null,
+ "default": 255,
"description": "Maximum character length for prompt display name (title). Defaults to 255. Cannot exceed 255.",
- "title": "Max display name length"
+ "minimum": 0,
+ "maximum": 255,
+ "title": "Max display name length",
+ "type": "integer"
},
"max_content_length": {
- "type": "integer",
- "nullable": true,
- "default": null,
+ "default": 10000,
"description": "Maximum character length for the prompt content body. Defaults to 10000. Cannot exceed 30000.",
- "title": "Max content length"
+ "minimum": 0,
+ "maximum": 30000,
+ "title": "Max content length",
+ "type": "integer"
}
},
"title": "SavedPromptsConfiguration",
"type": "object"
},
+ "SavedPromptsListResponse": {
+ "additionalProperties": false,
+ "description": "List of saved prompts belonging to the authenticated user.\n\nAttributes:\n prompts: Saved prompts ordered by created_at descending (newest first).",
+ "examples": [
+ {
+ "prompts": [
+ {
+ "content": "Help me write a deployment checklist\u2026",
+ "created_at": "2026-07-22T16:00:00+00:00",
+ "id": "abc123",
+ "name": "Deploy to staging",
+ "updated_at": "2026-07-22T16:00:00+00:00"
+ }
+ ]
+ },
+ {
+ "prompts": []
+ }
+ ],
+ "properties": {
+ "prompts": {
+ "description": "Saved prompts for the authenticated user",
+ "items": {
+ "$ref": "`#/components/schemas/`SavedPromptResponse"
+ },
+ "title": "Prompts",
+ "type": "array"
+ }
+ },
+ "required": [
+ "prompts"
+ ],
+ "title": "SavedPromptsListResponse",
+ "type": "object"
+ },
"SearchRankingOptions": {
- "description": "Options for ranking and filtering search results.\n\nThis class configures how search results are ranked and filtered. You can use algorithm-based\nrerankers (weighted, RRF) or neural rerankers. Defaults from VectorStoresConfig are\nused when parameters are not provided.\n\nExamples:\n # Weighted ranker with custom alpha\n SearchRankingOptions(ranker=\"weighted\", alpha=0.7)\n\n # RRF ranker with custom impact factor\n SearchRankingOptions(ranker=\"rrf\", impact_factor=50.0)\n\n # Use config defaults (just specify ranker type)\n SearchRankingOptions(ranker=\"weighted\") # Uses alpha from VectorStoresConfig\n\n # Score threshold filtering\n SearchRankingOptions(ranker=\"weighted\", score_threshold=0.5)\n\n:param ranker: (Optional) Name of the ranking algorithm to use. Supported values:\n - \"weighted\": Weighted combination of vector and keyword scores\n - \"rrf\": Reciprocal Rank Fusion algorithm\n - \"neural\": Neural reranking model (requires model parameter, Part II)\n Note: For OpenAI API compatibility, any string value is accepted, but only the above values are supported.\n:param score_threshold: (Optional) Minimum relevance score threshold for results. Default: 0.0\n:param alpha: (Optional) Weight factor for weighted ranker (0-1).\n - 0.0 = keyword only\n - 0.5 = equal weight (default)\n - 1.0 = vector only\n Only used when ranker=\"weighted\" and weights is not provided.\n Falls back to VectorStoresConfig.chunk_retrieval_params.weighted_search_alpha if not provided.\n:param impact_factor: (Optional) Impact factor (k) for RRF algorithm.\n Lower values emphasize higher-ranked results. Default: 60.0 (optimal from research).\n Only used when ranker=\"rrf\".\n Falls back to VectorStoresConfig.chunk_retrieval_params.rrf_impact_factor if not provided.\n:param weights: (Optional) Dictionary of weights for combining different signal types.\n Keys can be \"vector\", \"keyword\", \"neural\". Values should sum to 1.0.\n Used when combining algorithm-based reranking with neural reranking (Part II).\n Example: {\"vector\": 0.3, \"keyword\": 0.3, \"neural\": 0.4}\n:param model: (Optional) Model identifier for neural reranker (e.g., \"vllm/Qwen3-Reranker-0.6B\").\n Required when ranker=\"neural\" or when weights contains \"neural\" (Part II).",
+ "description": "Options for ranking and filtering search results.\n\nThis class configures how search results are ranked and filtered. You can use algorithm-based\nrerankers (weighted, RRF) or neural rerankers. Defaults from VectorStoresConfig are\nused when parameters are not provided.\n\nExamples:\n # Weighted ranker with custom alpha\n SearchRankingOptions(ranker=\"weighted\", alpha=0.7)\n\n # RRF ranker with custom impact factor\n SearchRankingOptions(ranker=\"rrf\", impact_factor=50.0)\n\n # Use config defaults (just specify ranker type)\n SearchRankingOptions(ranker=\"weighted\") # Uses alpha from VectorStoresConfig\n\n # Score threshold filtering\n SearchRankingOptions(ranker=\"weighted\", score_threshold=0.5)\n\n:param ranker: (Optional) Name of the ranking algorithm to use. Supported values:\n - \"weighted\": Weighted combination of vector and keyword scores\n - \"rrf\": Reciprocal Rank Fusion algorithm\n - \"neural\": Neural reranking model (requires model parameter)\n Note: For OpenAI API compatibility, any string value is accepted, but only the above values are supported.\n:param score_threshold: (Optional) Minimum relevance score threshold for results. Default: 0.0\n:param alpha: (Optional) Weight factor for weighted ranker (0-1).\n - 0.0 = keyword only\n - 0.5 = equal weight (default)\n - 1.0 = vector only\n Only used when ranker=\"weighted\" and weights is not provided.\n Falls back to VectorStoresConfig.chunk_retrieval_params.weighted_search_alpha if not provided.\n:param impact_factor: (Optional) Impact factor (k) for RRF algorithm.\n Lower values emphasize higher-ranked results. Default: 60.0 (optimal from research).\n Only used when ranker=\"rrf\".\n Falls back to VectorStoresConfig.chunk_retrieval_params.rrf_impact_factor if not provided.\n:param weights: (Optional) Dictionary of weights for combining different signal types.\n Keys can be \"vector\", \"keyword\", \"neural\". Values should sum to 1.0.\n Used when combining algorithm-based reranking with neural reranking.\n Example: {\"vector\": 0.3, \"keyword\": 0.3, \"neural\": 0.4}\n:param model: (Optional) Model identifier for neural reranker (e.g., \"transformers/Qwen/Qwen3-Reranker-0.6B\").\n Required when ranker=\"neural\" or when weights contains \"neural\".",
"properties": {
"ranker": {
"type": "string",
@@ -7342,7 +8174,7 @@ def test_dump_models(tmpdir: Path) -> None:
"cause": "Connection error while trying to reach backend service.",
"response": "Unable to connect to OGX"
},
- "label": "llama stack"
+ "label": "ogx"
},
{
"detail": {
@@ -7386,15 +8218,11 @@ def test_dump_models(tmpdir: Path) -> None:
"moderation_id": {
"title": "Moderation Id",
"type": "string"
- },
- "refusal_response": {
- "$ref": "`#/components/schemas/`OpenAIResponseMessage"
}
},
"required": [
"message",
- "moderation_id",
- "refusal_response"
+ "moderation_id"
],
"title": "ShieldModerationBlocked",
"type": "object"
@@ -7418,10 +8246,28 @@ def test_dump_models(tmpdir: Path) -> None:
{
"shields": [
{
- "identifier": "lightspeed_question_validity-shield",
- "params": {},
- "provider_id": "lightspeed_question_validity",
- "provider_resource_id": "lightspeed_question_validity-shield",
+ "config": {
+ "invalid_question_response": "I can only answer questions about the product.",
+ "model_id": "openai/gpt-4o-mini",
+ "model_prompt": "Is this question valid?"
+ },
+ "name": "question-validity",
+ "provider_id": "question_validity",
+ "type": "shield"
+ },
+ {
+ "config": {
+ "case_sensitive": false,
+ "rules": [
+ {
+ "case_sensitive": null,
+ "pattern": "\\b\\d{3}-\\d{2}-\\d{4}\\b",
+ "replacement": "[REDACTED]"
+ }
+ ]
+ },
+ "name": "pii-redaction",
+ "provider_id": "redaction",
"type": "shield"
}
]
@@ -7429,10 +8275,9 @@ def test_dump_models(tmpdir: Path) -> None:
],
"properties": {
"shields": {
- "description": "List of shields available",
+ "description": "List of shields configured in Lightspeed Core Stack",
"items": {
- "additionalProperties": true,
- "type": "object"
+ "$ref": "`#/components/schemas/`CatalogShield"
},
"title": "Shields",
"type": "array"
@@ -8002,8 +8847,7 @@ def test_dump_models(tmpdir: Path) -> None:
"tools": {
"description": "List of tools available from all configured MCP servers and built-in toolgroups",
"items": {
- "additionalProperties": true,
- "type": "object"
+ "$ref": "`#/components/schemas/`CatalogTool"
},
"title": "Tools",
"type": "array"
@@ -8246,6 +9090,7 @@ def test_dump_models(tmpdir: Path) -> None:
"mcp_call": "`#/components/schemas/`OpenAIResponseOutputMessageMCPCall",
"mcp_list_tools": "`#/components/schemas/`OpenAIResponseOutputMessageMCPListTools",
"message": "`#/components/schemas/`OpenAIResponseMessage",
+ "reasoning": "`#/components/schemas/`OpenAIResponseOutputMessageReasoningItem",
"web_search_call": "`#/components/schemas/`OpenAIResponseOutputMessageWebSearchToolCall"
},
"propertyName": "type"
@@ -8271,6 +9116,9 @@ def test_dump_models(tmpdir: Path) -> None:
},
{
"$ref": "`#/components/schemas/`OpenAIResponseMCPApprovalRequest"
+ },
+ {
+ "$ref": "`#/components/schemas/`OpenAIResponseOutputMessageReasoningItem"
}
]
},
@@ -8556,6 +9404,43 @@ def test_dump_models(tmpdir: Path) -> None:
"title": "UserDataCollection",
"type": "object"
},
+ "VectorStoreConfiguration": {
+ "additionalProperties": false,
+ "description": "Configuration for dynamic vector-store providers.\n\nMirrors ``InferenceConfiguration``: a providers list plus a sibling\n``default_provider`` pointer, rather than a per-entry default flag.\n\nAttributes:\n default_provider: Provider id used for vector_stores.default_* in the\n synthesized Llama Stack config. Required when providers is\n non-empty; must match one of providers[].id. Must be omitted when\n providers is empty.\n providers: Dynamic vector-store provider capacity for runtime\n POST /v1/vector-stores creates. Not the same as byok_rag (static\n registered corpora).",
+ "properties": {
+ "default_provider": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Provider id used for vector_stores.default_* in the synthesized Llama Stack config. Required when providers is non-empty; must match one of providers[].id.",
+ "title": "Default provider"
+ },
+ "providers": {
+ "description": "Dynamic vector-store provider capacity for runtime POST /v1/vector-stores creates. Not the same as byok_rag (static registered corpora).",
+ "items": {
+ "discriminator": {
+ "mapping": {
+ "faiss": "`#/components/schemas/`FaissVectorStoreProvider",
+ "pgvector": "`#/components/schemas/`PgvectorVectorStoreProvider"
+ },
+ "propertyName": "type"
+ },
+ "oneOf": [
+ {
+ "$ref": "`#/components/schemas/`FaissVectorStoreProvider"
+ },
+ {
+ "$ref": "`#/components/schemas/`PgvectorVectorStoreProvider"
+ }
+ ]
+ },
+ "title": "Vector store providers",
+ "type": "array"
+ }
+ },
+ "title": "VectorStoreConfiguration",
+ "type": "object"
+ },
"VectorStoreCreateRequest": {
"additionalProperties": false,
"description": "Model representing a request to create a vector store.\n\nAttributes:\n name: Name of the vector store.\n embedding_model: Optional embedding model to use.\n embedding_dimension: Optional embedding dimension.\n chunking_strategy: Optional chunking strategy configuration.\n provider_id: Optional vector store provider identifier.\n metadata: Optional metadata dictionary for storing session information.",
@@ -9093,25 +9978,6 @@ def test_dump_models(tmpdir: Path) -> None:
"title": "VectorStoresListResponse",
"type": "object"
},
- "ogx_api__openai_responses__ApprovalFilter": {
- "description": "Filter configuration for MCP tool approval requirements.\n\n:param always: (Optional) List of tool names that always require approval\n:param never: (Optional) List of tool names that never require approval",
- "properties": {
- "always": {
- "type": "array",
- "nullable": true,
- "default": null,
- "title": "Always"
- },
- "never": {
- "type": "array",
- "nullable": true,
- "default": null,
- "title": "Never"
- }
- },
- "title": "ApprovalFilter",
- "type": "object"
- },
"models__config__ApprovalFilter": {
"additionalProperties": false,
"description": "Granular approval control for specific MCP tools.\n\nAttributes:\n always: Tool names that always require human approval before execution.\n never: Tool names that never require approval (pre-approved).",
@@ -9135,6 +10001,25 @@ def test_dump_models(tmpdir: Path) -> None:
},
"title": "ApprovalFilter",
"type": "object"
+ },
+ "ogx_api__openai_responses__ApprovalFilter": {
+ "description": "Filter configuration for MCP tool approval requirements.\n\n:param always: (Optional) List of tool names that always require approval\n:param never: (Optional) List of tool names that never require approval",
+ "properties": {
+ "always": {
+ "type": "array",
+ "nullable": true,
+ "default": null,
+ "title": "Always"
+ },
+ "never": {
+ "type": "array",
+ "nullable": true,
+ "default": null,
+ "title": "Never"
+ }
+ },
+ "title": "ApprovalFilter",
+ "type": "object"
}
}
},
@@ -9436,6 +10321,7 @@ def test_dump_models_group_requests(tmpdir: Path) -> None:
"RlsapiV1InferRequest",
"RlsapiV1SystemInfo",
"RlsapiV1Terminal",
+ "SavedPromptCreateRequest",
"StreamingInterruptRequest",
"VectorStoreCreateRequest",
"VectorStoreFileCreateRequest",
From 4e3c9385c3c0fec0fa5934d551e1c6fa6de9a45b Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Sun, 9 Aug 2026 11:30:02 +0200
Subject: [PATCH 063/197] LCORE-3473: Updated models doc
---
docs/models/requests.json | 34 ++++++++++++++++++++++++++++++++++
docs/models/requests.md | 19 +++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/docs/models/requests.json b/docs/models/requests.json
index dce6cbea7..746de36d6 100644
--- a/docs/models/requests.json
+++ b/docs/models/requests.json
@@ -2574,6 +2574,40 @@
"title": "RlsapiV1Terminal",
"type": "object"
},
+ "SavedPromptCreateRequest": {
+ "additionalProperties": false,
+ "description": "Request body to create a user-scoped saved prompt.\n\nLength and emptiness limits are enforced by the endpoint using configured\nsaved-prompts limits, not by static field constraints here.\n\nAttributes:\n name: Display name of the saved prompt.\n content: Prompt body text.",
+ "examples": [
+ {
+ "content": "Help me write a deployment checklist\u2026",
+ "name": "Deploy to staging"
+ }
+ ],
+ "properties": {
+ "name": {
+ "description": "Display name of the saved prompt",
+ "examples": [
+ "Deploy to staging"
+ ],
+ "title": "Name",
+ "type": "string"
+ },
+ "content": {
+ "description": "Prompt body text",
+ "examples": [
+ "Help me write a deployment checklist\u2026"
+ ],
+ "title": "Content",
+ "type": "string"
+ }
+ },
+ "required": [
+ "name",
+ "content"
+ ],
+ "title": "SavedPromptCreateRequest",
+ "type": "object"
+ },
"SearchRankingOptions": {
"description": "Options for ranking and filtering search results.\n\nThis class configures how search results are ranked and filtered. You can use algorithm-based\nrerankers (weighted, RRF) or neural rerankers. Defaults from VectorStoresConfig are\nused when parameters are not provided.\n\nExamples:\n # Weighted ranker with custom alpha\n SearchRankingOptions(ranker=\"weighted\", alpha=0.7)\n\n # RRF ranker with custom impact factor\n SearchRankingOptions(ranker=\"rrf\", impact_factor=50.0)\n\n # Use config defaults (just specify ranker type)\n SearchRankingOptions(ranker=\"weighted\") # Uses alpha from VectorStoresConfig\n\n # Score threshold filtering\n SearchRankingOptions(ranker=\"weighted\", score_threshold=0.5)\n\n:param ranker: (Optional) Name of the ranking algorithm to use. Supported values:\n - \"weighted\": Weighted combination of vector and keyword scores\n - \"rrf\": Reciprocal Rank Fusion algorithm\n - \"neural\": Neural reranking model (requires model parameter)\n Note: For OpenAI API compatibility, any string value is accepted, but only the above values are supported.\n:param score_threshold: (Optional) Minimum relevance score threshold for results. Default: 0.0\n:param alpha: (Optional) Weight factor for weighted ranker (0-1).\n - 0.0 = keyword only\n - 0.5 = equal weight (default)\n - 1.0 = vector only\n Only used when ranker=\"weighted\" and weights is not provided.\n Falls back to VectorStoresConfig.chunk_retrieval_params.weighted_search_alpha if not provided.\n:param impact_factor: (Optional) Impact factor (k) for RRF algorithm.\n Lower values emphasize higher-ranked results. Default: 60.0 (optimal from research).\n Only used when ranker=\"rrf\".\n Falls back to VectorStoresConfig.chunk_retrieval_params.rrf_impact_factor if not provided.\n:param weights: (Optional) Dictionary of weights for combining different signal types.\n Keys can be \"vector\", \"keyword\", \"neural\". Values should sum to 1.0.\n Used when combining algorithm-based reranking with neural reranking.\n Example: {\"vector\": 0.3, \"keyword\": 0.3, \"neural\": 0.4}\n:param model: (Optional) Model identifier for neural reranker (e.g., \"transformers/Qwen/Qwen3-Reranker-0.6B\").\n Required when ranker=\"neural\" or when weights contains \"neural\".",
"properties": {
diff --git a/docs/models/requests.md b/docs/models/requests.md
index ada2aa145..0d9821e9d 100644
--- a/docs/models/requests.md
+++ b/docs/models/requests.md
@@ -1113,6 +1113,25 @@ Attributes:
| output | string | Terminal output from client |
+## SavedPromptCreateRequest
+
+
+Request body to create a user-scoped saved prompt.
+
+Length and emptiness limits are enforced by the endpoint using configured
+saved-prompts limits, not by static field constraints here.
+
+Attributes:
+ name: Display name of the saved prompt.
+ content: Prompt body text.
+
+
+| Field | Type | Description |
+|-------|------|-------------|
+| name | string | Display name of the saved prompt |
+| content | string | Prompt body text |
+
+
## SearchRankingOptions
From 219363e8f096f71c83e4c9c692f9352344b91f60 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Mon, 10 Aug 2026 09:41:44 +0200
Subject: [PATCH 064/197] LCORE-3473: Added new successfu responses models
---
src/models/api/responses/successful/__init__.py | 6 ++++++
src/utils/models_dumper.py | 3 +++
2 files changed, 9 insertions(+)
diff --git a/src/models/api/responses/successful/__init__.py b/src/models/api/responses/successful/__init__.py
index 534eedca5..aa3b731c9 100644
--- a/src/models/api/responses/successful/__init__.py
+++ b/src/models/api/responses/successful/__init__.py
@@ -1,5 +1,9 @@
"""Concrete successful HTTP response models grouped by domain."""
+from models.api.responses.successful.bases import (
+ AbstractDeleteResponse,
+ AbstractSuccessfulResponse,
+)
from models.api.responses.successful.catalog import (
ModelsResponse,
ProviderResponse,
@@ -67,6 +71,8 @@
)
__all__ = [
+ "AbstractDeleteResponse",
+ "AbstractSuccessfulResponse",
"AuthorizedResponse",
"ConfigurationResponse",
"ConversationDeleteResponse",
diff --git a/src/utils/models_dumper.py b/src/utils/models_dumper.py
index fe0bbc221..cc3b075c4 100644
--- a/src/utils/models_dumper.py
+++ b/src/utils/models_dumper.py
@@ -41,6 +41,9 @@
]
successful_responses_models: list[type[BaseModel]] = [
+ s.AbstractDeleteResponse,
+ s.AbstractSuccessfulResponse,
+ s.SavedPromptsConfigResponse,
s.AuthorizedResponse,
s.ConfigurationResponse,
s.ConversationDeleteResponse,
From 74eb7310d88ad2ef5403f3ec9d36c4f2af460259 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Mon, 10 Aug 2026 09:42:00 +0200
Subject: [PATCH 065/197] Updated unit tests accordingly
---
tests/unit/utils/test_models_dumper.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tests/unit/utils/test_models_dumper.py b/tests/unit/utils/test_models_dumper.py
index c808f4ed3..36dfb5f15 100644
--- a/tests/unit/utils/test_models_dumper.py
+++ b/tests/unit/utils/test_models_dumper.py
@@ -10338,6 +10338,9 @@ def test_dump_models_group_successful_responses(tmpdir: Path) -> None:
# list of schemas expected in a dump
expected_schemas = [
+ "AbstractDeleteResponse",
+ "AbstractSuccessfulResponse",
+ "SavedPromptsConfigResponse",
"AuthorizedResponse",
"ConfigurationResponse",
"ConversationDeleteResponse",
From 6addc10a50a6a3c05b135775365ad6af69df0feb Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Mon, 10 Aug 2026 09:44:28 +0200
Subject: [PATCH 066/197] LCORE-2922: Updated dependencies
---
uv.lock | 38 ++++++++++++++++++++++++--------------
1 file changed, 24 insertions(+), 14 deletions(-)
diff --git a/uv.lock b/uv.lock
index a08b5b67f..e3c0062ad 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1371,15 +1371,15 @@ wheels = [
[[package]]
name = "httpcore2"
-version = "2.9.1"
+version = "2.10.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "h11" },
- { name = "truststore" },
+ { name = "h11", marker = "sys_platform != 'emscripten'" },
+ { name = "truststore", marker = "sys_platform != 'emscripten'" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/39/a8/20ed1ed79cbc2ecdf5301c0968ab7c85547212e2a7bd126ddd2d986e206e/httpcore2-2.9.1.tar.gz", hash = "sha256:4d8acbf8b306f48c9d6046591fd5ba4037d1b1b1000d140fc2c3eab1e9a0c0e2", size = 67089, upload-time = "2026-07-24T09:21:03.867Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/a9/83/a896fc59940fc5a6e2aff3a4be1d92fa890112936803b331cae75a993c34/httpcore2-2.10.0.tar.gz", hash = "sha256:13c0cc3d1919d4f28457f60cd2c2abe04113a8af184ccf1142811beba936f9dc", size = 67427, upload-time = "2026-08-09T09:11:32.123Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/9f/fb/46c52b781975c335a2bcf1072c7bbc007cbdc8d674217f5ee1daba2c848b/httpcore2-2.9.1-py3-none-any.whl", hash = "sha256:6182472379e855fe4221246a2bb7ecede403bc61c6798062ae1787d051ccde26", size = 82809, upload-time = "2026-07-24T09:21:01.178Z" },
+ { url = "https://files.pythonhosted.org/packages/e5/4f/d149104195a35e2853a2fc203a8e3477747e58c80e17dda686dace174383/httpcore2-2.10.0-py3-none-any.whl", hash = "sha256:7df06cfb34070cae4f7c89be69dc1095eca138e9704ceffb98d25c1912ab6f01", size = 83000, upload-time = "2026-08-09T09:11:29.555Z" },
]
[[package]]
@@ -1408,18 +1408,28 @@ wheels = [
[[package]]
name = "httpx2"
-version = "2.9.1"
+version = "2.10.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "anyio" },
- { name = "httpcore2" },
+ { name = "anyio", marker = "sys_platform != 'emscripten'" },
+ { name = "httpcore2", marker = "sys_platform != 'emscripten'" },
+ { name = "httpx2-jsfetch", marker = "sys_platform == 'emscripten'" },
{ name = "idna" },
- { name = "truststore" },
+ { name = "truststore", marker = "sys_platform != 'emscripten'" },
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/21/14/38128fbafd7e0ed41d874df6c9a653d47c2d111cfe59e2b4ac95161b4abd/httpx2-2.9.1.tar.gz", hash = "sha256:1932a768737e3666291582833da748cc4e563c337cf96706fccc04fa6e58764a", size = 95458, upload-time = "2026-07-24T09:21:04.972Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/bd/3d/f9a8c07a3884f3e5b26205e8436a18b3af61c5d53192c3bea235574dbbec/httpx2-2.10.0.tar.gz", hash = "sha256:8741d7329fe2c7885fc9ceb61c8217acfb87a85f75723714b89ebf7ad7196338", size = 98749, upload-time = "2026-08-09T09:11:33.24Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b9/6d/a637d52449d98a6892d9a4dc0262587afdb6a66f201871842dce5a97b1c1/httpx2-2.10.0-py3-none-any.whl", hash = "sha256:5e3194a432701e1cc6f69a8b1b2fa199ef907013fede8d9a09a2c5b7b8141a18", size = 94355, upload-time = "2026-08-09T09:11:30.882Z" },
+]
+
+[[package]]
+name = "httpx2-jsfetch"
+version = "1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/cd/c4/0e5636363151a2a1795e0a77617168b9ca438e1748ec05fc9b5687f93d64/httpx2_jsfetch-1.0.tar.gz", hash = "sha256:70a0e3eabfef7cce5ad9c629f7d01ca05e418f586646f4ddf14782e4c1454c60", size = 6872, upload-time = "2026-08-07T00:13:07.492Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/13/b8/cfd91c4ab9134d386d48f0b6ac662ff3d4be6efdee59ee1c67ebc3c0487c/httpx2-2.9.1-py3-none-any.whl", hash = "sha256:1820fe14a9ab1107bfeff39259987429450b070ec0ff38cc87eb0d8c97fdc71a", size = 91191, upload-time = "2026-07-24T09:21:02.6Z" },
+ { url = "https://files.pythonhosted.org/packages/9b/43/832f631d32e4f1211caa2ba368317739fe71f0b8530e4c9d15dc454bac2a/httpx2_jsfetch-1.0-py3-none-any.whl", hash = "sha256:cb916b707601e69a07721aabc8f3f6659be3a6893bc1ff5c6f9e02241df2da32", size = 6382, upload-time = "2026-08-07T00:13:06.567Z" },
]
[[package]]
@@ -3372,7 +3382,7 @@ crypto = [
[[package]]
name = "pylint"
-version = "4.0.6"
+version = "4.0.7"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "astroid" },
@@ -3383,9 +3393,9 @@ dependencies = [
{ name = "platformdirs" },
{ name = "tomlkit" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/7d/1d/3bb57f303701549550d74bf7ced2b07412be97125c167a0c9d216aa9f762/pylint-4.0.6.tar.gz", hash = "sha256:52f19191bee08bf103f9705ad1a0ece4aa5a0a4ef2bdcbd969375a1e6f6579d5", size = 1585588, upload-time = "2026-06-14T14:43:26.772Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/de/92/98dace02f2d11b88160354c53944f77ea7327aa78bce1c75971e7aaa4347/pylint-4.0.7.tar.gz", hash = "sha256:9b2d1d15791c84b77a4fe2aafe8f0d9570717e2dea06d53b19c105cf60275a52", size = 1594770, upload-time = "2026-08-09T19:13:23.289Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/ab/da/acb2e7d4dbd2dfb792d38c0d850481f29ad7049b356d23f56c687d35203b/pylint-4.0.6-py3-none-any.whl", hash = "sha256:d11a0e1fdb7b1cd46ec5d6fc78fee8b95f28695b2d6140e5809925f61e32ea54", size = 538389, upload-time = "2026-06-14T14:43:24.873Z" },
+ { url = "https://files.pythonhosted.org/packages/e0/b0/3a8040e53df6c5c1e04b0e23ed53fdbeb64f333723a334d313fba2f581ce/pylint-4.0.7-py3-none-any.whl", hash = "sha256:be4a3111557a614411ed1fc89347ce4a8e1013a59e1f33d11485227a02e3304d", size = 539710, upload-time = "2026-08-09T19:13:21.228Z" },
]
[[package]]
From ff6a94ca499b4a54c205ba42121e2f728f4b504b Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Mon, 10 Aug 2026 11:32:38 +0200
Subject: [PATCH 067/197] LCORE-3473: Added new common models
---
src/models/common/__init__.py | 8 ++++++++
src/utils/models_dumper.py | 5 +++++
2 files changed, 13 insertions(+)
diff --git a/src/models/common/__init__.py b/src/models/common/__init__.py
index 6db7467b0..aa3a40783 100644
--- a/src/models/common/__init__.py
+++ b/src/models/common/__init__.py
@@ -21,6 +21,11 @@
from models.common.query import Attachment, SolrVectorSearchRequest
from models.common.shields import CatalogShield
from models.common.skills import SkillMetadata
+from models.common.tools import (
+ CatalogTool,
+ CatalogToolParameter,
+ ListedMcpTool,
+)
from models.common.transcripts import Transcript, TranscriptMetadata
from models.common.turn_summary import (
MCPListToolsSummary,
@@ -37,11 +42,14 @@
"Attachment",
"CatalogModel",
"CatalogShield",
+ "CatalogTool",
+ "CatalogToolParameter",
"ConversationData",
"ConversationDetails",
"ConversationTurn",
"FeedbackCategory",
"HealthStatus",
+ "ListedMcpTool",
"MCPListToolsSummary",
"MCPServerAuthInfo",
"MCPServerInfo",
diff --git a/src/utils/models_dumper.py b/src/utils/models_dumper.py
index cc3b075c4..e4de38f4f 100644
--- a/src/utils/models_dumper.py
+++ b/src/utils/models_dumper.py
@@ -108,6 +108,8 @@
common_models: list[type[BaseModel]] = [
c.Attachment,
+ c.CatalogModel,
+ c.CatalogShield,
c.ConversationData,
c.ConversationDetails,
c.ConversationTurn,
@@ -129,6 +131,9 @@
c.Transcript,
c.TranscriptMetadata,
c.TurnSummary,
+ c.CatalogTool,
+ c.CatalogToolParameter,
+ c.ListedMcpTool,
]
agents_models: list[type[BaseModel]] = [
From dfa6b6098eedb8a2c9089b3602ddb8cc8b4a8391 Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Mon, 10 Aug 2026 11:33:00 +0200
Subject: [PATCH 068/197] Updated unit tests
---
tests/unit/utils/test_models_dumper.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tests/unit/utils/test_models_dumper.py b/tests/unit/utils/test_models_dumper.py
index 36dfb5f15..c3c90fa13 100644
--- a/tests/unit/utils/test_models_dumper.py
+++ b/tests/unit/utils/test_models_dumper.py
@@ -10439,6 +10439,9 @@ def test_dump_models_group_common(tmpdir: Path) -> None:
"Transcript",
"TranscriptMetadata",
"TurnSummary",
+ "CatalogTool",
+ "CatalogToolParameter",
+ "ListedMcpTool",
]
check_json_file_content(filename, expected_schemas)
From be4e228d27c7a4a569dad3d2efce6d192efd472f Mon Sep 17 00:00:00 2001
From: Pavel Tisnovsky
Date: Mon, 10 Aug 2026 13:34:43 +0200
Subject: [PATCH 069/197] LCORE-3473: Regenerated models doc
---
docs/models/common.json | 202 ++++
docs/models/common.md | 85 ++
docs/models/common.puml | 198 ++--
docs/models/common.svg | 1146 +++++++++++------------
docs/models/requests.puml | 75 +-
docs/models/requests.svg | 520 +++++------
docs/models/responses.puml | 200 ++--
docs/models/responses.svg | 1236 ++++++++++++-------------
docs/models/successful_responses.json | 69 ++
docs/models/successful_responses.md | 37 +
10 files changed, 2056 insertions(+), 1712 deletions(-)
diff --git a/docs/models/common.json b/docs/models/common.json
index 7648a7ea1..d4c2034f8 100644
--- a/docs/models/common.json
+++ b/docs/models/common.json
@@ -68,6 +68,182 @@
"title": "Attachment",
"type": "object"
},
+ "CatalogModel": {
+ "description": "Normalized model entry used by ``/models`` and internal model resolution.\n\nUnifies OpenAI-style, Anthropic, and Google ``models.list()`` payloads into\none catalog shape.",
+ "properties": {
+ "identifier": {
+ "description": "Model identifier",
+ "title": "Identifier",
+ "type": "string"
+ },
+ "metadata": {
+ "additionalProperties": true,
+ "description": "Provider-specific metadata excluding core catalog fields",
+ "title": "Metadata",
+ "type": "object"
+ },
+ "api_model_type": {
+ "description": "API model type (typically mirrors model_type)",
+ "title": "Api Model Type",
+ "type": "string"
+ },
+ "provider_id": {
+ "description": "Provider identifier",
+ "title": "Provider Id",
+ "type": "string"
+ },
+ "type": {
+ "default": "model",
+ "description": "Object type, always 'model'",
+ "title": "Type",
+ "type": "string"
+ },
+ "provider_resource_id": {
+ "default": "",
+ "description": "Provider-native resource identifier for the model",
+ "title": "Provider Resource Id",
+ "type": "string"
+ },
+ "model_type": {
+ "description": "Model type such as 'llm' or 'embedding'",
+ "title": "Model Type",
+ "type": "string"
+ }
+ },
+ "required": [
+ "identifier",
+ "api_model_type",
+ "provider_id",
+ "model_type"
+ ],
+ "title": "CatalogModel",
+ "type": "object"
+ },
+ "CatalogShield": {
+ "description": "Shield entry in the ``/shields`` catalog response.\n\nAttributes:\n name: Unique, user-facing name identifying this shield instance.\n provider_id: Shield provider / type discriminator.\n type: Catalog entry type; always shield.\n config: Type-specific shield configuration.",
+ "properties": {
+ "name": {
+ "description": "Unique, user-facing name of the shield instance",
+ "title": "Name",
+ "type": "string"
+ },
+ "provider_id": {
+ "description": "Shield provider / type discriminator",
+ "enum": [
+ "question_validity",
+ "redaction"
+ ],
+ "title": "Provider Id",
+ "type": "string"
+ },
+ "type": {
+ "const": "shield",
+ "default": "shield",
+ "description": "Catalog entry type; always shield",
+ "title": "Type",
+ "type": "string"
+ },
+ "config": {
+ "additionalProperties": true,
+ "description": "Type-specific shield configuration",
+ "title": "Config",
+ "type": "object"
+ }
+ },
+ "required": [
+ "name",
+ "provider_id",
+ "config"
+ ],
+ "title": "CatalogShield",
+ "type": "object"
+ },
+ "CatalogTool": {
+ "description": "Tool entry in the ``/tools`` catalog response.",
+ "properties": {
+ "identifier": {
+ "title": "Identifier",
+ "type": "string"
+ },
+ "description": {
+ "title": "Description",
+ "type": "string"
+ },
+ "parameters": {
+ "items": {
+ "$ref": "`#/components/schemas/`CatalogToolParameter"
+ },
+ "title": "Parameters",
+ "type": "array"
+ },
+ "provider_id": {
+ "title": "Provider Id",
+ "type": "string"
+ },
+ "toolgroup_id": {
+ "title": "Toolgroup Id",
+ "type": "string"
+ },
+ "server_source": {
+ "title": "Server Source",
+ "type": "string"
+ },
+ "type": {
+ "default": "tool",
+ "title": "Type",
+ "type": "string"
+ }
+ },
+ "required": [
+ "identifier",
+ "description",
+ "parameters",
+ "provider_id",
+ "toolgroup_id",
+ "server_source"
+ ],
+ "title": "CatalogTool",
+ "type": "object"
+ },
+ "CatalogToolParameter": {
+ "description": "Parameter entry for a tool in the ``/tools`` catalog response.",
+ "properties": {
+ "name": {
+ "title": "Name",
+ "type": "string"
+ },
+ "description": {
+ "title": "Description",
+ "type": "string"
+ },
+ "parameter_type": {
+ "title": "Parameter Type",
+ "type": "string"
+ },
+ "required": {
+ "default": false,
+ "title": "Required",
+ "type": "boolean"
+ },
+ "default": {
+ "anyOf": [
+ {},
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Default"
+ }
+ },
+ "required": [
+ "name",
+ "description",
+ "parameter_type"
+ ],
+ "title": "CatalogToolParameter",
+ "type": "object"
+ },
"ConversationData": {
"description": "Model representing conversation data returned by cache list operations.\n\nAttributes:\n conversation_id: The conversation ID\n topic_summary: The topic summary for the conversation (can be None)\n last_message_timestamp: The timestamp of the last message in the conversation",
"properties": {
@@ -242,6 +418,32 @@
"title": "ConversationTurn",
"type": "object"
},
+ "ListedMcpTool": {
+ "description": "Tool metadata returned from an MCP ``tools/list`` call.",
+ "properties": {
+ "name": {
+ "title": "Name",
+ "type": "string"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "title": "Description"
+ },
+ "input_schema": {
+ "type": "object",
+ "nullable": true,
+ "default": null,
+ "title": "Input Schema"
+ }
+ },
+ "required": [
+ "name"
+ ],
+ "title": "ListedMcpTool",
+ "type": "object"
+ },
"MCPListToolsSummary": {
"description": "Model representing MCP list tools payload serialized into tool results.",
"properties": {
diff --git a/docs/models/common.md b/docs/models/common.md
index 1f8b56246..1846c3a73 100644
--- a/docs/models/common.md
+++ b/docs/models/common.md
@@ -37,6 +37,78 @@ Attributes:
| content | string | The actual attachment content (text or base64-encoded image data) |
+## CatalogModel
+
+
+Normalized model entry used by ``/models`` and internal model resolution.
+
+Unifies OpenAI-style, Anthropic, and Google ``models.list()`` payloads into
+one catalog shape.
+
+
+| Field | Type | Description |
+|-------|------|-------------|
+| identifier | string | Model identifier |
+| metadata | object | Provider-specific metadata excluding core catalog fields |
+| api_model_type | string | API model type (typically mirrors model_type) |
+| provider_id | string | Provider identifier |
+| type | string | Object type, always 'model' |
+| provider_resource_id | string | Provider-native resource identifier for the model |
+| model_type | string | Model type such as 'llm' or 'embedding' |
+
+
+## CatalogShield
+
+
+Shield entry in the ``/shields`` catalog response.
+
+Attributes:
+ name: Unique, user-facing name identifying this shield instance.
+ provider_id: Shield provider / type discriminator.
+ type: Catalog entry type; always shield.
+ config: Type-specific shield configuration.
+
+
+| Field | Type | Description |
+|-------|------|-------------|
+| name | string | Unique, user-facing name of the shield instance |
+| provider_id | string | Shield provider / type discriminator |
+| type | string | Catalog entry type; always shield |
+| config | object | Type-specific shield configuration |
+
+
+## CatalogTool
+
+
+Tool entry in the ``/tools`` catalog response.
+
+
+| Field | Type | Description |
+|-------|------|-------------|
+| identifier | string | |
+| description | string | |
+| parameters | array | |
+| provider_id | string | |
+| toolgroup_id | string | |
+| server_source | string | |
+| type | string | |
+
+
+## CatalogToolParameter
+
+
+Parameter entry for a tool in the ``/tools`` catalog response.
+
+
+| Field | Type | Description |
+|-------|------|-------------|
+| name | string | |
+| description | string | |
+| parameter_type | string | |
+| required | boolean | |
+| default | | |
+
+
## ConversationData
@@ -120,6 +192,19 @@ Attributes:
| completed_at | string | ISO 8601 timestamp when the turn completed |
+## ListedMcpTool
+
+
+Tool metadata returned from an MCP ``tools/list`` call.
+
+
+| Field | Type | Description |
+|-------|------|-------------|
+| name | string | |
+| description | string | |
+| input_schema | object | |
+
+
## MCPListToolsSummary
diff --git a/docs/models/common.puml b/docs/models/common.puml
index a7fd7d100..8090972f0 100644
--- a/docs/models/common.puml
+++ b/docs/models/common.puml
@@ -10,31 +10,31 @@ class "AgentTurnAccumulator" as src.models.common.agents.turn_accumulator.AgentT
seen_docs : set[tuple[str, str]]
text_parts : list[str]
tool_round : int
- turn_summary
+ turn_summary : TurnSummary
vector_store_ids : Final[list[str]]
increment_round_if_pending() -> None
}
class "Attachment" as src.models.common.query.Attachment {
- attachment_type : str
- content : str
- content_type : str
+ attachment_type : Optional[str]
+ content : Optional[str]
+ content_type : Optional[str]
model_config : dict
validate_image_attachment() -> Self
}
class "CatalogModel" as src.models.common.models.CatalogModel {
- api_model_type : str
- identifier : str
- metadata : dict[str, Any]
- model_type : str
- provider_id : str
- provider_resource_id : str
- type : str
+ api_model_type : Optional[str]
+ identifier : Optional[str]
+ metadata : Optional[dict[str, Any]]
+ model_type : Optional[str]
+ provider_id : Optional[str]
+ provider_resource_id : Optional[str]
+ type : Optional[str]
}
class "CatalogShield" as src.models.common.shields.CatalogShield {
- config : dict[str, Any]
- name : str
- provider_id : Literal['question_validity', 'redaction']
- type : Literal['shield']
+ config : Optional[dict[str, Any]]
+ name : Optional[str]
+ provider_id : Optional[Literal['question_validity', 'redaction']]
+ type : Optional[Literal['shield']]
}
class "CatalogTool" as src.models.common.tools.CatalogTool {
description : str
@@ -58,7 +58,7 @@ class "ConversationData" as src.models.common.conversation.ConversationData {
topic_summary : Optional[str]
}
class "ConversationDetails" as src.models.common.conversation.ConversationDetails {
- conversation_id : str
+ conversation_id : Optional[str]
created_at : Optional[str]
last_message_at : Optional[str]
last_used_model : Optional[str]
@@ -67,13 +67,13 @@ class "ConversationDetails" as src.models.common.conversation.ConversationDetail
topic_summary : Optional[str]
}
class "ConversationTurn" as src.models.common.conversation.ConversationTurn {
- completed_at : str
- messages : list[Message]
- model : str
- provider : str
- started_at : str
- tool_calls : list[ToolCallSummary]
- tool_results : list[ToolResultSummary]
+ completed_at : Optional[str]
+ messages : Optional[list[Message]]
+ model : Optional[str]
+ provider : Optional[str]
+ started_at : Optional[str]
+ tool_calls : Optional[list[ToolCallSummary]]
+ tool_results : Optional[list[ToolResultSummary]]
}
class "EndEventData" as src.models.common.agents.stream_payloads.EndEventData {
input_tokens : int
@@ -123,39 +123,39 @@ class "ListedMcpTool" as src.models.common.tools.ListedMcpTool {
name : str
}
class "MCPListToolsSummary" as src.models.common.turn_summary.MCPListToolsSummary {
- server_label : str
- tools : list[ToolInfoSummary]
+ server_label : Optional[str]
+ tools : Optional[list[ToolInfoSummary]]
}
class "MCPServerAuthInfo" as src.models.common.mcp.MCPServerAuthInfo {
- client_auth_headers : list[str]
- name : str
+ client_auth_headers : Optional[list[str]]
+ name : Optional[str]
}
class "MCPServerInfo" as src.models.common.mcp.MCPServerInfo {
- name : str
- provider_id : str
- source : str
- url : str
+ name : Optional[str]
+ provider_id : Optional[str]
+ source : Optional[str]
+ url : Optional[str]
}
class "Message" as src.models.common.conversation.Message {
- content : str
+ content : Optional[str]
referenced_documents : Optional[list[ReferencedDocument]]
- type : Literal['user', 'assistant', 'system', 'developer']
+ type : Optional[Literal['user', 'assistant', 'system', 'developer']]
}
class "ProviderHealthStatus" as src.models.common.health.ProviderHealthStatus {
message : Optional[str]
- provider_id : str
- status : str
+ provider_id : Optional[str]
+ status : Optional[str]
}
class "RAGChunk" as src.models.common.turn_summary.RAGChunk {
attributes : Optional[dict[str, Any]]
- content : str
+ content : Optional[str]
score : Optional[float]
source : Optional[str]
}
class "RAGContext" as src.models.common.turn_summary.RAGContext {
- context_text : str
- rag_chunks : list[RAGChunk]
- referenced_documents : list[ReferencedDocument]
+ context_text : Optional[str]
+ rag_chunks : Optional[list[RAGChunk]]
+ referenced_documents : Optional[list[ReferencedDocument]]
}
class "ReferencedDocument" as src.models.common.turn_summary.ReferencedDocument {
doc_title : Optional[str]
@@ -164,12 +164,12 @@ class "ReferencedDocument" as src.models.common.turn_summary.ReferencedDocument
source : Optional[str]
}
class "ResponseGeneratorContext" as src.models.common.responses.contexts.ResponseGeneratorContext {
- client
+ client : AsyncOgxClient
conversation_id : str
- inline_rag_context
+ inline_rag_context : RAGContext
model_id : str
moderation_result
- query_request
+ query_request : QueryRequest
rag_id_mapping : dict[str, str]
request_id : str
skip_userid_check : bool
@@ -178,24 +178,24 @@ class "ResponseGeneratorContext" as src.models.common.responses.contexts.Respons
vector_store_ids : list[str]
}
class "ResponsesApiParams" as src.models.common.responses.responses_api_params.ResponsesApiParams {
- conversation : str
+ conversation : Optional[str]
extra_headers : Optional[dict[str, str]]
include : Optional[list[IncludeParameter]]
- input
+ input : Optional[ResponseInput]
instructions : Optional[str]
max_infer_iters : Optional[int]
max_output_tokens : Optional[int]
max_tool_calls : Optional[int]
metadata : Optional[dict[str, str]]
- model : str
- omit_conversation : bool
+ model : Optional[str]
+ omit_conversation : Optional[bool]
parallel_tool_calls : Optional[bool]
previous_response_id : Optional[str]
prompt : Optional[Prompt]
reasoning : Optional[Reasoning]
safety_identifier : Optional[str]
- store : bool
- stream : bool
+ store : Optional[bool]
+ stream : Optional[bool]
temperature : Optional[float]
text : Optional[Text]
tool_choice : Optional[ToolChoice]
@@ -204,44 +204,44 @@ class "ResponsesApiParams" as src.models.common.responses.responses_api_params.R
model_dump() -> dict[str, Any]
}
class "ResponsesContext" as src.models.common.responses.contexts.ResponsesContext {
- auth : tuple[str, str, bool, str]
+ auth : Optional[tuple[str, str, bool, str]]
background_tasks : Optional[BackgroundTasks]
- client
+ client : Optional[AsyncOgxClient]
compacted_original_input : Optional[ResponseInput]
- endpoint_path : str
- filter_server_tools : bool
- generate_topic_summary : bool
- inline_rag_context
- input_text : str
- model_config
- moderation_result
- rh_identity_context : tuple[str, str]
- started_at : datetime
+ endpoint_path : Optional[str]
+ filter_server_tools : Optional[bool]
+ generate_topic_summary : Optional[bool]
+ inline_rag_context : Optional[RAGContext]
+ input_text : Optional[str]
+ model_config : ConfigDict
+ moderation_result : Optional[ShieldModerationResult]
+ rh_identity_context : Optional[tuple[str, str]]
+ started_at : Optional[datetime]
user_agent : Optional[str]
}
class "ResponsesConversationContext" as src.models.common.responses.responses_conversation_context.ResponsesConversationContext {
- conversation : str
- generate_topic_summary : bool
- model_config
+ conversation : Optional[str]
+ generate_topic_summary : Optional[bool]
+ model_config : ConfigDict
user_conversation : Optional[UserConversation]
}
class "ShieldModerationBlocked" as src.models.common.moderation.ShieldModerationBlocked {
decision : Literal['blocked']
message : str
moderation_id : str
- refusal_response
+ refusal_response : ResponseMessage
}
class "ShieldModerationPassed" as src.models.common.moderation.ShieldModerationPassed {
decision : Literal['passed']
}
class "SkillMetadata" as src.models.common.skills.SkillMetadata {
- description : str
- name : str
+ description : Optional[str]
+ name : Optional[str]
}
class "SolrVectorSearchRequest" as src.models.common.query.SolrVectorSearchRequest {
filters : Optional[dict[str, Any]]
mode : Optional[Literal['semantic', 'hybrid', 'lexical']]
- model_config
+ model_config : ConfigDict
coerce_legacy_plain_dict(data: Any) -> Any
}
class "StartEventData" as src.models.common.agents.stream_payloads.StartEventData {
@@ -254,7 +254,7 @@ class "StartStreamPayload" as src.models.common.agents.stream_payloads.StartStre
create() -> Self
}
class "StreamPayloadBase" as src.models.common.agents.stream_payloads.StreamPayloadBase {
- model_config
+ model_config : ConfigDict
serialize_json() -> str
serialize_text() -> str
}
@@ -269,42 +269,42 @@ class "TokenStreamPayload" as src.models.common.agents.stream_payloads.TokenStre
serialize_text() -> str
}
class "ToolCallStreamPayload" as src.models.common.agents.stream_payloads.ToolCallStreamPayload {
- data
+ data : ToolCallSummary
event : Literal['tool_call']
serialize_text() -> str
}
class "ToolCallSummary" as src.models.common.turn_summary.ToolCallSummary {
- args : dict[str, Any]
- id : str
- name : str
- type : str
+ args : Optional[dict[str, Any]]
+ id : Optional[str]
+ name : Optional[str]
+ type : Optional[str]
}
class "ToolInfoSummary" as src.models.common.turn_summary.ToolInfoSummary {
description : Optional[str]
input_schema : Optional[dict[str, Any]]
- name : str
+ name : Optional[str]
}
class "ToolResultStreamPayload" as src.models.common.agents.stream_payloads.ToolResultStreamPayload {
- data
+ data : ToolResultSummary
event : Literal['tool_result']
serialize_text() -> str
}
class "ToolResultSummary" as src.models.common.turn_summary.ToolResultSummary {
- content : str
- id : str
- round : int
- status : str
- type : str
+ content : Optional[str]
+ id : Optional[str]
+ round : Optional[int]
+ status : Optional[str]
+ type : Optional[str]
}
class "Transcript" as src.models.common.transcripts.Transcript {
- attachments : list[dict[str, Any]]
+ attachments : Optional[list[dict[str, Any]]]
llm_response : str
metadata
query_is_valid : bool
- rag_chunks : list[dict[str, Any]]
+ rag_chunks : Optional[list[dict[str, Any]]]
redacted_query : str
- tool_calls : list[dict[str, Any]]
- tool_results : list[dict[str, Any]]
+ tool_calls : Optional[list[dict[str, Any]]]
+ tool_results : Optional[list[dict[str, Any]]]
truncated : bool
}
class "TranscriptMetadata" as src.models.common.transcripts.TranscriptMetadata {
@@ -322,16 +322,16 @@ class "TurnCompleteStreamPayload" as src.models.common.agents.stream_payloads.Tu
create() -> Self
}
class "TurnSummary" as src.models.common.turn_summary.TurnSummary {
- id : str
+ id : Optional[str]
llm_response : str
- next_chunk_id : int
- output_items : list[OpenAIResponseOutput]
- partial_tokens : list[str]
- rag_chunks : list[RAGChunk]
- referenced_documents : list[ReferencedDocument]
- token_usage
- tool_calls : list[ToolCallSummary]
- tool_results : list[ToolResultSummary]
+ next_chunk_id : Optional[int]
+ output_items : Optional[list[OpenAIResponseOutput]]
+ partial_tokens : Optional[list[str]]
+ rag_chunks : Optional[list[RAGChunk]]
+ referenced_documents : Optional[list[ReferencedDocument]]
+ token_usage : Optional[TokenCounter]
+ tool_calls : Optional[list[ToolCallSummary]]
+ tool_results : Optional[list[ToolResultSummary]]
}
src.models.common.agents.stream_payloads.EndStreamPayload --|> src.models.common.agents.stream_payloads.StreamPayloadBase
src.models.common.agents.stream_payloads.ErrorStreamPayload --|> src.models.common.agents.stream_payloads.StreamPayloadBase
@@ -341,11 +341,11 @@ src.models.common.agents.stream_payloads.TokenStreamPayload --|> src.models.comm
src.models.common.agents.stream_payloads.ToolCallStreamPayload --|> src.models.common.agents.stream_payloads.StreamPayloadBase
src.models.common.agents.stream_payloads.ToolResultStreamPayload --|> src.models.common.agents.stream_payloads.StreamPayloadBase
src.models.common.agents.stream_payloads.TurnCompleteStreamPayload --|> src.models.common.agents.stream_payloads.StreamPayloadBase
-src.models.common.agents.stream_payloads.EndEventData --* src.models.common.agents.stream_payloads.EndStreamPayload : data
-src.models.common.agents.stream_payloads.ErrorEventData --* src.models.common.agents.stream_payloads.ErrorStreamPayload : data
-src.models.common.agents.stream_payloads.InterruptedEventData --* src.models.common.agents.stream_payloads.InterruptedStreamPayload : data
-src.models.common.agents.stream_payloads.StartEventData --* src.models.common.agents.stream_payloads.StartStreamPayload : data
-src.models.common.agents.stream_payloads.TokenChunkData --* src.models.common.agents.stream_payloads.TokenStreamPayload : data
-src.models.common.agents.stream_payloads.TokenChunkData --* src.models.common.agents.stream_payloads.TurnCompleteStreamPayload : data
-src.models.common.transcripts.TranscriptMetadata --* src.models.common.transcripts.Transcript : metadata
+src.models.common.agents.stream_payloads.EndStreamPayload --> src.models.common.agents.stream_payloads.EndEventData : data
+src.models.common.agents.stream_payloads.ErrorStreamPayload --> src.models.common.agents.stream_payloads.ErrorEventData : data
+src.models.common.agents.stream_payloads.InterruptedStreamPayload --> src.models.common.agents.stream_payloads.InterruptedEventData : data
+src.models.common.agents.stream_payloads.StartStreamPayload --> src.models.common.agents.stream_payloads.StartEventData : data
+src.models.common.agents.stream_payloads.TokenStreamPayload --> src.models.common.agents.stream_payloads.TokenChunkData : data
+src.models.common.agents.stream_payloads.TurnCompleteStreamPayload --> src.models.common.agents.stream_payloads.TokenChunkData : data
+src.models.common.transcripts.Transcript --> src.models.common.transcripts.TranscriptMetadata : metadata
@enduml
diff --git a/docs/models/common.svg b/docs/models/common.svg
index 676c1d91b..62325d509 100644
--- a/docs/models/common.svg
+++ b/docs/models/common.svg
@@ -1,5 +1,5 @@
-
@@ -1422,6 +1481,108 @@
OkpConfiguration
Solr boolean syntax, e.g. ‘product:ansible AND
product:openshift’.
+
+
search_mode
+
string
+
Default Solr search mode for OKP queries. ‘keyword’ uses BM25 text
+search (no embedding model needed). ‘hybrid’ combines vector + keyword
+search. ‘semantic’ uses pure vector search. When unset, falls back to
+the global default (‘hybrid’).
Llama Stack vector_io provider_id. Surrounding whitespace is
+stripped before validation and emission.
+
+
+
embedding_model
+
string
+
Embedding model identification used for stores created against this
+provider.
+
+
+
embedding_dimension
+
integer
+
Dimensionality of embedding vectors for this provider.
+
+
+
type
+
string
+
Product type for this dynamic vector-store provider.
+
+
+
config
+
+
pgvector connection settings for this provider.
+
+
+
+
PgvectorVectorStoreProviderConfig
+
Storage config for a pgvector dynamic vector-store provider.
+
+
+
+
+
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
host
+
string
+
PostgreSQL host. Defaults to ${env.POSTGRES_HOST}.
+
+
+
port
+
+
PostgreSQL port. Defaults to ${env.POSTGRES_PORT}. Accepts string
+placeholders and integer values.
+
+
+
db
+
string
+
PostgreSQL database name. Defaults to ${env.POSTGRES_DATABASE}.
+
+
+
user
+
string
+
PostgreSQL user. Defaults to ${env.POSTGRES_USER}.
+
+
+
password
+
string
+
PostgreSQL password. Defaults to ${env.POSTGRES_PASSWORD}.
+
PostgreSQLDatabaseConfiguration
@@ -1506,12 +1667,84 @@
PostgreSQLDatabaseConfiguration
-
QuotaHandlersConfiguration
-
Quota limiter configuration.
-
It is possible to limit quota usage per user or per service or
-services (that typically run in one cluster). Each limit is configured
-as a separate quota limiter. It can be of type
-user_limiter or cluster_limiter (which is name
+
QuestionValidityConfig
+
Configuration for the question validity guardrail.
+
+
+
+
+
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
model_id
+
string
+
The model_id to use for the guard
+
+
+
model_prompt
+
string
+
The default prompt sent to the LLM used to validate the Users’
+question.
+
+
+
invalid_question_response
+
string
+
The default response when the Users’ question is determined to be
+invalid.
+
+
+
+
QuestionValidityShieldConfiguration
+
Configuration for a named question-validity guardrail shield.
+
Attributes: name: Unique, user-facing name identifying this shield
+instance. provider_id: Discriminator identifying this as a
+question-validity shield. config: Question-validity-specific
+configuration.
+
+
+
+
+
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
name
+
string
+
Unique, user-facing name identifying this shield instance.
+
+
+
provider_id
+
string
+
Discriminator identifying this as a question-validity shield.
+
+
+
config
+
+
Question-validity-specific configuration for this shield.
+
+
+
+
QuotaHandlersConfiguration
+
Quota limiter configuration.
+
It is possible to limit quota usage per user or per service or
+services (that typically run in one cluster). Each limit is configured
+as a separate quota limiter. It can be of type
+user_limiter or cluster_limiter (which is name
that makes sense in OpenShift deployment).
@@ -1684,17 +1917,9 @@
RHIdentityConfiguration
RagConfiguration
-
RAG strategy configuration.
-
Controls which RAG sources are used for inline and tool-based
-retrieval.
-
Each strategy lists RAG IDs to include. The special ID
-"okp" defined in constants, activates the OKP provider; all
-other IDs refer to entries in byok_rag.
-
Backward compatibility: - inline defaults to
-[] (no inline RAG). - tool defaults to
-[] (no tool RAG).
-
If no RAG strategy is defined (inline and tool are empty), the RAG
-tool will register all stores available to llama-stack.
+
Unified RAG configuration.
+
Groups all RAG-related settings: BYOK stores, OKP provider, and
+retrieval strategies (inline and tool).
@@ -1710,18 +1935,218 @@
RagConfiguration
-
inline
-
array
-
RAG IDs whose sources are injected as context before the LLM call.
-Use ‘okp’ to enable OKP inline RAG. Empty by default (no inline
-RAG).
+
byok
+
+
Bring Your Own Knowledge store configurations and settings.
-
tool
+
okp
+
+
OKP provider settings. Only used when ‘okp’ is listed in
+retrieval.inline.sources or retrieval.tool.sources.
+
+
+
retrieval
+
+
Inline and tool retrieval strategy settings.
+
+
+
+
RagStore
+
BYOK (Bring Your Own Knowledge) RAG store configuration.
+
+
+
+
+
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
rag_id
+
string
+
Unique RAG ID
+
+
+
backend
+
string
+
Type of RAG database (e.g. ‘faiss’, ‘pgvector’).
+
+
+
embedding_model
+
string
+
Embedding model identification
+
+
+
embedding_dimension
+
integer
+
Dimensionality of embedding vectors.
+
+
+
vector_db_id
+
string
+
Vector database identification.
+
+
+
db_path
+
string
+
Path to RAG database. Required for faiss backend.
+
+
+
score_multiplier
+
number
+
Multiplier applied to relevance scores from this vector store. Used
+to weight results when querying multiple knowledge sources. Values >
+1 boost this store’s results; values < 1 reduce them.
+
+
+
relevance_cutoff_score
+
number
+
Minimum raw similarity score to consider a result relevant. Results
+with a similarity score below this threshold are not returned.
+
+
+
host
+
string
+
PostgreSQL host for pgvector backend. Defaults to
+${env.POSTGRES_HOST} when backend is pgvector.
+
+
+
port
+
+
PostgreSQL port for pgvector backend. Defaults to
+${env.POSTGRES_PORT} when backend is pgvector.
+
+
+
db
+
string
+
PostgreSQL database name for pgvector backend. Defaults to
+${env.POSTGRES_DATABASE} when backend is pgvector.
+
+
+
user
+
string
+
PostgreSQL user for pgvector backend. Defaults to
+${env.POSTGRES_USER} when backend is pgvector.
+
+
+
password
+
string
+
PostgreSQL password for pgvector backend. Defaults to
+${env.POSTGRES_PASSWORD} when backend is pgvector.
+
+
+
+
RedactionConfig
+
Configuration for PII redaction with regex-based rules.
+
Rules are validated and compiled at construction time. Invalid regex
+patterns raise a ValueError immediately.
+
Attributes: rules: Ordered list of redaction rules applied
+sequentially. case_sensitive: When False, patterns are compiled with
+re.IGNORECASE. Defaults to False.
+
+
+
+
+
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
rules
array
-
RAG IDs made available to the LLM as a file_search tool. Use ‘okp’
-to include the OKP vector store. When omitted, all registered BYOK
-vector stores are used (backward compatibility).
+
Ordered list of PII redaction rules
+
+
+
case_sensitive
+
boolean
+
When False, patterns are compiled with re.IGNORECASE
+
+
+
+
RedactionRule
+
A single regex-based redaction rule.
+
Attributes: pattern: Raw regex pattern string to match sensitive
+data. replacement: Text to substitute for each match. case_sensitive:
+Per-rule override for case sensitivity. When None, the global
+RedactionConfig.case_sensitive flag applies.
+
+
+
+
+
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
pattern
+
string
+
Regex pattern to match sensitive data
+
+
+
replacement
+
string
+
Replacement string for matched text
+
+
+
case_sensitive
+
boolean
+
Per-rule case sensitivity override. When None, the global config
+flag applies.
+
+
+
+
RedactionShieldConfiguration
+
Configuration for a named PII-redaction guardrail shield.
+
Attributes: name: Unique, user-facing name identifying this shield
+instance. provider_id: Discriminator identifying this as a redaction
+shield. config: Redaction-specific configuration.
+
+
+
+
+
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
name
+
string
+
Unique, user-facing name identifying this shield instance.
+
+
+
provider_id
+
string
+
Discriminator identifying this as a redaction shield.
+
+
+
config
+
+
Redaction-specific configuration for this shield.
@@ -1755,6 +2180,64 @@
RerankerConfiguration
+
RetrievalConfiguration
+
Configuration for inline and tool retrieval strategies.
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
inline
+
+
Inline RAG: context injected before the LLM request.
+
+
+
tool
+
+
Tool RAG: LLM can call file_search on demand.
+
+
+
+
RetrievalStrategyConfiguration
+
Configuration for a single retrieval strategy (inline or tool).
+
+
+
+
+
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
sources
+
array
+
RAG IDs to use for this retrieval strategy. Use ‘okp’ to include the
+OKP vector store.
+
+
+
max_chunks
+
integer
+
Maximum number of chunks returned by this retrieval strategy.
+
+
+
reranker
+
+
Neural reranking of RAG chunks using cross-encoder. Only applicable
+to inline retrieval.
+
+
+
RlsapiV1Configuration
Configuration for the rlsapi v1 /infer endpoint.
Settings specific to the RHEL Lightspeed Command Line Assistant (CLA)
@@ -1812,6 +2295,49 @@
SQLiteDatabaseConfiguration
+
SavedPromptsConfiguration
+
Configuration for saved prompts feature limits.
+
Controls the maximum number of prompts a user can save, the maximum
+display name (title) length, and the maximum prompt content length.
+Omitted fields use the defaults defined in constants.
+
Attributes: max_prompts_per_user: Maximum number of saved prompts
+allowed per user. max_display_name_length: Maximum character length for
+the prompt display name. max_content_length: Maximum character length
+for the prompt content body.
+
+
+
+
+
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
max_prompts_per_user
+
integer
+
Maximum number of saved prompts a user can create. Defaults to 50.
+Cannot exceed 200.
+
+
+
max_display_name_length
+
integer
+
Maximum character length for prompt display name (title). Defaults
+to 255. Cannot exceed 255.
+
+
+
max_content_length
+
integer
+
Maximum character length for the prompt content body. Defaults to
+10000. Cannot exceed 30000.
+
+
+
ServiceConfiguration
Service configuration.
Lightspeed Core Stack is a REST API service that accepts requests on
@@ -2109,14 +2635,13 @@
UnifiedInferenceProvider
the Llama Stack provider_id. When omitted, synthesized as type with
underscores hyphenated. If set, must be non-empty after stripping
whitespace and may contain only lowercase letters, digits, underscores,
-and hyphens. api_key_env: Name of the environment
-variable holding the provider API key. Emitted verbatim as
-${env.<name>} so the secret never lands on disk
-resolved. allowed_models: Optional allow-list of model identifiers
-passed through to the synthesized provider config. extra: Additional
-provider-config keys merged verbatim into the synthesized provider’s
-config block — an escape hatch for provider-specific knobs
-not modeled here.
+and hyphens. api_key_env: Name of the environment variable holding the
+provider API key. Emitted verbatim as ${env.<name>}
+so the secret never lands on disk resolved. allowed_models: Optional
+allow-list of model identifiers passed through to the synthesized
+provider config. extra: Additional provider-config keys merged verbatim
+into the synthesized provider’s config block — an escape
+hatch for provider-specific knobs not modeled here.
@@ -2258,5 +2783,46 @@
UserDataCollection
+
VectorStoreConfiguration
+
Configuration for dynamic vector-store providers.
+
Mirrors InferenceConfiguration: a providers list plus a
+sibling default_provider pointer, rather than a per-entry
+default flag.
+
Attributes: default_provider: Provider id used for
+vector_stores.default_* in the synthesized Llama Stack config. Required
+when providers is non-empty; must match one of providers[].id. Must be
+omitted when providers is empty. providers: Dynamic vector-store
+provider capacity for runtime POST /v1/vector-stores creates. Not the
+same as rag.byok.stores (static registered corpora).
+
+
+
+
+
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
default_provider
+
string
+
Provider id used for vector_stores.default_* in the synthesized
+Llama Stack config. Required when providers is non-empty; must match one
+of providers[].id.
+
+
+
providers
+
array
+
Dynamic vector-store provider capacity for runtime POST
+/v1/vector-stores creates. Not the same as rag.byok.stores (static
+registered corpora).