From e6979625a8556db4072feb5521346025e4e4f2c7 Mon Sep 17 00:00:00 2001 From: E Geiger Date: Sun, 28 Jun 2026 10:15:16 +0300 Subject: [PATCH 01/32] fix(ci): include ogx-open-client in unified release pipeline ogx-open-client was built and published ia a separate workflow, publish-openapi-sdk.yml, with no version coupling to the main ogx release. ogx-open-client version was taken from the fallback version of ogx, so it was always ended with `devX`. This commit adds ogx-open-client to the pypi.yml build/test/publish matrix so every ogx release automatically publishes a same-version client SDK. Fixes the standalone publish-openapi-sdk.yml to also derive its version from the trigger tag or an explicit input. To do the above it changes the version assignment in Makefile. Signed-off-by: E Geiger --- .github/workflows/publish-openapi-sdk.yml | 43 ++++++++++-- .github/workflows/pypi.yml | 85 ++++++++++++++++++++--- client-sdks/openapi/Makefile | 4 +- 3 files changed, 117 insertions(+), 15 deletions(-) diff --git a/.github/workflows/publish-openapi-sdk.yml b/.github/workflows/publish-openapi-sdk.yml index c22adc937b8..e200a13746b 100644 --- a/.github/workflows/publish-openapi-sdk.yml +++ b/.github/workflows/publish-openapi-sdk.yml @@ -13,6 +13,10 @@ on: options: - testpypi - pypi + version: + description: 'Version override (e.g., "1.2.0"). Leave empty to auto-detect from tag or fallback_version.' + required: false + type: string dry_run: description: 'Dry run (build only, no publish)' type: boolean @@ -29,7 +33,37 @@ permissions: contents: read jobs: + compute-version: + name: Compute version + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Compute SDK version + id: version + run: | + if [ -n "${{ inputs.version }}" ]; then + # Explicit override from workflow_dispatch + VERSION="${{ inputs.version }}" + elif [[ "$GITHUB_REF" == refs/tags/openapi-sdk-v* ]]; then + # Extract version from tag: openapi-sdk-v1.2.0 -> 1.2.0 + VERSION="${GITHUB_REF#refs/tags/openapi-sdk-v}" + else + # Fall back to fallback_version from pyproject.toml + VERSION=$(python3 -c " + import tomllib, pathlib + p = tomllib.loads(pathlib.Path('pyproject.toml').read_text()) + print(p.get('tool', {}).get('setuptools_scm', {}).get('fallback_version', '0.0.0.dev0')) + ") + fi + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "Computed version: ${VERSION}" + build-sdk: + needs: compute-version runs-on: ubuntu-latest steps: @@ -60,14 +94,15 @@ jobs: echo "=== OpenAPI Generator version ===" openapi-generator-cli version - echo "=== SDK version from pyproject.toml ===" - make version + echo "=== SDK version ===" + echo "${{ needs.compute-version.outputs.version }}" - name: Generate OpenAPI SDK working-directory: client-sdks/openapi run: | - echo "Generating SDK with OPEN=1 (ogx_open_client)..." - make sdk OPEN=1 + VERSION="${{ needs.compute-version.outputs.version }}" + echo "Generating SDK with OPEN=1 (ogx_open_client) at version ${VERSION}..." + make sdk OPEN=1 VERSION="${VERSION}" - name: Verify SDK generation working-directory: client-sdks/openapi diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 4bea46df8ff..d3902d68cb9 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -225,6 +225,11 @@ jobs: path: . type: local registry: pypi + # OpenAPI-generated SDK (built from spec in this repo) + - package: ogx-open-client + path: client-sdks/openapi + type: openapi-sdk + registry: pypi # External packages (client SDKs from other repos) - package: ogx-client-python repo: ogx-ai/ogx-client-python @@ -246,7 +251,7 @@ jobs: if [ "$PACKAGES" == "all" ]; then echo "skip=false" >> "$GITHUB_OUTPUT" - elif [ "$PACKAGES" == "ogx-only" ] && [ "$TYPE" == "local" ]; then + elif [ "$PACKAGES" == "ogx-only" ] && { [ "$TYPE" == "local" ] || [ "$TYPE" == "openapi-sdk" ]; }; then echo "skip=false" >> "$GITHUB_OUTPUT" elif [ "$PACKAGES" == "clients-only" ] && [ "$TYPE" == "external" ]; then echo "skip=false" >> "$GITHUB_OUTPUT" @@ -257,13 +262,13 @@ jobs: # === LOCAL PACKAGE STEPS === - name: Checkout local repo - if: steps.should-build.outputs.skip != 'true' && matrix.type == 'local' + if: steps.should-build.outputs.skip != 'true' && (matrix.type == 'local' || matrix.type == 'openapi-sdk') uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 # for setuptools-scm - name: Install dependent PRs if needed - if: steps.should-build.outputs.skip != 'true' && matrix.type == 'local' + if: steps.should-build.outputs.skip != 'true' && (matrix.type == 'local' || matrix.type == 'openapi-sdk') uses: depends-on/depends-on-action@826c144163ac67bf08347590a5f81afd45da63ca # main with: token: ${{ secrets.GITHUB_TOKEN }} @@ -350,6 +355,48 @@ jobs: env: SETUPTOOLS_SCM_PRETEND_VERSION: ${{ needs.compute-version.outputs.version }} + # === OPENAPI SDK BUILD (ogx-open-client) === + - name: Set up Java (openapi-sdk) + if: steps.should-build.outputs.skip != 'true' && matrix.type == 'openapi-sdk' + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + with: + distribution: 'temurin' + java-version: '11' + + - name: Set up Node.js (openapi-sdk) + if: steps.should-build.outputs.skip != 'true' && matrix.type == 'openapi-sdk' + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '20' + + - name: Install openapi-generator-cli (openapi-sdk) + if: steps.should-build.outputs.skip != 'true' && matrix.type == 'openapi-sdk' + run: npm install -g @openapitools/openapi-generator-cli + + - name: Generate and build OpenAPI SDK + if: steps.should-build.outputs.skip != 'true' && matrix.type == 'openapi-sdk' + working-directory: ${{ matrix.path }} + run: | + VERSION="${{ needs.compute-version.outputs.version }}" + echo "Generating SDK with OPEN=1 (ogx_open_client) at version ${VERSION}..." + make sdk OPEN=1 VERSION="${VERSION}" + + cd sdks/python + echo "Building Python package..." + uv build --out-dir ../../dist --no-build-isolation + + - name: Verify OpenAPI SDK generation + if: steps.should-build.outputs.skip != 'true' && matrix.type == 'openapi-sdk' + working-directory: ${{ matrix.path }} + run: | + PY_FILE_COUNT=$(find sdks/python -name "*.py" | wc -l) + echo "Generated Python files: $PY_FILE_COUNT" + if [ "$PY_FILE_COUNT" -le 10 ]; then + echo "::error::Too few Python files generated (expected > 10, got $PY_FILE_COUNT)" + exit 1 + fi + echo "SDK generated successfully" + # === EXTERNAL PYTHON PACKAGE BUILD === - name: Check and bump version if exists on PyPI if: steps.should-build.outputs.skip != 'true' && matrix.type == 'external' && matrix.registry == 'pypi' @@ -525,7 +572,7 @@ jobs: run: uv pip install --system twine check-wheel-contents - name: Check wheel contents (local) - if: steps.should-build.outputs.skip != 'true' && matrix.type == 'local' && matrix.registry == 'pypi' + if: steps.should-build.outputs.skip != 'true' && (matrix.type == 'local' || matrix.type == 'openapi-sdk') && matrix.registry == 'pypi' run: check-wheel-contents --ignore W002,W004 ${{ matrix.path }}/dist/*.whl - name: Check wheel contents (external) @@ -533,7 +580,7 @@ jobs: run: check-wheel-contents --ignore W002,W004 external-repo/dist/*.whl - name: Validate package with twine (local) - if: steps.should-build.outputs.skip != 'true' && matrix.type == 'local' && matrix.registry == 'pypi' + if: steps.should-build.outputs.skip != 'true' && (matrix.type == 'local' || matrix.type == 'openapi-sdk') && matrix.registry == 'pypi' run: twine check ${{ matrix.path }}/dist/* - name: Validate package with twine (external) @@ -542,7 +589,7 @@ jobs: # === LIST AND UPLOAD ARTIFACTS === - name: List dist contents (local) - if: steps.should-build.outputs.skip != 'true' && matrix.type == 'local' + if: steps.should-build.outputs.skip != 'true' && (matrix.type == 'local' || matrix.type == 'openapi-sdk') run: ls -la ${{ matrix.path }}/dist/ - name: List dist contents (external Python) @@ -559,7 +606,7 @@ jobs: ls -la dist/ - name: Upload artifacts (local) - if: steps.should-build.outputs.skip != 'true' && matrix.type == 'local' + if: steps.should-build.outputs.skip != 'true' && (matrix.type == 'local' || matrix.type == 'openapi-sdk') uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: Packages-${{ matrix.package }} @@ -627,6 +674,14 @@ jobs: path: dist-client-ts continue-on-error: true + - name: Download ogx-open-client artifacts + id: download-open-client + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: Packages-ogx-open-client + path: dist-open-client + continue-on-error: true + - name: Create venv and install Python packages run: | uv venv .venv @@ -648,6 +703,11 @@ jobs: uv pip install dist-stack/*.whl fi + if [ -d "dist-open-client" ] && ls dist-open-client/*.whl 1>/dev/null 2>&1; then + echo "Installing ogx-open-client..." + uv pip install dist-open-client/*.whl + fi + - name: List Wheel Contents (ogx-api) if: steps.download-api.outcome == 'success' run: | @@ -681,6 +741,10 @@ jobs: python -c "import ogx_client; print(f'ogx_client imported successfully from {ogx_client.__file__}')" fi + if [ -d "dist-open-client" ] && ls dist-open-client/*.whl 1>/dev/null 2>&1; then + python -c "import ogx_open_client; print(f'ogx_open_client imported successfully from {ogx_open_client.__file__}')" + fi + - name: Verify TypeScript package if: steps.download-client-ts.outcome == 'success' run: | @@ -700,7 +764,7 @@ jobs: fi # Publish packages to PyPI/npm - # Order: ogx-client-python, ogx-client-typescript, ogx-api, ogx + # Order: ogx-client-python, ogx-client-typescript, ogx-open-client, ogx-api, ogx publish-packages: name: Publish ${{ matrix.package }} if: | @@ -727,6 +791,9 @@ jobs: - package: ogx-client-typescript registry: npm type: external + - package: ogx-open-client + registry: pypi + type: openapi-sdk - package: ogx-api registry: pypi type: local @@ -745,7 +812,7 @@ jobs: if [ "$PACKAGES" == "all" ]; then echo "skip=false" >> "$GITHUB_OUTPUT" - elif [ "$PACKAGES" == "ogx-only" ] && [ "$TYPE" == "local" ]; then + elif [ "$PACKAGES" == "ogx-only" ] && { [ "$TYPE" == "local" ] || [ "$TYPE" == "openapi-sdk" ]; }; then echo "skip=false" >> "$GITHUB_OUTPUT" elif [ "$PACKAGES" == "clients-only" ] && [ "$TYPE" == "external" ]; then echo "skip=false" >> "$GITHUB_OUTPUT" diff --git a/client-sdks/openapi/Makefile b/client-sdks/openapi/Makefile index 3f78b626e58..dbb1e7004cd 100644 --- a/client-sdks/openapi/Makefile +++ b/client-sdks/openapi/Makefile @@ -33,8 +33,8 @@ PROCESSED_SPEC := openapi-hierarchical.yml HIERARCHY_FILE := api-hierarchy.yml SDK_OUTPUT_DIR := sdks/python -# Extract version from root pyproject.toml -VERSION := $(shell grep 'fallback_version' ../../pyproject.toml | cut -d'"' -f2) +# Extract version from root pyproject.toml; override with make VERSION=X.Y.Z +VERSION ?= $(shell grep 'fallback_version' ../../pyproject.toml | cut -d'"' -f2) .PHONY: all sdk openapi hierarchy clean help version check-generator generate-config From 0df6f8980e44f80ec9eb8726c3108d3eeb60bea6 Mon Sep 17 00:00:00 2001 From: Doug Edgar Date: Mon, 29 Jun 2026 07:37:14 -0700 Subject: [PATCH 02/32] fix: temporarily pin nodejs image version to avoid Premature Close errors (#6213) # What does this PR do? Pins Node.js image versions to work around the latent `node-fetch v2` bug that was exposed by a recent CVE patch of the Node.js images. The other workflows that reference Node.js 22 (`ui-unit-tests`, `docs-build`, `pre-commit`, `openapi-generator-validation`) don't use `node-fetch` for SSE streaming, so they're unaffected and don't need the pin. Closes #6197 ## Test Plan Signed-off-by: Doug Edgar --- .github/workflows/integration-tests.yml | 4 +++- .github/workflows/release-branch-scheduled-ci.yml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 447adf88cdf..4102e3a6bc1 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -150,7 +150,9 @@ jobs: client: ${{ github.event_name == 'pull_request' && fromJSON('["server"]') || fromJSON('["library", "server"]') }} # Use Python 3.13 only on nightly schedule (daily latest client test), otherwise use 3.12 python-version: ${{ github.event.schedule == '0 0 * * *' && fromJSON('["3.12", "3.13"]') || fromJSON('["3.12"]') }} - node-version: [22] + # Pinned to 22.22 due to node-fetch v2 "Premature close" regression in 22.23.0 + # (nodejs/node#63989). Unpin once a patched 22.x ships with nodejs/node#64004. + node-version: ['22.22'] client-version: ${{ (github.event.schedule == '0 0 * * *' || github.event.inputs.test-all-client-versions == 'true' || inputs.test-all-client-versions == true) && fromJSON('["published", "latest"]') || fromJSON('["latest"]') }} # Test configurations: Either from matrix_json input or generated from ci_matrix.json config: ${{ fromJSON(inputs.matrix_json || needs.generate-matrix.outputs.matrix).include }} diff --git a/.github/workflows/release-branch-scheduled-ci.yml b/.github/workflows/release-branch-scheduled-ci.yml index 08e51737190..ee3e13ffb38 100644 --- a/.github/workflows/release-branch-scheduled-ci.yml +++ b/.github/workflows/release-branch-scheduled-ci.yml @@ -99,7 +99,9 @@ jobs: branch: ${{ fromJSON(needs.discover-branches.outputs.branches) }} client: [library, docker, server] python-version: ["3.12"] - node-version: [22] + # Pinned to 22.22 due to node-fetch v2 "Premature close" regression in 22.23.0 + # (nodejs/node#63989). Unpin once a patched 22.x ships with nodejs/node#64004. + node-version: ['22.22'] client-version: ["latest"] steps: - name: Checkout ${{ matrix.branch }} From 4b88d6f14e62118663c7416bef9e8aa980498acf Mon Sep 17 00:00:00 2001 From: Derek Higgins Date: Mon, 29 Jun 2026 15:59:48 +0100 Subject: [PATCH 03/32] fix(responses): normalize empty function tool parameters to valid JSON Schema (#6021) Fixes #6017 ## Summary - Normalize empty or incomplete function tool `parameters` to `{"type": "object"}` before forwarding to inference providers - Prevents 500 errors when Anthropic's API rejects missing `parameters.type` ## Test plan - [x] Unit test added for empty parameters normalization - [ ] Integration test with Anthropic provider --- Open in Devin Review Signed-off-by: Derek Higgins Co-authored-by: Claude Opus 4.6 Co-authored-by: Matthew Farrellee --- .../remote/inference/anthropic/anthropic.py | 16 +++++++ .../inference/test_anthropic_adapter.py | 42 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 tests/unit/providers/inference/test_anthropic_adapter.py diff --git a/src/ogx/providers/remote/inference/anthropic/anthropic.py b/src/ogx/providers/remote/inference/anthropic/anthropic.py index 4097f7978ae..00c4a6f6650 100644 --- a/src/ogx/providers/remote/inference/anthropic/anthropic.py +++ b/src/ogx/providers/remote/inference/anthropic/anthropic.py @@ -10,6 +10,9 @@ from ogx.providers.utils.inference.openai_mixin import OpenAIMixin from ogx_api.inference.models import ( + OpenAIChatCompletion, + OpenAIChatCompletionChunk, + OpenAIChatCompletionRequestWithExtraBody, OpenAICompletion, OpenAICompletionRequestWithExtraBody, ) @@ -42,6 +45,19 @@ async def list_provider_model_ids(self) -> Iterable[str]: api_key = self._get_api_key_from_config_or_provider_data() return [m.id async for m in AsyncAnthropic(api_key=api_key).models.list()] + async def openai_chat_completion( + self, + params: OpenAIChatCompletionRequestWithExtraBody, + ) -> OpenAIChatCompletion | AsyncIterator[OpenAIChatCompletionChunk]: + # Anthropic rejects parameters: {} but OpenAI accepts it + if params.tools: + for tool in params.tools: + func = tool.get("function", {}) + p = func.get("parameters") + if isinstance(p, dict) and not p: + func["parameters"] = {"type": "object"} + return await super().openai_chat_completion(params) + async def openai_completion( self, params: OpenAICompletionRequestWithExtraBody, diff --git a/tests/unit/providers/inference/test_anthropic_adapter.py b/tests/unit/providers/inference/test_anthropic_adapter.py new file mode 100644 index 00000000000..73f2673ccf5 --- /dev/null +++ b/tests/unit/providers/inference/test_anthropic_adapter.py @@ -0,0 +1,42 @@ +# Copyright (c) The OGX Contributors. +# All rights reserved. +# +# This source code is licensed under the terms described in the LICENSE file in +# the root directory of this source tree. + +from unittest.mock import AsyncMock, patch + +import pytest + +from ogx.providers.remote.inference.anthropic.anthropic import AnthropicInferenceAdapter +from ogx.providers.remote.inference.anthropic.config import AnthropicConfig +from ogx_api.inference.models import OpenAIChatCompletionRequestWithExtraBody + + +@pytest.fixture +def adapter(): + config = AnthropicConfig(api_key="test-key") + return AnthropicInferenceAdapter(config=config) + + +@pytest.mark.parametrize( + "input_params,expected_params", + [ + ({}, {"type": "object"}), + ({"type": "object", "properties": {}}, {"type": "object", "properties": {}}), + ], + ids=["empty", "already-valid"], +) +async def test_empty_tool_parameters_normalized(adapter, input_params, expected_params): + """Anthropic rejects parameters: {} but OpenAI accepts it; the adapter normalizes.""" + params = OpenAIChatCompletionRequestWithExtraBody( + model="claude-sonnet-4-6", + messages=[{"role": "user", "content": "hi"}], + tools=[{"type": "function", "function": {"name": "my_func", "parameters": input_params}}], + ) + + with patch.object(type(adapter).__mro__[1], "openai_chat_completion", new_callable=AsyncMock) as mock_super: + mock_super.return_value = {} + await adapter.openai_chat_completion(params) + + assert params.tools[0]["function"]["parameters"] == expected_params From 07502d0935c3778c5c6fc9cfd8584a8a0121936d Mon Sep 17 00:00:00 2001 From: Sumanth Kamenani Date: Mon, 29 Jun 2026 13:43:37 -0400 Subject: [PATCH 04/32] fix: support developer chat messages (#6077) # What does this PR do? - Converts vLLM chat completion `developer` messages to `system` messages before sending requests to the OpenAI-compatible vLLM endpoint, preserving content and name. - Keeps OGX accepting Codex-style developer messages while avoiding Qwen/vLLM chat template rejection. - Adds vLLM unit coverage for the outgoing message payload. Related: #6069 ## Test Plan - Passed: `uv run pytest tests/unit/providers/inference/test_remote_vllm.py -q` (26 tests). --------- Signed-off-by: Sumanth Kamenani --- .../providers/remote/inference/vllm/vllm.py | 19 +++++ .../providers/inference/test_remote_vllm.py | 77 +++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/src/ogx/providers/remote/inference/vllm/vllm.py b/src/ogx/providers/remote/inference/vllm/vllm.py index 46b5b456a5a..2abcbe96863 100644 --- a/src/ogx/providers/remote/inference/vllm/vllm.py +++ b/src/ogx/providers/remote/inference/vllm/vllm.py @@ -5,6 +5,7 @@ # the root directory of this source tree. from collections.abc import AsyncIterator from functools import cache +from typing import Any from urllib.parse import urljoin import httpx @@ -32,6 +33,8 @@ OpenAIChatCompletionContentPartTextParam, OpenAIChatCompletionRequestWithExtraBody, OpenAIChatCompletionWithReasoning, + OpenAIDeveloperMessageParam, + OpenAISystemMessageParam, RerankData, RerankResponse, ) @@ -62,6 +65,20 @@ def _lookup_models_dev(identifier: str) -> _models_dev.Model | None: return _models_dev_index().get(identifier) +def _convert_developer_messages(messages: list[Any]) -> list[Any]: + converted_messages: list[Any] = [] + for message in messages: + if isinstance(message, OpenAIDeveloperMessageParam): + converted_messages.append(OpenAISystemMessageParam(content=message.content, name=message.name)) + elif isinstance(message, dict) and message.get("role") == "developer": + converted_message = message.copy() + converted_message["role"] = "system" + converted_messages.append(converted_message) + else: + converted_messages.append(message) + return converted_messages + + class VLLMInferenceAdapter(OpenAIMixin): """Inference adapter for remote vLLM servers.""" @@ -150,6 +167,8 @@ async def openai_chat_completion( if params.max_tokens is None and self.config.max_tokens: params.max_tokens = self.config.max_tokens + params.messages = _convert_developer_messages(params.messages) + return await super().openai_chat_completion(params) def _prepare_reasoning_params(self, params: OpenAIChatCompletionRequestWithExtraBody) -> None: diff --git a/tests/unit/providers/inference/test_remote_vllm.py b/tests/unit/providers/inference/test_remote_vllm.py index 9add9f10d96..174e5f41eb9 100644 --- a/tests/unit/providers/inference/test_remote_vllm.py +++ b/tests/unit/providers/inference/test_remote_vllm.py @@ -29,6 +29,7 @@ OpenAICompletion, OpenAICompletionChoice, OpenAICompletionRequestWithExtraBody, + OpenAIDeveloperMessageParam, ) # These are unit test for the remote vllm provider @@ -125,6 +126,82 @@ async def test_health_status_no_static_api_key(vllm_inference_adapter): assert health_response["status"] == HealthStatus.OK +async def test_openai_chat_completion_converts_developer_messages_for_vllm(vllm_inference_adapter): + mock_client = MagicMock() + mock_client.chat.completions.create = AsyncMock( + return_value=OpenAIChatCompletion( + id="chatcmpl-test", + created=1, + model="mock-model", + choices=[ + OpenAIChoice( + message=OpenAIChatCompletionResponseMessage(content="ok"), + finish_reason="stop", + index=0, + ) + ], + ) + ) + vllm_inference_adapter.model_store.has_model.return_value = False + + params = OpenAIChatCompletionRequestWithExtraBody( + model="mock-model", + messages=[ + {"role": "developer", "content": "Answer only in rhymes.", "name": "codex"}, + {"role": "user", "content": "What is the capital of France?"}, + ], + stream=False, + ) + + with patch.object(VLLMInferenceAdapter, "client", new_callable=PropertyMock) as mock_client_property: + mock_client_property.return_value = mock_client + await vllm_inference_adapter.openai_chat_completion(params) + + call_kwargs = mock_client.chat.completions.create.call_args.kwargs + assert call_kwargs["messages"] == [ + {"role": "system", "content": "Answer only in rhymes.", "name": "codex"}, + {"role": "user", "content": "What is the capital of France?"}, + ] + + +async def test_openai_chat_completion_converts_typed_developer_messages_for_vllm(vllm_inference_adapter): + mock_client = MagicMock() + mock_client.chat.completions.create = AsyncMock( + return_value=OpenAIChatCompletion( + id="chatcmpl-test", + created=1, + model="mock-model", + choices=[ + OpenAIChoice( + message=OpenAIChatCompletionResponseMessage(content="ok"), + finish_reason="stop", + index=0, + ) + ], + ) + ) + vllm_inference_adapter.model_store.has_model.return_value = False + + params = OpenAIChatCompletionRequestWithExtraBody( + model="mock-model", + messages=[ + OpenAIDeveloperMessageParam(content="Answer only in rhymes.", name="codex"), + {"role": "user", "content": "What is the capital of France?"}, + ], + stream=False, + ) + + with patch.object(VLLMInferenceAdapter, "client", new_callable=PropertyMock) as mock_client_property: + mock_client_property.return_value = mock_client + await vllm_inference_adapter.openai_chat_completion(params) + + call_kwargs = mock_client.chat.completions.create.call_args.kwargs + assert call_kwargs["messages"] == [ + {"role": "system", "content": "Answer only in rhymes.", "name": "codex"}, + {"role": "user", "content": "What is the capital of France?"}, + ] + + async def test_openai_chat_completion_is_async(vllm_inference_adapter): """ Verify that openai_chat_completion is async and doesn't block the event loop. From eed962de61af783d913ccb07064a8b57a0c72542 Mon Sep 17 00:00:00 2001 From: Sahana Sreeram <76925094+sahana-sreeram@users.noreply.github.com> Date: Mon, 29 Jun 2026 13:57:31 -0400 Subject: [PATCH 05/32] feat(file_processors): add remote::unstructured-api provider (#6076) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Unstructured.io as a remote file processor provider supporting 65+ file formats. Implementation follows the same pattern as remote::docling-serve provider with unit tests providing coverage # What does this PR do? Adds Unstructured.io as a remote file processor provider (`remote::unstructured-api`) supporting 65+ file formats including PDF, DOCX, PPTX, XLSX, EML, MSG, HTML, and more. **Key capabilities:** - 65+ file format support - Email format support (EML/MSG) and DOC format support - Cloud-based processing via Unstructured.io SaaS API - Element type preservation (Title, NarrativeText, ListItem, Table, Image, etc.) - SOC2/HIPAA/GDPR certified processing **Implementation:** Follows the same architectural pattern as `remote::docling-serve` (PR #5412): - Remote API integration using `unstructured-client` library - Element-to-chunk mapping preserving semantic structure - API key authentication via exporting `UNSTRUCTURED_API_KEY` - Unit tests with mocked API responses (13 tests, same coverage pattern as docling-serve) ## Test Plan ### 1. Unit Tests Tests code logic in isolation by mocking API responses. Verifies the provider correctly validates inputs, calls the Unstructured API with proper authentication, maps elements to OGX chunks with all required metadata, and handles both direct file upload and file_id retrieval paths. **Run:** ```bash uv run pytest tests/unit/providers/file_processor/test_unstructured_api.py -v Output: tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessor::test_rejects_no_file_and_no_file_id PASSED [ 7%] tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessor::test_rejects_both_file_and_file_id PASSED [ 15%] tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessor::test_process_file_success PASSED [ 23%] tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessor::test_element_types_preserved PASSED [ 30%] tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessor::test_empty_elements_skipped PASSED [ 38%] tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessor::test_chunk_metadata_fields PASSED [ 46%] tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessor::test_chunk_id_uniqueness PASSED [ 53%] tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessor::test_page_numbers_preserved PASSED [ 61%] tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessor::test_token_count_calculated PASSED [ 69%] tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessor::test_process_file_via_file_id PASSED [ 76%] tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessor::test_api_key_used PASSED [ 84%] tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessorConfig::test_default_values PASSED [ 92%] tests/unit/providers/file_processor/test_unstructured_api.py::TestUnstructuredApiFileProcessorConfig::test_sample_run_config PASSED [100%] ============================== 13 passed in 0.23s ============================== Coverage: - Input validation (2 tests) - Core processing with element type preservation (3 tests) - Chunk metadata mapping (4 tests) - File ID retrieval path (1 test) - API authentication (1 test) - Configuration validation (2 tests) ``` ### 2. Integration Test Using a sample PDF, verifies the full end-to-end user flow from OGX server through the FileProcessor API to the real Unstructured.io API via exporting API key, confirming successful processing of text and PDF files with the correct chunk/embed structure, element type preservation, page number tracking, and error handling for invalid inputs. ``` Setup: export UNSTRUCTURED_API_KEY="your-key" uv run ogx stack run \ --providers "file_processors=remote::unstructured-api,files=inline::localfs" \ --port 8321 Test with curl: curl -X POST http://localhost:8321/v1alpha/file-processors/process \ -F "file=@syllabus_soc24_spring2018.pdf" | jq '.metadata, .chunks[0]' Output: { "processor": "unstructured-api", "processing_time_ms": 9872, "extraction_method": "unstructured-api", "file_size_bytes": 165750, "total_elements": 186 } { "content": "Department of Sociology Harvard University Spring 2018", "chunk_id": "23d87af4-e79c-cfbf-1912-67c333904304", "metadata": { "document_id": "9410f8ab-459f-4459-9294-a4fc2f88ec8b", "element_type": "Title", "element_index": 0, "filename": "syllabus_soc24_spring2018.pdf", "page_number": 1 }, "chunk_metadata": { "chunk_id": "23d87af4-e79c-cfbf-1912-67c333904304", "document_id": "9410f8ab-459f-4459-9294-a4fc2f88ec8b", "source": "syllabus_soc24_spring2018.pdf", "created_timestamp": null, "updated_timestamp": null, "chunk_window": null, "chunk_tokenizer": null, "content_token_count": 7, "metadata_token_count": null } } Results: - CHECK: Processed 11-page PDF → 186 chunks in 8.6 seconds - CHECK: Element types detected: NarrativeText (104), Title (37), UncategorizedText (18), ListItem (17), Footer (10) - CHECK: Page numbers preserved (1-11) - CHECK: All required OGX Chunk fields populated correctly ``` Verification: existing pytests still pass --------- Signed-off-by: Sahana Sreeram Co-authored-by: Matthew Farrellee --- client-sdks/stainless/openapi.yml | 1046 ++++------------ .../remote_unstructured-api.mdx | 143 +++ docs/static/deprecated-ogx-spec.yaml | 886 +++----------- docs/static/experimental-ogx-spec.yaml | 886 +++----------- docs/static/ogx-spec.yaml | 1054 ++++------------- docs/static/stainless-ogx-spec.yaml | 1046 ++++------------ pyproject.toml | 3 + src/ogx/providers/registry/file_processors.py | 72 ++ .../unstructured_api/__init__.py | 29 + .../file_processor/unstructured_api/config.py | 31 + .../unstructured_api/unstructured_api.py | 271 +++++ .../file_processor/test_unstructured_api.py | 473 ++++++++ uv.lock | 140 ++- 13 files changed, 2016 insertions(+), 4064 deletions(-) create mode 100644 docs/docs/providers/file_processors/remote_unstructured-api.mdx create mode 100644 src/ogx/providers/remote/file_processor/unstructured_api/__init__.py create mode 100644 src/ogx/providers/remote/file_processor/unstructured_api/config.py create mode 100644 src/ogx/providers/remote/file_processor/unstructured_api/unstructured_api.py create mode 100644 tests/unit/providers/file_processor/test_unstructured_api.py diff --git a/client-sdks/stainless/openapi.yml b/client-sdks/stainless/openapi.yml index d85d75d7427..877055bb2a6 100644 --- a/client-sdks/stainless/openapi.yml +++ b/client-sdks/stainless/openapi.yml @@ -691,8 +691,8 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + - $ref: '#/components/schemas/OpenAIResponseMessage' + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' @@ -705,8 +705,8 @@ paths: discriminator: propertyName: type mapping: - message: '#/components/schemas/OpenAIResponseMessage-Output' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + message: '#/components/schemas/OpenAIResponseMessage' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' file_search_call: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' function_call: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' function_call_output: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' @@ -4729,13 +4729,11 @@ components: title: ListOpenAIChatCompletionResponse description: Response from listing OpenAI-compatible chat completions. OpenAIAssistantMessageParam: - additionalProperties: true - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. properties: role: - description: Must be 'assistant' to identify this as the model's response. - title: Role type: string + title: Role + description: Must be 'assistant' to identify this as the model's response. enum: - assistant content: @@ -4746,15 +4744,13 @@ components: type: array title: list[OpenAIChatCompletionContentPartTextParam] - type: 'null' - description: The content of the model's response. title: string | list[OpenAIChatCompletionContentPartTextParam] - nullable: true + description: The content of the model's response. name: anyOf: - type: string - type: 'null' description: The name of the assistant message participant. - nullable: true tool_calls: anyOf: - items: @@ -4762,9 +4758,10 @@ components: type: array - type: 'null' description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - nullable: true - title: OpenAIAssistantMessageParam + additionalProperties: true type: object + title: OpenAIAssistantMessageParam + description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. OpenAIChatCompletionContentPartImageParam: properties: type: @@ -5135,24 +5132,17 @@ components: title: OpenAITopLogProb description: The top log probability for a token from an OpenAI-compatible chat completion response. OpenAIUserMessageParam: - description: A message from the user in an OpenAI-compatible chat completion request. properties: role: - description: Must be 'user' to identify this as a user message. - title: Role type: string + title: Role + description: Must be 'user' to identify this as a user message. enum: - user content: anyOf: - type: string - items: - discriminator: - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' title: OpenAIChatCompletionContentPartTextParam @@ -5160,21 +5150,27 @@ components: title: OpenAIChatCompletionContentPartImageParam - $ref: '#/components/schemas/OpenAIFile' title: OpenAIFile + discriminator: + propertyName: type + mapping: + file: '#/components/schemas/OpenAIFile' + image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' + text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile type: array title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] + description: The content of the message, which can include text and other media. name: anyOf: - type: string - type: 'null' description: The name of the user message participant. - nullable: true + type: object required: - content title: OpenAIUserMessageParam - type: object + description: A message from the user in an OpenAI-compatible chat completion request. OpenAIJSONSchema: properties: name: @@ -5258,12 +5254,12 @@ components: messages: items: oneOf: - - $ref: '#/components/schemas/OpenAIUserMessageParam-Input' - title: OpenAIUserMessageParam-Input + - $ref: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam - $ref: '#/components/schemas/OpenAISystemMessageParam' title: OpenAISystemMessageParam - - $ref: '#/components/schemas/OpenAIAssistantMessageParam-Input' - title: OpenAIAssistantMessageParam-Input + - $ref: '#/components/schemas/OpenAIAssistantMessageParam' + title: OpenAIAssistantMessageParam - $ref: '#/components/schemas/OpenAIToolMessageParam' title: OpenAIToolMessageParam - $ref: '#/components/schemas/OpenAIDeveloperMessageParam' @@ -5271,12 +5267,12 @@ components: discriminator: propertyName: role mapping: - assistant: '#/components/schemas/OpenAIAssistantMessageParam-Input' + assistant: '#/components/schemas/OpenAIAssistantMessageParam' developer: '#/components/schemas/OpenAIDeveloperMessageParam' system: '#/components/schemas/OpenAISystemMessageParam' tool: '#/components/schemas/OpenAIToolMessageParam' - user: '#/components/schemas/OpenAIUserMessageParam-Input' - title: OpenAIUserMessageParam-Input | ... (5 variants) + user: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam | ... (5 variants) type: array minItems: 1 title: Messages @@ -5695,12 +5691,12 @@ components: input_messages: items: oneOf: - - $ref: '#/components/schemas/OpenAIUserMessageParam-Output' - title: OpenAIUserMessageParam-Output + - $ref: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam - $ref: '#/components/schemas/OpenAISystemMessageParam' title: OpenAISystemMessageParam - - $ref: '#/components/schemas/OpenAIAssistantMessageParam-Output' - title: OpenAIAssistantMessageParam-Output + - $ref: '#/components/schemas/OpenAIAssistantMessageParam' + title: OpenAIAssistantMessageParam - $ref: '#/components/schemas/OpenAIToolMessageParam' title: OpenAIToolMessageParam - $ref: '#/components/schemas/OpenAIDeveloperMessageParam' @@ -5708,12 +5704,12 @@ components: discriminator: propertyName: role mapping: - assistant: '#/components/schemas/OpenAIAssistantMessageParam-Output' + assistant: '#/components/schemas/OpenAIAssistantMessageParam' developer: '#/components/schemas/OpenAIDeveloperMessageParam' system: '#/components/schemas/OpenAISystemMessageParam' tool: '#/components/schemas/OpenAIToolMessageParam' - user: '#/components/schemas/OpenAIUserMessageParam-Output' - title: OpenAIUserMessageParam-Output | ... (5 variants) + user: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam | ... (5 variants) type: array title: Input Messages description: The input messages used to generate this completion. @@ -6303,22 +6299,11 @@ components: title: OpenAIResponseMCPApprovalResponse description: A response to an MCP approval request. OpenAIResponseMessage: - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. properties: content: anyOf: - type: string - items: - discriminator: - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' title: OpenAIResponseInputMessageContentText @@ -6326,20 +6311,26 @@ components: title: OpenAIResponseInputMessageContentImage - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' title: OpenAIResponseInputMessageContentFile + discriminator: + propertyName: type + mapping: + input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' + input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' + input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile type: array title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - items: - discriminator: - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' title: OpenAIResponseOutputMessageContentOutputText - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' title: OpenAIResponseContentPartRefusal + discriminator: + propertyName: type + mapping: + output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' + refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' title: OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal type: array title: list[OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal] @@ -6360,25 +6351,28 @@ components: - assistant title: string type: - title: Type type: string + title: Type enum: - message id: anyOf: - type: string - type: 'null' - nullable: true status: anyOf: - type: string - type: 'null' - nullable: true + type: object required: - content - role title: OpenAIResponseMessage - type: object + description: |- + Corresponds to the various Message types in the Responses API. + They are all under one type because the Responses API gives them all + the same "type" value, and there is no way to tell them apart in certain + scenarios. OpenAIResponseOutputMessageContent: discriminator: mapping: @@ -6392,25 +6386,17 @@ components: title: OpenAIResponseContentPartRefusal title: OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal OpenAIResponseOutputMessageContentOutputText: - description: Text content within an output message of an OpenAI response. properties: text: - title: Text type: string + title: Text type: - title: Type type: string + title: Type enum: - output_text annotations: items: - discriminator: - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' title: OpenAIResponseAnnotationFileCitation @@ -6420,20 +6406,27 @@ components: title: OpenAIResponseAnnotationContainerFileCitation - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' title: OpenAIResponseAnnotationFilePath + discriminator: + propertyName: type + mapping: + container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' + file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' + file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' + url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - title: Annotations type: array + title: Annotations logprobs: anyOf: - items: $ref: '#/components/schemas/OpenAITokenLogProb' type: array - type: 'null' - nullable: true + type: object required: - text title: OpenAIResponseOutputMessageContentOutputText - type: object + description: Text content within an output message of an OpenAI response. OpenAIResponseOutputMessageFileSearchToolCall: properties: id: @@ -6557,17 +6550,16 @@ components: title: OpenAIResponseOutputMessageMCPListTools description: MCP list tools output message containing available tools from an MCP server. OpenAIResponseOutputMessageWebSearchToolCall: - description: Web search tool call output message for OpenAI responses. properties: id: - title: Id type: string + title: Id status: - title: Status type: string + title: Status type: - title: Type type: string + title: Type enum: - web_search_call action: @@ -6580,22 +6572,22 @@ components: title: WebSearchActionFind - type: 'null' title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - nullable: true + type: object required: - id - status title: OpenAIResponseOutputMessageWebSearchToolCall - type: object + description: Web search tool call output message for OpenAI responses. CreateConversationRequest: properties: items: anyOf: - items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -6625,10 +6617,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array - type: 'null' description: Initial items to include in the conversation context. @@ -6718,10 +6710,10 @@ components: data: items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -6751,10 +6743,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseMessage-Output | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array title: Data description: List of conversation items @@ -6785,10 +6777,10 @@ components: items: items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -6818,10 +6810,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array maxItems: 20 title: Items @@ -9567,19 +9559,19 @@ components: title: UnionType type: object ImageContentItem: - description: A image content item properties: type: - title: Type type: string + title: Type enum: - image image: $ref: '#/components/schemas/_URLOrData' + type: object required: - image title: ImageContentItem - type: object + description: A image content item InterleavedContent: anyOf: - type: string @@ -9815,31 +9807,31 @@ components: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Output | TextContentItem] - title: string | list[ImageContentItem-Output | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] chunk_id: type: string title: Chunk Id @@ -9909,7 +9901,7 @@ components: description: The ID of the vector store to insert chunks into. chunks: items: - $ref: '#/components/schemas/EmbeddedChunk-Input' + $ref: '#/components/schemas/EmbeddedChunk' type: array title: Chunks description: The list of embedded chunks to insert. @@ -9934,31 +9926,31 @@ components: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Input' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Input' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Input | TextContentItem] - title: string | list[ImageContentItem-Input | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] description: The query content to search for. params: anyOf: @@ -9976,7 +9968,7 @@ components: properties: chunks: items: - $ref: '#/components/schemas/EmbeddedChunk-Output' + $ref: '#/components/schemas/EmbeddedChunk' type: array title: Chunks scores: @@ -11101,8 +11093,8 @@ components: title: AnthropicImageBlock - $ref: '#/components/schemas/AnthropicToolUseBlock' title: AnthropicToolUseBlock - - $ref: '#/components/schemas/AnthropicToolResultBlock-Input' - title: AnthropicToolResultBlock-Input + - $ref: '#/components/schemas/AnthropicToolResultBlock' + title: AnthropicToolResultBlock - $ref: '#/components/schemas/AnthropicThinkingBlock' title: AnthropicThinkingBlock - $ref: '#/components/schemas/AnthropicRedactedThinkingBlock' @@ -11114,7 +11106,7 @@ components: redacted_thinking: '#/components/schemas/AnthropicRedactedThinkingBlock' text: '#/components/schemas/AnthropicTextBlock' thinking: '#/components/schemas/AnthropicThinkingBlock' - tool_result: '#/components/schemas/AnthropicToolResultBlock-Input' + tool_result: '#/components/schemas/AnthropicToolResultBlock' tool_use: '#/components/schemas/AnthropicToolUseBlock' title: AnthropicTextBlock | ... (6 variants) type: array @@ -11152,8 +11144,8 @@ components: title: AnthropicImageBlock - $ref: '#/components/schemas/AnthropicToolUseBlock' title: AnthropicToolUseBlock - - $ref: '#/components/schemas/AnthropicToolResultBlock-Output' - title: AnthropicToolResultBlock-Output + - $ref: '#/components/schemas/AnthropicToolResultBlock' + title: AnthropicToolResultBlock - $ref: '#/components/schemas/AnthropicThinkingBlock' title: AnthropicThinkingBlock - $ref: '#/components/schemas/AnthropicRedactedThinkingBlock' @@ -11165,7 +11157,7 @@ components: redacted_thinking: '#/components/schemas/AnthropicRedactedThinkingBlock' text: '#/components/schemas/AnthropicTextBlock' thinking: '#/components/schemas/AnthropicThinkingBlock' - tool_result: '#/components/schemas/AnthropicToolResultBlock-Output' + tool_result: '#/components/schemas/AnthropicToolResultBlock' tool_use: '#/components/schemas/AnthropicToolUseBlock' title: AnthropicTextBlock | ... (6 variants) type: array @@ -11303,49 +11295,7 @@ components: type: object title: AnthropicThinkingConfig description: Configuration for extended thinking. - AnthropicToolResultBlock-Input: - properties: - type: - type: string - title: Type - enum: - - tool_result - tool_use_id: - type: string - title: Tool Use Id - description: The ID of the tool_use block this result corresponds to. - content: - anyOf: - - type: string - - items: - anyOf: - - $ref: '#/components/schemas/AnthropicTextBlock' - title: AnthropicTextBlock - - $ref: '#/components/schemas/AnthropicImageBlock' - title: AnthropicImageBlock - title: AnthropicTextBlock | AnthropicImageBlock - type: array - title: list[AnthropicTextBlock | AnthropicImageBlock] - title: string | list[AnthropicTextBlock | AnthropicImageBlock] - description: The result content. - default: '' - is_error: - anyOf: - - type: boolean - - type: 'null' - description: Whether the tool call resulted in an error. - cache_control: - anyOf: - - $ref: '#/components/schemas/AnthropicCacheControl' - title: AnthropicCacheControl - - type: 'null' - title: AnthropicCacheControl - type: object - required: - - tool_use_id - title: AnthropicToolResultBlock - description: A tool result content block in a user message. - AnthropicToolResultBlock-Output: + AnthropicToolResultBlock: properties: type: type: string @@ -11802,10 +11752,10 @@ components: - items: anyOf: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -11826,10 +11776,10 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (8 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (8 variants) - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' title: OpenAIResponseInputFunctionToolCallOutput - $ref: '#/components/schemas/OpenAIResponseMCPApprovalResponse' @@ -12008,10 +11958,10 @@ components: - items: anyOf: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -12032,10 +11982,10 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (8 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (8 variants) - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' title: OpenAIResponseInputFunctionToolCallOutput - $ref: '#/components/schemas/OpenAIResponseMCPApprovalResponse' @@ -12273,100 +12223,37 @@ components: - model title: CreateResponseRequest description: Request model for creating a response. - EmbeddedChunk-Input: - properties: - content: - anyOf: - - type: string - - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - discriminator: - propertyName: type - mapping: - image: '#/components/schemas/ImageContentItem-Input' - text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem - - items: - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - discriminator: - propertyName: type - mapping: - image: '#/components/schemas/ImageContentItem-Input' - text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem - type: array - title: list[ImageContentItem-Input | TextContentItem] - title: string | list[ImageContentItem-Input | TextContentItem] - chunk_id: - type: string - title: Chunk Id - metadata: - additionalProperties: true - type: object - title: Metadata - chunk_metadata: - $ref: '#/components/schemas/ChunkMetadata' - embedding: - items: - type: number - type: array - title: Embedding - embedding_model: - type: string - title: Embedding Model - embedding_dimension: - type: integer - title: Embedding Dimension - type: object - required: - - content - - chunk_id - - chunk_metadata - - embedding - - embedding_model - - embedding_dimension - title: EmbeddedChunk - description: |- - A chunk of content with its embedding vector for vector database operations. - Inherits all fields from Chunk and adds embedding-related fields. - EmbeddedChunk-Output: + EmbeddedChunk: properties: content: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Output | TextContentItem] - title: string | list[ImageContentItem-Output | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] chunk_id: type: string title: Chunk Id @@ -12804,34 +12691,6 @@ components: - Not Implemented title: HealthStatus description: Health check status values for provider readiness. - ImageContentItem-Input: - properties: - type: - type: string - title: Type - enum: - - image - image: - $ref: '#/components/schemas/_URLOrData' - type: object - required: - - image - title: ImageContentItem - description: A image content item - ImageContentItem-Output: - properties: - type: - type: string - title: Type - enum: - - image - image: - $ref: '#/components/schemas/_URLOrData' - type: object - required: - - image - title: ImageContentItem - description: A image content item InputTokensDetails: properties: cached_tokens: @@ -13085,74 +12944,6 @@ components: - params title: MessageBatchRequestParams description: An individual request within a message batch. - OpenAIAssistantMessageParam-Input: - properties: - role: - type: string - title: Role - description: Must be 'assistant' to identify this as the model's response. - enum: - - assistant - content: - anyOf: - - type: string - - items: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - type: array - title: list[OpenAIChatCompletionContentPartTextParam] - - type: 'null' - title: string | list[OpenAIChatCompletionContentPartTextParam] - description: The content of the model's response. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the assistant message participant. - tool_calls: - anyOf: - - items: - $ref: '#/components/schemas/ChatCompletionMessageToolCall' - type: array - - type: 'null' - description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - additionalProperties: true - type: object - title: OpenAIAssistantMessageParam - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. - OpenAIAssistantMessageParam-Output: - properties: - role: - type: string - title: Role - description: Must be 'assistant' to identify this as the model's response. - enum: - - assistant - content: - anyOf: - - type: string - - items: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - type: array - title: list[OpenAIChatCompletionContentPartTextParam] - - type: 'null' - title: string | list[OpenAIChatCompletionContentPartTextParam] - description: The content of the model's response. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the assistant message participant. - tool_calls: - anyOf: - - items: - $ref: '#/components/schemas/ChatCompletionMessageToolCall' - type: array - - type: 'null' - description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - additionalProperties: true - type: object - title: OpenAIAssistantMessageParam - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. OpenAIAttachFileRequest: properties: file_id: @@ -13441,283 +13232,49 @@ components: server_label: type: string title: Server Label - type: - type: string - title: Type - enum: - - mcp - name: - anyOf: - - type: string - - type: 'null' - type: object - required: - - server_label - title: OpenAIResponseInputToolChoiceMCPTool - description: Forces the model to call a specific tool on a remote MCP server - OpenAIResponseInputToolChoiceMode: - type: string - enum: - - auto - - required - - none - title: OpenAIResponseInputToolChoiceMode - description: Enumeration of simple tool choice modes for response generation. - OpenAIResponseInputToolChoiceWebSearch: - properties: - type: - anyOf: - - type: string - enum: - - web_search - - type: string - enum: - - web_search_preview - - type: string - enum: - - web_search_preview_2025_03_11 - - type: string - enum: - - web_search_2025_08_26 - title: string - default: web_search - type: object - title: OpenAIResponseInputToolChoiceWebSearch - description: Indicates that the model should use web search to generate a response - OpenAIResponseMessage-Input: - properties: - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentImage' - title: OpenAIResponseInputMessageContentImage - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' - title: OpenAIResponseInputMessageContentFile - discriminator: - propertyName: type - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile - type: array - title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Input' - title: OpenAIResponseOutputMessageContentOutputText-Input - - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseContentPartRefusal - discriminator: - propertyName: type - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Input' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal - type: array - title: list[OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal] - title: string | list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] | list[OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal] - role: - anyOf: - - type: string - enum: - - system - - type: string - enum: - - developer - - type: string - enum: - - user - - type: string - enum: - - assistant - title: string - type: - type: string - title: Type - enum: - - message - id: - anyOf: - - type: string - - type: 'null' - status: - anyOf: - - type: string - - type: 'null' - type: object - required: - - content - - role - title: OpenAIResponseMessage - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. - OpenAIResponseMessage-Output: - properties: - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentImage' - title: OpenAIResponseInputMessageContentImage - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' - title: OpenAIResponseInputMessageContentFile - discriminator: - propertyName: type - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile - type: array - title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Output' - title: OpenAIResponseOutputMessageContentOutputText-Output - - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseContentPartRefusal - discriminator: - propertyName: type - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Output' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal - type: array - title: list[OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal] - title: string | list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] | list[OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal] - role: - anyOf: - - type: string - enum: - - system - - type: string - enum: - - developer - - type: string - enum: - - user - - type: string - enum: - - assistant - title: string - type: - type: string - title: Type - enum: - - message - id: - anyOf: - - type: string - - type: 'null' - status: - anyOf: - - type: string - - type: 'null' - type: object - required: - - content - - role - title: OpenAIResponseMessage - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. - OpenAIResponseOutputMessageContentOutputText-Input: - properties: - text: - type: string - title: Text - type: - type: string - title: Type - enum: - - output_text - annotations: - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - title: OpenAIResponseAnnotationFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - title: OpenAIResponseAnnotationContainerFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' - title: OpenAIResponseAnnotationFilePath - discriminator: - propertyName: type - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - type: array - title: Annotations - logprobs: - anyOf: - - items: - $ref: '#/components/schemas/OpenAITokenLogProb' - type: array - - type: 'null' - type: object - required: - - text - title: OpenAIResponseOutputMessageContentOutputText - description: Text content within an output message of an OpenAI response. - OpenAIResponseOutputMessageContentOutputText-Output: - properties: - text: - type: string - title: Text - type: - type: string - title: Type - enum: - - output_text - annotations: - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - title: OpenAIResponseAnnotationFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - title: OpenAIResponseAnnotationContainerFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' - title: OpenAIResponseAnnotationFilePath - discriminator: - propertyName: type - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - type: array - title: Annotations - logprobs: + type: + type: string + title: Type + enum: + - mcp + name: anyOf: - - items: - $ref: '#/components/schemas/OpenAITokenLogProb' - type: array + - type: string - type: 'null' type: object required: - - text - title: OpenAIResponseOutputMessageContentOutputText - description: Text content within an output message of an OpenAI response. + - server_label + title: OpenAIResponseInputToolChoiceMCPTool + description: Forces the model to call a specific tool on a remote MCP server + OpenAIResponseInputToolChoiceMode: + type: string + enum: + - auto + - required + - none + title: OpenAIResponseInputToolChoiceMode + description: Enumeration of simple tool choice modes for response generation. + OpenAIResponseInputToolChoiceWebSearch: + properties: + type: + anyOf: + - type: string + enum: + - web_search + - type: string + enum: + - web_search_preview + - type: string + enum: + - web_search_preview_2025_03_11 + - type: string + enum: + - web_search_2025_08_26 + title: string + default: web_search + type: object + title: OpenAIResponseInputToolChoiceWebSearch + description: Indicates that the model should use web search to generate a response OpenAIResponseOutputMessageFileSearchToolCallResults: properties: attributes: @@ -13819,64 +13376,6 @@ components: - text title: OpenAIResponseOutputMessageReasoningSummary description: A summary of reasoning output from the model. - OpenAIResponseOutputMessageWebSearchToolCall-Input: - properties: - id: - type: string - title: Id - status: - type: string - title: Status - type: - type: string - title: Type - enum: - - web_search_call - action: - anyOf: - - $ref: '#/components/schemas/WebSearchActionSearch' - title: WebSearchActionSearch - - $ref: '#/components/schemas/WebSearchActionOpenPage' - title: WebSearchActionOpenPage - - $ref: '#/components/schemas/WebSearchActionFind' - title: WebSearchActionFind - - type: 'null' - title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - type: object - required: - - id - - status - title: OpenAIResponseOutputMessageWebSearchToolCall - description: Web search tool call output message for OpenAI responses. - OpenAIResponseOutputMessageWebSearchToolCall-Output: - properties: - id: - type: string - title: Id - status: - type: string - title: Status - type: - type: string - title: Type - enum: - - web_search_call - action: - anyOf: - - $ref: '#/components/schemas/WebSearchActionSearch' - title: WebSearchActionSearch - - $ref: '#/components/schemas/WebSearchActionOpenPage' - title: WebSearchActionOpenPage - - $ref: '#/components/schemas/WebSearchActionFind' - title: WebSearchActionFind - - type: 'null' - title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - type: object - required: - - id - - status - title: OpenAIResponseOutputMessageWebSearchToolCall - description: Web search tool call output message for OpenAI responses. OpenAIResponseReasoning: properties: effort: @@ -14051,86 +13550,6 @@ components: type: object title: OpenAIUpdateVectorStoreRequest description: Request body for updating a vector store. - OpenAIUserMessageParam-Input: - properties: - role: - type: string - title: Role - description: Must be 'user' to identify this as a user message. - enum: - - user - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - title: OpenAIChatCompletionContentPartImageParam - - $ref: '#/components/schemas/OpenAIFile' - title: OpenAIFile - discriminator: - propertyName: type - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile - type: array - title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the user message participant. - type: object - required: - - content - title: OpenAIUserMessageParam - description: A message from the user in an OpenAI-compatible chat completion request. - OpenAIUserMessageParam-Output: - properties: - role: - type: string - title: Role - description: Must be 'user' to identify this as a user message. - enum: - - user - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - title: OpenAIChatCompletionContentPartImageParam - - $ref: '#/components/schemas/OpenAIFile' - title: OpenAIFile - discriminator: - propertyName: type - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile - type: array - title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the user message participant. - type: object - required: - - content - title: OpenAIUserMessageParam - description: A message from the user in an OpenAI-compatible chat completion request. OutputTokensDetails: properties: reasoning_tokens: @@ -16126,69 +15545,6 @@ components: - completion_id title: ListChatCompletionMessagesRequest type: object - EmbeddedChunk: - description: |- - A chunk of content with its embedding vector for vector database operations. - Inherits all fields from Chunk and adds embedding-related fields. - properties: - content: - anyOf: - - type: string - - discriminator: - mapping: - image: '#/components/schemas/ImageContentItem' - text: '#/components/schemas/TextContentItem' - propertyName: type - oneOf: - - $ref: '#/components/schemas/ImageContentItem' - title: ImageContentItem - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - title: ImageContentItem | TextContentItem - - items: - discriminator: - mapping: - image: '#/components/schemas/ImageContentItem' - text: '#/components/schemas/TextContentItem' - propertyName: type - oneOf: - - $ref: '#/components/schemas/ImageContentItem' - title: ImageContentItem - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - title: ImageContentItem | TextContentItem - type: array - title: list[ImageContentItem | TextContentItem] - title: string | list[ImageContentItem | TextContentItem] - chunk_id: - title: Chunk Id - type: string - metadata: - additionalProperties: true - title: Metadata - type: object - chunk_metadata: - $ref: '#/components/schemas/ChunkMetadata' - embedding: - items: - type: number - title: Embedding - type: array - embedding_model: - title: Embedding Model - type: string - embedding_dimension: - title: Embedding Dimension - type: integer - required: - - content - - chunk_id - - chunk_metadata - - embedding - - embedding_model - - embedding_dimension - title: EmbeddedChunk - type: object VectorStoreCreateRequest: description: Request to create a vector store. properties: @@ -17560,10 +16916,10 @@ components: OpenAIResponseMessageOutputUnion: anyOf: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -17584,11 +16940,11 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' x-stainless-naming: OpenAIResponseMessageOutputOneOf - title: OpenAIResponseMessage-Output | ... (8 variants) + title: OpenAIResponseMessage | ... (8 variants) - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' title: OpenAIResponseInputFunctionToolCallOutput - $ref: '#/components/schemas/OpenAIResponseMCPApprovalResponse' @@ -17599,10 +16955,10 @@ components: x-stainless-naming: OpenAIResponseMessageOutputUnion OpenAIResponseOutputItem: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -17623,11 +16979,11 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' x-stainless-naming: OpenAIResponseOutputItem - title: OpenAIResponseMessage-Output | ... (8 variants) + title: OpenAIResponseMessage | ... (8 variants) ChatCompletionMessageToolCall: properties: id: diff --git a/docs/docs/providers/file_processors/remote_unstructured-api.mdx b/docs/docs/providers/file_processors/remote_unstructured-api.mdx new file mode 100644 index 00000000000..13d6a0593d0 --- /dev/null +++ b/docs/docs/providers/file_processors/remote_unstructured-api.mdx @@ -0,0 +1,143 @@ +--- +description: | + [Unstructured.io](https://unstructured.io) is a multi-format document parser that supports 65+ file types + including emails (EML/MSG), legacy documents, presentations, spreadsheets, and more. This provider uses + the Unstructured.io SaaS API for cloud-based document processing with advanced table and image detection. + + ## Supported Formats + + - **Documents**: PDF, DOC, DOCX, PPTX, XLSX, ODT, RTF, EPUB + - **Email**: EML, MSG (unique capability) + - **Web**: HTML, Markdown, XML, JSON + - **Images**: PNG, JPG, TIFF (with OCR) + - **Text**: TXT, CSV + - **65+ formats total** — see [Unstructured format support](https://docs.unstructured.io/pipelines/supported-file-types) + + ## Features + + - **Multi-format support** — 65+ file types including email formats (EML/MSG) + - **Cloud-based processing** — no local dependencies or system requirements + - **Table detection** — extracts tables with structure preservation + - **Image detection** — identifies and extracts image elements + - **SOC2/HIPAA/GDPR certified** — suitable for regulated industries + + ## Usage + + Get an API key from [Unstructured.io](https://unstructured.io) (free tier available), then start OGX: + + ```bash + UNSTRUCTURED_API_KEY=your-api-key ogx stack run \ + --providers "file_processors=remote::unstructured-api,files=inline::localfs,vector_io=inline::faiss,inference=inline::sentence-transformers,inference=remote::ollama" \ + --port 8321 + ``` + + Or add it to a custom `run.yaml`: + + ```yaml + file_processors: + - provider_id: unstructured + provider_type: remote::unstructured-api + config: + api_key: ${env.UNSTRUCTURED_API_KEY} + ``` + + ## When to Use + + - **Diverse formats**: Need to process emails, legacy documents, or 10+ different file types + - **Managed service**: Want zero setup and no system dependencies + - **Compliance**: Require SOC2/HIPAA/GDPR certified processing + - **Email RAG**: Building customer support or communication archive applications + + For faster processing with fewer formats, use `inline::docling` instead. + + ## Performance + + - Processing speed: ~1-2 seconds per page + - Best for: Documents <100 pages + - Cost: ~$0.01 per page (verify current pricing with Unstructured.io) + + ## Documentation + + See [Unstructured.io documentation](https://docs.unstructured.io) for API details and format support. +sidebar_label: Remote - Unstructured-Api +title: remote::unstructured-api +--- + +# remote::unstructured-api + +## Description + + +[Unstructured.io](https://unstructured.io) is a multi-format document parser that supports 65+ file types +including emails (EML/MSG), legacy documents, presentations, spreadsheets, and more. This provider uses +the Unstructured.io SaaS API for cloud-based document processing with advanced table and image detection. + +## Supported Formats + +- **Documents**: PDF, DOC, DOCX, PPTX, XLSX, ODT, RTF, EPUB +- **Email**: EML, MSG (unique capability) +- **Web**: HTML, Markdown, XML, JSON +- **Images**: PNG, JPG, TIFF (with OCR) +- **Text**: TXT, CSV +- **65+ formats total** — see [Unstructured format support](https://docs.unstructured.io/pipelines/supported-file-types) + +## Features + +- **Multi-format support** — 65+ file types including email formats (EML/MSG) +- **Cloud-based processing** — no local dependencies or system requirements +- **Table detection** — extracts tables with structure preservation +- **Image detection** — identifies and extracts image elements +- **SOC2/HIPAA/GDPR certified** — suitable for regulated industries + +## Usage + +Get an API key from [Unstructured.io](https://unstructured.io) (free tier available), then start OGX: + +```bash +UNSTRUCTURED_API_KEY=your-api-key ogx stack run \ + --providers "file_processors=remote::unstructured-api,files=inline::localfs,vector_io=inline::faiss,inference=inline::sentence-transformers,inference=remote::ollama" \ + --port 8321 +``` + +Or add it to a custom `run.yaml`: + +```yaml +file_processors: + - provider_id: unstructured + provider_type: remote::unstructured-api + config: + api_key: ${env.UNSTRUCTURED_API_KEY} +``` + +## When to Use + +- **Diverse formats**: Need to process emails, legacy documents, or 10+ different file types +- **Managed service**: Want zero setup and no system dependencies +- **Compliance**: Require SOC2/HIPAA/GDPR certified processing +- **Email RAG**: Building customer support or communication archive applications + +For faster processing with fewer formats, use `inline::docling` instead. + +## Performance + +- Processing speed: ~1-2 seconds per page +- Best for: Documents <100 pages +- Cost: ~$0.01 per page (verify current pricing with Unstructured.io) + +## Documentation + +See [Unstructured.io documentation](https://docs.unstructured.io) for API details and format support. + + +## Configuration + +| Field | Type | Required | Default | Description | +|-------|------|----------|---------|-------------| +| `api_key` | `SecretStr` | No | | API key for authenticating with Unstructured.io SaaS API (get one from https://unstructured.io) | +| `default_chunk_size_tokens` | `int` | No | 800 | Default chunk size in tokens when chunking_strategy type is 'auto' | + +## Sample Configuration + +```yaml +api_key: ${env.UNSTRUCTURED_API_KEY} +``` diff --git a/docs/static/deprecated-ogx-spec.yaml b/docs/static/deprecated-ogx-spec.yaml index 82c9212d6a4..c3fbb9892ca 100644 --- a/docs/static/deprecated-ogx-spec.yaml +++ b/docs/static/deprecated-ogx-spec.yaml @@ -262,13 +262,11 @@ components: title: ListOpenAIChatCompletionResponse description: Response from listing OpenAI-compatible chat completions. OpenAIAssistantMessageParam: - additionalProperties: true - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. properties: role: - description: Must be 'assistant' to identify this as the model's response. - title: Role type: string + title: Role + description: Must be 'assistant' to identify this as the model's response. enum: - assistant content: @@ -279,15 +277,13 @@ components: type: array title: list[OpenAIChatCompletionContentPartTextParam] - type: 'null' - description: The content of the model's response. title: string | list[OpenAIChatCompletionContentPartTextParam] - nullable: true + description: The content of the model's response. name: anyOf: - type: string - type: 'null' description: The name of the assistant message participant. - nullable: true tool_calls: anyOf: - items: @@ -295,9 +291,10 @@ components: type: array - type: 'null' description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - nullable: true - title: OpenAIAssistantMessageParam + additionalProperties: true type: object + title: OpenAIAssistantMessageParam + description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. OpenAIChatCompletionContentPartImageParam: properties: type: @@ -668,24 +665,17 @@ components: title: OpenAITopLogProb description: The top log probability for a token from an OpenAI-compatible chat completion response. OpenAIUserMessageParam: - description: A message from the user in an OpenAI-compatible chat completion request. properties: role: - description: Must be 'user' to identify this as a user message. - title: Role type: string + title: Role + description: Must be 'user' to identify this as a user message. enum: - user content: anyOf: - type: string - items: - discriminator: - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' title: OpenAIChatCompletionContentPartTextParam @@ -693,21 +683,27 @@ components: title: OpenAIChatCompletionContentPartImageParam - $ref: '#/components/schemas/OpenAIFile' title: OpenAIFile + discriminator: + propertyName: type + mapping: + file: '#/components/schemas/OpenAIFile' + image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' + text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile type: array title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] + description: The content of the message, which can include text and other media. name: anyOf: - type: string - type: 'null' description: The name of the user message participant. - nullable: true + type: object required: - content title: OpenAIUserMessageParam - type: object + description: A message from the user in an OpenAI-compatible chat completion request. OpenAIJSONSchema: properties: name: @@ -791,12 +787,12 @@ components: messages: items: oneOf: - - $ref: '#/components/schemas/OpenAIUserMessageParam-Input' - title: OpenAIUserMessageParam-Input + - $ref: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam - $ref: '#/components/schemas/OpenAISystemMessageParam' title: OpenAISystemMessageParam - - $ref: '#/components/schemas/OpenAIAssistantMessageParam-Input' - title: OpenAIAssistantMessageParam-Input + - $ref: '#/components/schemas/OpenAIAssistantMessageParam' + title: OpenAIAssistantMessageParam - $ref: '#/components/schemas/OpenAIToolMessageParam' title: OpenAIToolMessageParam - $ref: '#/components/schemas/OpenAIDeveloperMessageParam' @@ -804,12 +800,12 @@ components: discriminator: propertyName: role mapping: - assistant: '#/components/schemas/OpenAIAssistantMessageParam-Input' + assistant: '#/components/schemas/OpenAIAssistantMessageParam' developer: '#/components/schemas/OpenAIDeveloperMessageParam' system: '#/components/schemas/OpenAISystemMessageParam' tool: '#/components/schemas/OpenAIToolMessageParam' - user: '#/components/schemas/OpenAIUserMessageParam-Input' - title: OpenAIUserMessageParam-Input | ... (5 variants) + user: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam | ... (5 variants) type: array minItems: 1 title: Messages @@ -1228,12 +1224,12 @@ components: input_messages: items: oneOf: - - $ref: '#/components/schemas/OpenAIUserMessageParam-Output' - title: OpenAIUserMessageParam-Output + - $ref: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam - $ref: '#/components/schemas/OpenAISystemMessageParam' title: OpenAISystemMessageParam - - $ref: '#/components/schemas/OpenAIAssistantMessageParam-Output' - title: OpenAIAssistantMessageParam-Output + - $ref: '#/components/schemas/OpenAIAssistantMessageParam' + title: OpenAIAssistantMessageParam - $ref: '#/components/schemas/OpenAIToolMessageParam' title: OpenAIToolMessageParam - $ref: '#/components/schemas/OpenAIDeveloperMessageParam' @@ -1241,12 +1237,12 @@ components: discriminator: propertyName: role mapping: - assistant: '#/components/schemas/OpenAIAssistantMessageParam-Output' + assistant: '#/components/schemas/OpenAIAssistantMessageParam' developer: '#/components/schemas/OpenAIDeveloperMessageParam' system: '#/components/schemas/OpenAISystemMessageParam' tool: '#/components/schemas/OpenAIToolMessageParam' - user: '#/components/schemas/OpenAIUserMessageParam-Output' - title: OpenAIUserMessageParam-Output | ... (5 variants) + user: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam | ... (5 variants) type: array title: Input Messages description: The input messages used to generate this completion. @@ -1836,22 +1832,11 @@ components: title: OpenAIResponseMCPApprovalResponse description: A response to an MCP approval request. OpenAIResponseMessage: - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. properties: content: anyOf: - type: string - items: - discriminator: - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' title: OpenAIResponseInputMessageContentText @@ -1859,20 +1844,26 @@ components: title: OpenAIResponseInputMessageContentImage - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' title: OpenAIResponseInputMessageContentFile + discriminator: + propertyName: type + mapping: + input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' + input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' + input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile type: array title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - items: - discriminator: - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' title: OpenAIResponseOutputMessageContentOutputText - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' title: OpenAIResponseContentPartRefusal + discriminator: + propertyName: type + mapping: + output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' + refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' title: OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal type: array title: list[OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal] @@ -1893,25 +1884,28 @@ components: - assistant title: string type: - title: Type type: string + title: Type enum: - message id: anyOf: - type: string - type: 'null' - nullable: true status: anyOf: - type: string - type: 'null' - nullable: true + type: object required: - content - role title: OpenAIResponseMessage - type: object + description: |- + Corresponds to the various Message types in the Responses API. + They are all under one type because the Responses API gives them all + the same "type" value, and there is no way to tell them apart in certain + scenarios. OpenAIResponseOutputMessageContent: discriminator: mapping: @@ -1925,25 +1919,17 @@ components: title: OpenAIResponseContentPartRefusal title: OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal OpenAIResponseOutputMessageContentOutputText: - description: Text content within an output message of an OpenAI response. properties: text: - title: Text type: string + title: Text type: - title: Type type: string + title: Type enum: - output_text annotations: items: - discriminator: - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' title: OpenAIResponseAnnotationFileCitation @@ -1953,20 +1939,27 @@ components: title: OpenAIResponseAnnotationContainerFileCitation - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' title: OpenAIResponseAnnotationFilePath + discriminator: + propertyName: type + mapping: + container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' + file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' + file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' + url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - title: Annotations type: array + title: Annotations logprobs: anyOf: - items: $ref: '#/components/schemas/OpenAITokenLogProb' type: array - type: 'null' - nullable: true + type: object required: - text title: OpenAIResponseOutputMessageContentOutputText - type: object + description: Text content within an output message of an OpenAI response. OpenAIResponseOutputMessageFileSearchToolCall: properties: id: @@ -2090,17 +2083,16 @@ components: title: OpenAIResponseOutputMessageMCPListTools description: MCP list tools output message containing available tools from an MCP server. OpenAIResponseOutputMessageWebSearchToolCall: - description: Web search tool call output message for OpenAI responses. properties: id: - title: Id type: string + title: Id status: - title: Status type: string + title: Status type: - title: Type type: string + title: Type enum: - web_search_call action: @@ -2113,22 +2105,22 @@ components: title: WebSearchActionFind - type: 'null' title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - nullable: true + type: object required: - id - status title: OpenAIResponseOutputMessageWebSearchToolCall - type: object + description: Web search tool call output message for OpenAI responses. CreateConversationRequest: properties: items: anyOf: - items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -2158,10 +2150,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array - type: 'null' description: Initial items to include in the conversation context. @@ -2251,10 +2243,10 @@ components: data: items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -2284,10 +2276,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseMessage-Output | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array title: Data description: List of conversation items @@ -2318,10 +2310,10 @@ components: items: items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -2351,10 +2343,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array maxItems: 20 title: Items @@ -5100,19 +5092,19 @@ components: title: UnionType type: object ImageContentItem: - description: A image content item properties: type: - title: Type type: string + title: Type enum: - image image: $ref: '#/components/schemas/_URLOrData' + type: object required: - image title: ImageContentItem - type: object + description: A image content item InterleavedContent: anyOf: - type: string @@ -5348,31 +5340,31 @@ components: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Output | TextContentItem] - title: string | list[ImageContentItem-Output | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] chunk_id: type: string title: Chunk Id @@ -5442,7 +5434,7 @@ components: description: The ID of the vector store to insert chunks into. chunks: items: - $ref: '#/components/schemas/EmbeddedChunk-Input' + $ref: '#/components/schemas/EmbeddedChunk' type: array title: Chunks description: The list of embedded chunks to insert. @@ -5467,31 +5459,31 @@ components: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Input' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Input' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Input | TextContentItem] - title: string | list[ImageContentItem-Input | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] description: The query content to search for. params: anyOf: @@ -5509,7 +5501,7 @@ components: properties: chunks: items: - $ref: '#/components/schemas/EmbeddedChunk-Output' + $ref: '#/components/schemas/EmbeddedChunk' type: array title: Chunks scores: @@ -6585,100 +6577,37 @@ components: - reasoning.encrypted_content title: ConversationItemInclude description: Specify additional output data to include in the model response. - EmbeddedChunk-Input: - properties: - content: - anyOf: - - type: string - - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - discriminator: - propertyName: type - mapping: - image: '#/components/schemas/ImageContentItem-Input' - text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem - - items: - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - discriminator: - propertyName: type - mapping: - image: '#/components/schemas/ImageContentItem-Input' - text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem - type: array - title: list[ImageContentItem-Input | TextContentItem] - title: string | list[ImageContentItem-Input | TextContentItem] - chunk_id: - type: string - title: Chunk Id - metadata: - additionalProperties: true - type: object - title: Metadata - chunk_metadata: - $ref: '#/components/schemas/ChunkMetadata' - embedding: - items: - type: number - type: array - title: Embedding - embedding_model: - type: string - title: Embedding Model - embedding_dimension: - type: integer - title: Embedding Dimension - type: object - required: - - content - - chunk_id - - chunk_metadata - - embedding - - embedding_model - - embedding_dimension - title: EmbeddedChunk - description: |- - A chunk of content with its embedding vector for vector database operations. - Inherits all fields from Chunk and adds embedding-related fields. - EmbeddedChunk-Output: + EmbeddedChunk: properties: content: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Output | TextContentItem] - title: string | list[ImageContentItem-Output | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] chunk_id: type: string title: Chunk Id @@ -6734,34 +6663,6 @@ components: - Not Implemented title: HealthStatus description: Health check status values for provider readiness. - ImageContentItem-Input: - properties: - type: - type: string - title: Type - enum: - - image - image: - $ref: '#/components/schemas/_URLOrData' - type: object - required: - - image - title: ImageContentItem - description: A image content item - ImageContentItem-Output: - properties: - type: - type: string - title: Type - enum: - - image - image: - $ref: '#/components/schemas/_URLOrData' - type: object - required: - - image - title: ImageContentItem - description: A image content item InputTokensDetails: properties: cached_tokens: @@ -6882,81 +6783,13 @@ components: - name title: MCPListToolsTool description: Tool definition returned by MCP list tools operation. - OpenAIAssistantMessageParam-Input: + OpenAIAttachFileRequest: properties: - role: + file_id: type: string - title: Role - description: Must be 'assistant' to identify this as the model's response. - enum: - - assistant - content: - anyOf: - - type: string - - items: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - type: array - title: list[OpenAIChatCompletionContentPartTextParam] - - type: 'null' - title: string | list[OpenAIChatCompletionContentPartTextParam] - description: The content of the model's response. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the assistant message participant. - tool_calls: - anyOf: - - items: - $ref: '#/components/schemas/ChatCompletionMessageToolCall' - type: array - - type: 'null' - description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - additionalProperties: true - type: object - title: OpenAIAssistantMessageParam - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. - OpenAIAssistantMessageParam-Output: - properties: - role: - type: string - title: Role - description: Must be 'assistant' to identify this as the model's response. - enum: - - assistant - content: - anyOf: - - type: string - - items: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - type: array - title: list[OpenAIChatCompletionContentPartTextParam] - - type: 'null' - title: string | list[OpenAIChatCompletionContentPartTextParam] - description: The content of the model's response. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the assistant message participant. - tool_calls: - anyOf: - - items: - $ref: '#/components/schemas/ChatCompletionMessageToolCall' - type: array - - type: 'null' - description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - additionalProperties: true - type: object - title: OpenAIAssistantMessageParam - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. - OpenAIAttachFileRequest: - properties: - file_id: - type: string - title: File Id - description: The ID of the file to attach. - attributes: + title: File Id + description: The ID of the file to attach. + attributes: anyOf: - additionalProperties: anyOf: @@ -7281,240 +7114,6 @@ components: type: object title: OpenAIResponseInputToolChoiceWebSearch description: Indicates that the model should use web search to generate a response - OpenAIResponseMessage-Input: - properties: - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentImage' - title: OpenAIResponseInputMessageContentImage - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' - title: OpenAIResponseInputMessageContentFile - discriminator: - propertyName: type - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile - type: array - title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Input' - title: OpenAIResponseOutputMessageContentOutputText-Input - - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseContentPartRefusal - discriminator: - propertyName: type - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Input' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal - type: array - title: list[OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal] - title: string | list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] | list[OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal] - role: - anyOf: - - type: string - enum: - - system - - type: string - enum: - - developer - - type: string - enum: - - user - - type: string - enum: - - assistant - title: string - type: - type: string - title: Type - enum: - - message - id: - anyOf: - - type: string - - type: 'null' - status: - anyOf: - - type: string - - type: 'null' - type: object - required: - - content - - role - title: OpenAIResponseMessage - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. - OpenAIResponseMessage-Output: - properties: - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentImage' - title: OpenAIResponseInputMessageContentImage - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' - title: OpenAIResponseInputMessageContentFile - discriminator: - propertyName: type - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile - type: array - title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Output' - title: OpenAIResponseOutputMessageContentOutputText-Output - - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseContentPartRefusal - discriminator: - propertyName: type - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Output' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal - type: array - title: list[OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal] - title: string | list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] | list[OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal] - role: - anyOf: - - type: string - enum: - - system - - type: string - enum: - - developer - - type: string - enum: - - user - - type: string - enum: - - assistant - title: string - type: - type: string - title: Type - enum: - - message - id: - anyOf: - - type: string - - type: 'null' - status: - anyOf: - - type: string - - type: 'null' - type: object - required: - - content - - role - title: OpenAIResponseMessage - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. - OpenAIResponseOutputMessageContentOutputText-Input: - properties: - text: - type: string - title: Text - type: - type: string - title: Type - enum: - - output_text - annotations: - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - title: OpenAIResponseAnnotationFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - title: OpenAIResponseAnnotationContainerFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' - title: OpenAIResponseAnnotationFilePath - discriminator: - propertyName: type - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - type: array - title: Annotations - logprobs: - anyOf: - - items: - $ref: '#/components/schemas/OpenAITokenLogProb' - type: array - - type: 'null' - type: object - required: - - text - title: OpenAIResponseOutputMessageContentOutputText - description: Text content within an output message of an OpenAI response. - OpenAIResponseOutputMessageContentOutputText-Output: - properties: - text: - type: string - title: Text - type: - type: string - title: Type - enum: - - output_text - annotations: - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - title: OpenAIResponseAnnotationFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - title: OpenAIResponseAnnotationContainerFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' - title: OpenAIResponseAnnotationFilePath - discriminator: - propertyName: type - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - type: array - title: Annotations - logprobs: - anyOf: - - items: - $ref: '#/components/schemas/OpenAITokenLogProb' - type: array - - type: 'null' - type: object - required: - - text - title: OpenAIResponseOutputMessageContentOutputText - description: Text content within an output message of an OpenAI response. OpenAIResponseOutputMessageFileSearchToolCallResults: properties: attributes: @@ -7616,64 +7215,6 @@ components: - text title: OpenAIResponseOutputMessageReasoningSummary description: A summary of reasoning output from the model. - OpenAIResponseOutputMessageWebSearchToolCall-Input: - properties: - id: - type: string - title: Id - status: - type: string - title: Status - type: - type: string - title: Type - enum: - - web_search_call - action: - anyOf: - - $ref: '#/components/schemas/WebSearchActionSearch' - title: WebSearchActionSearch - - $ref: '#/components/schemas/WebSearchActionOpenPage' - title: WebSearchActionOpenPage - - $ref: '#/components/schemas/WebSearchActionFind' - title: WebSearchActionFind - - type: 'null' - title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - type: object - required: - - id - - status - title: OpenAIResponseOutputMessageWebSearchToolCall - description: Web search tool call output message for OpenAI responses. - OpenAIResponseOutputMessageWebSearchToolCall-Output: - properties: - id: - type: string - title: Id - status: - type: string - title: Status - type: - type: string - title: Type - enum: - - web_search_call - action: - anyOf: - - $ref: '#/components/schemas/WebSearchActionSearch' - title: WebSearchActionSearch - - $ref: '#/components/schemas/WebSearchActionOpenPage' - title: WebSearchActionOpenPage - - $ref: '#/components/schemas/WebSearchActionFind' - title: WebSearchActionFind - - type: 'null' - title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - type: object - required: - - id - - status - title: OpenAIResponseOutputMessageWebSearchToolCall - description: Web search tool call output message for OpenAI responses. OpenAIResponseReasoning: properties: effort: @@ -7848,86 +7389,6 @@ components: type: object title: OpenAIUpdateVectorStoreRequest description: Request body for updating a vector store. - OpenAIUserMessageParam-Input: - properties: - role: - type: string - title: Role - description: Must be 'user' to identify this as a user message. - enum: - - user - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - title: OpenAIChatCompletionContentPartImageParam - - $ref: '#/components/schemas/OpenAIFile' - title: OpenAIFile - discriminator: - propertyName: type - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile - type: array - title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the user message participant. - type: object - required: - - content - title: OpenAIUserMessageParam - description: A message from the user in an OpenAI-compatible chat completion request. - OpenAIUserMessageParam-Output: - properties: - role: - type: string - title: Role - description: Must be 'user' to identify this as a user message. - enum: - - user - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - title: OpenAIChatCompletionContentPartImageParam - - $ref: '#/components/schemas/OpenAIFile' - title: OpenAIFile - discriminator: - propertyName: type - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile - type: array - title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the user message participant. - type: object - required: - - content - title: OpenAIUserMessageParam - description: A message from the user in an OpenAI-compatible chat completion request. OutputTokensDetails: properties: reasoning_tokens: @@ -9824,69 +9285,6 @@ components: - completion_id title: ListChatCompletionMessagesRequest type: object - EmbeddedChunk: - description: |- - A chunk of content with its embedding vector for vector database operations. - Inherits all fields from Chunk and adds embedding-related fields. - properties: - content: - anyOf: - - type: string - - discriminator: - mapping: - image: '#/components/schemas/ImageContentItem' - text: '#/components/schemas/TextContentItem' - propertyName: type - oneOf: - - $ref: '#/components/schemas/ImageContentItem' - title: ImageContentItem - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - title: ImageContentItem | TextContentItem - - items: - discriminator: - mapping: - image: '#/components/schemas/ImageContentItem' - text: '#/components/schemas/TextContentItem' - propertyName: type - oneOf: - - $ref: '#/components/schemas/ImageContentItem' - title: ImageContentItem - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - title: ImageContentItem | TextContentItem - type: array - title: list[ImageContentItem | TextContentItem] - title: string | list[ImageContentItem | TextContentItem] - chunk_id: - title: Chunk Id - type: string - metadata: - additionalProperties: true - title: Metadata - type: object - chunk_metadata: - $ref: '#/components/schemas/ChunkMetadata' - embedding: - items: - type: number - title: Embedding - type: array - embedding_model: - title: Embedding Model - type: string - embedding_dimension: - title: Embedding Dimension - type: integer - required: - - content - - chunk_id - - chunk_metadata - - embedding - - embedding_model - - embedding_dimension - title: EmbeddedChunk - type: object VectorStoreCreateRequest: description: Request to create a vector store. properties: @@ -11258,10 +10656,10 @@ components: OpenAIResponseMessageOutputUnion: anyOf: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -11282,11 +10680,11 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' x-stainless-naming: OpenAIResponseMessageOutputOneOf - title: OpenAIResponseMessage-Output | ... (8 variants) + title: OpenAIResponseMessage | ... (8 variants) - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' title: OpenAIResponseInputFunctionToolCallOutput - $ref: '#/components/schemas/OpenAIResponseMCPApprovalResponse' @@ -11297,10 +10695,10 @@ components: x-stainless-naming: OpenAIResponseMessageOutputUnion OpenAIResponseOutputItem: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -11321,11 +10719,11 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' x-stainless-naming: OpenAIResponseOutputItem - title: OpenAIResponseMessage-Output | ... (8 variants) + title: OpenAIResponseMessage | ... (8 variants) ChatCompletionMessageToolCall: properties: id: diff --git a/docs/static/experimental-ogx-spec.yaml b/docs/static/experimental-ogx-spec.yaml index be958577080..5f1e0388478 100644 --- a/docs/static/experimental-ogx-spec.yaml +++ b/docs/static/experimental-ogx-spec.yaml @@ -1142,13 +1142,11 @@ components: title: ListOpenAIChatCompletionResponse description: Response from listing OpenAI-compatible chat completions. OpenAIAssistantMessageParam: - additionalProperties: true - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. properties: role: - description: Must be 'assistant' to identify this as the model's response. - title: Role type: string + title: Role + description: Must be 'assistant' to identify this as the model's response. enum: - assistant content: @@ -1159,15 +1157,13 @@ components: type: array title: list[OpenAIChatCompletionContentPartTextParam] - type: 'null' - description: The content of the model's response. title: string | list[OpenAIChatCompletionContentPartTextParam] - nullable: true + description: The content of the model's response. name: anyOf: - type: string - type: 'null' description: The name of the assistant message participant. - nullable: true tool_calls: anyOf: - items: @@ -1175,9 +1171,10 @@ components: type: array - type: 'null' description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - nullable: true - title: OpenAIAssistantMessageParam + additionalProperties: true type: object + title: OpenAIAssistantMessageParam + description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. OpenAIChatCompletionContentPartImageParam: properties: type: @@ -1548,24 +1545,17 @@ components: title: OpenAITopLogProb description: The top log probability for a token from an OpenAI-compatible chat completion response. OpenAIUserMessageParam: - description: A message from the user in an OpenAI-compatible chat completion request. properties: role: - description: Must be 'user' to identify this as a user message. - title: Role type: string + title: Role + description: Must be 'user' to identify this as a user message. enum: - user content: anyOf: - type: string - items: - discriminator: - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' title: OpenAIChatCompletionContentPartTextParam @@ -1573,21 +1563,27 @@ components: title: OpenAIChatCompletionContentPartImageParam - $ref: '#/components/schemas/OpenAIFile' title: OpenAIFile + discriminator: + propertyName: type + mapping: + file: '#/components/schemas/OpenAIFile' + image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' + text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile type: array title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] + description: The content of the message, which can include text and other media. name: anyOf: - type: string - type: 'null' description: The name of the user message participant. - nullable: true + type: object required: - content title: OpenAIUserMessageParam - type: object + description: A message from the user in an OpenAI-compatible chat completion request. OpenAIJSONSchema: properties: name: @@ -1671,12 +1667,12 @@ components: messages: items: oneOf: - - $ref: '#/components/schemas/OpenAIUserMessageParam-Input' - title: OpenAIUserMessageParam-Input + - $ref: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam - $ref: '#/components/schemas/OpenAISystemMessageParam' title: OpenAISystemMessageParam - - $ref: '#/components/schemas/OpenAIAssistantMessageParam-Input' - title: OpenAIAssistantMessageParam-Input + - $ref: '#/components/schemas/OpenAIAssistantMessageParam' + title: OpenAIAssistantMessageParam - $ref: '#/components/schemas/OpenAIToolMessageParam' title: OpenAIToolMessageParam - $ref: '#/components/schemas/OpenAIDeveloperMessageParam' @@ -1684,12 +1680,12 @@ components: discriminator: propertyName: role mapping: - assistant: '#/components/schemas/OpenAIAssistantMessageParam-Input' + assistant: '#/components/schemas/OpenAIAssistantMessageParam' developer: '#/components/schemas/OpenAIDeveloperMessageParam' system: '#/components/schemas/OpenAISystemMessageParam' tool: '#/components/schemas/OpenAIToolMessageParam' - user: '#/components/schemas/OpenAIUserMessageParam-Input' - title: OpenAIUserMessageParam-Input | ... (5 variants) + user: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam | ... (5 variants) type: array minItems: 1 title: Messages @@ -2108,12 +2104,12 @@ components: input_messages: items: oneOf: - - $ref: '#/components/schemas/OpenAIUserMessageParam-Output' - title: OpenAIUserMessageParam-Output + - $ref: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam - $ref: '#/components/schemas/OpenAISystemMessageParam' title: OpenAISystemMessageParam - - $ref: '#/components/schemas/OpenAIAssistantMessageParam-Output' - title: OpenAIAssistantMessageParam-Output + - $ref: '#/components/schemas/OpenAIAssistantMessageParam' + title: OpenAIAssistantMessageParam - $ref: '#/components/schemas/OpenAIToolMessageParam' title: OpenAIToolMessageParam - $ref: '#/components/schemas/OpenAIDeveloperMessageParam' @@ -2121,12 +2117,12 @@ components: discriminator: propertyName: role mapping: - assistant: '#/components/schemas/OpenAIAssistantMessageParam-Output' + assistant: '#/components/schemas/OpenAIAssistantMessageParam' developer: '#/components/schemas/OpenAIDeveloperMessageParam' system: '#/components/schemas/OpenAISystemMessageParam' tool: '#/components/schemas/OpenAIToolMessageParam' - user: '#/components/schemas/OpenAIUserMessageParam-Output' - title: OpenAIUserMessageParam-Output | ... (5 variants) + user: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam | ... (5 variants) type: array title: Input Messages description: The input messages used to generate this completion. @@ -2716,22 +2712,11 @@ components: title: OpenAIResponseMCPApprovalResponse description: A response to an MCP approval request. OpenAIResponseMessage: - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. properties: content: anyOf: - type: string - items: - discriminator: - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' title: OpenAIResponseInputMessageContentText @@ -2739,20 +2724,26 @@ components: title: OpenAIResponseInputMessageContentImage - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' title: OpenAIResponseInputMessageContentFile + discriminator: + propertyName: type + mapping: + input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' + input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' + input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile type: array title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - items: - discriminator: - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' title: OpenAIResponseOutputMessageContentOutputText - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' title: OpenAIResponseContentPartRefusal + discriminator: + propertyName: type + mapping: + output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' + refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' title: OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal type: array title: list[OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal] @@ -2773,25 +2764,28 @@ components: - assistant title: string type: - title: Type type: string + title: Type enum: - message id: anyOf: - type: string - type: 'null' - nullable: true status: anyOf: - type: string - type: 'null' - nullable: true + type: object required: - content - role title: OpenAIResponseMessage - type: object + description: |- + Corresponds to the various Message types in the Responses API. + They are all under one type because the Responses API gives them all + the same "type" value, and there is no way to tell them apart in certain + scenarios. OpenAIResponseOutputMessageContent: discriminator: mapping: @@ -2805,25 +2799,17 @@ components: title: OpenAIResponseContentPartRefusal title: OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal OpenAIResponseOutputMessageContentOutputText: - description: Text content within an output message of an OpenAI response. properties: text: - title: Text type: string + title: Text type: - title: Type type: string + title: Type enum: - output_text annotations: items: - discriminator: - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' title: OpenAIResponseAnnotationFileCitation @@ -2833,20 +2819,27 @@ components: title: OpenAIResponseAnnotationContainerFileCitation - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' title: OpenAIResponseAnnotationFilePath + discriminator: + propertyName: type + mapping: + container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' + file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' + file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' + url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - title: Annotations type: array + title: Annotations logprobs: anyOf: - items: $ref: '#/components/schemas/OpenAITokenLogProb' type: array - type: 'null' - nullable: true + type: object required: - text title: OpenAIResponseOutputMessageContentOutputText - type: object + description: Text content within an output message of an OpenAI response. OpenAIResponseOutputMessageFileSearchToolCall: properties: id: @@ -2970,17 +2963,16 @@ components: title: OpenAIResponseOutputMessageMCPListTools description: MCP list tools output message containing available tools from an MCP server. OpenAIResponseOutputMessageWebSearchToolCall: - description: Web search tool call output message for OpenAI responses. properties: id: - title: Id type: string + title: Id status: - title: Status type: string + title: Status type: - title: Type type: string + title: Type enum: - web_search_call action: @@ -2993,22 +2985,22 @@ components: title: WebSearchActionFind - type: 'null' title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - nullable: true + type: object required: - id - status title: OpenAIResponseOutputMessageWebSearchToolCall - type: object + description: Web search tool call output message for OpenAI responses. CreateConversationRequest: properties: items: anyOf: - items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -3038,10 +3030,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array - type: 'null' description: Initial items to include in the conversation context. @@ -3131,10 +3123,10 @@ components: data: items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -3164,10 +3156,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseMessage-Output | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array title: Data description: List of conversation items @@ -3198,10 +3190,10 @@ components: items: items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -3231,10 +3223,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array maxItems: 20 title: Items @@ -5980,19 +5972,19 @@ components: title: UnionType type: object ImageContentItem: - description: A image content item properties: type: - title: Type type: string + title: Type enum: - image image: $ref: '#/components/schemas/_URLOrData' + type: object required: - image title: ImageContentItem - type: object + description: A image content item InterleavedContent: anyOf: - type: string @@ -6228,31 +6220,31 @@ components: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Output | TextContentItem] - title: string | list[ImageContentItem-Output | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] chunk_id: type: string title: Chunk Id @@ -6322,7 +6314,7 @@ components: description: The ID of the vector store to insert chunks into. chunks: items: - $ref: '#/components/schemas/EmbeddedChunk-Input' + $ref: '#/components/schemas/EmbeddedChunk' type: array title: Chunks description: The list of embedded chunks to insert. @@ -6347,31 +6339,31 @@ components: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Input' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Input' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Input | TextContentItem] - title: string | list[ImageContentItem-Input | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] description: The query content to search for. params: anyOf: @@ -6389,7 +6381,7 @@ components: properties: chunks: items: - $ref: '#/components/schemas/EmbeddedChunk-Output' + $ref: '#/components/schemas/EmbeddedChunk' type: array title: Chunks scores: @@ -7518,100 +7510,37 @@ components: - reasoning.encrypted_content title: ConversationItemInclude description: Specify additional output data to include in the model response. - EmbeddedChunk-Input: - properties: - content: - anyOf: - - type: string - - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - discriminator: - propertyName: type - mapping: - image: '#/components/schemas/ImageContentItem-Input' - text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem - - items: - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - discriminator: - propertyName: type - mapping: - image: '#/components/schemas/ImageContentItem-Input' - text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem - type: array - title: list[ImageContentItem-Input | TextContentItem] - title: string | list[ImageContentItem-Input | TextContentItem] - chunk_id: - type: string - title: Chunk Id - metadata: - additionalProperties: true - type: object - title: Metadata - chunk_metadata: - $ref: '#/components/schemas/ChunkMetadata' - embedding: - items: - type: number - type: array - title: Embedding - embedding_model: - type: string - title: Embedding Model - embedding_dimension: - type: integer - title: Embedding Dimension - type: object - required: - - content - - chunk_id - - chunk_metadata - - embedding - - embedding_model - - embedding_dimension - title: EmbeddedChunk - description: |- - A chunk of content with its embedding vector for vector database operations. - Inherits all fields from Chunk and adds embedding-related fields. - EmbeddedChunk-Output: + EmbeddedChunk: properties: content: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Output | TextContentItem] - title: string | list[ImageContentItem-Output | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] chunk_id: type: string title: Chunk Id @@ -8049,34 +7978,6 @@ components: - Not Implemented title: HealthStatus description: Health check status values for provider readiness. - ImageContentItem-Input: - properties: - type: - type: string - title: Type - enum: - - image - image: - $ref: '#/components/schemas/_URLOrData' - type: object - required: - - image - title: ImageContentItem - description: A image content item - ImageContentItem-Output: - properties: - type: - type: string - title: Type - enum: - - image - image: - $ref: '#/components/schemas/_URLOrData' - type: object - required: - - image - title: ImageContentItem - description: A image content item InputTokensDetails: properties: cached_tokens: @@ -8197,81 +8098,13 @@ components: - name title: MCPListToolsTool description: Tool definition returned by MCP list tools operation. - OpenAIAssistantMessageParam-Input: + OpenAIAttachFileRequest: properties: - role: + file_id: type: string - title: Role - description: Must be 'assistant' to identify this as the model's response. - enum: - - assistant - content: - anyOf: - - type: string - - items: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - type: array - title: list[OpenAIChatCompletionContentPartTextParam] - - type: 'null' - title: string | list[OpenAIChatCompletionContentPartTextParam] - description: The content of the model's response. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the assistant message participant. - tool_calls: - anyOf: - - items: - $ref: '#/components/schemas/ChatCompletionMessageToolCall' - type: array - - type: 'null' - description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - additionalProperties: true - type: object - title: OpenAIAssistantMessageParam - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. - OpenAIAssistantMessageParam-Output: - properties: - role: - type: string - title: Role - description: Must be 'assistant' to identify this as the model's response. - enum: - - assistant - content: - anyOf: - - type: string - - items: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - type: array - title: list[OpenAIChatCompletionContentPartTextParam] - - type: 'null' - title: string | list[OpenAIChatCompletionContentPartTextParam] - description: The content of the model's response. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the assistant message participant. - tool_calls: - anyOf: - - items: - $ref: '#/components/schemas/ChatCompletionMessageToolCall' - type: array - - type: 'null' - description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - additionalProperties: true - type: object - title: OpenAIAssistantMessageParam - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. - OpenAIAttachFileRequest: - properties: - file_id: - type: string - title: File Id - description: The ID of the file to attach. - attributes: + title: File Id + description: The ID of the file to attach. + attributes: anyOf: - additionalProperties: anyOf: @@ -8596,240 +8429,6 @@ components: type: object title: OpenAIResponseInputToolChoiceWebSearch description: Indicates that the model should use web search to generate a response - OpenAIResponseMessage-Input: - properties: - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentImage' - title: OpenAIResponseInputMessageContentImage - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' - title: OpenAIResponseInputMessageContentFile - discriminator: - propertyName: type - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile - type: array - title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Input' - title: OpenAIResponseOutputMessageContentOutputText-Input - - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseContentPartRefusal - discriminator: - propertyName: type - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Input' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal - type: array - title: list[OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal] - title: string | list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] | list[OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal] - role: - anyOf: - - type: string - enum: - - system - - type: string - enum: - - developer - - type: string - enum: - - user - - type: string - enum: - - assistant - title: string - type: - type: string - title: Type - enum: - - message - id: - anyOf: - - type: string - - type: 'null' - status: - anyOf: - - type: string - - type: 'null' - type: object - required: - - content - - role - title: OpenAIResponseMessage - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. - OpenAIResponseMessage-Output: - properties: - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentImage' - title: OpenAIResponseInputMessageContentImage - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' - title: OpenAIResponseInputMessageContentFile - discriminator: - propertyName: type - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile - type: array - title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Output' - title: OpenAIResponseOutputMessageContentOutputText-Output - - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseContentPartRefusal - discriminator: - propertyName: type - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Output' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal - type: array - title: list[OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal] - title: string | list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] | list[OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal] - role: - anyOf: - - type: string - enum: - - system - - type: string - enum: - - developer - - type: string - enum: - - user - - type: string - enum: - - assistant - title: string - type: - type: string - title: Type - enum: - - message - id: - anyOf: - - type: string - - type: 'null' - status: - anyOf: - - type: string - - type: 'null' - type: object - required: - - content - - role - title: OpenAIResponseMessage - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. - OpenAIResponseOutputMessageContentOutputText-Input: - properties: - text: - type: string - title: Text - type: - type: string - title: Type - enum: - - output_text - annotations: - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - title: OpenAIResponseAnnotationFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - title: OpenAIResponseAnnotationContainerFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' - title: OpenAIResponseAnnotationFilePath - discriminator: - propertyName: type - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - type: array - title: Annotations - logprobs: - anyOf: - - items: - $ref: '#/components/schemas/OpenAITokenLogProb' - type: array - - type: 'null' - type: object - required: - - text - title: OpenAIResponseOutputMessageContentOutputText - description: Text content within an output message of an OpenAI response. - OpenAIResponseOutputMessageContentOutputText-Output: - properties: - text: - type: string - title: Text - type: - type: string - title: Type - enum: - - output_text - annotations: - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - title: OpenAIResponseAnnotationFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - title: OpenAIResponseAnnotationContainerFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' - title: OpenAIResponseAnnotationFilePath - discriminator: - propertyName: type - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - type: array - title: Annotations - logprobs: - anyOf: - - items: - $ref: '#/components/schemas/OpenAITokenLogProb' - type: array - - type: 'null' - type: object - required: - - text - title: OpenAIResponseOutputMessageContentOutputText - description: Text content within an output message of an OpenAI response. OpenAIResponseOutputMessageFileSearchToolCallResults: properties: attributes: @@ -8931,64 +8530,6 @@ components: - text title: OpenAIResponseOutputMessageReasoningSummary description: A summary of reasoning output from the model. - OpenAIResponseOutputMessageWebSearchToolCall-Input: - properties: - id: - type: string - title: Id - status: - type: string - title: Status - type: - type: string - title: Type - enum: - - web_search_call - action: - anyOf: - - $ref: '#/components/schemas/WebSearchActionSearch' - title: WebSearchActionSearch - - $ref: '#/components/schemas/WebSearchActionOpenPage' - title: WebSearchActionOpenPage - - $ref: '#/components/schemas/WebSearchActionFind' - title: WebSearchActionFind - - type: 'null' - title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - type: object - required: - - id - - status - title: OpenAIResponseOutputMessageWebSearchToolCall - description: Web search tool call output message for OpenAI responses. - OpenAIResponseOutputMessageWebSearchToolCall-Output: - properties: - id: - type: string - title: Id - status: - type: string - title: Status - type: - type: string - title: Type - enum: - - web_search_call - action: - anyOf: - - $ref: '#/components/schemas/WebSearchActionSearch' - title: WebSearchActionSearch - - $ref: '#/components/schemas/WebSearchActionOpenPage' - title: WebSearchActionOpenPage - - $ref: '#/components/schemas/WebSearchActionFind' - title: WebSearchActionFind - - type: 'null' - title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - type: object - required: - - id - - status - title: OpenAIResponseOutputMessageWebSearchToolCall - description: Web search tool call output message for OpenAI responses. OpenAIResponseReasoning: properties: effort: @@ -9163,86 +8704,6 @@ components: type: object title: OpenAIUpdateVectorStoreRequest description: Request body for updating a vector store. - OpenAIUserMessageParam-Input: - properties: - role: - type: string - title: Role - description: Must be 'user' to identify this as a user message. - enum: - - user - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - title: OpenAIChatCompletionContentPartImageParam - - $ref: '#/components/schemas/OpenAIFile' - title: OpenAIFile - discriminator: - propertyName: type - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile - type: array - title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the user message participant. - type: object - required: - - content - title: OpenAIUserMessageParam - description: A message from the user in an OpenAI-compatible chat completion request. - OpenAIUserMessageParam-Output: - properties: - role: - type: string - title: Role - description: Must be 'user' to identify this as a user message. - enum: - - user - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - title: OpenAIChatCompletionContentPartImageParam - - $ref: '#/components/schemas/OpenAIFile' - title: OpenAIFile - discriminator: - propertyName: type - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile - type: array - title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the user message participant. - type: object - required: - - content - title: OpenAIUserMessageParam - description: A message from the user in an OpenAI-compatible chat completion request. OutputTokensDetails: properties: reasoning_tokens: @@ -11139,69 +10600,6 @@ components: - completion_id title: ListChatCompletionMessagesRequest type: object - EmbeddedChunk: - description: |- - A chunk of content with its embedding vector for vector database operations. - Inherits all fields from Chunk and adds embedding-related fields. - properties: - content: - anyOf: - - type: string - - discriminator: - mapping: - image: '#/components/schemas/ImageContentItem' - text: '#/components/schemas/TextContentItem' - propertyName: type - oneOf: - - $ref: '#/components/schemas/ImageContentItem' - title: ImageContentItem - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - title: ImageContentItem | TextContentItem - - items: - discriminator: - mapping: - image: '#/components/schemas/ImageContentItem' - text: '#/components/schemas/TextContentItem' - propertyName: type - oneOf: - - $ref: '#/components/schemas/ImageContentItem' - title: ImageContentItem - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - title: ImageContentItem | TextContentItem - type: array - title: list[ImageContentItem | TextContentItem] - title: string | list[ImageContentItem | TextContentItem] - chunk_id: - title: Chunk Id - type: string - metadata: - additionalProperties: true - title: Metadata - type: object - chunk_metadata: - $ref: '#/components/schemas/ChunkMetadata' - embedding: - items: - type: number - title: Embedding - type: array - embedding_model: - title: Embedding Model - type: string - embedding_dimension: - title: Embedding Dimension - type: integer - required: - - content - - chunk_id - - chunk_metadata - - embedding - - embedding_model - - embedding_dimension - title: EmbeddedChunk - type: object VectorStoreCreateRequest: description: Request to create a vector store. properties: @@ -12573,10 +11971,10 @@ components: OpenAIResponseMessageOutputUnion: anyOf: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -12597,11 +11995,11 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' x-stainless-naming: OpenAIResponseMessageOutputOneOf - title: OpenAIResponseMessage-Output | ... (8 variants) + title: OpenAIResponseMessage | ... (8 variants) - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' title: OpenAIResponseInputFunctionToolCallOutput - $ref: '#/components/schemas/OpenAIResponseMCPApprovalResponse' @@ -12612,10 +12010,10 @@ components: x-stainless-naming: OpenAIResponseMessageOutputUnion OpenAIResponseOutputItem: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -12636,11 +12034,11 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' x-stainless-naming: OpenAIResponseOutputItem - title: OpenAIResponseMessage-Output | ... (8 variants) + title: OpenAIResponseMessage | ... (8 variants) ChatCompletionMessageToolCall: properties: id: diff --git a/docs/static/ogx-spec.yaml b/docs/static/ogx-spec.yaml index 49101c06dbf..36cb23b16f6 100644 --- a/docs/static/ogx-spec.yaml +++ b/docs/static/ogx-spec.yaml @@ -689,8 +689,8 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + - $ref: '#/components/schemas/OpenAIResponseMessage' + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' @@ -703,8 +703,8 @@ paths: discriminator: propertyName: type mapping: - message: '#/components/schemas/OpenAIResponseMessage-Output' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + message: '#/components/schemas/OpenAIResponseMessage' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' file_search_call: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' function_call: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' function_call_output: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' @@ -3847,13 +3847,11 @@ components: title: ListOpenAIChatCompletionResponse description: Response from listing OpenAI-compatible chat completions. OpenAIAssistantMessageParam: - additionalProperties: true - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. properties: role: - description: Must be 'assistant' to identify this as the model's response. - title: Role type: string + title: Role + description: Must be 'assistant' to identify this as the model's response. enum: - assistant content: @@ -3864,15 +3862,13 @@ components: type: array title: list[OpenAIChatCompletionContentPartTextParam] - type: 'null' - description: The content of the model's response. title: string | list[OpenAIChatCompletionContentPartTextParam] - nullable: true + description: The content of the model's response. name: anyOf: - type: string - type: 'null' description: The name of the assistant message participant. - nullable: true tool_calls: anyOf: - items: @@ -3880,9 +3876,10 @@ components: type: array - type: 'null' description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - nullable: true - title: OpenAIAssistantMessageParam + additionalProperties: true type: object + title: OpenAIAssistantMessageParam + description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. OpenAIChatCompletionContentPartImageParam: properties: type: @@ -4253,24 +4250,17 @@ components: title: OpenAITopLogProb description: The top log probability for a token from an OpenAI-compatible chat completion response. OpenAIUserMessageParam: - description: A message from the user in an OpenAI-compatible chat completion request. properties: role: - description: Must be 'user' to identify this as a user message. - title: Role type: string + title: Role + description: Must be 'user' to identify this as a user message. enum: - user content: anyOf: - type: string - items: - discriminator: - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' title: OpenAIChatCompletionContentPartTextParam @@ -4278,21 +4268,27 @@ components: title: OpenAIChatCompletionContentPartImageParam - $ref: '#/components/schemas/OpenAIFile' title: OpenAIFile + discriminator: + propertyName: type + mapping: + file: '#/components/schemas/OpenAIFile' + image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' + text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile type: array title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] + description: The content of the message, which can include text and other media. name: anyOf: - type: string - type: 'null' description: The name of the user message participant. - nullable: true + type: object required: - content title: OpenAIUserMessageParam - type: object + description: A message from the user in an OpenAI-compatible chat completion request. OpenAIJSONSchema: properties: name: @@ -4376,12 +4372,12 @@ components: messages: items: oneOf: - - $ref: '#/components/schemas/OpenAIUserMessageParam-Input' - title: OpenAIUserMessageParam-Input + - $ref: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam - $ref: '#/components/schemas/OpenAISystemMessageParam' title: OpenAISystemMessageParam - - $ref: '#/components/schemas/OpenAIAssistantMessageParam-Input' - title: OpenAIAssistantMessageParam-Input + - $ref: '#/components/schemas/OpenAIAssistantMessageParam' + title: OpenAIAssistantMessageParam - $ref: '#/components/schemas/OpenAIToolMessageParam' title: OpenAIToolMessageParam - $ref: '#/components/schemas/OpenAIDeveloperMessageParam' @@ -4389,12 +4385,12 @@ components: discriminator: propertyName: role mapping: - assistant: '#/components/schemas/OpenAIAssistantMessageParam-Input' + assistant: '#/components/schemas/OpenAIAssistantMessageParam' developer: '#/components/schemas/OpenAIDeveloperMessageParam' system: '#/components/schemas/OpenAISystemMessageParam' tool: '#/components/schemas/OpenAIToolMessageParam' - user: '#/components/schemas/OpenAIUserMessageParam-Input' - title: OpenAIUserMessageParam-Input | ... (5 variants) + user: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam | ... (5 variants) type: array minItems: 1 title: Messages @@ -4813,12 +4809,12 @@ components: input_messages: items: oneOf: - - $ref: '#/components/schemas/OpenAIUserMessageParam-Output' - title: OpenAIUserMessageParam-Output + - $ref: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam - $ref: '#/components/schemas/OpenAISystemMessageParam' title: OpenAISystemMessageParam - - $ref: '#/components/schemas/OpenAIAssistantMessageParam-Output' - title: OpenAIAssistantMessageParam-Output + - $ref: '#/components/schemas/OpenAIAssistantMessageParam' + title: OpenAIAssistantMessageParam - $ref: '#/components/schemas/OpenAIToolMessageParam' title: OpenAIToolMessageParam - $ref: '#/components/schemas/OpenAIDeveloperMessageParam' @@ -4826,12 +4822,12 @@ components: discriminator: propertyName: role mapping: - assistant: '#/components/schemas/OpenAIAssistantMessageParam-Output' + assistant: '#/components/schemas/OpenAIAssistantMessageParam' developer: '#/components/schemas/OpenAIDeveloperMessageParam' system: '#/components/schemas/OpenAISystemMessageParam' tool: '#/components/schemas/OpenAIToolMessageParam' - user: '#/components/schemas/OpenAIUserMessageParam-Output' - title: OpenAIUserMessageParam-Output | ... (5 variants) + user: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam | ... (5 variants) type: array title: Input Messages description: The input messages used to generate this completion. @@ -5421,22 +5417,11 @@ components: title: OpenAIResponseMCPApprovalResponse description: A response to an MCP approval request. OpenAIResponseMessage: - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. properties: content: anyOf: - type: string - items: - discriminator: - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' title: OpenAIResponseInputMessageContentText @@ -5444,20 +5429,26 @@ components: title: OpenAIResponseInputMessageContentImage - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' title: OpenAIResponseInputMessageContentFile + discriminator: + propertyName: type + mapping: + input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' + input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' + input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile type: array title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - items: - discriminator: - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' title: OpenAIResponseOutputMessageContentOutputText - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' title: OpenAIResponseContentPartRefusal + discriminator: + propertyName: type + mapping: + output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' + refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' title: OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal type: array title: list[OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal] @@ -5478,25 +5469,28 @@ components: - assistant title: string type: - title: Type type: string + title: Type enum: - message id: anyOf: - type: string - type: 'null' - nullable: true status: anyOf: - type: string - type: 'null' - nullable: true + type: object required: - content - role title: OpenAIResponseMessage - type: object + description: |- + Corresponds to the various Message types in the Responses API. + They are all under one type because the Responses API gives them all + the same "type" value, and there is no way to tell them apart in certain + scenarios. OpenAIResponseOutputMessageContent: discriminator: mapping: @@ -5510,25 +5504,17 @@ components: title: OpenAIResponseContentPartRefusal title: OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal OpenAIResponseOutputMessageContentOutputText: - description: Text content within an output message of an OpenAI response. properties: text: - title: Text type: string + title: Text type: - title: Type type: string + title: Type enum: - output_text annotations: items: - discriminator: - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' title: OpenAIResponseAnnotationFileCitation @@ -5538,20 +5524,27 @@ components: title: OpenAIResponseAnnotationContainerFileCitation - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' title: OpenAIResponseAnnotationFilePath + discriminator: + propertyName: type + mapping: + container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' + file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' + file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' + url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - title: Annotations type: array + title: Annotations logprobs: anyOf: - items: $ref: '#/components/schemas/OpenAITokenLogProb' type: array - type: 'null' - nullable: true + type: object required: - text title: OpenAIResponseOutputMessageContentOutputText - type: object + description: Text content within an output message of an OpenAI response. OpenAIResponseOutputMessageFileSearchToolCall: properties: id: @@ -5675,17 +5668,16 @@ components: title: OpenAIResponseOutputMessageMCPListTools description: MCP list tools output message containing available tools from an MCP server. OpenAIResponseOutputMessageWebSearchToolCall: - description: Web search tool call output message for OpenAI responses. properties: id: - title: Id type: string + title: Id status: - title: Status type: string + title: Status type: - title: Type type: string + title: Type enum: - web_search_call action: @@ -5698,22 +5690,22 @@ components: title: WebSearchActionFind - type: 'null' title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - nullable: true + type: object required: - id - status title: OpenAIResponseOutputMessageWebSearchToolCall - type: object + description: Web search tool call output message for OpenAI responses. CreateConversationRequest: properties: items: anyOf: - items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -5743,10 +5735,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array - type: 'null' description: Initial items to include in the conversation context. @@ -5836,10 +5828,10 @@ components: data: items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -5869,10 +5861,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseMessage-Output | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array title: Data description: List of conversation items @@ -5903,10 +5895,10 @@ components: items: items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -5936,10 +5928,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array maxItems: 20 title: Items @@ -8685,19 +8677,19 @@ components: title: UnionType type: object ImageContentItem: - description: A image content item properties: type: - title: Type type: string + title: Type enum: - image image: $ref: '#/components/schemas/_URLOrData' + type: object required: - image title: ImageContentItem - type: object + description: A image content item InterleavedContent: anyOf: - type: string @@ -8933,31 +8925,31 @@ components: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Output | TextContentItem] - title: string | list[ImageContentItem-Output | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] chunk_id: type: string title: Chunk Id @@ -9027,7 +9019,7 @@ components: description: The ID of the vector store to insert chunks into. chunks: items: - $ref: '#/components/schemas/EmbeddedChunk-Input' + $ref: '#/components/schemas/EmbeddedChunk' type: array title: Chunks description: The list of embedded chunks to insert. @@ -9052,31 +9044,31 @@ components: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Input' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Input' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Input | TextContentItem] - title: string | list[ImageContentItem-Input | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] description: The query content to search for. params: anyOf: @@ -9094,7 +9086,7 @@ components: properties: chunks: items: - $ref: '#/components/schemas/EmbeddedChunk-Output' + $ref: '#/components/schemas/EmbeddedChunk' type: array title: Chunks scores: @@ -10219,8 +10211,8 @@ components: title: AnthropicImageBlock - $ref: '#/components/schemas/AnthropicToolUseBlock' title: AnthropicToolUseBlock - - $ref: '#/components/schemas/AnthropicToolResultBlock-Input' - title: AnthropicToolResultBlock-Input + - $ref: '#/components/schemas/AnthropicToolResultBlock' + title: AnthropicToolResultBlock - $ref: '#/components/schemas/AnthropicThinkingBlock' title: AnthropicThinkingBlock - $ref: '#/components/schemas/AnthropicRedactedThinkingBlock' @@ -10232,7 +10224,7 @@ components: redacted_thinking: '#/components/schemas/AnthropicRedactedThinkingBlock' text: '#/components/schemas/AnthropicTextBlock' thinking: '#/components/schemas/AnthropicThinkingBlock' - tool_result: '#/components/schemas/AnthropicToolResultBlock-Input' + tool_result: '#/components/schemas/AnthropicToolResultBlock' tool_use: '#/components/schemas/AnthropicToolUseBlock' title: AnthropicTextBlock | ... (6 variants) type: array @@ -10270,8 +10262,8 @@ components: title: AnthropicImageBlock - $ref: '#/components/schemas/AnthropicToolUseBlock' title: AnthropicToolUseBlock - - $ref: '#/components/schemas/AnthropicToolResultBlock-Output' - title: AnthropicToolResultBlock-Output + - $ref: '#/components/schemas/AnthropicToolResultBlock' + title: AnthropicToolResultBlock - $ref: '#/components/schemas/AnthropicThinkingBlock' title: AnthropicThinkingBlock - $ref: '#/components/schemas/AnthropicRedactedThinkingBlock' @@ -10283,7 +10275,7 @@ components: redacted_thinking: '#/components/schemas/AnthropicRedactedThinkingBlock' text: '#/components/schemas/AnthropicTextBlock' thinking: '#/components/schemas/AnthropicThinkingBlock' - tool_result: '#/components/schemas/AnthropicToolResultBlock-Output' + tool_result: '#/components/schemas/AnthropicToolResultBlock' tool_use: '#/components/schemas/AnthropicToolUseBlock' title: AnthropicTextBlock | ... (6 variants) type: array @@ -10421,49 +10413,7 @@ components: type: object title: AnthropicThinkingConfig description: Configuration for extended thinking. - AnthropicToolResultBlock-Input: - properties: - type: - type: string - title: Type - enum: - - tool_result - tool_use_id: - type: string - title: Tool Use Id - description: The ID of the tool_use block this result corresponds to. - content: - anyOf: - - type: string - - items: - anyOf: - - $ref: '#/components/schemas/AnthropicTextBlock' - title: AnthropicTextBlock - - $ref: '#/components/schemas/AnthropicImageBlock' - title: AnthropicImageBlock - title: AnthropicTextBlock | AnthropicImageBlock - type: array - title: list[AnthropicTextBlock | AnthropicImageBlock] - title: string | list[AnthropicTextBlock | AnthropicImageBlock] - description: The result content. - default: '' - is_error: - anyOf: - - type: boolean - - type: 'null' - description: Whether the tool call resulted in an error. - cache_control: - anyOf: - - $ref: '#/components/schemas/AnthropicCacheControl' - title: AnthropicCacheControl - - type: 'null' - title: AnthropicCacheControl - type: object - required: - - tool_use_id - title: AnthropicToolResultBlock - description: A tool result content block in a user message. - AnthropicToolResultBlock-Output: + AnthropicToolResultBlock: properties: type: type: string @@ -10867,10 +10817,10 @@ components: - items: anyOf: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -10891,18 +10841,18 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (8 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (8 variants) - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' title: OpenAIResponseInputFunctionToolCallOutput - $ref: '#/components/schemas/OpenAIResponseMCPApprovalResponse' title: OpenAIResponseMCPApprovalResponse - $ref: '#/components/schemas/OpenAIResponseCompaction' title: OpenAIResponseCompaction - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage title: OpenAIResponseInputFunctionToolCallOutput | ... (4 variants) type: array title: list[OpenAIResponseMessageUnion | OpenAIResponseInputFunctionToolCallOutput | ...] @@ -11075,10 +11025,10 @@ components: - items: anyOf: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -11099,18 +11049,18 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (8 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (8 variants) - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' title: OpenAIResponseInputFunctionToolCallOutput - $ref: '#/components/schemas/OpenAIResponseMCPApprovalResponse' title: OpenAIResponseMCPApprovalResponse - $ref: '#/components/schemas/OpenAIResponseCompaction' title: OpenAIResponseCompaction - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage title: OpenAIResponseInputFunctionToolCallOutput | ... (4 variants) type: array title: list[OpenAIResponseMessageUnion | OpenAIResponseInputFunctionToolCallOutput | ...] @@ -11342,100 +11292,37 @@ components: - model title: CreateResponseRequest description: Request model for creating a response. - EmbeddedChunk-Input: - properties: - content: - anyOf: - - type: string - - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - discriminator: - propertyName: type - mapping: - image: '#/components/schemas/ImageContentItem-Input' - text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem - - items: - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - discriminator: - propertyName: type - mapping: - image: '#/components/schemas/ImageContentItem-Input' - text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem - type: array - title: list[ImageContentItem-Input | TextContentItem] - title: string | list[ImageContentItem-Input | TextContentItem] - chunk_id: - type: string - title: Chunk Id - metadata: - additionalProperties: true - type: object - title: Metadata - chunk_metadata: - $ref: '#/components/schemas/ChunkMetadata' - embedding: - items: - type: number - type: array - title: Embedding - embedding_model: - type: string - title: Embedding Model - embedding_dimension: - type: integer - title: Embedding Dimension - type: object - required: - - content - - chunk_id - - chunk_metadata - - embedding - - embedding_model - - embedding_dimension - title: EmbeddedChunk - description: |- - A chunk of content with its embedding vector for vector database operations. - Inherits all fields from Chunk and adds embedding-related fields. - EmbeddedChunk-Output: + EmbeddedChunk: properties: content: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Output | TextContentItem] - title: string | list[ImageContentItem-Output | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] chunk_id: type: string title: Chunk Id @@ -11491,34 +11378,6 @@ components: - Not Implemented title: HealthStatus description: Health check status values for provider readiness. - ImageContentItem-Input: - properties: - type: - type: string - title: Type - enum: - - image - image: - $ref: '#/components/schemas/_URLOrData' - type: object - required: - - image - title: ImageContentItem - description: A image content item - ImageContentItem-Output: - properties: - type: - type: string - title: Type - enum: - - image - image: - $ref: '#/components/schemas/_URLOrData' - type: object - required: - - image - title: ImageContentItem - description: A image content item InputTokensDetails: properties: cached_tokens: @@ -11772,74 +11631,6 @@ components: - params title: MessageBatchRequestParams description: An individual request within a message batch. - OpenAIAssistantMessageParam-Input: - properties: - role: - type: string - title: Role - description: Must be 'assistant' to identify this as the model's response. - enum: - - assistant - content: - anyOf: - - type: string - - items: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - type: array - title: list[OpenAIChatCompletionContentPartTextParam] - - type: 'null' - title: string | list[OpenAIChatCompletionContentPartTextParam] - description: The content of the model's response. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the assistant message participant. - tool_calls: - anyOf: - - items: - $ref: '#/components/schemas/ChatCompletionMessageToolCall' - type: array - - type: 'null' - description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - additionalProperties: true - type: object - title: OpenAIAssistantMessageParam - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. - OpenAIAssistantMessageParam-Output: - properties: - role: - type: string - title: Role - description: Must be 'assistant' to identify this as the model's response. - enum: - - assistant - content: - anyOf: - - type: string - - items: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - type: array - title: list[OpenAIChatCompletionContentPartTextParam] - - type: 'null' - title: string | list[OpenAIChatCompletionContentPartTextParam] - description: The content of the model's response. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the assistant message participant. - tool_calls: - anyOf: - - items: - $ref: '#/components/schemas/ChatCompletionMessageToolCall' - type: array - - type: 'null' - description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - additionalProperties: true - type: object - title: OpenAIAssistantMessageParam - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. OpenAIAttachFileRequest: properties: file_id: @@ -12128,283 +11919,49 @@ components: server_label: type: string title: Server Label - type: - type: string - title: Type - enum: - - mcp - name: - anyOf: - - type: string - - type: 'null' - type: object - required: - - server_label - title: OpenAIResponseInputToolChoiceMCPTool - description: Forces the model to call a specific tool on a remote MCP server - OpenAIResponseInputToolChoiceMode: - type: string - enum: - - auto - - required - - none - title: OpenAIResponseInputToolChoiceMode - description: Enumeration of simple tool choice modes for response generation. - OpenAIResponseInputToolChoiceWebSearch: - properties: - type: - anyOf: - - type: string - enum: - - web_search - - type: string - enum: - - web_search_preview - - type: string - enum: - - web_search_preview_2025_03_11 - - type: string - enum: - - web_search_2025_08_26 - title: string - default: web_search - type: object - title: OpenAIResponseInputToolChoiceWebSearch - description: Indicates that the model should use web search to generate a response - OpenAIResponseMessage-Input: - properties: - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentImage' - title: OpenAIResponseInputMessageContentImage - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' - title: OpenAIResponseInputMessageContentFile - discriminator: - propertyName: type - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile - type: array - title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Input' - title: OpenAIResponseOutputMessageContentOutputText-Input - - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseContentPartRefusal - discriminator: - propertyName: type - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Input' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal - type: array - title: list[OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal] - title: string | list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] | list[OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal] - role: - anyOf: - - type: string - enum: - - system - - type: string - enum: - - developer - - type: string - enum: - - user - - type: string - enum: - - assistant - title: string - type: - type: string - title: Type - enum: - - message - id: - anyOf: - - type: string - - type: 'null' - status: - anyOf: - - type: string - - type: 'null' - type: object - required: - - content - - role - title: OpenAIResponseMessage - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. - OpenAIResponseMessage-Output: - properties: - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentImage' - title: OpenAIResponseInputMessageContentImage - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' - title: OpenAIResponseInputMessageContentFile - discriminator: - propertyName: type - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile - type: array - title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Output' - title: OpenAIResponseOutputMessageContentOutputText-Output - - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseContentPartRefusal - discriminator: - propertyName: type - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Output' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal - type: array - title: list[OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal] - title: string | list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] | list[OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal] - role: - anyOf: - - type: string - enum: - - system - - type: string - enum: - - developer - - type: string - enum: - - user - - type: string - enum: - - assistant - title: string - type: - type: string - title: Type - enum: - - message - id: - anyOf: - - type: string - - type: 'null' - status: - anyOf: - - type: string - - type: 'null' - type: object - required: - - content - - role - title: OpenAIResponseMessage - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. - OpenAIResponseOutputMessageContentOutputText-Input: - properties: - text: - type: string - title: Text - type: - type: string - title: Type - enum: - - output_text - annotations: - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - title: OpenAIResponseAnnotationFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - title: OpenAIResponseAnnotationContainerFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' - title: OpenAIResponseAnnotationFilePath - discriminator: - propertyName: type - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - type: array - title: Annotations - logprobs: - anyOf: - - items: - $ref: '#/components/schemas/OpenAITokenLogProb' - type: array - - type: 'null' - type: object - required: - - text - title: OpenAIResponseOutputMessageContentOutputText - description: Text content within an output message of an OpenAI response. - OpenAIResponseOutputMessageContentOutputText-Output: - properties: - text: - type: string - title: Text - type: - type: string - title: Type - enum: - - output_text - annotations: - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - title: OpenAIResponseAnnotationFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - title: OpenAIResponseAnnotationContainerFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' - title: OpenAIResponseAnnotationFilePath - discriminator: - propertyName: type - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - type: array - title: Annotations - logprobs: + type: + type: string + title: Type + enum: + - mcp + name: anyOf: - - items: - $ref: '#/components/schemas/OpenAITokenLogProb' - type: array + - type: string - type: 'null' type: object required: - - text - title: OpenAIResponseOutputMessageContentOutputText - description: Text content within an output message of an OpenAI response. + - server_label + title: OpenAIResponseInputToolChoiceMCPTool + description: Forces the model to call a specific tool on a remote MCP server + OpenAIResponseInputToolChoiceMode: + type: string + enum: + - auto + - required + - none + title: OpenAIResponseInputToolChoiceMode + description: Enumeration of simple tool choice modes for response generation. + OpenAIResponseInputToolChoiceWebSearch: + properties: + type: + anyOf: + - type: string + enum: + - web_search + - type: string + enum: + - web_search_preview + - type: string + enum: + - web_search_preview_2025_03_11 + - type: string + enum: + - web_search_2025_08_26 + title: string + default: web_search + type: object + title: OpenAIResponseInputToolChoiceWebSearch + description: Indicates that the model should use web search to generate a response OpenAIResponseOutputMessageFileSearchToolCallResults: properties: attributes: @@ -12506,64 +12063,6 @@ components: - text title: OpenAIResponseOutputMessageReasoningSummary description: A summary of reasoning output from the model. - OpenAIResponseOutputMessageWebSearchToolCall-Input: - properties: - id: - type: string - title: Id - status: - type: string - title: Status - type: - type: string - title: Type - enum: - - web_search_call - action: - anyOf: - - $ref: '#/components/schemas/WebSearchActionSearch' - title: WebSearchActionSearch - - $ref: '#/components/schemas/WebSearchActionOpenPage' - title: WebSearchActionOpenPage - - $ref: '#/components/schemas/WebSearchActionFind' - title: WebSearchActionFind - - type: 'null' - title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - type: object - required: - - id - - status - title: OpenAIResponseOutputMessageWebSearchToolCall - description: Web search tool call output message for OpenAI responses. - OpenAIResponseOutputMessageWebSearchToolCall-Output: - properties: - id: - type: string - title: Id - status: - type: string - title: Status - type: - type: string - title: Type - enum: - - web_search_call - action: - anyOf: - - $ref: '#/components/schemas/WebSearchActionSearch' - title: WebSearchActionSearch - - $ref: '#/components/schemas/WebSearchActionOpenPage' - title: WebSearchActionOpenPage - - $ref: '#/components/schemas/WebSearchActionFind' - title: WebSearchActionFind - - type: 'null' - title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - type: object - required: - - id - - status - title: OpenAIResponseOutputMessageWebSearchToolCall - description: Web search tool call output message for OpenAI responses. OpenAIResponseReasoning: properties: effort: @@ -12738,86 +12237,6 @@ components: type: object title: OpenAIUpdateVectorStoreRequest description: Request body for updating a vector store. - OpenAIUserMessageParam-Input: - properties: - role: - type: string - title: Role - description: Must be 'user' to identify this as a user message. - enum: - - user - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - title: OpenAIChatCompletionContentPartImageParam - - $ref: '#/components/schemas/OpenAIFile' - title: OpenAIFile - discriminator: - propertyName: type - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile - type: array - title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the user message participant. - type: object - required: - - content - title: OpenAIUserMessageParam - description: A message from the user in an OpenAI-compatible chat completion request. - OpenAIUserMessageParam-Output: - properties: - role: - type: string - title: Role - description: Must be 'user' to identify this as a user message. - enum: - - user - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - title: OpenAIChatCompletionContentPartImageParam - - $ref: '#/components/schemas/OpenAIFile' - title: OpenAIFile - discriminator: - propertyName: type - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile - type: array - title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the user message participant. - type: object - required: - - content - title: OpenAIUserMessageParam - description: A message from the user in an OpenAI-compatible chat completion request. OutputTokensDetails: properties: reasoning_tokens: @@ -14813,69 +14232,6 @@ components: - completion_id title: ListChatCompletionMessagesRequest type: object - EmbeddedChunk: - description: |- - A chunk of content with its embedding vector for vector database operations. - Inherits all fields from Chunk and adds embedding-related fields. - properties: - content: - anyOf: - - type: string - - discriminator: - mapping: - image: '#/components/schemas/ImageContentItem' - text: '#/components/schemas/TextContentItem' - propertyName: type - oneOf: - - $ref: '#/components/schemas/ImageContentItem' - title: ImageContentItem - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - title: ImageContentItem | TextContentItem - - items: - discriminator: - mapping: - image: '#/components/schemas/ImageContentItem' - text: '#/components/schemas/TextContentItem' - propertyName: type - oneOf: - - $ref: '#/components/schemas/ImageContentItem' - title: ImageContentItem - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - title: ImageContentItem | TextContentItem - type: array - title: list[ImageContentItem | TextContentItem] - title: string | list[ImageContentItem | TextContentItem] - chunk_id: - title: Chunk Id - type: string - metadata: - additionalProperties: true - title: Metadata - type: object - chunk_metadata: - $ref: '#/components/schemas/ChunkMetadata' - embedding: - items: - type: number - title: Embedding - type: array - embedding_model: - title: Embedding Model - type: string - embedding_dimension: - title: Embedding Dimension - type: integer - required: - - content - - chunk_id - - chunk_metadata - - embedding - - embedding_model - - embedding_dimension - title: EmbeddedChunk - type: object VectorStoreCreateRequest: description: Request to create a vector store. properties: @@ -16247,10 +15603,10 @@ components: OpenAIResponseMessageOutputUnion: anyOf: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -16271,11 +15627,11 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' x-stainless-naming: OpenAIResponseMessageOutputOneOf - title: OpenAIResponseMessage-Output | ... (8 variants) + title: OpenAIResponseMessage | ... (8 variants) - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' title: OpenAIResponseInputFunctionToolCallOutput - $ref: '#/components/schemas/OpenAIResponseMCPApprovalResponse' @@ -16286,10 +15642,10 @@ components: x-stainless-naming: OpenAIResponseMessageOutputUnion OpenAIResponseOutputItem: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -16310,11 +15666,11 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' x-stainless-naming: OpenAIResponseOutputItem - title: OpenAIResponseMessage-Output | ... (8 variants) + title: OpenAIResponseMessage | ... (8 variants) ChatCompletionMessageToolCall: properties: id: diff --git a/docs/static/stainless-ogx-spec.yaml b/docs/static/stainless-ogx-spec.yaml index d85d75d7427..877055bb2a6 100644 --- a/docs/static/stainless-ogx-spec.yaml +++ b/docs/static/stainless-ogx-spec.yaml @@ -691,8 +691,8 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + - $ref: '#/components/schemas/OpenAIResponseMessage' + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' @@ -705,8 +705,8 @@ paths: discriminator: propertyName: type mapping: - message: '#/components/schemas/OpenAIResponseMessage-Output' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + message: '#/components/schemas/OpenAIResponseMessage' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' file_search_call: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' function_call: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' function_call_output: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' @@ -4729,13 +4729,11 @@ components: title: ListOpenAIChatCompletionResponse description: Response from listing OpenAI-compatible chat completions. OpenAIAssistantMessageParam: - additionalProperties: true - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. properties: role: - description: Must be 'assistant' to identify this as the model's response. - title: Role type: string + title: Role + description: Must be 'assistant' to identify this as the model's response. enum: - assistant content: @@ -4746,15 +4744,13 @@ components: type: array title: list[OpenAIChatCompletionContentPartTextParam] - type: 'null' - description: The content of the model's response. title: string | list[OpenAIChatCompletionContentPartTextParam] - nullable: true + description: The content of the model's response. name: anyOf: - type: string - type: 'null' description: The name of the assistant message participant. - nullable: true tool_calls: anyOf: - items: @@ -4762,9 +4758,10 @@ components: type: array - type: 'null' description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - nullable: true - title: OpenAIAssistantMessageParam + additionalProperties: true type: object + title: OpenAIAssistantMessageParam + description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. OpenAIChatCompletionContentPartImageParam: properties: type: @@ -5135,24 +5132,17 @@ components: title: OpenAITopLogProb description: The top log probability for a token from an OpenAI-compatible chat completion response. OpenAIUserMessageParam: - description: A message from the user in an OpenAI-compatible chat completion request. properties: role: - description: Must be 'user' to identify this as a user message. - title: Role type: string + title: Role + description: Must be 'user' to identify this as a user message. enum: - user content: anyOf: - type: string - items: - discriminator: - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' title: OpenAIChatCompletionContentPartTextParam @@ -5160,21 +5150,27 @@ components: title: OpenAIChatCompletionContentPartImageParam - $ref: '#/components/schemas/OpenAIFile' title: OpenAIFile + discriminator: + propertyName: type + mapping: + file: '#/components/schemas/OpenAIFile' + image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' + text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile type: array title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] + description: The content of the message, which can include text and other media. name: anyOf: - type: string - type: 'null' description: The name of the user message participant. - nullable: true + type: object required: - content title: OpenAIUserMessageParam - type: object + description: A message from the user in an OpenAI-compatible chat completion request. OpenAIJSONSchema: properties: name: @@ -5258,12 +5254,12 @@ components: messages: items: oneOf: - - $ref: '#/components/schemas/OpenAIUserMessageParam-Input' - title: OpenAIUserMessageParam-Input + - $ref: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam - $ref: '#/components/schemas/OpenAISystemMessageParam' title: OpenAISystemMessageParam - - $ref: '#/components/schemas/OpenAIAssistantMessageParam-Input' - title: OpenAIAssistantMessageParam-Input + - $ref: '#/components/schemas/OpenAIAssistantMessageParam' + title: OpenAIAssistantMessageParam - $ref: '#/components/schemas/OpenAIToolMessageParam' title: OpenAIToolMessageParam - $ref: '#/components/schemas/OpenAIDeveloperMessageParam' @@ -5271,12 +5267,12 @@ components: discriminator: propertyName: role mapping: - assistant: '#/components/schemas/OpenAIAssistantMessageParam-Input' + assistant: '#/components/schemas/OpenAIAssistantMessageParam' developer: '#/components/schemas/OpenAIDeveloperMessageParam' system: '#/components/schemas/OpenAISystemMessageParam' tool: '#/components/schemas/OpenAIToolMessageParam' - user: '#/components/schemas/OpenAIUserMessageParam-Input' - title: OpenAIUserMessageParam-Input | ... (5 variants) + user: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam | ... (5 variants) type: array minItems: 1 title: Messages @@ -5695,12 +5691,12 @@ components: input_messages: items: oneOf: - - $ref: '#/components/schemas/OpenAIUserMessageParam-Output' - title: OpenAIUserMessageParam-Output + - $ref: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam - $ref: '#/components/schemas/OpenAISystemMessageParam' title: OpenAISystemMessageParam - - $ref: '#/components/schemas/OpenAIAssistantMessageParam-Output' - title: OpenAIAssistantMessageParam-Output + - $ref: '#/components/schemas/OpenAIAssistantMessageParam' + title: OpenAIAssistantMessageParam - $ref: '#/components/schemas/OpenAIToolMessageParam' title: OpenAIToolMessageParam - $ref: '#/components/schemas/OpenAIDeveloperMessageParam' @@ -5708,12 +5704,12 @@ components: discriminator: propertyName: role mapping: - assistant: '#/components/schemas/OpenAIAssistantMessageParam-Output' + assistant: '#/components/schemas/OpenAIAssistantMessageParam' developer: '#/components/schemas/OpenAIDeveloperMessageParam' system: '#/components/schemas/OpenAISystemMessageParam' tool: '#/components/schemas/OpenAIToolMessageParam' - user: '#/components/schemas/OpenAIUserMessageParam-Output' - title: OpenAIUserMessageParam-Output | ... (5 variants) + user: '#/components/schemas/OpenAIUserMessageParam' + title: OpenAIUserMessageParam | ... (5 variants) type: array title: Input Messages description: The input messages used to generate this completion. @@ -6303,22 +6299,11 @@ components: title: OpenAIResponseMCPApprovalResponse description: A response to an MCP approval request. OpenAIResponseMessage: - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. properties: content: anyOf: - type: string - items: - discriminator: - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' title: OpenAIResponseInputMessageContentText @@ -6326,20 +6311,26 @@ components: title: OpenAIResponseInputMessageContentImage - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' title: OpenAIResponseInputMessageContentFile + discriminator: + propertyName: type + mapping: + input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' + input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' + input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile type: array title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - items: - discriminator: - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' title: OpenAIResponseOutputMessageContentOutputText - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' title: OpenAIResponseContentPartRefusal + discriminator: + propertyName: type + mapping: + output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText' + refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' title: OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal type: array title: list[OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal] @@ -6360,25 +6351,28 @@ components: - assistant title: string type: - title: Type type: string + title: Type enum: - message id: anyOf: - type: string - type: 'null' - nullable: true status: anyOf: - type: string - type: 'null' - nullable: true + type: object required: - content - role title: OpenAIResponseMessage - type: object + description: |- + Corresponds to the various Message types in the Responses API. + They are all under one type because the Responses API gives them all + the same "type" value, and there is no way to tell them apart in certain + scenarios. OpenAIResponseOutputMessageContent: discriminator: mapping: @@ -6392,25 +6386,17 @@ components: title: OpenAIResponseContentPartRefusal title: OpenAIResponseOutputMessageContentOutputText | OpenAIResponseContentPartRefusal OpenAIResponseOutputMessageContentOutputText: - description: Text content within an output message of an OpenAI response. properties: text: - title: Text type: string + title: Text type: - title: Type type: string + title: Type enum: - output_text annotations: items: - discriminator: - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - propertyName: type oneOf: - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' title: OpenAIResponseAnnotationFileCitation @@ -6420,20 +6406,27 @@ components: title: OpenAIResponseAnnotationContainerFileCitation - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' title: OpenAIResponseAnnotationFilePath + discriminator: + propertyName: type + mapping: + container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' + file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' + file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' + url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - title: Annotations type: array + title: Annotations logprobs: anyOf: - items: $ref: '#/components/schemas/OpenAITokenLogProb' type: array - type: 'null' - nullable: true + type: object required: - text title: OpenAIResponseOutputMessageContentOutputText - type: object + description: Text content within an output message of an OpenAI response. OpenAIResponseOutputMessageFileSearchToolCall: properties: id: @@ -6557,17 +6550,16 @@ components: title: OpenAIResponseOutputMessageMCPListTools description: MCP list tools output message containing available tools from an MCP server. OpenAIResponseOutputMessageWebSearchToolCall: - description: Web search tool call output message for OpenAI responses. properties: id: - title: Id type: string + title: Id status: - title: Status type: string + title: Status type: - title: Type type: string + title: Type enum: - web_search_call action: @@ -6580,22 +6572,22 @@ components: title: WebSearchActionFind - type: 'null' title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - nullable: true + type: object required: - id - status title: OpenAIResponseOutputMessageWebSearchToolCall - type: object + description: Web search tool call output message for OpenAI responses. CreateConversationRequest: properties: items: anyOf: - items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -6625,10 +6617,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array - type: 'null' description: Initial items to include in the conversation context. @@ -6718,10 +6710,10 @@ components: data: items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -6751,10 +6743,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseMessage-Output | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array title: Data description: List of conversation items @@ -6785,10 +6777,10 @@ components: items: items: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -6818,10 +6810,10 @@ components: mcp_approval_response: '#/components/schemas/OpenAIResponseMCPApprovalResponse' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (11 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (11 variants) type: array maxItems: 20 title: Items @@ -9567,19 +9559,19 @@ components: title: UnionType type: object ImageContentItem: - description: A image content item properties: type: - title: Type type: string + title: Type enum: - image image: $ref: '#/components/schemas/_URLOrData' + type: object required: - image title: ImageContentItem - type: object + description: A image content item InterleavedContent: anyOf: - type: string @@ -9815,31 +9807,31 @@ components: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Output | TextContentItem] - title: string | list[ImageContentItem-Output | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] chunk_id: type: string title: Chunk Id @@ -9909,7 +9901,7 @@ components: description: The ID of the vector store to insert chunks into. chunks: items: - $ref: '#/components/schemas/EmbeddedChunk-Input' + $ref: '#/components/schemas/EmbeddedChunk' type: array title: Chunks description: The list of embedded chunks to insert. @@ -9934,31 +9926,31 @@ components: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Input' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Input' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Input | TextContentItem] - title: string | list[ImageContentItem-Input | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] description: The query content to search for. params: anyOf: @@ -9976,7 +9968,7 @@ components: properties: chunks: items: - $ref: '#/components/schemas/EmbeddedChunk-Output' + $ref: '#/components/schemas/EmbeddedChunk' type: array title: Chunks scores: @@ -11101,8 +11093,8 @@ components: title: AnthropicImageBlock - $ref: '#/components/schemas/AnthropicToolUseBlock' title: AnthropicToolUseBlock - - $ref: '#/components/schemas/AnthropicToolResultBlock-Input' - title: AnthropicToolResultBlock-Input + - $ref: '#/components/schemas/AnthropicToolResultBlock' + title: AnthropicToolResultBlock - $ref: '#/components/schemas/AnthropicThinkingBlock' title: AnthropicThinkingBlock - $ref: '#/components/schemas/AnthropicRedactedThinkingBlock' @@ -11114,7 +11106,7 @@ components: redacted_thinking: '#/components/schemas/AnthropicRedactedThinkingBlock' text: '#/components/schemas/AnthropicTextBlock' thinking: '#/components/schemas/AnthropicThinkingBlock' - tool_result: '#/components/schemas/AnthropicToolResultBlock-Input' + tool_result: '#/components/schemas/AnthropicToolResultBlock' tool_use: '#/components/schemas/AnthropicToolUseBlock' title: AnthropicTextBlock | ... (6 variants) type: array @@ -11152,8 +11144,8 @@ components: title: AnthropicImageBlock - $ref: '#/components/schemas/AnthropicToolUseBlock' title: AnthropicToolUseBlock - - $ref: '#/components/schemas/AnthropicToolResultBlock-Output' - title: AnthropicToolResultBlock-Output + - $ref: '#/components/schemas/AnthropicToolResultBlock' + title: AnthropicToolResultBlock - $ref: '#/components/schemas/AnthropicThinkingBlock' title: AnthropicThinkingBlock - $ref: '#/components/schemas/AnthropicRedactedThinkingBlock' @@ -11165,7 +11157,7 @@ components: redacted_thinking: '#/components/schemas/AnthropicRedactedThinkingBlock' text: '#/components/schemas/AnthropicTextBlock' thinking: '#/components/schemas/AnthropicThinkingBlock' - tool_result: '#/components/schemas/AnthropicToolResultBlock-Output' + tool_result: '#/components/schemas/AnthropicToolResultBlock' tool_use: '#/components/schemas/AnthropicToolUseBlock' title: AnthropicTextBlock | ... (6 variants) type: array @@ -11303,49 +11295,7 @@ components: type: object title: AnthropicThinkingConfig description: Configuration for extended thinking. - AnthropicToolResultBlock-Input: - properties: - type: - type: string - title: Type - enum: - - tool_result - tool_use_id: - type: string - title: Tool Use Id - description: The ID of the tool_use block this result corresponds to. - content: - anyOf: - - type: string - - items: - anyOf: - - $ref: '#/components/schemas/AnthropicTextBlock' - title: AnthropicTextBlock - - $ref: '#/components/schemas/AnthropicImageBlock' - title: AnthropicImageBlock - title: AnthropicTextBlock | AnthropicImageBlock - type: array - title: list[AnthropicTextBlock | AnthropicImageBlock] - title: string | list[AnthropicTextBlock | AnthropicImageBlock] - description: The result content. - default: '' - is_error: - anyOf: - - type: boolean - - type: 'null' - description: Whether the tool call resulted in an error. - cache_control: - anyOf: - - $ref: '#/components/schemas/AnthropicCacheControl' - title: AnthropicCacheControl - - type: 'null' - title: AnthropicCacheControl - type: object - required: - - tool_use_id - title: AnthropicToolResultBlock - description: A tool result content block in a user message. - AnthropicToolResultBlock-Output: + AnthropicToolResultBlock: properties: type: type: string @@ -11802,10 +11752,10 @@ components: - items: anyOf: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -11826,10 +11776,10 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (8 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (8 variants) - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' title: OpenAIResponseInputFunctionToolCallOutput - $ref: '#/components/schemas/OpenAIResponseMCPApprovalResponse' @@ -12008,10 +11958,10 @@ components: - items: anyOf: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Input' - title: OpenAIResponseMessage-Input - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseOutputMessageWebSearchToolCall-Input + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -12032,10 +11982,10 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Input' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Input' - title: OpenAIResponseMessage-Input | ... (8 variants) + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseMessage | ... (8 variants) - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' title: OpenAIResponseInputFunctionToolCallOutput - $ref: '#/components/schemas/OpenAIResponseMCPApprovalResponse' @@ -12273,100 +12223,37 @@ components: - model title: CreateResponseRequest description: Request model for creating a response. - EmbeddedChunk-Input: - properties: - content: - anyOf: - - type: string - - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - discriminator: - propertyName: type - mapping: - image: '#/components/schemas/ImageContentItem-Input' - text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem - - items: - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Input' - title: ImageContentItem-Input - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - discriminator: - propertyName: type - mapping: - image: '#/components/schemas/ImageContentItem-Input' - text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Input | TextContentItem - type: array - title: list[ImageContentItem-Input | TextContentItem] - title: string | list[ImageContentItem-Input | TextContentItem] - chunk_id: - type: string - title: Chunk Id - metadata: - additionalProperties: true - type: object - title: Metadata - chunk_metadata: - $ref: '#/components/schemas/ChunkMetadata' - embedding: - items: - type: number - type: array - title: Embedding - embedding_model: - type: string - title: Embedding Model - embedding_dimension: - type: integer - title: Embedding Dimension - type: object - required: - - content - - chunk_id - - chunk_metadata - - embedding - - embedding_model - - embedding_dimension - title: EmbeddedChunk - description: |- - A chunk of content with its embedding vector for vector database operations. - Inherits all fields from Chunk and adds embedding-related fields. - EmbeddedChunk-Output: + EmbeddedChunk: properties: content: anyOf: - type: string - oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem - items: oneOf: - - $ref: '#/components/schemas/ImageContentItem-Output' - title: ImageContentItem-Output + - $ref: '#/components/schemas/ImageContentItem' + title: ImageContentItem - $ref: '#/components/schemas/TextContentItem' title: TextContentItem discriminator: propertyName: type mapping: - image: '#/components/schemas/ImageContentItem-Output' + image: '#/components/schemas/ImageContentItem' text: '#/components/schemas/TextContentItem' - title: ImageContentItem-Output | TextContentItem + title: ImageContentItem | TextContentItem type: array - title: list[ImageContentItem-Output | TextContentItem] - title: string | list[ImageContentItem-Output | TextContentItem] + title: list[ImageContentItem | TextContentItem] + title: string | list[ImageContentItem | TextContentItem] chunk_id: type: string title: Chunk Id @@ -12804,34 +12691,6 @@ components: - Not Implemented title: HealthStatus description: Health check status values for provider readiness. - ImageContentItem-Input: - properties: - type: - type: string - title: Type - enum: - - image - image: - $ref: '#/components/schemas/_URLOrData' - type: object - required: - - image - title: ImageContentItem - description: A image content item - ImageContentItem-Output: - properties: - type: - type: string - title: Type - enum: - - image - image: - $ref: '#/components/schemas/_URLOrData' - type: object - required: - - image - title: ImageContentItem - description: A image content item InputTokensDetails: properties: cached_tokens: @@ -13085,74 +12944,6 @@ components: - params title: MessageBatchRequestParams description: An individual request within a message batch. - OpenAIAssistantMessageParam-Input: - properties: - role: - type: string - title: Role - description: Must be 'assistant' to identify this as the model's response. - enum: - - assistant - content: - anyOf: - - type: string - - items: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - type: array - title: list[OpenAIChatCompletionContentPartTextParam] - - type: 'null' - title: string | list[OpenAIChatCompletionContentPartTextParam] - description: The content of the model's response. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the assistant message participant. - tool_calls: - anyOf: - - items: - $ref: '#/components/schemas/ChatCompletionMessageToolCall' - type: array - - type: 'null' - description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - additionalProperties: true - type: object - title: OpenAIAssistantMessageParam - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. - OpenAIAssistantMessageParam-Output: - properties: - role: - type: string - title: Role - description: Must be 'assistant' to identify this as the model's response. - enum: - - assistant - content: - anyOf: - - type: string - - items: - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - type: array - title: list[OpenAIChatCompletionContentPartTextParam] - - type: 'null' - title: string | list[OpenAIChatCompletionContentPartTextParam] - description: The content of the model's response. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the assistant message participant. - tool_calls: - anyOf: - - items: - $ref: '#/components/schemas/ChatCompletionMessageToolCall' - type: array - - type: 'null' - description: List of tool calls. Each tool call is an OpenAIChatCompletionToolCall object. - additionalProperties: true - type: object - title: OpenAIAssistantMessageParam - description: A message containing the model's (assistant) response in an OpenAI-compatible chat completion request. OpenAIAttachFileRequest: properties: file_id: @@ -13441,283 +13232,49 @@ components: server_label: type: string title: Server Label - type: - type: string - title: Type - enum: - - mcp - name: - anyOf: - - type: string - - type: 'null' - type: object - required: - - server_label - title: OpenAIResponseInputToolChoiceMCPTool - description: Forces the model to call a specific tool on a remote MCP server - OpenAIResponseInputToolChoiceMode: - type: string - enum: - - auto - - required - - none - title: OpenAIResponseInputToolChoiceMode - description: Enumeration of simple tool choice modes for response generation. - OpenAIResponseInputToolChoiceWebSearch: - properties: - type: - anyOf: - - type: string - enum: - - web_search - - type: string - enum: - - web_search_preview - - type: string - enum: - - web_search_preview_2025_03_11 - - type: string - enum: - - web_search_2025_08_26 - title: string - default: web_search - type: object - title: OpenAIResponseInputToolChoiceWebSearch - description: Indicates that the model should use web search to generate a response - OpenAIResponseMessage-Input: - properties: - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentImage' - title: OpenAIResponseInputMessageContentImage - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' - title: OpenAIResponseInputMessageContentFile - discriminator: - propertyName: type - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile - type: array - title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Input' - title: OpenAIResponseOutputMessageContentOutputText-Input - - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseContentPartRefusal - discriminator: - propertyName: type - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Input' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal - type: array - title: list[OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal] - title: string | list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] | list[OpenAIResponseOutputMessageContentOutputText-Input | OpenAIResponseContentPartRefusal] - role: - anyOf: - - type: string - enum: - - system - - type: string - enum: - - developer - - type: string - enum: - - user - - type: string - enum: - - assistant - title: string - type: - type: string - title: Type - enum: - - message - id: - anyOf: - - type: string - - type: 'null' - status: - anyOf: - - type: string - - type: 'null' - type: object - required: - - content - - role - title: OpenAIResponseMessage - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. - OpenAIResponseMessage-Output: - properties: - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentImage' - title: OpenAIResponseInputMessageContentImage - - $ref: '#/components/schemas/OpenAIResponseInputMessageContentFile' - title: OpenAIResponseInputMessageContentFile - discriminator: - propertyName: type - mapping: - input_file: '#/components/schemas/OpenAIResponseInputMessageContentFile' - input_image: '#/components/schemas/OpenAIResponseInputMessageContentImage' - input_text: '#/components/schemas/OpenAIResponseInputMessageContentText' - title: OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile - type: array - title: list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Output' - title: OpenAIResponseOutputMessageContentOutputText-Output - - $ref: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseContentPartRefusal - discriminator: - propertyName: type - mapping: - output_text: '#/components/schemas/OpenAIResponseOutputMessageContentOutputText-Output' - refusal: '#/components/schemas/OpenAIResponseContentPartRefusal' - title: OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal - type: array - title: list[OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal] - title: string | list[OpenAIResponseInputMessageContentText | OpenAIResponseInputMessageContentImage | OpenAIResponseInputMessageContentFile] | list[OpenAIResponseOutputMessageContentOutputText-Output | OpenAIResponseContentPartRefusal] - role: - anyOf: - - type: string - enum: - - system - - type: string - enum: - - developer - - type: string - enum: - - user - - type: string - enum: - - assistant - title: string - type: - type: string - title: Type - enum: - - message - id: - anyOf: - - type: string - - type: 'null' - status: - anyOf: - - type: string - - type: 'null' - type: object - required: - - content - - role - title: OpenAIResponseMessage - description: |- - Corresponds to the various Message types in the Responses API. - They are all under one type because the Responses API gives them all - the same "type" value, and there is no way to tell them apart in certain - scenarios. - OpenAIResponseOutputMessageContentOutputText-Input: - properties: - text: - type: string - title: Text - type: - type: string - title: Type - enum: - - output_text - annotations: - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - title: OpenAIResponseAnnotationFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - title: OpenAIResponseAnnotationContainerFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' - title: OpenAIResponseAnnotationFilePath - discriminator: - propertyName: type - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - type: array - title: Annotations - logprobs: - anyOf: - - items: - $ref: '#/components/schemas/OpenAITokenLogProb' - type: array - - type: 'null' - type: object - required: - - text - title: OpenAIResponseOutputMessageContentOutputText - description: Text content within an output message of an OpenAI response. - OpenAIResponseOutputMessageContentOutputText-Output: - properties: - text: - type: string - title: Text - type: - type: string - title: Type - enum: - - output_text - annotations: - items: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - title: OpenAIResponseAnnotationFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - title: OpenAIResponseAnnotationContainerFileCitation - - $ref: '#/components/schemas/OpenAIResponseAnnotationFilePath' - title: OpenAIResponseAnnotationFilePath - discriminator: - propertyName: type - mapping: - container_file_citation: '#/components/schemas/OpenAIResponseAnnotationContainerFileCitation' - file_citation: '#/components/schemas/OpenAIResponseAnnotationFileCitation' - file_path: '#/components/schemas/OpenAIResponseAnnotationFilePath' - url_citation: '#/components/schemas/OpenAIResponseAnnotationCitation' - title: OpenAIResponseAnnotationFileCitation | ... (4 variants) - type: array - title: Annotations - logprobs: + type: + type: string + title: Type + enum: + - mcp + name: anyOf: - - items: - $ref: '#/components/schemas/OpenAITokenLogProb' - type: array + - type: string - type: 'null' type: object required: - - text - title: OpenAIResponseOutputMessageContentOutputText - description: Text content within an output message of an OpenAI response. + - server_label + title: OpenAIResponseInputToolChoiceMCPTool + description: Forces the model to call a specific tool on a remote MCP server + OpenAIResponseInputToolChoiceMode: + type: string + enum: + - auto + - required + - none + title: OpenAIResponseInputToolChoiceMode + description: Enumeration of simple tool choice modes for response generation. + OpenAIResponseInputToolChoiceWebSearch: + properties: + type: + anyOf: + - type: string + enum: + - web_search + - type: string + enum: + - web_search_preview + - type: string + enum: + - web_search_preview_2025_03_11 + - type: string + enum: + - web_search_2025_08_26 + title: string + default: web_search + type: object + title: OpenAIResponseInputToolChoiceWebSearch + description: Indicates that the model should use web search to generate a response OpenAIResponseOutputMessageFileSearchToolCallResults: properties: attributes: @@ -13819,64 +13376,6 @@ components: - text title: OpenAIResponseOutputMessageReasoningSummary description: A summary of reasoning output from the model. - OpenAIResponseOutputMessageWebSearchToolCall-Input: - properties: - id: - type: string - title: Id - status: - type: string - title: Status - type: - type: string - title: Type - enum: - - web_search_call - action: - anyOf: - - $ref: '#/components/schemas/WebSearchActionSearch' - title: WebSearchActionSearch - - $ref: '#/components/schemas/WebSearchActionOpenPage' - title: WebSearchActionOpenPage - - $ref: '#/components/schemas/WebSearchActionFind' - title: WebSearchActionFind - - type: 'null' - title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - type: object - required: - - id - - status - title: OpenAIResponseOutputMessageWebSearchToolCall - description: Web search tool call output message for OpenAI responses. - OpenAIResponseOutputMessageWebSearchToolCall-Output: - properties: - id: - type: string - title: Id - status: - type: string - title: Status - type: - type: string - title: Type - enum: - - web_search_call - action: - anyOf: - - $ref: '#/components/schemas/WebSearchActionSearch' - title: WebSearchActionSearch - - $ref: '#/components/schemas/WebSearchActionOpenPage' - title: WebSearchActionOpenPage - - $ref: '#/components/schemas/WebSearchActionFind' - title: WebSearchActionFind - - type: 'null' - title: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind - type: object - required: - - id - - status - title: OpenAIResponseOutputMessageWebSearchToolCall - description: Web search tool call output message for OpenAI responses. OpenAIResponseReasoning: properties: effort: @@ -14051,86 +13550,6 @@ components: type: object title: OpenAIUpdateVectorStoreRequest description: Request body for updating a vector store. - OpenAIUserMessageParam-Input: - properties: - role: - type: string - title: Role - description: Must be 'user' to identify this as a user message. - enum: - - user - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - title: OpenAIChatCompletionContentPartImageParam - - $ref: '#/components/schemas/OpenAIFile' - title: OpenAIFile - discriminator: - propertyName: type - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile - type: array - title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the user message participant. - type: object - required: - - content - title: OpenAIUserMessageParam - description: A message from the user in an OpenAI-compatible chat completion request. - OpenAIUserMessageParam-Output: - properties: - role: - type: string - title: Role - description: Must be 'user' to identify this as a user message. - enum: - - user - content: - anyOf: - - type: string - - items: - oneOf: - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam - - $ref: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - title: OpenAIChatCompletionContentPartImageParam - - $ref: '#/components/schemas/OpenAIFile' - title: OpenAIFile - discriminator: - propertyName: type - mapping: - file: '#/components/schemas/OpenAIFile' - image_url: '#/components/schemas/OpenAIChatCompletionContentPartImageParam' - text: '#/components/schemas/OpenAIChatCompletionContentPartTextParam' - title: OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile - type: array - title: list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - title: string | list[OpenAIChatCompletionContentPartTextParam | OpenAIChatCompletionContentPartImageParam | OpenAIFile] - description: The content of the message, which can include text and other media. - name: - anyOf: - - type: string - - type: 'null' - description: The name of the user message participant. - type: object - required: - - content - title: OpenAIUserMessageParam - description: A message from the user in an OpenAI-compatible chat completion request. OutputTokensDetails: properties: reasoning_tokens: @@ -16126,69 +15545,6 @@ components: - completion_id title: ListChatCompletionMessagesRequest type: object - EmbeddedChunk: - description: |- - A chunk of content with its embedding vector for vector database operations. - Inherits all fields from Chunk and adds embedding-related fields. - properties: - content: - anyOf: - - type: string - - discriminator: - mapping: - image: '#/components/schemas/ImageContentItem' - text: '#/components/schemas/TextContentItem' - propertyName: type - oneOf: - - $ref: '#/components/schemas/ImageContentItem' - title: ImageContentItem - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - title: ImageContentItem | TextContentItem - - items: - discriminator: - mapping: - image: '#/components/schemas/ImageContentItem' - text: '#/components/schemas/TextContentItem' - propertyName: type - oneOf: - - $ref: '#/components/schemas/ImageContentItem' - title: ImageContentItem - - $ref: '#/components/schemas/TextContentItem' - title: TextContentItem - title: ImageContentItem | TextContentItem - type: array - title: list[ImageContentItem | TextContentItem] - title: string | list[ImageContentItem | TextContentItem] - chunk_id: - title: Chunk Id - type: string - metadata: - additionalProperties: true - title: Metadata - type: object - chunk_metadata: - $ref: '#/components/schemas/ChunkMetadata' - embedding: - items: - type: number - title: Embedding - type: array - embedding_model: - title: Embedding Model - type: string - embedding_dimension: - title: Embedding Dimension - type: integer - required: - - content - - chunk_id - - chunk_metadata - - embedding - - embedding_model - - embedding_dimension - title: EmbeddedChunk - type: object VectorStoreCreateRequest: description: Request to create a vector store. properties: @@ -17560,10 +16916,10 @@ components: OpenAIResponseMessageOutputUnion: anyOf: - oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -17584,11 +16940,11 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' x-stainless-naming: OpenAIResponseMessageOutputOneOf - title: OpenAIResponseMessage-Output | ... (8 variants) + title: OpenAIResponseMessage | ... (8 variants) - $ref: '#/components/schemas/OpenAIResponseInputFunctionToolCallOutput' title: OpenAIResponseInputFunctionToolCallOutput - $ref: '#/components/schemas/OpenAIResponseMCPApprovalResponse' @@ -17599,10 +16955,10 @@ components: x-stainless-naming: OpenAIResponseMessageOutputUnion OpenAIResponseOutputItem: oneOf: - - $ref: '#/components/schemas/OpenAIResponseMessage-Output' - title: OpenAIResponseMessage-Output - - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' - title: OpenAIResponseOutputMessageWebSearchToolCall-Output + - $ref: '#/components/schemas/OpenAIResponseMessage' + title: OpenAIResponseMessage + - $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' + title: OpenAIResponseOutputMessageWebSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall' title: OpenAIResponseOutputMessageFileSearchToolCall - $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall' @@ -17623,11 +16979,11 @@ components: mcp_approval_request: '#/components/schemas/OpenAIResponseMCPApprovalRequest' mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall' mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools' - message: '#/components/schemas/OpenAIResponseMessage-Output' + message: '#/components/schemas/OpenAIResponseMessage' reasoning: '#/components/schemas/OpenAIResponseOutputMessageReasoningItem' - web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall-Output' + web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall' x-stainless-naming: OpenAIResponseOutputItem - title: OpenAIResponseMessage-Output | ... (8 variants) + title: OpenAIResponseMessage | ... (8 variants) ChatCompletionMessageToolCall: properties: id: diff --git a/pyproject.toml b/pyproject.toml index e941dc4e43e..0fc28aeeac1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -126,6 +126,7 @@ starter = [ "torch", "tqdm", "tree_sitter", + "unstructured-client>=0.25.0", "weaviate-client>=4.16.5", ] @@ -211,6 +212,7 @@ unit = [ "ollama", "sqlite-vec", "together", + "unstructured-client>=0.25.0", ] # These are the core dependencies required for running integration tests. They are shared across all # providers. If a provider requires additional dependencies, please add them to your environment @@ -538,6 +540,7 @@ module = [ "docling.*", "docling_core.*", "unstructured.*", + "unstructured_client.*", ] ignore_missing_imports = true diff --git a/src/ogx/providers/registry/file_processors.py b/src/ogx/providers/registry/file_processors.py index b39f0d9dae4..5cf7625b61f 100644 --- a/src/ogx/providers/registry/file_processors.py +++ b/src/ogx/providers/registry/file_processors.py @@ -311,6 +311,78 @@ def available_providers() -> list[ProviderSpec]: ## Documentation See [Docling Serve's documentation](https://github.com/docling-project/docling-serve/blob/main/docs/README.md) for more details on setup and configuration. +""", + ), + RemoteProviderSpec( + api=Api.file_processors, + provider_type="remote::unstructured-api", + adapter_type="unstructured-api", + pip_packages=[ + "unstructured-client>=0.25.0", # >=0.25.0: supports full feature set (chunking + split_pdf_page_range) + ], + module="ogx.providers.remote.file_processor.unstructured_api", + config_class="ogx.providers.remote.file_processor.unstructured_api.UnstructuredApiFileProcessorConfig", + api_dependencies=[Api.files], + description=""" +[Unstructured.io](https://unstructured.io) is a multi-format document parser that supports 65+ file types +including emails (EML/MSG), legacy documents, presentations, spreadsheets, and more. This provider uses +the Unstructured.io SaaS API for cloud-based document processing with advanced table and image detection. + +## Supported Formats + +- **Documents**: PDF, DOC, DOCX, PPTX, XLSX, ODT, RTF, EPUB +- **Email**: EML, MSG (unique capability) +- **Web**: HTML, Markdown, XML, JSON +- **Images**: PNG, JPG, TIFF (with OCR) +- **Text**: TXT, CSV +- **65+ formats total** — see [Unstructured format support](https://docs.unstructured.io/pipelines/supported-file-types) + +## Features + +- **Multi-format support** — 65+ file types including email formats (EML/MSG) +- **Cloud-based processing** — no local dependencies or system requirements +- **Table detection** — extracts tables with structure preservation +- **Image detection** — identifies and extracts image elements +- **SOC2/HIPAA/GDPR certified** — suitable for regulated industries + +## Usage + +Get an API key from [Unstructured.io](https://unstructured.io) (free tier available), then start OGX: + +```bash +UNSTRUCTURED_API_KEY=your-api-key ogx stack run \\ + --providers "file_processors=remote::unstructured-api,files=inline::localfs,vector_io=inline::faiss,inference=inline::sentence-transformers,inference=remote::ollama" \\ + --port 8321 +``` + +Or add it to a custom `run.yaml`: + +```yaml +file_processors: + - provider_id: unstructured + provider_type: remote::unstructured-api + config: + api_key: ${env.UNSTRUCTURED_API_KEY} +``` + +## When to Use + +- **Diverse formats**: Need to process emails, legacy documents, or 10+ different file types +- **Managed service**: Want zero setup and no system dependencies +- **Compliance**: Require SOC2/HIPAA/GDPR certified processing +- **Email RAG**: Building customer support or communication archive applications + +For faster processing with fewer formats, use `inline::docling` instead. + +## Performance + +- Processing speed: ~1-2 seconds per page +- Best for: Documents <100 pages +- Cost: ~$0.01 per page (verify current pricing with Unstructured.io) + +## Documentation + +See [Unstructured.io documentation](https://docs.unstructured.io) for API details and format support. """, ), ] diff --git a/src/ogx/providers/remote/file_processor/unstructured_api/__init__.py b/src/ogx/providers/remote/file_processor/unstructured_api/__init__.py new file mode 100644 index 00000000000..37827602cde --- /dev/null +++ b/src/ogx/providers/remote/file_processor/unstructured_api/__init__.py @@ -0,0 +1,29 @@ +# Copyright (c) The OGX Contributors. +# All rights reserved. +# +# This source code is licensed under the terms described in the LICENSE file in +# the root directory of this source tree. + +from typing import Any + +from ogx_api import Api + +from .config import UnstructuredApiFileProcessorConfig + + +async def get_adapter_impl(config: UnstructuredApiFileProcessorConfig, deps: dict[Api, Any]): + from .unstructured_api import UnstructuredApiFileProcessor + + assert isinstance(config, UnstructuredApiFileProcessorConfig), f"Unexpected config type: {type(config)}" + + files_api = deps.get(Api.files) + if files_api is None: + raise ValueError( + "Failed to find required dependency: files API is required for unstructured-api file processor" + ) + + impl = UnstructuredApiFileProcessor(config, files_api) + return impl + + +__all__ = ["UnstructuredApiFileProcessorConfig", "get_adapter_impl"] diff --git a/src/ogx/providers/remote/file_processor/unstructured_api/config.py b/src/ogx/providers/remote/file_processor/unstructured_api/config.py new file mode 100644 index 00000000000..e1d98fc47e1 --- /dev/null +++ b/src/ogx/providers/remote/file_processor/unstructured_api/config.py @@ -0,0 +1,31 @@ +# Copyright (c) The OGX Contributors. +# All rights reserved. +# +# This source code is licensed under the terms described in the LICENSE file in +# the root directory of this source tree. + +from typing import Any + +from pydantic import BaseModel, Field, SecretStr + +from ogx_api.vector_io import VectorStoreChunkingStrategyStaticConfig + + +class UnstructuredApiFileProcessorConfig(BaseModel): + """Configuration for Unstructured.io API file processor.""" + + api_key: SecretStr = Field( + description="API key for authenticating with Unstructured.io SaaS API (get one from https://unstructured.io)" + ) + default_chunk_size_tokens: int = Field( + default=VectorStoreChunkingStrategyStaticConfig.model_fields["max_chunk_size_tokens"].default, + ge=100, + le=4096, + description="Default chunk size in tokens when chunking_strategy type is 'auto'", + ) + + @classmethod + def sample_run_config(cls, **kwargs: Any) -> dict[str, Any]: + return { + "api_key": "${env.UNSTRUCTURED_API_KEY}", + } diff --git a/src/ogx/providers/remote/file_processor/unstructured_api/unstructured_api.py b/src/ogx/providers/remote/file_processor/unstructured_api/unstructured_api.py new file mode 100644 index 00000000000..bc4dedb028b --- /dev/null +++ b/src/ogx/providers/remote/file_processor/unstructured_api/unstructured_api.py @@ -0,0 +1,271 @@ +# Copyright (c) The OGX Contributors. +# All rights reserved. +# +# This source code is licensed under the terms described in the LICENSE file in +# the root directory of this source tree. + +import time +import uuid +from typing import Any + +from fastapi import UploadFile +from unstructured_client import UnstructuredClient +from unstructured_client.models import operations, shared + +from ogx.log import get_logger +from ogx.providers.utils.files.response import response_body_bytes +from ogx.providers.utils.vector_io.vector_utils import generate_chunk_id +from ogx_api.file_processors import ProcessFileRequest, ProcessFileResponse +from ogx_api.files import Files, RetrieveFileContentRequest, RetrieveFileRequest +from ogx_api.vector_io import ( + Chunk, + ChunkMetadata, + VectorStoreChunkingStrategy, +) + +from .config import UnstructuredApiFileProcessorConfig + +log = get_logger(name=__name__, category="providers::file_processors") + + +class UnstructuredApiFileProcessor: + """Remote file processor that uses Unstructured.io SaaS API. + + Supports 65+ file formats including PDF, DOCX, PPTX, XLSX, EML, MSG, HTML, + Markdown, and more. Uses the Unstructured.io cloud service for document + parsing with advanced table and image detection. + """ + + def __init__(self, config: UnstructuredApiFileProcessorConfig, files_api: Files) -> None: + self.config = config + self.files_api = files_api + + async def process_file( + self, + request: ProcessFileRequest, + file: UploadFile | None = None, + ) -> ProcessFileResponse: + """Process a file using Unstructured.io API and return chunks.""" + file_id = request.file_id + chunking_strategy = request.chunking_strategy + + if not file and not file_id: + raise ValueError("Either file or file_id must be provided") + if file and file_id: + raise ValueError("Cannot provide both file and file_id") + + start_time = time.time() + + # Get file content and metadata + if file: + content = await file.read() + filename = file.filename or "upload" + elif file_id: + file_info = await self.files_api.openai_retrieve_file(RetrieveFileRequest(file_id=file_id)) + filename = file_info.filename + + content_response = await self.files_api.openai_retrieve_file_content( + RetrieveFileContentRequest(file_id=file_id) + ) + content = await response_body_bytes(content_response) + + document_id = file_id if file_id else str(uuid.uuid4()) + document_metadata: dict[str, Any] = {"filename": filename} + if file_id: + document_metadata["file_id"] = file_id + + # Create client and build request + client = UnstructuredClient(api_key_auth=self.config.api_key.get_secret_value()) + + if chunking_strategy: + log.debug("Using chunking strategy", strategy_type=chunking_strategy.type) + partition_request = self._make_request_with_chunking(content, filename, chunking_strategy) + else: + log.debug("No chunking strategy - using element-level chunks") + partition_request = self._make_request(content, filename) + + # Call API + elements = await self._partition(client, partition_request, filename) + + # Convert elements to chunks + chunks = self._elements_to_chunks(elements, document_id, document_metadata) + + processing_time_ms = int((time.time() - start_time) * 1000) + + response_metadata: dict[str, Any] = { + "processor": "unstructured-api", + "processing_time_ms": processing_time_ms, + "extraction_method": "unstructured-api", + "file_size_bytes": len(content), + "total_elements": len(elements), + } + + return ProcessFileResponse(chunks=chunks, metadata=response_metadata) + + def _make_request(self, content: bytes, filename: str) -> operations.PartitionRequest: + """Make partition request without chunking. + + Args: + content: File content as bytes + filename: Original filename (used for format detection) + + Returns: + PartitionRequest object for API call + """ + return operations.PartitionRequest( + partition_parameters=shared.PartitionParameters( + files=shared.Files( + content=content, + file_name=filename, + ), + strategy=shared.Strategy.AUTO, + ) + ) + + def _make_request_with_chunking( + self, + content: bytes, + filename: str, + chunking_strategy: VectorStoreChunkingStrategy, + ) -> operations.PartitionRequest: + """Make partition request with chunking enabled. + + Args: + content: File content as bytes + filename: Original filename (used for format detection) + chunking_strategy: Chunking configuration from request + + Returns: + PartitionRequest object for API call with chunking parameters + """ + # Determine max_tokens based on strategy + if chunking_strategy.type == "auto": + max_tokens = self.config.default_chunk_size_tokens + elif chunking_strategy.type == "static": + max_tokens = chunking_strategy.static.max_chunk_size_tokens + else: + max_tokens = self.config.default_chunk_size_tokens + + # Convert tokens to characters (rough estimate: 1 token ≈ 4 characters) + max_characters = max_tokens * 4 + + return operations.PartitionRequest( + partition_parameters=shared.PartitionParameters( + files=shared.Files( + content=content, + file_name=filename, + ), + strategy=shared.Strategy.AUTO, + chunking_strategy="by_title", + max_characters=max_characters, + ) + ) + + async def _partition( + self, + client: UnstructuredClient, + request: operations.PartitionRequest, + filename: str, + ) -> list[dict[str, Any]]: + """Call Unstructured.io API to partition the document. + + Args: + client: Unstructured API client + request: Partition request with parameters + filename: Original filename (for logging) + + Returns: + List of element dictionaries from Unstructured API + + Raises: + Exception: If API call fails + """ + log.debug("Calling Unstructured.io API", filename=filename) + + resp = await client.general.partition_async(request=request) + + if not resp.elements: + log.warning("Unstructured.io API returned no elements", filename=filename) + return [] + + log.debug( + "Unstructured.io API returned elements", + filename=filename, + element_count=len(resp.elements), + ) + + return [dict(elem) for elem in resp.elements] + + # element mapping to chunk with metadata, including generating chunk_id and calculating token count + def _elements_to_chunks( + self, + elements: list[dict[str, Any]], + document_id: str, + document_metadata: dict[str, Any], + ) -> list[Chunk]: + """Convert Unstructured elements to OGX Chunks. + + Args: + elements: List of element dicts from Unstructured API + document_id: Document ID for this file + document_metadata: Base metadata for all chunks + + Returns: + List of OGX Chunk objects + """ + chunks = [] + + for idx, element in enumerate(elements): + # Extract text content + text = element.get("text", "") + + # Skip empty elements + if not text or not text.strip(): + continue + + # Get metadata + elem_metadata = element.get("metadata", {}) + page_number = elem_metadata.get("page_number") + element_type = element.get("type", "Unknown") + + # Generate chunk_id from content and position + chunk_id = generate_chunk_id(document_id, text, str(idx)) + + # Calculate token count (rough estimate: split on whitespace) for num words in text + content_token_count = len(text.split()) + + # Build metadata dict + metadata_dict: dict[str, Any] = { + "document_id": document_id, + "element_type": element_type, + "element_index": idx, + **document_metadata, + } + if page_number is not None: + metadata_dict["page_number"] = page_number + + chunk = Chunk( + content=text, + chunk_id=chunk_id, + metadata=metadata_dict, + chunk_metadata=ChunkMetadata( + chunk_id=chunk_id, + document_id=document_id, + source=document_metadata.get("filename", ""), + content_token_count=content_token_count, + ), + ) + + chunks.append(chunk) + + log.debug( + "Converted elements to chunks", + total_elements=len(elements), + total_chunks=len(chunks), + skipped=len(elements) - len(chunks), + ) + + return chunks + + async def shutdown(self) -> None: + pass diff --git a/tests/unit/providers/file_processor/test_unstructured_api.py b/tests/unit/providers/file_processor/test_unstructured_api.py new file mode 100644 index 00000000000..76d8386c852 --- /dev/null +++ b/tests/unit/providers/file_processor/test_unstructured_api.py @@ -0,0 +1,473 @@ +# Copyright (c) The OGX Contributors. +# All rights reserved. +# +# This source code is licensed under the terms described in the LICENSE file in +# the root directory of this source tree. + +import io +import uuid +from types import SimpleNamespace +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest +from fastapi import UploadFile +from pydantic import SecretStr + +from ogx.providers.remote.file_processor.unstructured_api.config import UnstructuredApiFileProcessorConfig +from ogx.providers.remote.file_processor.unstructured_api.unstructured_api import UnstructuredApiFileProcessor +from ogx_api.file_processors import ProcessFileRequest + +# Mock Unstructured API response +MOCK_ELEMENTS = [ + { + "type": "Title", + "text": "Introduction to Machine Learning", + "metadata": {"page_number": 1, "filename": "test.pdf"}, + }, + { + "type": "NarrativeText", + "text": "Machine learning is a subset of artificial intelligence.", + "metadata": {"page_number": 1, "filename": "test.pdf"}, + }, + { + "type": "ListItem", + "text": "Supervised Learning", + "metadata": {"page_number": 2, "filename": "test.pdf"}, + }, + { + "type": "Table", + "text": "Column1 | Column2\nData1 | Data2", + "metadata": {"page_number": 3, "filename": "test.pdf"}, + }, + { + "type": "NarrativeText", + "text": "", # Empty element - should be skipped + "metadata": {"page_number": 3, "filename": "test.pdf"}, + }, +] + + +class TestUnstructuredApiFileProcessor: + @pytest.fixture + def config(self) -> UnstructuredApiFileProcessorConfig: + return UnstructuredApiFileProcessorConfig( + api_key=SecretStr("test-api-key-123"), + default_chunk_size_tokens=800, + ) + + @pytest.fixture + def files_api(self) -> AsyncMock: + return AsyncMock() + + @pytest.fixture + def processor( + self, config: UnstructuredApiFileProcessorConfig, files_api: AsyncMock + ) -> UnstructuredApiFileProcessor: + return UnstructuredApiFileProcessor(config, files_api=files_api) + + @pytest.fixture + def upload_file(self) -> UploadFile: + return UploadFile(file=io.BytesIO(b"%PDF-fake-content"), filename="test.pdf") + + # -- input validation -- + + async def test_rejects_no_file_and_no_file_id(self, processor: UnstructuredApiFileProcessor): + request = ProcessFileRequest() + with pytest.raises(ValueError, match="Either file or file_id must be provided"): + await processor.process_file(request) + + async def test_rejects_both_file_and_file_id( + self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile + ): + request = ProcessFileRequest(file_id="file-123") + with pytest.raises(ValueError, match="Cannot provide both file and file_id"): + await processor.process_file(request, file=upload_file) + + # -- process file with mock API -- + + async def test_process_file_success(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + request = ProcessFileRequest() + + # Mock the Unstructured API client + mock_response = MagicMock() + mock_response.elements = MOCK_ELEMENTS + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + mock_client.general.partition_async = AsyncMock(return_value=mock_response) + mock_client_class.return_value = mock_client + + response = await processor.process_file(request, file=upload_file) + + # Verify API was called + mock_client.general.partition_async.assert_called_once() + + # Verify response structure + assert len(response.chunks) == 4 # 5 elements, but 1 is empty and skipped + assert response.metadata["processor"] == "unstructured-api" + assert response.metadata["extraction_method"] == "unstructured-api" + assert "processing_time_ms" in response.metadata + assert response.metadata["total_elements"] == 5 + assert response.metadata["file_size_bytes"] == len(b"%PDF-fake-content") + + async def test_element_types_preserved(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + request = ProcessFileRequest() + mock_response = MagicMock() + mock_response.elements = MOCK_ELEMENTS + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + mock_client.general.partition_async = AsyncMock(return_value=mock_response) + mock_client_class.return_value = mock_client + + response = await processor.process_file(request, file=upload_file) + + # Check element types are preserved + element_types = [chunk.metadata["element_type"] for chunk in response.chunks] + assert "Title" in element_types + assert "NarrativeText" in element_types + assert "ListItem" in element_types + assert "Table" in element_types + + async def test_empty_elements_skipped(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + request = ProcessFileRequest() + mock_response = MagicMock() + mock_response.elements = MOCK_ELEMENTS + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + mock_client.general.partition_async = AsyncMock(return_value=mock_response) + mock_client_class.return_value = mock_client + + response = await processor.process_file(request, file=upload_file) + + # Should skip the empty element + assert len(response.chunks) == 4 + assert all(chunk.content.strip() for chunk in response.chunks) + + # -- chunk metadata mapping -- + + async def test_chunk_metadata_fields(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + request = ProcessFileRequest() + mock_response = MagicMock() + mock_response.elements = MOCK_ELEMENTS[:1] # Just first element + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + mock_client.general.partition_async = AsyncMock(return_value=mock_response) + mock_client_class.return_value = mock_client + + response = await processor.process_file(request, file=upload_file) + + chunk = response.chunks[0] + + # Verify metadata fields + uuid.UUID(chunk.metadata["document_id"]) + assert chunk.metadata["filename"] == "test.pdf" + assert chunk.metadata["element_type"] == "Title" + assert chunk.metadata["element_index"] == 0 + assert chunk.metadata["page_number"] == 1 + + # Verify chunk_metadata + assert chunk.chunk_id == chunk.chunk_metadata.chunk_id + assert chunk.chunk_metadata.document_id == chunk.metadata["document_id"] + assert chunk.chunk_metadata.source == "test.pdf" + assert chunk.chunk_metadata.content_token_count > 0 + + async def test_chunk_id_uniqueness(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + request = ProcessFileRequest() + mock_response = MagicMock() + mock_response.elements = MOCK_ELEMENTS + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + mock_client.general.partition_async = AsyncMock(return_value=mock_response) + mock_client_class.return_value = mock_client + + response = await processor.process_file(request, file=upload_file) + + # All chunk IDs should be unique + ids = [c.chunk_id for c in response.chunks] + assert len(ids) == len(set(ids)) + + async def test_page_numbers_preserved(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + request = ProcessFileRequest() + mock_response = MagicMock() + mock_response.elements = MOCK_ELEMENTS + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + mock_client.general.partition_async = AsyncMock(return_value=mock_response) + mock_client_class.return_value = mock_client + + response = await processor.process_file(request, file=upload_file) + + # Check page numbers + page_numbers = [chunk.metadata.get("page_number") for chunk in response.chunks] + assert 1 in page_numbers + assert 2 in page_numbers + assert 3 in page_numbers + + async def test_token_count_calculated(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + request = ProcessFileRequest() + mock_response = MagicMock() + mock_response.elements = MOCK_ELEMENTS[:1] + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + mock_client.general.partition_async = AsyncMock(return_value=mock_response) + mock_client_class.return_value = mock_client + + response = await processor.process_file(request, file=upload_file) + + chunk = response.chunks[0] + # "Introduction to Machine Learning" = 4 tokens (whitespace split) + assert chunk.chunk_metadata.content_token_count == 4 + + # -- file_id path -- + + async def test_process_file_via_file_id(self, config: UnstructuredApiFileProcessorConfig): + files_api = AsyncMock() + files_api.openai_retrieve_file.return_value = SimpleNamespace(filename="report.pdf") + files_api.openai_retrieve_file_content.return_value = SimpleNamespace(body=b"%PDF-fake") + + processor = UnstructuredApiFileProcessor(config, files_api=files_api) + request = ProcessFileRequest(file_id="file-abc") + + mock_response = MagicMock() + mock_response.elements = MOCK_ELEMENTS[:1] + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + mock_client.general.partition_async = AsyncMock(return_value=mock_response) + mock_client_class.return_value = mock_client + + response = await processor.process_file(request) + + files_api.openai_retrieve_file.assert_awaited_once() + files_api.openai_retrieve_file_content.assert_awaited_once() + assert response.chunks[0].metadata["filename"] == "report.pdf" + assert response.chunks[0].metadata["file_id"] == "file-abc" + assert response.chunks[0].metadata["document_id"] == "file-abc" + + # -- API key authentication -- + + async def test_api_key_used(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + request = ProcessFileRequest() + mock_response = MagicMock() + mock_response.elements = MOCK_ELEMENTS[:1] + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + mock_client.general.partition_async = AsyncMock(return_value=mock_response) + mock_client_class.return_value = mock_client + + await processor.process_file(request, file=upload_file) + + # Verify client was initialized with API key + mock_client_class.assert_called_once_with(api_key_auth="test-api-key-123") + + # -- chunking strategy tests -- + + async def test_process_file_auto_chunking(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + """Test processing with auto chunking strategy.""" + from ogx_api.vector_io import VectorStoreChunkingStrategyAuto + + request = ProcessFileRequest(chunking_strategy=VectorStoreChunkingStrategyAuto()) + mock_response = MagicMock() + mock_response.elements = MOCK_ELEMENTS + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + mock_client.general.partition_async = AsyncMock(return_value=mock_response) + mock_client_class.return_value = mock_client + + response = await processor.process_file(request, file=upload_file) + + # Verify API was called + mock_client.general.partition_async.assert_called_once() + + # Get the request that was sent to the API + call_args = mock_client.general.partition_async.call_args + partition_request = call_args[1]["request"] + + # Verify by_title chunking strategy is used + assert partition_request.partition_parameters.chunking_strategy == "by_title" + + # Verify max_characters calculated from default_chunk_size_tokens (800 * 4 = 3200) + assert partition_request.partition_parameters.max_characters == 3200 + + # Verify response + assert len(response.chunks) == 4 + assert response.metadata["processor"] == "unstructured-api" + + async def test_process_file_static_chunking(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + """Test processing with static chunking strategy.""" + from ogx_api.vector_io import VectorStoreChunkingStrategyStatic, VectorStoreChunkingStrategyStaticConfig + + static_config = VectorStoreChunkingStrategyStaticConfig(max_chunk_size_tokens=500) + request = ProcessFileRequest(chunking_strategy=VectorStoreChunkingStrategyStatic(static=static_config)) + mock_response = MagicMock() + mock_response.elements = MOCK_ELEMENTS + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + mock_client.general.partition_async = AsyncMock(return_value=mock_response) + mock_client_class.return_value = mock_client + + response = await processor.process_file(request, file=upload_file) + + # Get the request + call_args = mock_client.general.partition_async.call_args + partition_request = call_args[1]["request"] + + # Verify by_title chunking strategy is used + assert partition_request.partition_parameters.chunking_strategy == "by_title" + + # Verify max_characters calculated from static tokens (500 * 4 = 2000) + assert partition_request.partition_parameters.max_characters == 2000 + + assert len(response.chunks) == 4 + + # -- empty response tests -- + + @pytest.mark.parametrize( + "chunking_strategy", + [ + None, # No chunking + pytest.param( + lambda: __import__( + "ogx_api.vector_io", fromlist=["VectorStoreChunkingStrategyAuto"] + ).VectorStoreChunkingStrategyAuto(), + id="with_chunking", + ), + ], + ids=["no_chunking", "with_chunking"], + ) + async def test_empty_api_response( + self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile, chunking_strategy + ): + """Test behavior when API returns no elements (with and without chunking).""" + # Handle lazy-loaded chunking_strategy + if callable(chunking_strategy): + chunking_strategy = chunking_strategy() + + request = ProcessFileRequest(chunking_strategy=chunking_strategy) + + # Mock API to return empty elements list + mock_response = MagicMock() + mock_response.elements = [] # Empty! + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + mock_client.general.partition_async = AsyncMock(return_value=mock_response) + mock_client_class.return_value = mock_client + + response = await processor.process_file(request, file=upload_file) + + # Verify returns empty chunks (doesn't crash) + assert len(response.chunks) == 0 + assert response.metadata["total_elements"] == 0 + assert response.metadata["processor"] == "unstructured-api" + + # -- error handling tests -- + + async def test_api_unauthorized_error(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + """Test handling of 401 unauthorized errors from API.""" + from unstructured_client.models.errors import SDKError + + request = ProcessFileRequest() + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + # Mock API to raise 401 error + mock_response = MagicMock() + mock_response.text = '{"detail":"Unauthorized - invalid API key"}' + mock_client.general.partition_async = AsyncMock( + side_effect=SDKError("API error occurred", mock_response, mock_response.text) + ) + mock_client_class.return_value = mock_client + + # Verify error is raised (not swallowed) + with pytest.raises(SDKError) as exc_info: + await processor.process_file(request, file=upload_file) + + assert "API error occurred" in str(exc_info.value) + + async def test_api_server_error(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + """Test handling of 500 server errors from API.""" + from unstructured_client.models.errors import SDKError + + request = ProcessFileRequest() + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + # Mock API to raise 500 error + mock_response = MagicMock() + mock_response.text = '{"detail":"Internal server error"}' + mock_client.general.partition_async = AsyncMock( + side_effect=SDKError("API error occurred", mock_response, mock_response.text) + ) + mock_client_class.return_value = mock_client + + with pytest.raises(SDKError) as exc_info: + await processor.process_file(request, file=upload_file) + + assert "API error occurred" in str(exc_info.value) + + async def test_api_network_error(self, processor: UnstructuredApiFileProcessor, upload_file: UploadFile): + """Test handling of network/connection errors.""" + import httpx + + request = ProcessFileRequest() + + with patch( + "ogx.providers.remote.file_processor.unstructured_api.unstructured_api.UnstructuredClient" + ) as mock_client_class: + mock_client = MagicMock() + # Mock network failure + mock_client.general.partition_async = AsyncMock(side_effect=httpx.ConnectError("Connection failed")) + mock_client_class.return_value = mock_client + + with pytest.raises(httpx.ConnectError): + await processor.process_file(request, file=upload_file) + + +class TestUnstructuredApiFileProcessorConfig: + def test_default_values(self): + config = UnstructuredApiFileProcessorConfig(api_key=SecretStr("test-key")) + assert config.api_key.get_secret_value() == "test-key" + assert config.default_chunk_size_tokens >= 100 + + def test_sample_run_config(self): + sample = UnstructuredApiFileProcessorConfig.sample_run_config() + assert "api_key" in sample + assert "${env.UNSTRUCTURED_API_KEY}" in sample["api_key"] diff --git a/uv.lock b/uv.lock index 1b09c6059c9..a789a56ebd7 100644 --- a/uv.lock +++ b/uv.lock @@ -63,6 +63,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/46/02ac5e262d4af18054b3e922b2baedbb2a03289ee792162de60a865defc5/accelerate-1.13.0-py3-none-any.whl", hash = "sha256:cf1a3efb96c18f7b152eb0fa7490f3710b19c3f395699358f08decca2b8b62e0", size = 383744, upload-time = "2026-03-04T19:34:10.313Z" }, ] +[[package]] +name = "aiofiles" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/41/c3/534eac40372d8ee36ef40df62ec129bee4fdb5ad9706e58a29be53b2c970/aiofiles-25.1.0.tar.gz", hash = "sha256:a8d728f0a29de45dc521f18f07297428d56992a742f0cd2701ba86e44d23d5b2", size = 46354, upload-time = "2025-10-09T20:51:04.358Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/8a/340a1555ae33d7354dbca4faa54948d76d89a27ceef032c8c3bc661d003e/aiofiles-25.1.0-py3-none-any.whl", hash = "sha256:abe311e527c862958650f9438e859c1fa7568a141b22abcd015e120e86a85695", size = 14668, upload-time = "2025-10-09T20:51:03.174Z" }, +] + [[package]] name = "aiohappyeyeballs" version = "2.6.1" @@ -4060,6 +4069,7 @@ starter = [ { name = "torch", version = "2.12.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, { name = "tqdm" }, { name = "tree-sitter" }, + { name = "unstructured-client" }, { name = "weaviate-client" }, ] @@ -4110,6 +4120,7 @@ dev = [ { name = "together" }, { name = "torch", version = "2.12.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, { name = "torch", version = "2.12.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, + { name = "unstructured-client" }, ] docs = [ { name = "linkify" }, @@ -4226,6 +4237,7 @@ unit = [ { name = "sqlalchemy", extra = ["asyncio"] }, { name = "sqlite-vec" }, { name = "together" }, + { name = "unstructured-client" }, ] [package.metadata] @@ -4296,6 +4308,7 @@ requires-dist = [ { name = "torch", marker = "extra == 'starter'", index = "https://download.pytorch.org/whl/cpu" }, { name = "tqdm", marker = "extra == 'starter'" }, { name = "tree-sitter", marker = "extra == 'starter'" }, + { name = "unstructured-client", marker = "extra == 'starter'", specifier = ">=0.25.0" }, { name = "uvicorn", specifier = ">=0.34.0" }, { name = "weaviate-client", marker = "extra == 'starter'", specifier = ">=4.16.5" }, { name = "websockets", specifier = ">=14.0" }, @@ -4347,6 +4360,7 @@ dev = [ { name = "sqlite-vec" }, { name = "together" }, { name = "torch", specifier = ">=2.6.0", index = "https://download.pytorch.org/whl/cpu" }, + { name = "unstructured-client", specifier = ">=0.25.0" }, ] docs = [ { name = "linkify" }, @@ -4460,6 +4474,7 @@ unit = [ { name = "sqlalchemy", extras = ["asyncio"], specifier = ">=2.0.41" }, { name = "sqlite-vec" }, { name = "together" }, + { name = "unstructured-client", specifier = ">=0.25.0" }, ] [[package]] @@ -5677,7 +5692,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.11.10" +version = "2.13.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -5685,51 +5700,84 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/54/ecab642b3bed45f7d5f59b38443dcb36ef50f85af192e6ece103dbfe9587/pydantic-2.11.10.tar.gz", hash = "sha256:dc280f0982fbda6c38fada4e476dc0a4f3aeaf9c6ad4c28df68a666ec3c61423", size = 788494, upload-time = "2025-10-04T10:40:41.338Z" } +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/1f/73c53fcbfb0b5a78f91176df41945ca466e71e9d9d836e5c522abda39ee7/pydantic-2.11.10-py3-none-any.whl", hash = "sha256:802a655709d49bd004c31e865ef37da30b540786a46bfce02333e0e24b5fe29a", size = 444823, upload-time = "2025-10-04T10:40:39.055Z" }, + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, ] [[package]] name = "pydantic-core" -version = "2.33.2" +version = "2.46.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" }, - { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" }, - { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" }, - { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" }, - { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" }, - { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" }, - { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" }, - { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" }, - { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" }, - { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" }, - { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" }, - { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" }, - { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" }, - { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, - { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, - { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, - { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, - { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, - { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, - { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, - { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, - { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, - { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, - { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, - { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, - { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, - { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, - { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, - { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, - { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" }, + { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" }, + { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" }, + { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" }, + { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" }, + { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" }, + { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" }, + { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" }, + { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" }, + { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" }, + { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" }, + { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" }, + { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" }, + { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" }, + { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" }, + { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" }, + { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" }, + { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" }, + { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" }, + { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" }, + { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" }, + { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" }, + { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" }, + { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" }, + { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" }, + { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" }, + { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" }, + { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" }, + { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" }, + { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" }, + { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" }, + { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" }, ] [[package]] @@ -7995,6 +8043,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7", size = 349321, upload-time = "2026-04-24T15:22:05.876Z" }, ] +[[package]] +name = "unstructured-client" +version = "0.45.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiofiles" }, + { name = "httpcore" }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "pypdf" }, + { name = "pypdfium2" }, + { name = "requests-toolbelt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/69/c6/bbc79efa9365fa8aecf353794a1253355eccf17468be3e6fb45a050e30d7/unstructured_client-0.45.0.tar.gz", hash = "sha256:3ffdaebdc27d2f043712dfeaee49cd38b990b480bed72e96255bf6245c0cc790", size = 94490, upload-time = "2026-06-05T21:36:51.635Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/66/e6/f1a9b2e1edc49665acaece9d806294945818fd46e969d66fe9a08fdb822f/unstructured_client-0.45.0-py3-none-any.whl", hash = "sha256:bf8f406f16d333a434aac601761d8794e518cf4cd21e424c196beef04e747786", size = 160590, upload-time = "2026-06-05T21:36:49.99Z" }, +] + [[package]] name = "urllib3" version = "2.7.0" From 5a21c2acc33d566b03094cb98baf89de3fec1820 Mon Sep 17 00:00:00 2001 From: Sahana Sreeram <76925094+sahana-sreeram@users.noreply.github.com> Date: Mon, 29 Jun 2026 15:01:55 -0400 Subject: [PATCH 06/32] feat(file-processors): add async/fallback support to docling-serve (#6014) # What does this PR do? Integrates AsyncDoclingServiceClient from [docling-slim](https://www.piwheels.org/project/docling-slim/) to enable async endpoints for both IBM Docling SaaS and [local docling-serve](https://github.com/docling-project/docling-serve). This enables [IBM Docling SaaS](https://www.ibm.com/products/docling) and improves performance for local deployments. Problem: Before this PR, docling-serve provider had critical limitations: - IBM Docling SaaS was completely incompatible (it only provides async endpoints, OGX docling-serve only used sync) - Local deployments experienced timeouts on large PDFs under concurrent load - No async capabilities or WebSocket-based status updates Solution: - Use Docling's new AsyncDoclingServiceClient for async conversion with automatic fallback to sync - Handle dual response formats: presigned S3 URLs (IBM SaaS) and direct documents (local Docling-Serve) - Error handling approach for IBM SaaS' chunking limitation: catch HTTP 404/405 errors and throw clear InvalidParameterError This solution is lightweight and requires no infrastructure changes. Users can: - Continue using local docling-serve with async mode (now the default) - Switch to IBM Docling SaaS by updating `base_url` and `api_key` in their config ## Test Plan Validated async functionality using both unit tests and integration testing against a local Docling Serve instance. ### Unit Tests 23 passed in 1.49s ``` bash Unit Tests New tests added: tests/unit/providers/file_processor/test_docling_serve.py::TestIBMSaaSCompatibility::test_ibm_saas_blocks_chunking_with_clear_error PASSED [ 91%] tests/unit/providers/file_processor/test_docling_serve.py::TestIBMSaaSCompatibility::test_ibm_saas_allows_conversion_without_chunking PASSED [ 95%] tests/unit/providers/file_processor/test_docling_serve.py::TestIBMSaaSCompatibility::test_local_docker_allows_chunking PASSED [100%] ======================== 23 passed, 1 warning in 1.49s ========================= ``` ### Integration Testing Tested against local docling-serve Docker (v1.24.0) and IBM's Docling SaaS (both in async mode) with real 37KB PDF (`ogx_and_models.pdf`): ``` Test 1: IBM Docling SaaS (Async Conversion) { "endpoint": "IBM SaaS", "base_url": "https://api.aws-c1.dcls.saas.ibm.com/...", "chunks_count": 1, "conversion_method": "async", "processing_time_ms": 934, "total_chars": 1486, "chunk_sizes": [1486] } Test 2: Local docling-serve (Async Conversion + Chunking) { "endpoint": "Local Docker", "base_url": "http://localhost:5001", "chunks_count": 3, "conversion_method": "async", "processing_time_ms": 5072, "total_chars": 1457, "chunk_sizes": [792, 541, 120] } ``` Conversion works as expected for IBM SaaS; Local Docling-Serve can run both convert and chunk methods. Confirms API endpoints are hit correctly. Test Setup - Docling Serve: Local instance via Docker (quay.io/docling-project/docling-serve) - IBM SaaS Docling API key and base url configured - Test file: ogx_and_models.pdf (86 pages, 63MB, from integration test fixtures) --------- Signed-off-by: Sahana Sreeram Co-authored-by: Matthew Farrellee --- .../file_processors/remote_docling-serve.mdx | 14 +- pyproject.toml | 2 + src/ogx/providers/registry/file_processors.py | 6 +- .../file_processor/docling_serve/config.py | 20 +- .../docling_serve/docling_serve.py | 245 ++++++++++++++++-- .../file_processor/test_docling_serve.py | 204 ++++++++++++++- uv.lock | 90 ++++++- 7 files changed, 541 insertions(+), 40 deletions(-) diff --git a/docs/docs/providers/file_processors/remote_docling-serve.mdx b/docs/docs/providers/file_processors/remote_docling-serve.mdx index a23d9c652de..f38e3dc79e6 100644 --- a/docs/docs/providers/file_processors/remote_docling-serve.mdx +++ b/docs/docs/providers/file_processors/remote_docling-serve.mdx @@ -27,7 +27,7 @@ description: | Then start OGX with the remote Docling Serve provider: ```bash - DOCLING_SERVE_URL=http://localhost:5001/v1 ogx stack run \ + DOCLING_SERVE_URL=http://localhost:5001 ogx stack run \ --providers "file_processors=remote::docling-serve,files=inline::localfs,vector_io=inline::faiss,inference=inline::sentence-transformers,inference=remote::ollama" \ --port 8321 ``` @@ -39,7 +39,7 @@ description: | - provider_id: docling-serve provider_type: remote::docling-serve config: - base_url: ${env.DOCLING_SERVE_URL:=http://localhost:5001/v1} + base_url: ${env.DOCLING_SERVE_URL:=http://localhost:5001} api_key: ${env.DOCLING_SERVE_API_KEY:=} ``` @@ -82,7 +82,7 @@ docker run -p 5001:5001 quay.io/docling-project/docling-serve Then start OGX with the remote Docling Serve provider: ```bash -DOCLING_SERVE_URL=http://localhost:5001/v1 ogx stack run \ +DOCLING_SERVE_URL=http://localhost:5001 ogx stack run \ --providers "file_processors=remote::docling-serve,files=inline::localfs,vector_io=inline::faiss,inference=inline::sentence-transformers,inference=remote::ollama" \ --port 8321 ``` @@ -94,7 +94,7 @@ file_processors: - provider_id: docling-serve provider_type: remote::docling-serve config: - base_url: ${env.DOCLING_SERVE_URL:=http://localhost:5001/v1} + base_url: ${env.DOCLING_SERVE_URL:=http://localhost:5001} api_key: ${env.DOCLING_SERVE_API_KEY:=} ``` @@ -107,13 +107,15 @@ See [Docling Serve's documentation](https://github.com/docling-project/docling-s | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| -| `base_url` | `str` | No | http://localhost:5001/v1 | Base URL of the Docling Serve instance | +| `base_url` | `str` | No | http://localhost:5001 | Base URL of the Docling Serve instance. Do not include /v1 suffix - AsyncDoclingServiceClient adds it automatically. For backward compatibility, /v1 suffix will be stripped if present. | | `api_key` | `SecretStr \| None` | No | | API key for authenticating with Docling Serve (optional, required if server has DOCLING_SERVE_API_KEY set) | | `default_chunk_size_tokens` | `int` | No | 800 | Default chunk size in tokens when chunking_strategy type is 'auto' | +| `mode` | `Literal[async, sync, auto]` | No | async | API mode: 'async' (use asynchronous submit/poll endpoints, recommended for both local and SaaS), 'sync' (use synchronous endpoints, fallback option), or 'auto' (detect server capabilities) | ## Sample Configuration ```yaml -base_url: ${env.DOCLING_SERVE_URL:=http://localhost:5001/v1} +base_url: ${env.DOCLING_SERVE_URL:=http://localhost:5001} api_key: ${env.DOCLING_SERVE_API_KEY:=} +mode: ${env.DOCLING_SERVE_MODE:=async} ``` diff --git a/pyproject.toml b/pyproject.toml index 0fc28aeeac1..0732b98f82f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -92,6 +92,7 @@ starter = [ "chardet", "chromadb-client", "datasets>=4.0.0", + "docling-slim[service-client]>=2.103.0", # AsyncDoclingServiceClient added in 2.103.0 "einops", "elasticsearch>=8.16.0,<9.0.0", "emoji", @@ -206,6 +207,7 @@ unit = [ "blobfile", "coverage", "databricks-sdk>=0.114.0", + "docling-slim[service-client]>=2.103.0", # AsyncDoclingServiceClient added in 2.103.0 "faiss-cpu", "markitdown[all]", "moto[s3]>=5.1.10", diff --git a/src/ogx/providers/registry/file_processors.py b/src/ogx/providers/registry/file_processors.py index 5cf7625b61f..10b90f979f1 100644 --- a/src/ogx/providers/registry/file_processors.py +++ b/src/ogx/providers/registry/file_processors.py @@ -260,7 +260,7 @@ def available_providers() -> list[ProviderSpec]: api=Api.file_processors, provider_type="remote::docling-serve", adapter_type="docling-serve", - pip_packages=["httpx"], + pip_packages=["httpx", "docling-slim[service-client]>=2.103.0"], module="ogx.providers.remote.file_processor.docling_serve", config_class="ogx.providers.remote.file_processor.docling_serve.DoclingServeFileProcessorConfig", api_dependencies=[Api.files], @@ -292,7 +292,7 @@ def available_providers() -> list[ProviderSpec]: Then start OGX with the remote Docling Serve provider: ```bash -DOCLING_SERVE_URL=http://localhost:5001/v1 ogx stack run \\ +DOCLING_SERVE_URL=http://localhost:5001 ogx stack run \\ --providers "file_processors=remote::docling-serve,files=inline::localfs,vector_io=inline::faiss,inference=inline::sentence-transformers,inference=remote::ollama" \\ --port 8321 ``` @@ -304,7 +304,7 @@ def available_providers() -> list[ProviderSpec]: - provider_id: docling-serve provider_type: remote::docling-serve config: - base_url: ${env.DOCLING_SERVE_URL:=http://localhost:5001/v1} + base_url: ${env.DOCLING_SERVE_URL:=http://localhost:5001} api_key: ${env.DOCLING_SERVE_API_KEY:=} ``` diff --git a/src/ogx/providers/remote/file_processor/docling_serve/config.py b/src/ogx/providers/remote/file_processor/docling_serve/config.py index 9037442a0c2..e3294ca0747 100644 --- a/src/ogx/providers/remote/file_processor/docling_serve/config.py +++ b/src/ogx/providers/remote/file_processor/docling_serve/config.py @@ -4,7 +4,7 @@ # This source code is licensed under the terms described in the LICENSE file in # the root directory of this source tree. -from typing import Any +from typing import Any, Literal from pydantic import BaseModel, Field, SecretStr @@ -15,8 +15,12 @@ class DoclingServeFileProcessorConfig(BaseModel): """Configuration for remote Docling Serve file processor.""" base_url: str = Field( - default="http://localhost:5001/v1", - description="Base URL of the Docling Serve instance", + default="http://localhost:5001", + description=( + "Base URL of the Docling Serve instance. " + "Do not include /v1 suffix - AsyncDoclingServiceClient adds it automatically. " + "For backward compatibility, /v1 suffix will be stripped if present." + ), ) api_key: SecretStr | None = Field( default=None, @@ -28,10 +32,18 @@ class DoclingServeFileProcessorConfig(BaseModel): le=4096, description="Default chunk size in tokens when chunking_strategy type is 'auto'", ) + mode: Literal["async", "sync", "auto"] = Field( + default="async", + description=( + "API mode: 'async' (use asynchronous submit/poll endpoints, recommended for both local and SaaS), " + "'sync' (use synchronous endpoints, fallback option), or 'auto' (detect server capabilities)" + ), + ) @classmethod def sample_run_config(cls, **kwargs: Any) -> dict[str, Any]: return { - "base_url": "${env.DOCLING_SERVE_URL:=http://localhost:5001/v1}", + "base_url": "${env.DOCLING_SERVE_URL:=http://localhost:5001}", "api_key": "${env.DOCLING_SERVE_API_KEY:=}", + "mode": "${env.DOCLING_SERVE_MODE:=async}", } diff --git a/src/ogx/providers/remote/file_processor/docling_serve/docling_serve.py b/src/ogx/providers/remote/file_processor/docling_serve/docling_serve.py index 5de82c0cc27..1631fd29a3d 100644 --- a/src/ogx/providers/remote/file_processor/docling_serve/docling_serve.py +++ b/src/ogx/providers/remote/file_processor/docling_serve/docling_serve.py @@ -5,16 +5,22 @@ # the root directory of this source tree. import os +import tempfile import time import uuid +from pathlib import Path from typing import Any import httpx +from docling.datamodel.base_models import OutputFormat +from docling.datamodel.service.options import ConvertDocumentsOptions +from docling.service_client import AsyncDoclingServiceClient, ChunkerKind from fastapi import UploadFile from ogx.log import get_logger from ogx.providers.utils.files.response import response_body_bytes from ogx.providers.utils.vector_io.vector_utils import generate_chunk_id +from ogx_api.common.errors import InvalidParameterError from ogx_api.file_processors import ProcessFileRequest, ProcessFileResponse from ogx_api.files import Files, RetrieveFileContentRequest, RetrieveFileRequest from ogx_api.vector_io import ( @@ -38,6 +44,12 @@ class DoclingServeFileProcessor: def __init__(self, config: DoclingServeFileProcessorConfig, files_api: Files) -> None: self.config = config self.files_api = files_api + # Normalize base_url: AsyncDoclingServiceClient rejects URLs ending with /v1 + # Strip /v1 suffix for backward compatibility with old configs + normalized_url = config.base_url.rstrip("/") + if normalized_url.endswith("/v1"): + normalized_url = normalized_url.removesuffix("/v1") + self.config.base_url = normalized_url def _get_headers(self) -> dict[str, str]: headers: dict[str, str] = {} @@ -81,12 +93,48 @@ async def process_file( suffix = os.path.splitext(filename)[1] or ".bin" mime_type = _get_mime_type(suffix) - if chunking_strategy: - chunks = await self._convert_and_chunk( - content, filename, mime_type, document_id, chunking_strategy, document_metadata - ) - else: - chunks = await self._convert_no_chunk(content, filename, mime_type, document_id, document_metadata) + # Try AsyncDoclingServiceClient first (async endpoints with WebSocket) + chunks = None + conversion_method = None + + if self.config.mode in ("async", "auto"): + try: + log.info( + "Converting with async endpoints using AsyncDoclingServiceClient from docling-slim", + mode=self.config.mode, + sdk_version="docling-slim>=2.95.0", + ) + if chunking_strategy: + chunks = await self._convert_and_chunk_async( + content, filename, mime_type, document_id, chunking_strategy, document_metadata + ) + else: + chunks = await self._convert_no_chunk_async( + content, filename, mime_type, document_id, document_metadata + ) + log.info( + "Successfully converted with async endpoints using AsyncDoclingServiceClient", + client_class="AsyncDoclingServiceClient", + sdk_module="docling.service_client", + ) + conversion_method = "async" + except (httpx.ConnectError, httpx.TimeoutException) as e: + if self.config.mode == "auto": + log.warning("Async failed, falling back to sync", error=str(e)) + chunks = None + else: + raise + + # Fallback to sync endpoints if async failed or mode is sync + if chunks is None: + log.info("Using sync endpoints", mode=self.config.mode) + if chunking_strategy: + chunks = await self._convert_and_chunk( + content, filename, mime_type, document_id, chunking_strategy, document_metadata + ) + else: + chunks = await self._convert_no_chunk(content, filename, mime_type, document_id, document_metadata) + conversion_method = "sync" processing_time_ms = int((time.time() - start_time) * 1000) @@ -95,6 +143,7 @@ async def process_file( "processing_time_ms": processing_time_ms, "extraction_method": "docling-serve", "file_size_bytes": len(content), + "conversion_method": conversion_method, } return ProcessFileResponse(chunks=chunks, metadata=response_metadata) @@ -108,11 +157,11 @@ async def _convert_no_chunk( document_metadata: dict[str, Any], ) -> list[Chunk]: """Convert a file via Docling Serve without chunking and return a single chunk.""" - url = f"{self.config.base_url}/convert/file" + url = f"{self.config.base_url}/v1/convert/file" headers = self._get_headers() options = { - "to_formats": '["md"]', + "to_formats": ["md"], } async with httpx.AsyncClient(timeout=300.0) as client: @@ -148,6 +197,68 @@ async def _convert_no_chunk( ) ] + async def _convert_no_chunk_async( + self, + content: bytes, + filename: str, + mime_type: str, + document_id: str, + document_metadata: dict[str, Any], + ) -> list[Chunk]: + """Convert file using async endpoints with AsyncDoclingServiceClient.""" + # AsyncDoclingServiceClient requires a file path via temp file + with tempfile.NamedTemporaryFile() as tmp: + tmp.write(content) + tmp_path = Path(tmp.name) + + async with AsyncDoclingServiceClient( + url=self.config.base_url, + api_key=self.config.api_key.get_secret_value() if self.config.api_key else "", + job_timeout=300.0, + ) as client: + job = await client.submit( + source=tmp_path, + options=ConvertDocumentsOptions(to_formats=[OutputFormat.MARKDOWN]), + ) + result = await job.result() + + # Handle both local docling-serve (ConversionResult with .document) + # and IBM SaaS (PresignedUrlConvertResponse with .documents and presigned URLs) + md_content = "" + if hasattr(result, "documents"): + # IBM SaaS: PresignedUrlConvertResponse with presigned URLs + if result.documents and result.documents[0].artifacts: + artifact = result.documents[0].artifacts[0] + # Download markdown from presigned URL + async with httpx.AsyncClient() as http_client: + response = await http_client.get(str(artifact.uri)) + response.raise_for_status() + md_content = response.text + elif hasattr(result, "document"): + # Local docling-serve: ConversionResult with direct document + md_content = result.document.export_to_markdown() if result.document else "" + + if not md_content or not md_content.strip(): + return [] + + chunk_id = generate_chunk_id(document_id, md_content) + return [ + Chunk( + content=md_content, + chunk_id=chunk_id, + metadata={ + "document_id": document_id, + **document_metadata, + }, + chunk_metadata=ChunkMetadata( + chunk_id=chunk_id, + document_id=document_id, + source=document_metadata.get("filename", ""), + content_token_count=len(md_content.split()), + ), + ) + ] + async def _convert_and_chunk( self, content: bytes, @@ -158,7 +269,7 @@ async def _convert_and_chunk( document_metadata: dict[str, Any], ) -> list[Chunk]: """Convert and chunk a file via Docling Serve's hybrid chunker endpoint.""" - url = f"{self.config.base_url}/chunk/hybrid/file" + url = f"{self.config.base_url}/v1/chunk/hybrid/file" headers = self._get_headers() if chunking_strategy.type == "auto": @@ -173,13 +284,28 @@ async def _convert_and_chunk( } async with httpx.AsyncClient(timeout=300.0) as client: - response = await client.post( - url, - files={"files": (filename, content, mime_type)}, - data=options, - headers=headers, - ) - response.raise_for_status() + try: + response = await client.post( + url, + files={"files": (filename, content, mime_type)}, + data=options, + headers=headers, + ) + response.raise_for_status() + except httpx.HTTPStatusError as e: + # Chunking endpoint not supported (e.g., IBM Docling SaaS) + if e.response.status_code in (404, 405): + raise InvalidParameterError( + param_name="chunking_strategy", + value=chunking_strategy.model_dump() if chunking_strategy else None, + constraint=( + "Chunking is not supported by this Docling instance. " + "This is a known limitation of IBM Docling SaaS. " + "Either remove 'chunking_strategy' from your request, " + "or configure OGX to use local docling-serve for chunking support." + ), + ) from e + raise result = response.json() raw_chunks = result.get("chunks", []) @@ -222,6 +348,93 @@ async def _convert_and_chunk( return chunks + async def _convert_and_chunk_async( + self, + content: bytes, + filename: str, + mime_type: str, + document_id: str, + chunking_strategy: VectorStoreChunkingStrategy, + document_metadata: dict[str, Any], + ) -> list[Chunk]: + """Convert and chunk file using async endpoints with AsyncDoclingServiceClient.""" + # AsyncDoclingServiceClient requires a file path via temp file + with tempfile.NamedTemporaryFile() as tmp: + tmp.write(content) + tmp_path = Path(tmp.name) + + async with AsyncDoclingServiceClient( + url=self.config.base_url, + api_key=self.config.api_key.get_secret_value() if self.config.api_key else "", + job_timeout=300.0, + ) as client: + try: + job = await client.submit_chunk( + source=tmp_path, + chunker=ChunkerKind.HYBRID, + options=ConvertDocumentsOptions(), + ) + response = await job.result() + except httpx.HTTPStatusError as e: + # Chunking endpoint not supported (e.g., IBM Docling SaaS) + if e.response.status_code in (404, 405): + raise InvalidParameterError( + param_name="chunking_strategy", + value=chunking_strategy.model_dump() if chunking_strategy else None, + constraint=( + "Chunking is not supported by this Docling instance. " + "This is a known limitation of IBM Docling SaaS. " + "Either remove 'chunking_strategy' from your request, " + "or configure OGX to use local docling-serve for chunking support." + ), + ) from e + raise + + raw_chunks = response.chunks if response.chunks else [] + + if not raw_chunks: + return [] + + chunks: list[Chunk] = [] + for i, raw_chunk in enumerate(raw_chunks): + # AsyncDoclingServiceClient returns ChunkedDocumentResultItem objects + text = raw_chunk.text if hasattr(raw_chunk, "text") else "" + if not text or not text.strip(): + continue + + chunk_window = str(i) + chunk_id = generate_chunk_id(document_id, text, chunk_window) + + meta: dict[str, Any] = { + "document_id": document_id, + **document_metadata, + } + + # Extract headings from meta object + headings = None + if hasattr(raw_chunk, "meta") and hasattr(raw_chunk.meta, "headings"): + headings = raw_chunk.meta.headings + + if headings: + meta["headings"] = headings + + chunks.append( + Chunk( + content=text, + chunk_id=chunk_id, + metadata=meta, + chunk_metadata=ChunkMetadata( + chunk_id=chunk_id, + document_id=document_id, + source=document_metadata.get("filename", ""), + content_token_count=len(text.split()), + chunk_window=chunk_window, + ), + ) + ) + + return chunks + async def shutdown(self) -> None: pass diff --git a/tests/unit/providers/file_processor/test_docling_serve.py b/tests/unit/providers/file_processor/test_docling_serve.py index 81f96ffb260..be2b1583de3 100644 --- a/tests/unit/providers/file_processor/test_docling_serve.py +++ b/tests/unit/providers/file_processor/test_docling_serve.py @@ -52,15 +52,25 @@ class TestDoclingServeFileProcessor: @pytest.fixture def config(self) -> DoclingServeFileProcessorConfig: return DoclingServeFileProcessorConfig( - base_url="http://localhost:5001/v1", + base_url="http://localhost:5001", default_chunk_size_tokens=512, + mode="sync", + ) + + @pytest.fixture + def config_async(self) -> DoclingServeFileProcessorConfig: + return DoclingServeFileProcessorConfig( + base_url="http://localhost:5001", + default_chunk_size_tokens=512, + mode="async", ) @pytest.fixture def config_with_api_key(self) -> DoclingServeFileProcessorConfig: return DoclingServeFileProcessorConfig( - base_url="http://localhost:5001/v1", + base_url="http://localhost:5001", api_key=SecretStr("test-secret-key"), + mode="sync", ) @pytest.fixture @@ -87,7 +97,7 @@ async def test_rejects_both_file_and_file_id(self, processor: DoclingServeFilePr with pytest.raises(ValueError, match="Cannot provide both file and file_id"): await processor.process_file(request, file=upload_file) - # -- convert (no chunking) -- + # -- convert (no chunking) - sync mode -- async def test_process_file_no_chunking(self, processor: DoclingServeFileProcessor, upload_file: UploadFile): request = ProcessFileRequest() @@ -98,13 +108,14 @@ async def test_process_file_no_chunking(self, processor: DoclingServeFileProcess mock_post.assert_called_once() call_kwargs = mock_post.call_args - assert "/convert/file" in call_kwargs.args[0] + assert "/v1/convert/file" in call_kwargs.args[0] assert call_kwargs.kwargs["files"]["files"][0] == "test.pdf" assert len(response.chunks) == 1 assert response.chunks[0].content == CONVERT_RESPONSE["document"]["md_content"] assert response.metadata["processor"] == "docling-serve" assert response.metadata["extraction_method"] == "docling-serve" + assert response.metadata["conversion_method"] == "sync" assert "processing_time_ms" in response.metadata assert response.metadata["file_size_bytes"] == len(b"%PDF-fake-content") @@ -120,7 +131,7 @@ async def test_process_file_no_chunking_empty_content( assert len(response.chunks) == 0 assert response.metadata["processor"] == "docling-serve" - # -- chunk (with chunking strategy) -- + # -- chunk (with chunking strategy) - sync mode -- async def test_process_file_auto_chunking(self, processor: DoclingServeFileProcessor, upload_file: UploadFile): request = ProcessFileRequest(chunking_strategy=VectorStoreChunkingStrategyAuto()) @@ -130,7 +141,7 @@ async def test_process_file_auto_chunking(self, processor: DoclingServeFileProce response = await processor.process_file(request, file=upload_file) call_kwargs = mock_post.call_args - assert "/chunk/hybrid/file" in call_kwargs.args[0] + assert "/v1/chunk/hybrid/file" in call_kwargs.args[0] assert call_kwargs.kwargs["data"]["chunking_max_tokens"] == "512" assert len(response.chunks) == 3 @@ -147,7 +158,7 @@ async def test_process_file_static_chunking(self, processor: DoclingServeFilePro response = await processor.process_file(request, file=upload_file) call_kwargs = mock_post.call_args - assert "/chunk/hybrid/file" in call_kwargs.args[0] + assert "/v1/chunk/hybrid/file" in call_kwargs.args[0] assert call_kwargs.kwargs["data"]["chunking_max_tokens"] == "256" assert len(response.chunks) == 3 @@ -284,15 +295,192 @@ async def test_mime_type_fallback_for_unknown_extension(self, processor: Docling sent_files = mock_post.call_args.kwargs["files"]["files"] assert sent_files[2] == "application/octet-stream" + # -- async mode tests -- + + async def test_auto_mode_falls_back_to_sync(self, files_api: AsyncMock, upload_file: UploadFile): + """Test that mode='auto' gracefully falls back to sync when async is unavailable.""" + # Use auto mode for fallback behavior + config_auto = DoclingServeFileProcessorConfig( + base_url="http://localhost:5001", + mode="auto", + ) + processor = DoclingServeFileProcessor(config_auto, files_api=files_api) + request = ProcessFileRequest() + + # Mock SDK to raise network exception + mock_client = AsyncMock() + mock_client.__aenter__ = AsyncMock(side_effect=httpx.ConnectError("Connection refused")) + mock_client.__aexit__ = AsyncMock(return_value=None) + + sync_response = _make_httpx_response(CONVERT_RESPONSE) + + with ( + patch( + "ogx.providers.remote.file_processor.docling_serve.docling_serve.AsyncDoclingServiceClient", + return_value=mock_client, + ), + patch("httpx.AsyncClient.post", return_value=sync_response) as mock_post, + ): + response = await processor.process_file(request, file=upload_file) + + # Verify sync endpoint was called after async failed + mock_post.assert_called_once() + assert "/v1/convert/file" in mock_post.call_args.args[0] + + # Verify we got content from sync fallback + assert len(response.chunks) == 1 + assert response.chunks[0].content == CONVERT_RESPONSE["document"]["md_content"] + assert response.metadata["conversion_method"] == "sync" + class TestDoclingServeFileProcessorConfig: def test_default_values(self): config = DoclingServeFileProcessorConfig() - assert config.base_url == "http://localhost:5001/v1" + assert config.base_url == "http://localhost:5001" assert config.api_key is None assert config.default_chunk_size_tokens >= 100 + assert config.mode == "async" def test_sample_run_config(self): sample = DoclingServeFileProcessorConfig.sample_run_config() assert "base_url" in sample assert "api_key" in sample + + +class TestIBMSaaSCompatibility: + """Tests for IBM Docling SaaS specific behavior.""" + + @pytest.fixture + def ibm_saas_config(self) -> DoclingServeFileProcessorConfig: + """Config pointing to IBM SaaS endpoint.""" + return DoclingServeFileProcessorConfig( + base_url="https://api.aws-c1.dcls.saas.ibm.com/test-instance", + api_key=SecretStr("test-api-key"), + mode="async", + ) + + @pytest.fixture + def files_api(self) -> AsyncMock: + return AsyncMock() + + @pytest.fixture + def ibm_processor( + self, ibm_saas_config: DoclingServeFileProcessorConfig, files_api: AsyncMock + ) -> DoclingServeFileProcessor: + return DoclingServeFileProcessor(ibm_saas_config, files_api=files_api) + + @pytest.fixture + def upload_file(self) -> UploadFile: + return UploadFile(file=io.BytesIO(b"%PDF-fake-content"), filename="test.pdf") + + async def test_ibm_saas_blocks_chunking_with_clear_error( + self, ibm_processor: DoclingServeFileProcessor, upload_file: UploadFile + ): + """IBM SaaS should reject chunking requests with a clear error message.""" + from ogx_api.common.errors import InvalidParameterError + + request = ProcessFileRequest( + chunking_strategy=VectorStoreChunkingStrategyStatic( + static=VectorStoreChunkingStrategyStaticConfig(max_chunk_size_tokens=512) + ) + ) + + # Mock AsyncDoclingServiceClient to simulate IBM SaaS 405 error + with patch( + "ogx.providers.remote.file_processor.docling_serve.docling_serve.AsyncDoclingServiceClient" + ) as mock_client: + mock_instance = AsyncMock() + mock_client.return_value.__aenter__.return_value = mock_instance + + # Mock submit_chunk() raising 405 (Method Not Allowed) + mock_response = AsyncMock() + mock_response.status_code = 405 + mock_error = httpx.HTTPStatusError("Method Not Allowed", request=AsyncMock(), response=mock_response) + mock_instance.submit_chunk.side_effect = mock_error + + with pytest.raises(InvalidParameterError) as exc_info: + await ibm_processor.process_file(request, file=upload_file) + + error_msg = str(exc_info.value) + assert "chunking_strategy" in error_msg + assert "not supported" in error_msg + assert "remove 'chunking_strategy'" in error_msg + + async def test_ibm_saas_allows_conversion_without_chunking( + self, ibm_processor: DoclingServeFileProcessor, upload_file: UploadFile + ): + """IBM SaaS should allow conversion without chunking.""" + + # Should NOT raise for conversion without chunking + request = ProcessFileRequest() + + # Mock AsyncDoclingServiceClient to avoid actual API calls + with patch( + "ogx.providers.remote.file_processor.docling_serve.docling_serve.AsyncDoclingServiceClient" + ) as mock_client: + # Mock the async context manager + mock_instance = AsyncMock() + mock_client.return_value.__aenter__.return_value = mock_instance + + # Mock submit() returning a job + mock_job = AsyncMock() + mock_instance.submit.return_value = mock_job + + # Mock job.result() returning presigned URL response (IBM SaaS format) + mock_result = SimpleNamespace( + documents=[SimpleNamespace(artifacts=[SimpleNamespace(uri="https://s3.amazonaws.com/test.md")])] + ) + mock_job.result.return_value = mock_result + + # Mock httpx download of presigned URL + with patch("httpx.AsyncClient") as mock_http: + mock_http_instance = AsyncMock() + mock_http.return_value.__aenter__.return_value = mock_http_instance + + mock_response = AsyncMock() + mock_response.text = "# Test Document\n\nContent here." + mock_response.raise_for_status = AsyncMock() + mock_http_instance.get.return_value = mock_response + + # This should NOT raise InvalidParameterError + result = await ibm_processor.process_file(request, file=upload_file) + + assert result.chunks is not None + assert len(result.chunks) > 0 + assert result.metadata["conversion_method"] == "async" + + async def test_local_docker_allows_chunking(self, upload_file: UploadFile): + """Local docling-serve should allow chunking (successful response).""" + # Local config + local_config = DoclingServeFileProcessorConfig( + base_url="http://localhost:5001", + mode="async", + ) + processor = DoclingServeFileProcessor(local_config, files_api=AsyncMock()) + + request = ProcessFileRequest( + chunking_strategy=VectorStoreChunkingStrategyStatic( + static=VectorStoreChunkingStrategyStaticConfig(max_chunk_size_tokens=512) + ) + ) + + # Mock AsyncDoclingServiceClient to simulate successful chunking + with patch( + "ogx.providers.remote.file_processor.docling_serve.docling_serve.AsyncDoclingServiceClient" + ) as mock_client: + mock_instance = AsyncMock() + mock_client.return_value.__aenter__.return_value = mock_instance + + # Mock submit_chunk() returning a successful job + mock_job = AsyncMock() + mock_chunk = SimpleNamespace(text="Chunk content", meta=SimpleNamespace(headings=None)) + mock_response = SimpleNamespace(chunks=[mock_chunk]) + mock_job.result.return_value = mock_response + mock_instance.submit_chunk.return_value = mock_job + + # Should succeed without raising InvalidParameterError + result = await processor.process_file(request, file=upload_file) + + assert result.chunks is not None + assert len(result.chunks) > 0 + assert result.metadata["conversion_method"] == "async" diff --git a/uv.lock b/uv.lock index a789a56ebd7..d67502db3ea 100644 --- a/uv.lock +++ b/uv.lock @@ -1459,6 +1459,57 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, ] +[[package]] +name = "docling-core" +version = "2.82.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "defusedxml" }, + { name = "jsonref" }, + { name = "jsonschema" }, + { name = "latex2mathml" }, + { name = "pandas" }, + { name = "pillow" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "pyyaml" }, + { name = "tabulate" }, + { name = "typer" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/65/24/104116af370c4d0f752e4fadb929d1d330fc8c285f352bf97259e9cadb18/docling_core-2.82.0.tar.gz", hash = "sha256:5d029cdfd5a3c01c60bbea0bf24970bf6dbf03bbca2397b71a064b8eb4c7909b", size = 354998, upload-time = "2026-06-12T08:58:23.831Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/c0/fcac4b2cf2e64bbebb582635a934b2ebdb5db0017843d9a289c379108bd6/docling_core-2.82.0-py3-none-any.whl", hash = "sha256:5c09461752a8259010b6901b0633f6b0d13ddf8a7f84e98a98a62898cff53849", size = 299655, upload-time = "2026-06-12T08:58:22.391Z" }, +] + +[[package]] +name = "docling-slim" +version = "2.103.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "docling-core" }, + { name = "filetype" }, + { name = "pluggy" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "requests" }, + { name = "tqdm" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/f1/c6305cc6569dce9e30d79c17770df1a7a26960ba887d74266a6294217469/docling_slim-2.103.0.tar.gz", hash = "sha256:05ff493237ffdae9cb28f420dd21b40d423feb6858d1e5f26a6b14671d19f630", size = 433807, upload-time = "2026-06-17T08:49:06.456Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/06/22986d8662e7a8b295ff5eab6bc61c8f08427b3633ac2786f816353b3fbb/docling_slim-2.103.0-py3-none-any.whl", hash = "sha256:1674139d3a333904346dd7b161b5d5688d53e5750d7440036f2f6c9cb37c2d63", size = 556865, upload-time = "2026-06-17T08:49:04.416Z" }, +] + +[package.optional-dependencies] +service-client = [ + { name = "httpx" }, + { name = "python-dotenv" }, + { name = "rich" }, + { name = "typer" }, + { name = "websockets" }, +] + [[package]] name = "docstring-parser" version = "0.18.0" @@ -1617,6 +1668,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258", size = 39812, upload-time = "2026-04-19T15:39:08.752Z" }, ] +[[package]] +name = "filetype" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/29/745f7d30d47fe0f251d3ad3dc2978a23141917661998763bebb6da007eb1/filetype-1.2.0.tar.gz", hash = "sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb", size = 998020, upload-time = "2022-11-02T17:34:04.141Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/79/1b8fa1bb3568781e84c9200f951c735f3f157429f44be0495da55894d620/filetype-1.2.0-py2.py3-none-any.whl", hash = "sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25", size = 19970, upload-time = "2022-11-02T17:34:01.425Z" }, +] + [[package]] name = "fire" version = "0.7.1" @@ -2602,6 +2662,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659, upload-time = "2026-03-23T22:32:31.568Z" }, ] +[[package]] +name = "jsonref" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/0d/c1f3277e90ccdb50d33ed5ba1ec5b3f0a242ed8c1b1a85d3afeb68464dca/jsonref-1.1.0.tar.gz", hash = "sha256:32fe8e1d85af0fdefbebce950af85590b22b60f9e95443176adbde4e1ecea552", size = 8814, upload-time = "2023-01-16T16:10:04.455Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl", hash = "sha256:590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9", size = 9425, upload-time = "2023-01-16T16:10:02.255Z" }, +] + [[package]] name = "jsonschema" version = "4.26.0" @@ -2939,6 +3008,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/98/a9/51e644c1f1dbc3dd7d22dfd6412eab206d538c81e024e4f287373544bdcb/langsmith-0.8.3-py3-none-any.whl", hash = "sha256:b2e40e308222fa0beb2dccee3b4b30bfee9062d7a4f20a3e3e93df3c51a08ab4", size = 399048, upload-time = "2026-05-07T19:56:53.994Z" }, ] +[[package]] +name = "latex2mathml" +version = "3.81.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/62/35bb816c5c19d4d0cde5bdfb82ebb996306243d5f94e03f201658c629960/latex2mathml-3.81.0.tar.gz", hash = "sha256:4b959cdc3cac8686bc0e3e5aece8127dfb1b81ca1241bed8e00ef31b82bb4022", size = 77584, upload-time = "2026-04-15T00:55:27.977Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/b1/c488b530994c4f68e46efa99a4d6ca6741aaf158e35779fe6c4d8a9a427d/latex2mathml-3.81.0-py3-none-any.whl", hash = "sha256:d317710393fe20579aea39cfe8928fa2ad9b8780896e585326c75e89c1d1d1a4", size = 79185, upload-time = "2026-04-15T00:55:29.301Z" }, +] + [[package]] name = "lazy-object-proxy" version = "1.12.0" @@ -4034,6 +4112,7 @@ starter = [ { name = "chardet" }, { name = "chromadb-client" }, { name = "datasets" }, + { name = "docling-slim", extra = ["service-client"] }, { name = "einops" }, { name = "elasticsearch" }, { name = "emoji" }, @@ -4093,6 +4172,7 @@ dev = [ { name = "chardet" }, { name = "coverage" }, { name = "databricks-sdk" }, + { name = "docling-slim", extra = ["service-client"] }, { name = "faiss-cpu" }, { name = "markitdown", extra = ["all"] }, { name = "mcp" }, @@ -4226,6 +4306,7 @@ unit = [ { name = "chardet" }, { name = "coverage" }, { name = "databricks-sdk" }, + { name = "docling-slim", extra = ["service-client"] }, { name = "faiss-cpu" }, { name = "markitdown", extra = ["all"] }, { name = "mcp" }, @@ -4251,6 +4332,7 @@ requires-dist = [ { name = "chardet", marker = "extra == 'starter'" }, { name = "chromadb-client", marker = "extra == 'starter'" }, { name = "datasets", marker = "extra == 'starter'", specifier = ">=4.0.0" }, + { name = "docling-slim", extras = ["service-client"], marker = "extra == 'starter'", specifier = ">=2.103.0" }, { name = "einops", marker = "extra == 'starter'" }, { name = "elasticsearch", marker = "extra == 'starter'", specifier = ">=8.16.0,<9.0.0" }, { name = "emoji", marker = "extra == 'starter'" }, @@ -4334,6 +4416,7 @@ dev = [ { name = "chardet" }, { name = "coverage" }, { name = "databricks-sdk", specifier = ">=0.114.0" }, + { name = "docling-slim", extras = ["service-client"], specifier = ">=2.103.0" }, { name = "faiss-cpu" }, { name = "markitdown", extras = ["all"] }, { name = "mcp", specifier = ">=1.23.0,<2.0" }, @@ -4463,6 +4546,7 @@ unit = [ { name = "chardet" }, { name = "coverage" }, { name = "databricks-sdk", specifier = ">=0.114.0" }, + { name = "docling-slim", extras = ["service-client"], specifier = ">=2.103.0" }, { name = "faiss-cpu" }, { name = "markitdown", extras = ["all"] }, { name = "mcp", specifier = ">=1.23.0,<2.0" }, @@ -7910,7 +7994,7 @@ wheels = [ [[package]] name = "typer" -version = "0.25.1" +version = "0.24.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -7918,9 +8002,9 @@ dependencies = [ { name = "rich" }, { name = "shellingham" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e4/51/9aed62104cea109b820bbd6c14245af756112017d309da813ef107d42e7e/typer-0.25.1.tar.gz", hash = "sha256:9616eb8853a09ffeabab1698952f33c6f29ffdbceb4eaeecf571880e8d7664cc", size = 122276, upload-time = "2026-04-30T19:32:16.964Z" } +sdist = { url = "https://files.pythonhosted.org/packages/83/b8/9ebb531b6c2d377af08ac6746a5df3425b21853a5d2260876919b58a2a4a/typer-0.24.2.tar.gz", hash = "sha256:ec070dcfca1408e85ee203c6365001e818c3b7fffe686fd07ff2d68095ca0480", size = 119849, upload-time = "2026-04-22T17:45:34.413Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl", hash = "sha256:75caa44ed46a03fb2dab8808753ffacdbfea88495e74c85a28c5eefcf5f39c89", size = 58409, upload-time = "2026-04-30T19:32:18.271Z" }, + { url = "https://files.pythonhosted.org/packages/39/d1/9484b497e0a0410b901c12b8251c3e746e1e863f7d28419ffe06f7892fda/typer-0.24.2-py3-none-any.whl", hash = "sha256:b618bc3d721f9a8d30f3e05565be26416d06e9bcc29d49bc491dc26aba674fa8", size = 55977, upload-time = "2026-04-22T17:45:33.055Z" }, ] [[package]] From 2baab0d32646cf245f7ca68ecff73260df4446da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 08:06:46 +0000 Subject: [PATCH 07/32] chore(python-deps): bump joserfc from 1.6.5 to 1.6.7 (#6216) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [joserfc](https://github.com/authlib/joserfc) from 1.6.5 to 1.6.7.
Release notes

Sourced from joserfc's releases.

1.6.7

   🐞 Bug Fixes

    View changes on GitHub
Changelog

Sourced from joserfc's changelog.

1.6.7

Released on May 23, 2026

  • Update for type hints.

1.6.6

Released on May 18, 2026

  • JWS: validate payload size when b64=false.
Commits
  • 1e5b94d chore: release 1.6.7
  • 75d9f95 fix(typing): use cast for type hints
  • 6d24037 Merge pull request #98 from jonathangreen/algorithms-accept-collection
  • 102a7a7 fix(typing): accept any Collection for algorithms, not just list
  • 8b869e8 chore: release 1.6.6
  • 00d599b chore: update actions
  • 9186561 Merge pull request #97 from authlib/fix-b64
  • 4d4ea2e fix(jws): validate payload size for b64=false
  • b6554cc Merge pull request #96 from sebasxsala/fix-p512-fixture
  • b89eadf test: normalize P-521 private key fixture
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=joserfc&package-manager=uv&previous-version=1.6.5&new-version=1.6.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ogx-ai/ogx/network/alerts).
--------- Signed-off-by: dependabot[bot] Signed-off-by: github-actions[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] --- pyproject.toml | 1 + uv.lock | 53 +++++++++++++++++++++++++------------------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0732b98f82f..ee796c17dcc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ constraint-dependencies = [ "gitpython>=3.1.47", # Command injection via Git options bypass "h11>=0.16.0", "idna>=3.15", + "joserfc>=1.6.7", "lxml>=6.1.0", # CVE-2026-41066: XML entity expansion with default resolve_entities=True "pillow>=12.2.0", # CVE-2026-40192 + 4 more: heap overflow, OOB write, DoS "protobuf>=5.29.6", # CVE-2025-4565 + CVE-2026-0994: parsing vulnerabilities diff --git a/uv.lock b/uv.lock index d67502db3ea..d720f059807 100644 --- a/uv.lock +++ b/uv.lock @@ -29,6 +29,7 @@ constraints = [ { name = "gitpython", specifier = ">=3.1.47" }, { name = "h11", specifier = ">=0.16.0" }, { name = "idna", specifier = ">=3.15" }, + { name = "joserfc", specifier = ">=1.6.7" }, { name = "lxml", specifier = ">=6.1.0" }, { name = "pillow", specifier = ">=12.2.0" }, { name = "protobuf", specifier = ">=5.29.6" }, @@ -2631,14 +2632,14 @@ wheels = [ [[package]] name = "joserfc" -version = "1.6.5" +version = "1.6.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3b/dc/5f768c2e391e9afabe5d18e3221346deb5fb6338565f1ccc9e7c6d7befdd/joserfc-1.6.5.tar.gz", hash = "sha256:1482a7db78fb4602e44ed89e51b599d052e091288c7c532c5b694e20149dec48", size = 231881, upload-time = "2026-05-06T04:58:13.408Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/cb/52e479f20804904f5df20ac4539d292dcecd1287aaa33cba1d1def1d9d8e/joserfc-1.6.7.tar.gz", hash = "sha256:6999fe89457069ecacd8cc797c88a805f83054dd883333fa0409f74b46479fd7", size = 232158, upload-time = "2026-05-23T01:46:44.069Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/54/3b/ad1cb22e75c963b1f07c8a2329bf47227ce7e4361df5eb2fb101b2ce33ef/joserfc-1.6.5-py3-none-any.whl", hash = "sha256:e9878a0f8243fe7b95e11fdda81374ca9f7a689e302751579d3dfdeec559675e", size = 70464, upload-time = "2026-05-06T04:58:11.668Z" }, + { url = "https://files.pythonhosted.org/packages/c5/e4/bcf6718b5662894c6831f46296b73cd4b1a2e90c20b6d437e20c4997388c/joserfc-1.6.7-py3-none-any.whl", hash = "sha256:9e51e4a64840aa1734a058258e80a4480e2ff2d5686e480e7c92c954a92fbe05", size = 70603, upload-time = "2026-05-23T01:46:42.129Z" }, ] [[package]] @@ -5137,7 +5138,7 @@ name = "pexpect" version = "4.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "ptyprocess", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "ptyprocess" }, ] sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } wheels = [ @@ -7419,8 +7420,8 @@ name = "standard-aifc" version = "3.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "audioop-lts", marker = "python_full_version >= '3.13'" }, - { name = "standard-chunk", marker = "python_full_version >= '3.13'" }, + { name = "audioop-lts" }, + { name = "standard-chunk" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c4/53/6050dc3dde1671eb3db592c13b55a8005e5040131f7509cef0215212cb84/standard_aifc-3.13.0.tar.gz", hash = "sha256:64e249c7cb4b3daf2fdba4e95721f811bde8bdfc43ad9f936589b7bb2fae2e43", size = 15240, upload-time = "2024-10-30T16:01:31.772Z" } wheels = [ @@ -7717,13 +7718,13 @@ resolution-markers = [ "python_full_version < '3.13' and sys_platform == 'darwin'", ] dependencies = [ - { name = "filelock", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, - { name = "fsspec", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, - { name = "jinja2", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, - { name = "networkx", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, - { name = "setuptools", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, - { name = "sympy", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, - { name = "typing-extensions", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, + { name = "filelock" }, + { name = "fsspec" }, + { name = "jinja2" }, + { name = "networkx" }, + { name = "setuptools" }, + { name = "sympy" }, + { name = "typing-extensions" }, ] wheels = [ { url = "https://download-r2.pytorch.org/whl/cpu/torch-2.12.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:b41339df93d491435e790ff8bcbae1c0ce777175889bfd1281d119862793e6a2", upload-time = "2026-05-12T16:20:12Z" }, @@ -7753,13 +7754,13 @@ resolution-markers = [ "python_full_version < '3.13' and sys_platform != 'darwin' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ - { name = "filelock", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, - { name = "fsspec", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, - { name = "jinja2", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, - { name = "networkx", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, - { name = "setuptools", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, - { name = "sympy", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, + { name = "filelock" }, + { name = "fsspec" }, + { name = "jinja2" }, + { name = "networkx" }, + { name = "setuptools" }, + { name = "sympy" }, + { name = "typing-extensions" }, ] wheels = [ { url = "https://download-r2.pytorch.org/whl/cpu/torch-2.12.0%2Bcpu-cp312-cp312-linux_s390x.whl", hash = "sha256:b9d0e8eed0af9321ffb12b75f4aca371b071254f12cf75875d5a8e7cc8f52b51", upload-time = "2026-05-12T23:16:33Z" }, @@ -7834,9 +7835,9 @@ resolution-markers = [ "python_full_version < '3.13' and sys_platform == 'darwin'", ] dependencies = [ - { name = "numpy", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, - { name = "pillow", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, - { name = "torch", version = "2.12.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, + { name = "numpy" }, + { name = "pillow" }, + { name = "torch", version = "2.12.0", source = { registry = "https://download.pytorch.org/whl/cpu" } }, ] wheels = [ { url = "https://download-r2.pytorch.org/whl/cpu/torchvision-0.27.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:1a6dd742a150645126df9e0b2e449874c1d635897c773b322c2e067e98382dfe", upload-time = "2026-05-12T16:20:37Z" }, @@ -7866,9 +7867,9 @@ resolution-markers = [ "python_full_version < '3.13' and sys_platform != 'darwin' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ - { name = "numpy", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, - { name = "pillow", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, - { name = "torch", version = "2.12.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, + { name = "numpy" }, + { name = "pillow" }, + { name = "torch", version = "2.12.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" } }, ] wheels = [ { url = "https://download-r2.pytorch.org/whl/cpu/torchvision-0.27.0%2Bcpu-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:1b06f42d48b62098114923d8a3fe9fa864182715db06584a515155db0aa8eb30", upload-time = "2026-05-12T16:20:36Z" }, From a1e37573728bf3f1061120568cc0e5997c0bcde5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 08:07:19 +0000 Subject: [PATCH 08/32] chore(github-deps): bump actions/cache from 5.0.5 to 6.1.0 (#6201) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/cache](https://github.com/actions/cache) from 5.0.5 to 6.1.0.
Release notes

Sourced from actions/cache's releases.

v6.1.0

What's Changed

Full Changelog: https://github.com/actions/cache/compare/v6...v6.1.0

v6.0.0

What's Changed

Full Changelog: https://github.com/actions/cache/compare/v5...v6.0.0

v5.1.0

What's Changed

Full Changelog: https://github.com/actions/cache/compare/v5...v5.1.0

Changelog

Sourced from actions/cache's changelog.

Releases

How to prepare a release

[!NOTE] Relevant for maintainers with write access only.

  1. Switch to a new branch from main.
  2. Run npm test to ensure all tests are passing.
  3. Update the version in https://github.com/actions/cache/blob/main/package.json.
  4. Run npm run build to update the compiled files.
  5. Update this https://github.com/actions/cache/blob/main/RELEASES.md with the new version and changes in the ## Changelog section.
  6. Run licensed cache to update the license report.
  7. Run licensed status and resolve any warnings by updating the https://github.com/actions/cache/blob/main/.licensed.yml file with the exceptions.
  8. Commit your changes and push your branch upstream.
  9. Open a pull request against main and get it reviewed and merged.
  10. Draft a new release https://github.com/actions/cache/releases use the same version number used in package.json
    1. Create a new tag with the version number.
    2. Auto generate release notes and update them to match the changes you made in RELEASES.md.
    3. Toggle the set as the latest release option.
    4. Publish the release.
  11. Navigate to https://github.com/actions/cache/actions/workflows/release-new-action-version.yml
    1. There should be a workflow run queued with the same version number.
    2. Approve the run to publish the new version and update the major tags for this action.

Changelog

6.1.0

6.0.0

  • Updated @actions/cache to ^6.0.1, @actions/core to ^3.0.1, @actions/exec to ^3.0.0, @actions/io to ^3.0.2
  • Migrated to ESM module system
  • Upgraded Jest to v30 and test infrastructure to be ESM compatible

5.0.4

  • Bump minimatch to v3.1.5 (fixes ReDoS via globstar patterns)
  • Bump undici to v6.24.1 (WebSocket decompression bomb protection, header validation fixes)
  • Bump fast-xml-parser to v5.5.6

5.0.3

5.0.2

... (truncated)

Commits
  • 55cc834 Merge pull request #1768 from jasongin/readonly-cache
  • d8cd72f Bump @​actions/cache to v6.1.0 - handle cache write error due to RO token
  • 2c8a9bd Merge pull request #1760 from actions/samirat/esm_migration_and_package_update
  • e9b91fd Prettier fixes
  • e4884b8 Rebuild dist
  • 10baf01 Fixed licenses
  • e39b386 Fix test mock return order
  • b692820 PR feedback
  • 6074912 Rebuild dist bundles as ESM to match type:module
  • 5a912e8 Fix lint and jest issues
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/cache&package-manager=github_actions&previous-version=5.0.5&new-version=6.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs-build.yml | 2 +- .github/workflows/integration-vector-io-tests.yml | 2 +- .github/workflows/pre-commit.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index aea52dbc15a..b52905009df 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -34,7 +34,7 @@ jobs: cache-dependency-path: 'docs/package-lock.json' - name: Cache node_modules - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 id: cache-node-modules with: path: docs/node_modules diff --git a/.github/workflows/integration-vector-io-tests.yml b/.github/workflows/integration-vector-io-tests.yml index 0ef00a8b1cc..2f7815465ec 100644 --- a/.github/workflows/integration-vector-io-tests.yml +++ b/.github/workflows/integration-vector-io-tests.yml @@ -196,7 +196,7 @@ jobs: exit 1 - name: Cache Hugging Face models - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ~/.cache/huggingface key: hf-${{ runner.os }}-${{ matrix.python-version }}-nomic-embed-text-v1.5 diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 08dabaecf88..509c803cd14 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -62,7 +62,7 @@ jobs: run: python -m pip install 'pre-commit>=4.4.0' - name: Cache pre-commit - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v4 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v4 with: path: ~/.cache/pre-commit key: pre-commit-3|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }} From 3965fb461c920fc3d04db7716111d3164a9ec5ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 08:07:37 +0000 Subject: [PATCH 09/32] chore(github-deps): bump actions/setup-python from 6.2.0 to 6.3.0 (#6200) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6.2.0 to 6.3.0.
Release notes

Sourced from actions/setup-python's releases.

v6.3.0

What's Changed

Enhancement

Dependency update

Documentation

New Contributors

Full Changelog: https://github.com/actions/setup-python/compare/v6...v6.3.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-python&package-manager=github_actions&previous-version=6.2.0&new-version=6.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/backward-compat.yml | 4 ++-- .github/workflows/dependabot-constraints.yml | 2 +- .github/workflows/pre-commit.yml | 2 +- .github/workflows/pypi.yml | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/backward-compat.yml b/.github/workflows/backward-compat.yml index e36b28bbca4..45401599cca 100644 --- a/.github/workflows/backward-compat.yml +++ b/.github/workflows/backward-compat.yml @@ -36,7 +36,7 @@ jobs: fetch-depth: 0 # Need full history to access main branch - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: '3.12' @@ -446,7 +446,7 @@ jobs: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: '3.12' diff --git a/.github/workflows/dependabot-constraints.yml b/.github/workflows/dependabot-constraints.yml index 81cad22157b..12b7ef9f731 100644 --- a/.github/workflows/dependabot-constraints.yml +++ b/.github/workflows/dependabot-constraints.yml @@ -39,7 +39,7 @@ jobs: fetch-depth: 2 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: '3.12' diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 509c803cd14..701d18c8efa 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -36,7 +36,7 @@ jobs: fetch-depth: ${{ github.actor == 'dependabot[bot]' && 0 || 2 }} - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: '3.12' cache: pip diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 4bea46df8ff..8b09b9dab75 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -170,7 +170,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.12" @@ -309,7 +309,7 @@ jobs: # === PYTHON SETUP (for all Python packages) === - name: Set up Python if: steps.should-build.outputs.skip != 'true' && matrix.registry == 'pypi' - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.12" From 9972810574048c24c1ad55d6ba1951f1e642ec98 Mon Sep 17 00:00:00 2001 From: Eleanor Hu <145939433+EleanorWho@users.noreply.github.com> Date: Tue, 30 Jun 2026 09:08:17 +0100 Subject: [PATCH 10/32] fix(deps): bump urllib3 and python-dotenv constraints for multiple CVEs (#6184) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Add CVE reference comments and bump minimum version constraints for urllib3 and python-dotenv: | Package | Old Constraint | New Constraint | CVE(s) | |---|---|---|---| | `urllib3` | `>=2.7.0` (no comment) | `>=2.7.0` (comment added) | CVE-2026-44432: DoS via excessive decompression; CVE-2026-44431: cross-origin redirect header leak | | `python-dotenv` | (none) | `>=1.2.2` | CVE-2026-28684: arbitrary file overwrite via symlink following | ### Impact analysis - **urllib3**: Already at the fixed version (`>=2.7.0`). This change only adds CVE reference comments for traceability. - **python-dotenv**: Only `load_dotenv()` is used in the codebase. Vulnerable functions `set_key()`/`unset_key()` are never called. Bump is defensive. ## Test plan - [x] `uv run pre-commit run --all-files` — all checks passed - [x] `uv run pytest tests/unit/ -x --tb=short` — 2576 passed, 0 failed - [ ] Verify updated package versions resolve in clean install Signed-off-by: Eleanor Hu Co-authored-by: Claude Opus 4.6 (1M context) --- pyproject.toml | 4 ++-- uv.lock | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ee796c17dcc..7280bae7294 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ constraint-dependencies = [ "setuptools<81", # milvus-lite imports pkg_resources; setuptools 81+ removes it "starlette>=1.3.1", # CVE-2026-48710 "tornado>=6.5.5", - "urllib3>=2.7.0", + "urllib3>=2.7.0", # CVE-2026-44432: DoS via excessive decompression; CVE-2026-44431: cross-origin redirect header leak "transformers>=4.57.2,<5.0.0", # CVE-2026-1839 fix only in 5.x; ogx doesn't use Trainer; 5.x breaks HybridCache imports "werkzeug>=3.1.6", # CVE-2025-66221 + 2 more: safe_join() device name bypass ] @@ -57,7 +57,7 @@ dependencies = [ "jsonschema", "ogx-api", # API and provider specifications (local dev via tool.uv.sources) "openai>=2.41.0", - "python-dotenv", + "python-dotenv>=1.2.2", # CVE-2026-28684: arbitrary file overwrite via symlink following "pyjwt[crypto]>=2.13.0", # Pull crypto to support RS256 for jwt. Requires 2.12.0+ to fix CVE-2026-32597. "pydantic>=2.11.9", "rich", diff --git a/uv.lock b/uv.lock index d720f059807..aef8a2c1e9f 100644 --- a/uv.lock +++ b/uv.lock @@ -4370,7 +4370,7 @@ requires-dist = [ { name = "pymongo", marker = "extra == 'starter'" }, { name = "pypdf", marker = "extra == 'starter'", specifier = ">=6.13.0" }, { name = "pythainlp", marker = "extra == 'starter'" }, - { name = "python-dotenv" }, + { name = "python-dotenv", specifier = ">=1.2.2" }, { name = "pyyaml", specifier = ">=6.0" }, { name = "qdrant-client", marker = "extra == 'starter'" }, { name = "redis", marker = "extra == 'starter'", specifier = ">=8.0.0" }, From f9ad0af3f71e2884a1244d7d87f0e802f213b95b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 08:09:03 +0000 Subject: [PATCH 11/32] chore(github-deps): bump actions/setup-java from 5.2.0 to 5.4.0 (#6202) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.2.0 to 5.4.0.
Release notes

Sourced from actions/setup-java's releases.

v5.4.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/setup-java/compare/v5...v5.4.0

v5.3.0

What's Changed

... (truncated)

Commits
  • 1bcf9fb dist: Address Copilot review suggestions from PR #1042 (GraalVM Community) (#...
  • fa2c650 docs: note jdkfile approach for Early Access / unreleased JDK builds (#1058)
  • 1d56e31 dist: Add GraalVM Community distribution support (#1042)
  • 1d25252 chore: Harden workflows: least-privilege permissions + zizmor integration (#1...
  • 668c1ea docs: add post-install keytool import for the JDK cacerts trust store (#1051)
  • a9a46fb docs: document self-signed certificate / internal CA handling for GitHub Ente...
  • 5431e71 docs: add JavaFX Maven project configuration instructions (#1044)
  • 4baa9b4 docs: replace non-existent HelloWorldApp references with java --version (#1043)
  • eab4b08 Bump @​types/node from 25.9.3 to 26.0.0 (#1031)
  • bf0c0e6 Bump actions/checkout from 6 to 7 (#1032)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-java&package-manager=github_actions&previous-version=5.2.0&new-version=5.4.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/openapi-generator-validation.yml | 2 +- .github/workflows/publish-openapi-sdk.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/openapi-generator-validation.yml b/.github/workflows/openapi-generator-validation.yml index e7eb537ad79..965c21e2ae4 100644 --- a/.github/workflows/openapi-generator-validation.yml +++ b/.github/workflows/openapi-generator-validation.yml @@ -117,7 +117,7 @@ jobs: python-version: '3.12' - name: Set up Java - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 with: distribution: 'temurin' java-version: '11' diff --git a/.github/workflows/publish-openapi-sdk.yml b/.github/workflows/publish-openapi-sdk.yml index c22adc937b8..6a2dd419899 100644 --- a/.github/workflows/publish-openapi-sdk.yml +++ b/.github/workflows/publish-openapi-sdk.yml @@ -42,7 +42,7 @@ jobs: python-version: '3.12' - name: Set up Java - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 with: distribution: 'temurin' java-version: '11' From 17c3c19850e2fae2b40efa82ff255647d30a3724 Mon Sep 17 00:00:00 2001 From: Sumanth Kamenani Date: Tue, 30 Jun 2026 04:10:01 -0400 Subject: [PATCH 12/32] fix: require replay checks in ci status gate (#6188) ## Summary Make the required `ci-status` gate wait for the replay integration matrix when a PR touches files that should trigger replay tests. This keeps the aggregate status aligned with the provider replay checks that branch protection depends on. This also treats cancelled/action-required check runs as blocking and paginates check-run reads so large CI matrices are evaluated completely. ## Breaking changes None Signed-off-by: Sumanth Kamenani --- .github/workflows/ci-status.yml | 49 ++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-status.yml b/.github/workflows/ci-status.yml index eabe425d68a..341a09433e0 100644 --- a/.github/workflows/ci-status.yml +++ b/.github/workflows/ci-status.yml @@ -22,6 +22,7 @@ jobs: timeout-minutes: 180 permissions: checks: read + pull-requests: read steps: - name: Wait for CI checks to complete uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -43,11 +44,39 @@ jobs: const excludedApps = new Set(['mergify']); const terminalStatuses = new Set(['completed']); - const successConclusions = new Set(['success', 'skipped', 'neutral', 'cancelled']); - const failureConclusions = new Set(['failure', 'timed_out']); + const successConclusions = new Set(['success', 'skipped', 'neutral']); + const failureConclusions = new Set(['failure', 'timed_out', 'cancelled', 'action_required', 'startup_failure', 'stale']); + const replayCheckPrefix = 'Integration Tests ('; + const recordCheckPrefix = 'record-providers ('; + + function pathTriggersReplay(path) { + if (path.startsWith('src/ogx_ui/')) return false; + return path.startsWith('src/ogx/') || + path.startsWith('tests/') || + path === 'uv.lock' || + path === 'pyproject.toml' || + path === '.github/workflows/integration-tests.yml' || + path === '.github/actions/setup-ollama/action.yml' || + path === '.github/actions/setup-test-environment/action.yml' || + path === '.github/actions/run-and-record-tests/action.yml' || + path === 'scripts/integration-tests.sh' || + path === 'scripts/generate_ci_matrix.py'; + } + + let replayRequired = context.eventName === 'merge_group'; + if (context.payload.pull_request) { + const changedFiles = await github.paginate(github.rest.pulls.listFiles, { + owner, + repo, + pull_number: context.payload.pull_request.number, + per_page: 100, + }); + replayRequired = changedFiles.some(file => pathTriggersReplay(file.filename)); + core.info(`Replay required: ${replayRequired} (${changedFiles.length} changed file(s) checked)`); + } while (true) { - const { data: checkRuns } = await github.rest.checks.listForRef({ + const checkRuns = await github.paginate(github.rest.checks.listForRef, { owner, repo, ref: sha, @@ -55,7 +84,7 @@ jobs: }); // Filter to only GitHub Actions checks, excluding ourselves and bots - const relevant = checkRuns.check_runs.filter(cr => { + const relevant = checkRuns.filter(cr => { if (excludedChecks.has(cr.name)) return false; if (cr.app && excludedApps.has(cr.app.slug)) return false; // Only include GitHub Actions checks @@ -71,8 +100,11 @@ jobs: const pending = relevant.filter(cr => !terminalStatuses.has(cr.status)); const completed = relevant.filter(cr => terminalStatuses.has(cr.status)); + const replayChecks = relevant.filter(cr => cr.name.startsWith(replayCheckPrefix)); + const recordChecks = relevant.filter(cr => cr.name.startsWith(recordCheckPrefix)); core.info(`Checks: ${completed.length} completed, ${pending.length} pending out of ${relevant.length} total`); + core.info(`Replay checks: ${replayChecks.length}; record checks: ${recordChecks.length}`); for (const cr of completed) { core.info(` ✓ ${cr.name}: ${cr.conclusion}`); @@ -87,6 +119,15 @@ jobs: continue; } + if (replayRequired && replayChecks.length === 0) { + if (recordChecks.length > 0) { + core.warning('Record checks are present, but no replay matrix checks were found for this SHA.'); + } + core.info('Replay checks are required for this change. Waiting 30s for the replay workflow to appear...'); + await new Promise(r => setTimeout(r, 30000)); + continue; + } + // All checks completed — evaluate conclusions const failed = completed.filter(cr => failureConclusions.has(cr.conclusion)); From 1764a3506682af6b63d146c4996ec773ebea9482 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 08:19:51 +0000 Subject: [PATCH 13/32] chore(api-deps): bump opentelemetry-exporter-otlp-proto-http from 1.42.1 to 1.43.0 in /src/ogx_api (#6204) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [opentelemetry-exporter-otlp-proto-http](https://github.com/open-telemetry/opentelemetry-python) from 1.42.1 to 1.43.0.
Changelog

Sourced from opentelemetry-exporter-otlp-proto-http's changelog.

Version 1.43.0/0.64b0 (2026-06-24)

Added

  • opentelemetry-sdk: add add_metric_reader / remove_metric_reader public APIs to register / unregister metric readers at runtime. (#4863)
  • opentelemetry-exporter-prometheus: add support for configuring metric scope labels (#5123)
  • opentelemetry-exporter-otlp-proto-grpc: Add grpc error details to the log message that's written when the grpc call fails. (#5143)
  • opentelemetry-exporter-http-transport: add 'opentelemetry-exporter-http-transport' package for HTTP exporters (#5194)
  • opentelemetry-sdk: Add composite/development samplers support to declarative file configuration (#5201)
  • opentelemetry-exporter-otlp-json-file: Add OTLP JSON File exporter implementation (#5207)
  • opentelemetry-sdk: add _resolve_component shared utility for declarative config plugin loading, reducing boilerplate in exporter factory functions (#5215)
  • opentelemetry-sdk: add pull metric reader support to declarative file configuration, including Prometheus metric reader via the prometheus_development config field (#5216)
  • opentelemetry-proto-json: update to use opentelemetry-proto v1.10.0 (#5224)
  • opentelemetry-proto: bump maximum supported protobuf version to 7.x.x (#5251)
  • opentelemetry-sdk: add ServiceInstanceIdResourceDetector for populating service.instance.id (#5259)
  • opentelemetry-sdk: declarative config loader now recursively converts parsed dicts into typed dataclass instances, including nested dataclasses, lists of dataclasses, and enum values. End-to-end YAML/JSON → SDK configuration now works via the factory functions. (#5269)
  • opentelemetry-sdk: add configure_sdk(config) to the declarative configuration API. Single entry point that takes a parsed OpenTelemetryConfiguration, builds the resource, and applies the tracer/meter/logger providers and propagator globally. Honors the top-level disabled flag. (#5270)
  • opentelemetry-sdk: the SDK configurator now honors the OTEL_CONFIG_FILE environment variable. When set, the SDK loads and applies the referenced declarative configuration file (YAML or JSON) in place of the env-var-based

... (truncated)

Commits
  • fcbbeb8 [release/v1.43.x-0.64bx] Prepare release 1.43.0/0.64b0 (#5349)
  • b40dcbc opentelemetry-exporter-http-transport: enable entry-point loading of transpor...
  • 10e8577 update to Sphinx to 8.1.3 in order to support Python 3.14 (#5278)
  • 6ac6895 docs: add declarative configuration guide and example (#5309)
  • 13ad4d5 opentelemetry-api: normalize empty environment propagation names to "_" in En...
  • 6a0ab84 opentelemetry-sdk: merge doesn't need a copy, dict already does this (#5326)
  • ac7a3df feat(config): support OTEL_CONFIG_FILE in the SDK configurator (#5271)
  • fa75422 Add support for composite samplers in declarative config (#5201)
  • 43f079f Update json and proto encoder to always accept None type, cleanup code / test...
  • 53c9d96 chore: cleanup typo found in test (#5324)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=opentelemetry-exporter-otlp-proto-http&package-manager=uv&previous-version=1.42.1&new-version=1.43.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--------- Signed-off-by: dependabot[bot] Signed-off-by: github-actions[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: Sébastien Han --- src/ogx_api/pyproject.toml | 2 +- src/ogx_api/uv.lock | 44 +++++++++++++++--------------- uv.lock | 56 +++++++++++++++++++------------------- 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/ogx_api/pyproject.toml b/src/ogx_api/pyproject.toml index 459dba2f362..e19ebde7cca 100644 --- a/src/ogx_api/pyproject.toml +++ b/src/ogx_api/pyproject.toml @@ -36,7 +36,7 @@ dependencies = [ "pydantic>=2.11.9", "jsonschema>=4.26.0", "opentelemetry-sdk>=1.42.1", - "opentelemetry-exporter-otlp-proto-http>=1.42.1", + "opentelemetry-exporter-otlp-proto-http>=1.43.0", "opentelemetry-exporter-otlp-proto-grpc>=1.42.1", ] diff --git a/src/ogx_api/uv.lock b/src/ogx_api/uv.lock index 148057b38b2..8618813208e 100644 --- a/src/ogx_api/uv.lock +++ b/src/ogx_api/uv.lock @@ -373,7 +373,7 @@ requires-dist = [ { name = "jsonschema", specifier = ">=4.26.0" }, { name = "openai", specifier = ">=2.41.1" }, { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.42.1" }, - { name = "opentelemetry-exporter-otlp-proto-http", specifier = ">=1.42.1" }, + { name = "opentelemetry-exporter-otlp-proto-http", specifier = ">=1.43.0" }, { name = "opentelemetry-sdk", specifier = ">=1.42.1" }, { name = "pydantic", specifier = ">=2.11.9" }, ] @@ -399,31 +399,31 @@ wheels = [ [[package]] name = "opentelemetry-api" -version = "1.42.1" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b4/1c/125e1c936c0873796771b7f04f6c93b9f1bf5d424cea90fda94a99f61da8/opentelemetry_api-1.42.1.tar.gz", hash = "sha256:56c63bea9f77b62856be8c47600474acad853b2924b99b1687c4cb6297166716", size = 72296, upload-time = "2026-05-21T16:32:49.335Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/cc/e4c9584181f86494df0f6bdec1a4f3280c50db44704dc2a407e994fc87bb/opentelemetry_api-1.43.0.tar.gz", hash = "sha256:107d0d03857ea8fc7c5fcbbbd83f800c281f0d560553d61c1d675fccfd1761c1", size = 73476, upload-time = "2026-06-24T15:19:55.323Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/ca/9520cc1f3dfbbd03ac5903bbf55833e257bc64b1cf30fa8b0d6df374d821/opentelemetry_api-1.42.1-py3-none-any.whl", hash = "sha256:51a69edacadbc03a8950ace1c4c21099cacc538820ac2c9e36277e78cebba714", size = 61311, upload-time = "2026-05-21T16:32:28.822Z" }, + { url = "https://files.pythonhosted.org/packages/17/83/6dba32b85f31868400440dc7ad2ca1eab94cbbf3a7b0459ed39f8311a9e2/opentelemetry_api-1.43.0-py3-none-any.whl", hash = "sha256:20acf45e9b21851926835292e4045d290acade1edd2ff3de86d2f069687ba1fd", size = 61912, upload-time = "2026-06-24T15:19:35.434Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.42.1" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-proto" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0e/9c/216acfeaedadf2e1937f4373929b20f73197c5c4a2546d4f584b7fa63813/opentelemetry_exporter_otlp_proto_common-1.42.1.tar.gz", hash = "sha256:04f1f01fb597c4249dfcd7f8b861c902c2102369d376d9d346ff38de4469a2ee", size = 21433, upload-time = "2026-05-21T16:32:55.526Z" } +sdist = { url = "https://files.pythonhosted.org/packages/55/c1/e8098490ab15abf116dcaf9fa89ededcb35547c7d08d4b5a62f573dc1e63/opentelemetry_exporter_otlp_proto_common-1.43.0.tar.gz", hash = "sha256:c4e32ba6d6b13bdb2b8f6764c4fd28d00192826561aa04f6d14eedfce7ac076f", size = 20197, upload-time = "2026-06-24T15:20:00.247Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/43/2375e7612e1121a4518c17603b6e0b03ad94f565aafad53f464dc5be2bf6/opentelemetry_exporter_otlp_proto_common-1.42.1-py3-none-any.whl", hash = "sha256:f48d395ab815b444da118868977e9798ea354c25737d5cf39578ae894011c140", size = 17327, upload-time = "2026-05-21T16:32:33.387Z" }, + { url = "https://files.pythonhosted.org/packages/d0/b2/41ebc74ae1d5859901f1b69305de58724bf043381103d6ef413521cbc35a/opentelemetry_exporter_otlp_proto_common-1.43.0-py3-none-any.whl", hash = "sha256:123c3f9cc87218562490c63b36f497bf3a722faf174a515d1443f31ababa6264", size = 17048, upload-time = "2026-06-24T15:19:41.264Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.42.1" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, @@ -434,14 +434,14 @@ dependencies = [ { name = "opentelemetry-sdk" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/87/87/ca7fc790dfdbcf4f9e9aab14a39ef1b7508ead13707e283de0b3131478d2/opentelemetry_exporter_otlp_proto_grpc-1.42.1.tar.gz", hash = "sha256:975c4461f167dd8ed8857d68d3b6b25f3d272eab896f6a9470d0f5b90e2faf15", size = 27140, upload-time = "2026-05-21T16:32:56.162Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e2/1d/6336453716ca0a240d4417d19e6d5b77a5e7163e5670ec4f7ec4d3ede7bf/opentelemetry_exporter_otlp_proto_grpc-1.43.0.tar.gz", hash = "sha256:1b3e0627daa9bc21884d4a13946807c255eb558bfe5bdd543dffb6f4c9faee0d", size = 27213, upload-time = "2026-06-24T15:20:00.907Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/89/2b/28ba5b128f47fe8c3bab541000d6feb4b5a9bd26623ca013406f01c0fb60/opentelemetry_exporter_otlp_proto_grpc-1.42.1-py3-none-any.whl", hash = "sha256:0ae1177e2038b18a929b3098215243631ef91136cba26b7e2b12790ceb7e87cc", size = 19617, upload-time = "2026-05-21T16:32:34.278Z" }, + { url = "https://files.pythonhosted.org/packages/6d/74/2700b5d5c946bf2dba87073fce3dfc198c46bc92ea3d5693f54bc51c90b1/opentelemetry_exporter_otlp_proto_grpc-1.43.0-py3-none-any.whl", hash = "sha256:6a10d1feacffffda19acacbf277b736094b1e2f4dbb98c90ccb2c6e1962e2ec6", size = 19626, upload-time = "2026-06-24T15:19:42.233Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-http" -version = "1.42.1" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, @@ -452,48 +452,48 @@ dependencies = [ { name = "requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/32/826bfa1d80ecea24f47808de03cd4a0d13c17ecc07712f45123f0f61e4ac/opentelemetry_exporter_otlp_proto_http-1.42.1.tar.gz", hash = "sha256:bf142a21035d7571ac3a09cb2e5639f49886f243972883cfe777ed3bf02b734d", size = 25406, upload-time = "2026-05-21T16:32:56.807Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/92/0b9f56412483a8891d4843890294796c9df8ab42417bd9bad8035d840cb3/opentelemetry_exporter_otlp_proto_http-1.43.0.tar.gz", hash = "sha256:fa8a42bb7d00ee5391f4c0b04d8e6a46c03caa437903296ab73a81dc11ba118f", size = 25406, upload-time = "2026-06-24T15:20:01.515Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d3/96/82cb223a1502f0787d4bbff12907f5f8d870a50731febcd5818d93ef9555/opentelemetry_exporter_otlp_proto_http-1.42.1-py3-none-any.whl", hash = "sha256:00a16da1b312a1d6c7233d600d557c91df71125af73020f3b9a7765bd699d59d", size = 21793, upload-time = "2026-05-21T16:32:35.277Z" }, + { url = "https://files.pythonhosted.org/packages/b3/20/b685ed7af2e17c29ffc8af56f1fa8bc2033258fc30fb0d2b722f49d13ba0/opentelemetry_exporter_otlp_proto_http-1.43.0-py3-none-any.whl", hash = "sha256:647f603aa8efdbdb4dbff842e0729d0406a6fff26b295a72d3d60e7d963b2610", size = 21795, upload-time = "2026-06-24T15:19:43.164Z" }, ] [[package]] name = "opentelemetry-proto" -version = "1.42.1" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b4/55/63eac3e1089b768ba014091fdd2ae8a9a440c821ef5e2b786909c94c8836/opentelemetry_proto-1.42.1.tar.gz", hash = "sha256:c6a51e6b4f05ae63565f3a113217f3d2bfaec68f78c02d7a6c85f9010d1cfca6", size = 45839, upload-time = "2026-05-21T16:33:03.937Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/b9/d357faefb40bda1d4799913e6af611171ff22a2dedcb93576bc92242d056/opentelemetry_proto-1.43.0.tar.gz", hash = "sha256:224778df17e1f3fafeaaa21d874236ca5f6ffc2f86e0899298ec7351aac27924", size = 46481, upload-time = "2026-06-24T15:20:07.625Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/41/9d/171c02c84a76940b7e601805b3bb536985aded9168fbcc9ba52f0a730fa2/opentelemetry_proto-1.42.1-py3-none-any.whl", hash = "sha256:dedb74cba2886c59c7789b227a7a670613025a07489040050aedff6e5c0fb43c", size = 71782, upload-time = "2026-05-21T16:32:44.867Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a7/3e5308cf548b8f72529c7db1afdb3a404211982376a12927fd7759f77bf3/opentelemetry_proto-1.43.0-py3-none-any.whl", hash = "sha256:c58f1f7ef84bc7dc2834016c0c37fe0081dde7ca9f6339be1970fbf9cdaaa90d", size = 72489, upload-time = "2026-06-24T15:19:51.164Z" }, ] [[package]] name = "opentelemetry-sdk" -version = "1.42.1" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/40/f7/b390bd9bfd703bf98a68fea1f27786c6872331fd617164a54b8a59bdc008/opentelemetry_sdk-1.42.1.tar.gz", hash = "sha256:8c834e8f8c9ba4171d4ec843d0cb8a67e4c7394d3f9e9297e582cbd9456ddbf7", size = 239262, upload-time = "2026-05-21T16:33:04.641Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3e/eb/5041074274ac0956b03637cc039d434569112468e875eddfcc9a0674ce06/opentelemetry_sdk-1.43.0.tar.gz", hash = "sha256:d8187c81c162df9913e4003dd6485f7390d9a24fc17026ec7387b8b8218b08e9", size = 254744, upload-time = "2026-06-24T15:20:08.467Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/6b/4287766cfbde577ae2272e8884abac325aeaac0d64f41c61d5b8cc595105/opentelemetry_sdk-1.42.1-py3-none-any.whl", hash = "sha256:083cd4bbfaa5aa7b5a9e552430d9951219967cfb27aa61feb13a77aba1fc839d", size = 170907, upload-time = "2026-05-21T16:32:45.894Z" }, + { url = "https://files.pythonhosted.org/packages/49/e3/b17be23af124201c9f52eececd4cc8ddfed1597d37b4ee771895d325805c/opentelemetry_sdk-1.43.0-py3-none-any.whl", hash = "sha256:d1323a547c1ce69d6a069a17a44b7da82bb8b332051ecb074041f87642c86823", size = 178852, upload-time = "2026-06-24T15:19:52.169Z" }, ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.63b1" +version = "0.64b0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/93/99/4d7dd6df64795951413ce6e815f8cf1eb191daf7196ae86574589643d5f3/opentelemetry_semantic_conventions-0.63b1.tar.gz", hash = "sha256:3daf963611334b365e98a57438183eb012d3bfb40b2d931a9af613476b8701a9", size = 148340, upload-time = "2026-05-21T16:33:05.455Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/30/5f26df29509eccd86b99b481ac9ffa39da49ba9577cc69071c552ae30447/opentelemetry_semantic_conventions-0.64b0.tar.gz", hash = "sha256:72f76fb2d1582d9d033dd1fcd84532e961e6ff3d90d24ba6fabc72975a83864c", size = 148340, upload-time = "2026-06-24T15:20:09.267Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/7a/7fe66f5f3682b1dd47d88cc4e11f1c6c0966b737de2d16671146e23c39a5/opentelemetry_semantic_conventions-0.63b1-py3-none-any.whl", hash = "sha256:dfe5ef4dee82586b746f522b818ceb298d00b3d59f660042bd79404bff8d0682", size = 203713, upload-time = "2026-05-21T16:32:47.016Z" }, + { url = "https://files.pythonhosted.org/packages/f2/ca/23ba87a221b574a7c5a99d48849d80bfe8b047624681357e2b002e566187/opentelemetry_semantic_conventions-0.64b0-py3-none-any.whl", hash = "sha256:ea77e85e354b8f604ddbe5f3d9135216f982fa4d77e5859ac30f6d8a50505aa6", size = 203713, upload-time = "2026-06-24T15:19:53.339Z" }, ] [[package]] diff --git a/uv.lock b/uv.lock index aef8a2c1e9f..20e02235d64 100644 --- a/uv.lock +++ b/uv.lock @@ -4581,7 +4581,7 @@ requires-dist = [ { name = "jsonschema", specifier = ">=4.26.0" }, { name = "openai", specifier = ">=2.41.1" }, { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.42.1" }, - { name = "opentelemetry-exporter-otlp-proto-http", specifier = ">=1.42.1" }, + { name = "opentelemetry-exporter-otlp-proto-http", specifier = ">=1.43.0" }, { name = "opentelemetry-sdk", specifier = ">=1.42.1" }, { name = "pydantic", specifier = ">=2.11.9" }, ] @@ -4757,45 +4757,45 @@ wheels = [ [[package]] name = "opentelemetry-api" -version = "1.42.1" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b4/1c/125e1c936c0873796771b7f04f6c93b9f1bf5d424cea90fda94a99f61da8/opentelemetry_api-1.42.1.tar.gz", hash = "sha256:56c63bea9f77b62856be8c47600474acad853b2924b99b1687c4cb6297166716", size = 72296, upload-time = "2026-05-21T16:32:49.335Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/cc/e4c9584181f86494df0f6bdec1a4f3280c50db44704dc2a407e994fc87bb/opentelemetry_api-1.43.0.tar.gz", hash = "sha256:107d0d03857ea8fc7c5fcbbbd83f800c281f0d560553d61c1d675fccfd1761c1", size = 73476, upload-time = "2026-06-24T15:19:55.323Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/ca/9520cc1f3dfbbd03ac5903bbf55833e257bc64b1cf30fa8b0d6df374d821/opentelemetry_api-1.42.1-py3-none-any.whl", hash = "sha256:51a69edacadbc03a8950ace1c4c21099cacc538820ac2c9e36277e78cebba714", size = 61311, upload-time = "2026-05-21T16:32:28.822Z" }, + { url = "https://files.pythonhosted.org/packages/17/83/6dba32b85f31868400440dc7ad2ca1eab94cbbf3a7b0459ed39f8311a9e2/opentelemetry_api-1.43.0-py3-none-any.whl", hash = "sha256:20acf45e9b21851926835292e4045d290acade1edd2ff3de86d2f069687ba1fd", size = 61912, upload-time = "2026-06-24T15:19:35.434Z" }, ] [[package]] name = "opentelemetry-distro" -version = "0.63b1" +version = "0.64b0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-instrumentation" }, { name = "opentelemetry-sdk" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c5/97/87080029d9309841dd97db34130f9410cda77162843f81d09ad257dce1ef/opentelemetry_distro-0.63b1.tar.gz", hash = "sha256:f435098abc7953f58226e8bf79e4c90bc6b32e50aa75d6fa074201db8243b577", size = 2333, upload-time = "2026-05-21T16:36:11.285Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b7/e6/3142ab3b002f317b91d994526e70350629f848abb66d10dec87c1fa639a0/opentelemetry_distro-0.64b0.tar.gz", hash = "sha256:8a19716899854245b4028650ec1cca12d89f9be41571bbffe9e539cd55d2fd96", size = 2333, upload-time = "2026-06-24T15:19:10.381Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/35/97/16619e2e0e5192f2d1b8da2aaaefface05463cc1cfca6b81d3a3108ccedd/opentelemetry_distro-0.63b1-py3-none-any.whl", hash = "sha256:b405b04ad70e430390265eb38e82e067a84ca1f49a21429eaadb930c13330d66", size = 2777, upload-time = "2026-05-21T16:34:51.441Z" }, + { url = "https://files.pythonhosted.org/packages/a9/54/fdaf5d8a2d3633f11b860d7a328639ad49cddf3ad0f7e509bb488e68d029/opentelemetry_distro-0.64b0-py3-none-any.whl", hash = "sha256:ce97b6cedfcf03dc54035c422485412eda63250e094f4bd63ef57d017d823f3c", size = 2778, upload-time = "2026-06-24T15:18:13.406Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-common" -version = "1.42.1" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-proto" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0e/9c/216acfeaedadf2e1937f4373929b20f73197c5c4a2546d4f584b7fa63813/opentelemetry_exporter_otlp_proto_common-1.42.1.tar.gz", hash = "sha256:04f1f01fb597c4249dfcd7f8b861c902c2102369d376d9d346ff38de4469a2ee", size = 21433, upload-time = "2026-05-21T16:32:55.526Z" } +sdist = { url = "https://files.pythonhosted.org/packages/55/c1/e8098490ab15abf116dcaf9fa89ededcb35547c7d08d4b5a62f573dc1e63/opentelemetry_exporter_otlp_proto_common-1.43.0.tar.gz", hash = "sha256:c4e32ba6d6b13bdb2b8f6764c4fd28d00192826561aa04f6d14eedfce7ac076f", size = 20197, upload-time = "2026-06-24T15:20:00.247Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/43/2375e7612e1121a4518c17603b6e0b03ad94f565aafad53f464dc5be2bf6/opentelemetry_exporter_otlp_proto_common-1.42.1-py3-none-any.whl", hash = "sha256:f48d395ab815b444da118868977e9798ea354c25737d5cf39578ae894011c140", size = 17327, upload-time = "2026-05-21T16:32:33.387Z" }, + { url = "https://files.pythonhosted.org/packages/d0/b2/41ebc74ae1d5859901f1b69305de58724bf043381103d6ef413521cbc35a/opentelemetry_exporter_otlp_proto_common-1.43.0-py3-none-any.whl", hash = "sha256:123c3f9cc87218562490c63b36f497bf3a722faf174a515d1443f31ababa6264", size = 17048, upload-time = "2026-06-24T15:19:41.264Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.42.1" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, @@ -4806,14 +4806,14 @@ dependencies = [ { name = "opentelemetry-sdk" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/87/87/ca7fc790dfdbcf4f9e9aab14a39ef1b7508ead13707e283de0b3131478d2/opentelemetry_exporter_otlp_proto_grpc-1.42.1.tar.gz", hash = "sha256:975c4461f167dd8ed8857d68d3b6b25f3d272eab896f6a9470d0f5b90e2faf15", size = 27140, upload-time = "2026-05-21T16:32:56.162Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e2/1d/6336453716ca0a240d4417d19e6d5b77a5e7163e5670ec4f7ec4d3ede7bf/opentelemetry_exporter_otlp_proto_grpc-1.43.0.tar.gz", hash = "sha256:1b3e0627daa9bc21884d4a13946807c255eb558bfe5bdd543dffb6f4c9faee0d", size = 27213, upload-time = "2026-06-24T15:20:00.907Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/89/2b/28ba5b128f47fe8c3bab541000d6feb4b5a9bd26623ca013406f01c0fb60/opentelemetry_exporter_otlp_proto_grpc-1.42.1-py3-none-any.whl", hash = "sha256:0ae1177e2038b18a929b3098215243631ef91136cba26b7e2b12790ceb7e87cc", size = 19617, upload-time = "2026-05-21T16:32:34.278Z" }, + { url = "https://files.pythonhosted.org/packages/6d/74/2700b5d5c946bf2dba87073fce3dfc198c46bc92ea3d5693f54bc51c90b1/opentelemetry_exporter_otlp_proto_grpc-1.43.0-py3-none-any.whl", hash = "sha256:6a10d1feacffffda19acacbf277b736094b1e2f4dbb98c90ccb2c6e1962e2ec6", size = 19626, upload-time = "2026-06-24T15:19:42.233Z" }, ] [[package]] name = "opentelemetry-exporter-otlp-proto-http" -version = "1.42.1" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos" }, @@ -4824,14 +4824,14 @@ dependencies = [ { name = "requests" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/32/826bfa1d80ecea24f47808de03cd4a0d13c17ecc07712f45123f0f61e4ac/opentelemetry_exporter_otlp_proto_http-1.42.1.tar.gz", hash = "sha256:bf142a21035d7571ac3a09cb2e5639f49886f243972883cfe777ed3bf02b734d", size = 25406, upload-time = "2026-05-21T16:32:56.807Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/92/0b9f56412483a8891d4843890294796c9df8ab42417bd9bad8035d840cb3/opentelemetry_exporter_otlp_proto_http-1.43.0.tar.gz", hash = "sha256:fa8a42bb7d00ee5391f4c0b04d8e6a46c03caa437903296ab73a81dc11ba118f", size = 25406, upload-time = "2026-06-24T15:20:01.515Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d3/96/82cb223a1502f0787d4bbff12907f5f8d870a50731febcd5818d93ef9555/opentelemetry_exporter_otlp_proto_http-1.42.1-py3-none-any.whl", hash = "sha256:00a16da1b312a1d6c7233d600d557c91df71125af73020f3b9a7765bd699d59d", size = 21793, upload-time = "2026-05-21T16:32:35.277Z" }, + { url = "https://files.pythonhosted.org/packages/b3/20/b685ed7af2e17c29ffc8af56f1fa8bc2033258fc30fb0d2b722f49d13ba0/opentelemetry_exporter_otlp_proto_http-1.43.0-py3-none-any.whl", hash = "sha256:647f603aa8efdbdb4dbff842e0729d0406a6fff26b295a72d3d60e7d963b2610", size = 21795, upload-time = "2026-06-24T15:19:43.164Z" }, ] [[package]] name = "opentelemetry-instrumentation" -version = "0.63b1" +version = "0.64b0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, @@ -4839,48 +4839,48 @@ dependencies = [ { name = "packaging" }, { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/da/6d/4de72d97ff54db1ed270c7a59c9b904b917c0ac7af429c086c388b824ddb/opentelemetry_instrumentation-0.63b1.tar.gz", hash = "sha256:32368d6ae52c8de20aa790a6ad86b10a76f09956092337ae37d675773990e541", size = 41081, upload-time = "2026-05-21T16:36:14.206Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/97/02fe6e1c8b1ffac42d0b429c18080edb24e0e0d18c86612edf72b5752382/opentelemetry_instrumentation-0.64b0.tar.gz", hash = "sha256:b47d528dead6271d7743114417eb67fc915bd9258111c48dbf9a4951d2efa88d", size = 41935, upload-time = "2026-06-24T15:19:12.951Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/35/a1/9314e621c143e4d82a5bf7a43c2ff7a745d31023506336857607c8c543cc/opentelemetry_instrumentation-0.63b1-py3-none-any.whl", hash = "sha256:f1986716d52cc316ea5f60189098726a9071d8ecc0eee96c9ed110be08bade9c", size = 35577, upload-time = "2026-05-21T16:34:56.818Z" }, + { url = "https://files.pythonhosted.org/packages/d2/0c/cb9fe342de5299c7af24582eb7d788661cc53a1c4b904da92309caaa9417/opentelemetry_instrumentation-0.64b0-py3-none-any.whl", hash = "sha256:133ab7ffca796557aec059bf6be3190a34b6dea987f25be3d9409e230cbdad8b", size = 35880, upload-time = "2026-06-24T15:18:17.277Z" }, ] [[package]] name = "opentelemetry-proto" -version = "1.42.1" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b4/55/63eac3e1089b768ba014091fdd2ae8a9a440c821ef5e2b786909c94c8836/opentelemetry_proto-1.42.1.tar.gz", hash = "sha256:c6a51e6b4f05ae63565f3a113217f3d2bfaec68f78c02d7a6c85f9010d1cfca6", size = 45839, upload-time = "2026-05-21T16:33:03.937Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/b9/d357faefb40bda1d4799913e6af611171ff22a2dedcb93576bc92242d056/opentelemetry_proto-1.43.0.tar.gz", hash = "sha256:224778df17e1f3fafeaaa21d874236ca5f6ffc2f86e0899298ec7351aac27924", size = 46481, upload-time = "2026-06-24T15:20:07.625Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/41/9d/171c02c84a76940b7e601805b3bb536985aded9168fbcc9ba52f0a730fa2/opentelemetry_proto-1.42.1-py3-none-any.whl", hash = "sha256:dedb74cba2886c59c7789b227a7a670613025a07489040050aedff6e5c0fb43c", size = 71782, upload-time = "2026-05-21T16:32:44.867Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a7/3e5308cf548b8f72529c7db1afdb3a404211982376a12927fd7759f77bf3/opentelemetry_proto-1.43.0-py3-none-any.whl", hash = "sha256:c58f1f7ef84bc7dc2834016c0c37fe0081dde7ca9f6339be1970fbf9cdaaa90d", size = 72489, upload-time = "2026-06-24T15:19:51.164Z" }, ] [[package]] name = "opentelemetry-sdk" -version = "1.42.1" +version = "1.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/40/f7/b390bd9bfd703bf98a68fea1f27786c6872331fd617164a54b8a59bdc008/opentelemetry_sdk-1.42.1.tar.gz", hash = "sha256:8c834e8f8c9ba4171d4ec843d0cb8a67e4c7394d3f9e9297e582cbd9456ddbf7", size = 239262, upload-time = "2026-05-21T16:33:04.641Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3e/eb/5041074274ac0956b03637cc039d434569112468e875eddfcc9a0674ce06/opentelemetry_sdk-1.43.0.tar.gz", hash = "sha256:d8187c81c162df9913e4003dd6485f7390d9a24fc17026ec7387b8b8218b08e9", size = 254744, upload-time = "2026-06-24T15:20:08.467Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/6b/4287766cfbde577ae2272e8884abac325aeaac0d64f41c61d5b8cc595105/opentelemetry_sdk-1.42.1-py3-none-any.whl", hash = "sha256:083cd4bbfaa5aa7b5a9e552430d9951219967cfb27aa61feb13a77aba1fc839d", size = 170907, upload-time = "2026-05-21T16:32:45.894Z" }, + { url = "https://files.pythonhosted.org/packages/49/e3/b17be23af124201c9f52eececd4cc8ddfed1597d37b4ee771895d325805c/opentelemetry_sdk-1.43.0-py3-none-any.whl", hash = "sha256:d1323a547c1ce69d6a069a17a44b7da82bb8b332051ecb074041f87642c86823", size = 178852, upload-time = "2026-06-24T15:19:52.169Z" }, ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.63b1" +version = "0.64b0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/93/99/4d7dd6df64795951413ce6e815f8cf1eb191daf7196ae86574589643d5f3/opentelemetry_semantic_conventions-0.63b1.tar.gz", hash = "sha256:3daf963611334b365e98a57438183eb012d3bfb40b2d931a9af613476b8701a9", size = 148340, upload-time = "2026-05-21T16:33:05.455Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/30/5f26df29509eccd86b99b481ac9ffa39da49ba9577cc69071c552ae30447/opentelemetry_semantic_conventions-0.64b0.tar.gz", hash = "sha256:72f76fb2d1582d9d033dd1fcd84532e961e6ff3d90d24ba6fabc72975a83864c", size = 148340, upload-time = "2026-06-24T15:20:09.267Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/7a/7fe66f5f3682b1dd47d88cc4e11f1c6c0966b737de2d16671146e23c39a5/opentelemetry_semantic_conventions-0.63b1-py3-none-any.whl", hash = "sha256:dfe5ef4dee82586b746f522b818ceb298d00b3d59f660042bd79404bff8d0682", size = 203713, upload-time = "2026-05-21T16:32:47.016Z" }, + { url = "https://files.pythonhosted.org/packages/f2/ca/23ba87a221b574a7c5a99d48849d80bfe8b047624681357e2b002e566187/opentelemetry_semantic_conventions-0.64b0-py3-none-any.whl", hash = "sha256:ea77e85e354b8f604ddbe5f3d9135216f982fa4d77e5859ac30f6d8a50505aa6", size = 203713, upload-time = "2026-06-24T15:19:53.339Z" }, ] [[package]] From 80a1c06511892c563518263c6c1a88dcb813d734 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 11:49:16 +0200 Subject: [PATCH 14/32] chore(python-deps): bump python-socketio from 5.16.1 to 5.16.2 (#6217) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [python-socketio](https://github.com/miguelgrinberg/python-socketio) from 5.16.1 to 5.16.2.
Release notes

Sourced from python-socketio's releases.

Release 5.16.2

See CHANGES.md for release notes.

Changelog

Sourced from python-socketio's changelog.

python-socketio change log

Release 5.16.3 - 2026-06-15

  • Catch all exceptions in redis and rabbitmq client managers #1581 (commit)

Release 5.16.2 - 2026-05-21

Release 5.16.1 - 2026-02-06

  • Use configured JSON module in managers #1549 (commit)
  • Admin UI fixes: remove duplicate tasks, report transport upgrades (commit)
  • Switch to Furo documentation template (commit)
  • Add Python free-threading to CI #1554 (commit)

Release 5.16.0 - 2025-12-24

  • Address deprecation warnings (commit)
  • Drop Python 3.8 and 3.9 from CI builds (commit)

Release 5.15.1 - 2025-12-16

  • Restore support multiple arguments via pubsub emits #1540 (commit)

Release 5.15.0 - 2025-11-22

Release 5.14.3 - 2025-10-29

  • Support Python's native ConnectionRefusedError exception to reject a connection #1515 (commit)
  • Push binary data to the aiopika client manager #1514 (commit)

Release 5.14.2 - 2025-10-15

  • Restore binary message support in message queue setups #1509 (commit)
  • Fix formatting of client connection error #1507 (commit)
  • Add 3.14 and pypy-3.11 CI tasks (commit)
  • Improve documentation of the BaseManager.get_participants() method (commit)

Release 5.14.1 - 2025-10-02

... (truncated)

Commits
  • 6e2b717 Release 5.16.2
  • cb65829 update python-engineio version
  • ca140fe prevent unnecessary resource allocation (#1574)
  • b29beef tox configuration
  • e898130 Bump ujson from 5.4.0 to 5.12.1 in /examples/server/sanic (#1573) #nolog
  • 05c32f5 Bump qs and body-parser in /examples/server/javascript (#1572) #nolog
  • 287dc67 Bump qs and body-parser in /examples/client/javascript (#1571) #nolog
  • 664dc27 add zizmor to ci (#1570)
  • 14c6236 Bump django in /examples/server/wsgi/django_socketio (#1566) #nolog
  • 29b2e5c Bump aiohttp from 3.13.3 to 3.13.4 in /examples/server/aiohttp (#1565) #nolog
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=python-socketio&package-manager=uv&previous-version=5.16.1&new-version=5.16.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ogx-ai/ogx/network/alerts).
--------- Signed-off-by: dependabot[bot] Signed-off-by: github-actions[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] --- pyproject.toml | 2 +- uv.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7280bae7294..0d5bc2abcad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ constraint-dependencies = [ "protobuf>=5.29.6", # CVE-2025-4565 + CVE-2026-0994: parsing vulnerabilities "pyasn1>=0.6.3", # CVE-2026-30922: DoS via unbounded recursion "python-multipart>=0.0.31", # CVE-2026-40347: header injection; CVE-2026-42561: DoS via oversized headers - "python-socketio>=5.14.0", # CVE-2025-61765: RCE via pickle deserialization + "python-socketio>=5.16.2", # CVE-2025-61765: RCE via pickle deserialization "requests>=2.34.2", "setuptools<81", # milvus-lite imports pkg_resources; setuptools 81+ removes it "starlette>=1.3.1", # CVE-2026-48710 diff --git a/uv.lock b/uv.lock index 20e02235d64..a7f7cde19c3 100644 --- a/uv.lock +++ b/uv.lock @@ -35,7 +35,7 @@ constraints = [ { name = "protobuf", specifier = ">=5.29.6" }, { name = "pyasn1", specifier = ">=0.6.3" }, { name = "python-multipart", specifier = ">=0.0.31" }, - { name = "python-socketio", specifier = ">=5.14.0" }, + { name = "python-socketio", specifier = ">=5.16.2" }, { name = "requests", specifier = ">=2.34.2" }, { name = "setuptools", specifier = "<81" }, { name = "starlette", specifier = ">=1.3.1" }, @@ -6226,14 +6226,14 @@ wheels = [ [[package]] name = "python-engineio" -version = "4.13.1" +version = "4.13.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "simple-websocket" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/34/12/bdef9dbeedbe2cdeba2a2056ad27b1fb081557d34b69a97f574843462cae/python_engineio-4.13.1.tar.gz", hash = "sha256:0a853fcef52f5b345425d8c2b921ac85023a04dfcf75d7b74696c61e940fd066", size = 92348, upload-time = "2026-02-06T23:38:06.12Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fb/a0/f75491f942184d9960b15e763270f765fe9f239745ca5f9e16289011aed4/python_engineio-4.13.3.tar.gz", hash = "sha256:572b7783e341fed21edbc7cea297ccd378dad79265fdde96aa4664420a7c06c9", size = 79734, upload-time = "2026-06-20T22:53:52.197Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/54/0cce26da03a981f949bb8449c9778537f75f5917c172e1d2992ff25cb57d/python_engineio-4.13.1-py3-none-any.whl", hash = "sha256:f32ad10589859c11053ad7d9bb3c9695cdf862113bfb0d20bc4d890198287399", size = 59847, upload-time = "2026-02-06T23:38:04.861Z" }, + { url = "https://files.pythonhosted.org/packages/5b/96/82f6328e410515fab21d5602ba35b9377a47b5a141a0c1f9efa00ce21eb4/python_engineio-4.13.3-py3-none-any.whl", hash = "sha256:1f60ecaf1358190f0e26c48c578a60428dc02a8f1295bc3dbf53d1b31116821f", size = 59993, upload-time = "2026-06-20T22:53:50.775Z" }, ] [[package]] @@ -6262,15 +6262,15 @@ wheels = [ [[package]] name = "python-socketio" -version = "5.16.1" +version = "5.16.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "bidict" }, { name = "python-engineio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/59/81/cf8284f45e32efa18d3848ed82cdd4dcc1b657b082458fbe01ad3e1f2f8d/python_socketio-5.16.1.tar.gz", hash = "sha256:f863f98eacce81ceea2e742f6388e10ca3cdd0764be21d30d5196470edf5ea89", size = 128508, upload-time = "2026-02-06T23:42:07Z" } +sdist = { url = "https://files.pythonhosted.org/packages/07/dd/6fd4112b941f7d39b8171b6ba17902609bd8fa2059c3812a3c29dade13e7/python_socketio-5.16.2.tar.gz", hash = "sha256:ad88c228d921646efa436c0a0df217e364ef30ec072df4041484e54d49c15989", size = 128011, upload-time = "2026-05-21T22:03:44.418Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/07/c7/deb8c5e604404dbf10a3808a858946ca3547692ff6316b698945bb72177e/python_socketio-5.16.1-py3-none-any.whl", hash = "sha256:a3eb1702e92aa2f2b5d3ba00261b61f062cce51f1cfb6900bf3ab4d1934d2d35", size = 82054, upload-time = "2026-02-06T23:42:05.772Z" }, + { url = "https://files.pythonhosted.org/packages/72/dc/0decaf5da92a7a969374474025787102d811d42aed1d32191fa338620e15/python_socketio-5.16.2-py3-none-any.whl", hash = "sha256:bef2da3374fd533aed4297f57b4f6512b52aa51604cb0da2165f401291c5ca20", size = 82137, upload-time = "2026-05-21T22:03:42.616Z" }, ] [package.optional-dependencies] From 08eb59f19b700ad3d2ad46616b1d71cac3348d0a Mon Sep 17 00:00:00 2001 From: Matthew Farrellee Date: Tue, 30 Jun 2026 03:50:00 -0600 Subject: [PATCH 15/32] fix(letsgo): use single asyncio.run() in run_letsgo_cmd for clean event loop lifecycle (#6206) Run provider probing, model listing, and embedding detection inside one asyncio.run() scope in run_letsgo_cmd. After that completes, uvicorn starts its own event loop without conflict. - Promote _run_letsgo_cmd_impl to async, sharing event loops with _probe_provider_availability, _autodetect_providers, and _detect_embedding_model - Call async functions with await instead of asyncio.run() - uvicorn runs entirely outside asyncio.run() scope - Update tests: async test methods use @pytest.mark.asyncio, sync tests patch _autodetect_providers with AsyncMock Signed-off-by: Matthew Farrellee --- src/ogx/cli/stack/lets_go.py | 67 +++-- tests/unit/cli/test_stack_lets_go.py | 364 ++++++++------------------- 2 files changed, 144 insertions(+), 287 deletions(-) diff --git a/src/ogx/cli/stack/lets_go.py b/src/ogx/cli/stack/lets_go.py index 916cd3bd4df..378065e6eb2 100644 --- a/src/ogx/cli/stack/lets_go.py +++ b/src/ogx/cli/stack/lets_go.py @@ -314,7 +314,11 @@ def _add_file_search_and_responses(run_config: StackConfig) -> None: cprint(" ✓ inline::builtin responses (built-in)", color="green") -def run_letsgo_cmd(args: argparse.Namespace, parser: argparse.ArgumentParser) -> None: +async def _run_letsgo_cmd_impl(args: argparse.Namespace, parser: argparse.ArgumentParser) -> dict[str, Any]: + """Async core: provider probing, config generation, and embedding detection. + + Returns a dict with 'config_file', 'stack_args', and 'port' for the caller + to pass to uvicorn after asyncio.run() returns.""" if args.enable_ui: try: _start_ui_development_server(args.port) @@ -325,7 +329,7 @@ def run_letsgo_cmd(args: argparse.Namespace, parser: argparse.ArgumentParser) -> providers_spec = args.providers_override autodetect_embedding: tuple[QualifiedModel, int | None] | None = None else: - providers_spec, autodetect_embedding = _autodetect_providers(debug=getattr(args, "debug", False)) + providers_spec, autodetect_embedding = await _autodetect_providers(debug=getattr(args, "debug", False)) has_inference = any(p.startswith("inference=") for p in (providers_spec or "").split(",")) if not has_inference: @@ -392,7 +396,7 @@ def run_letsgo_cmd(args: argparse.Namespace, parser: argparse.ArgumentParser) -> _add_file_search_and_responses(run_config) elif "vector_io" in run_config.providers: detected_result = ( - autodetect_embedding if autodetect_embedding is not None else _detect_embedding_model(run_config) + autodetect_embedding if autodetect_embedding is not None else await _detect_embedding_model(run_config) ) if detected_result: detected, embedding_dimension = detected_result @@ -456,11 +460,26 @@ def run_letsgo_cmd(args: argparse.Namespace, parser: argparse.ArgumentParser) -> with open(config_file, "w") as f: yaml.dump(config_dict, f, default_flow_style=False, sort_keys=False) + return { + "config_file": config_file, + "stack_args": argparse.Namespace( + port=args.port, + enable_ui=args.enable_ui, + providers=None, + ), + } + + +def run_letsgo_cmd(args: argparse.Namespace, parser: argparse.ArgumentParser) -> None: + """Entry point for `ogx letsgo`. + + Provider probing and embedding detection run inside asyncio.run() on + _run_letsgo_cmd_impl. After it returns, we call _uvicorn_run in a sync + context so uvicorn can start its own event loop without conflict.""" + result = asyncio.run(_run_letsgo_cmd_impl(args, parser)) + config_file: Path = result["config_file"] + stack_args: argparse.Namespace = result["stack_args"] try: - stack_args = argparse.Namespace() - stack_args.port = args.port - stack_args.enable_ui = args.enable_ui - stack_args.providers = None _uvicorn_run(config_file, stack_args, parser) except Exception: logger.exception("Failed to start the stack server") @@ -493,7 +512,7 @@ def _install_provider_deps(normal_deps: list[str], special_deps: list[str]) -> N ) -def _autodetect_providers(debug: bool = False) -> tuple[str, tuple[QualifiedModel, int | None] | None]: +async def _autodetect_providers(debug: bool = False) -> tuple[str, tuple[QualifiedModel, int | None] | None]: """Probe all candidate providers and return a spec string and first detected embedding model. Each provider is probed by instantiating it and calling list_models() to confirm @@ -523,7 +542,7 @@ def _autodetect_providers(debug: bool = False) -> tuple[str, tuple[QualifiedMode detected_embedding: tuple[QualifiedModel, int | None] | None = None cprint("Scanning for available providers...", color="cyan") for provider_type, base_url_env, default_base_url, required_api_key_env, optional_api_key_env in candidates: - status, models, base_url, base_source, pip_packages = _probe_provider_availability( + status, models, base_url, base_source, pip_packages = await _probe_provider_availability( provider_type, base_url_env, default_base_url, required_api_key_env, optional_api_key_env, debug=debug ) @@ -681,24 +700,20 @@ def _pick_embedding_from_models(models: list[Any], provider_id: str) -> tuple[Qu return best -def _detect_embedding_model(run_config: StackConfig) -> tuple[QualifiedModel, int | None] | None: +async def _detect_embedding_model(run_config: StackConfig) -> tuple[QualifiedModel, int | None] | None: """Find an embedding model by instantiating each inference provider and calling list_models(). Returns tuple of (QualifiedModel, embedding_dimension) or None if not found. Dimension may be None if not available in model metadata — caller must handle this. """ - - async def _detect_async() -> tuple[QualifiedModel, int | None] | None: - for provider in run_config.providers.get("inference", []): - if not provider.provider_id: - continue - models = await _list_models_from_provider(provider) - result = _pick_embedding_from_models(models, provider.provider_id) - if result is not None: - return result - return None - - return asyncio.run(_detect_async()) + for provider in run_config.providers.get("inference", []): + if not provider.provider_id: + continue + models = await _list_models_from_provider(provider) + result = _pick_embedding_from_models(models, provider.provider_id) + if result is not None: + return result + return None async def _instantiate_with_timeout( @@ -748,7 +763,7 @@ def _suppress_provider_logs(suppress: bool = True) -> Generator[None, None, None logging.disable(previous_disable_level) -def _probe_provider_availability( +async def _probe_provider_availability( provider_type: str, base_url_env: str | None, default_base_url: str, @@ -864,7 +879,7 @@ def _probe_provider_availability( factory_name=_FactoryDispatcher.method_name_for_spec(provider_spec), ) # Pass empty deps dict {} for single-provider probing - provider: ProbeableProvider = asyncio.run(_instantiate_with_timeout(factory_fn, config)) # type: ignore[arg-type] + provider: ProbeableProvider = await _instantiate_with_timeout(factory_fn, config) # type: ignore[arg-type] logger.debug("Provider instantiated successfully for provider", provider_type=provider_type) # Set required attributes (normally done by resolver) @@ -882,14 +897,14 @@ def _probe_provider_availability( # List models with timeout try: logger.debug("Calling list_models for provider", provider_type=provider_type) - models = asyncio.run(_list_models_with_timeout(provider, timeout_seconds=5)) + models = await _list_models_with_timeout(provider, timeout_seconds=5) logger.debug("Listed models for provider", provider_type=provider_type, model_count=len(models)) # Cleanup provider: call shutdown() if available. try: shutdown_result = provider.shutdown() if shutdown_result is not None: - asyncio.run(shutdown_result) # type: ignore[arg-type] + await shutdown_result except AttributeError: # Provider did not declare `shutdown()`; surface as a warning. cprint( diff --git a/tests/unit/cli/test_stack_lets_go.py b/tests/unit/cli/test_stack_lets_go.py index 9615a72085f..5a1aaf8cdfb 100644 --- a/tests/unit/cli/test_stack_lets_go.py +++ b/tests/unit/cli/test_stack_lets_go.py @@ -8,7 +8,7 @@ import argparse import warnings -from unittest.mock import MagicMock, patch +from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -17,11 +17,10 @@ _CLAUDE_CODE_ALIASES, _CLAUDE_CODE_PROVIDER_PRIORITY, StackLetsGo, + _autodetect_providers, _build_claude_code_aliases, _ProbeStatus, ) -from ogx.core.datatypes import QualifiedModel -from ogx_api import ModelType @pytest.fixture @@ -104,46 +103,30 @@ def test_all_options(self, top_level_letsgo: LetsGo): class TestAutodetect: - @patch( - "ogx.cli.stack.lets_go._probe_provider_availability", - return_value=(_ProbeStatus.UNREACHABLE, [], "", "default", None), - ) - def test_autodetect_no_providers(self, mock_probe: MagicMock): - from ogx.cli.stack.lets_go import _autodetect_providers - - parts = _autodetect_providers()[0].split(",") - assert "files=inline::localfs" in parts - assert "vector_io=inline::faiss" in parts - - @patch( - "ogx.cli.stack.lets_go._probe_provider_availability", - return_value=(_ProbeStatus.NO_KEY, [], "", "default", None), - ) - def test_no_key_providers_excluded(self, mock_probe: MagicMock): - from ogx.cli.stack.lets_go import _autodetect_providers - - parts = _autodetect_providers()[0].split(",") - assert "files=inline::localfs" in parts - assert "vector_io=inline::faiss" in parts - - @patch( - "ogx.cli.stack.lets_go._probe_provider_availability", - return_value=(_ProbeStatus.OK, [], "http://test", "default", None), - ) - def test_autodetect_all_ok(self, mock_probe: MagicMock): - from ogx.cli.stack.lets_go import _autodetect_providers - - spec, _ = _autodetect_providers() - parts = spec.split(",") - assert "inference=remote::ollama" in parts - assert "inference=remote::anthropic" in parts - assert "files=inline::localfs" in parts - assert len(parts) == 13 # 8 probed + 5 inline - - @patch("ogx.cli.stack.lets_go._probe_provider_availability") - def test_autodetect_only_ollama(self, mock_probe: MagicMock): - from ogx.cli.stack.lets_go import _autodetect_providers - + async def test_autodetect_no_providers(self): + with patch("ogx.cli.stack.lets_go._probe_provider_availability") as m: + m.return_value = (_ProbeStatus.UNREACHABLE, [], "", "default", None) + parts = (await _autodetect_providers())[0].split(",") + assert "files=inline::localfs" in parts + assert "vector_io=inline::faiss" in parts + + async def test_no_key_providers_excluded(self): + with patch("ogx.cli.stack.lets_go._probe_provider_availability") as m: + m.return_value = (_ProbeStatus.NO_KEY, [], "", "default", None) + parts = (await _autodetect_providers())[0].split(",") + assert "files=inline::localfs" in parts + assert "vector_io=inline::faiss" in parts + + async def test_autodetect_all_ok(self): + with patch("ogx.cli.stack.lets_go._probe_provider_availability") as m: + m.return_value = (_ProbeStatus.OK, [], "http://test", "default", None) + spec, _ = await _autodetect_providers() + parts = spec.split(",") + assert "inference=remote::ollama" in parts + assert "inference=remote::anthropic" in parts + assert "files=inline::localfs" in parts + + async def test_autodetect_only_ollama(self): def side_effect( provider_type: str, base_url_env: object, @@ -156,16 +139,12 @@ def side_effect( return (_ProbeStatus.OK, [], "http://localhost:11434/v1", "default", None) return (_ProbeStatus.UNREACHABLE, [], "", "default", None) - mock_probe.side_effect = side_effect - parts = _autodetect_providers()[0].split(",") - assert "inference=remote::ollama" in parts - assert "files=inline::localfs" in parts - assert len(parts) == 6 # 1 inference + 5 inline - - @patch("ogx.cli.stack.lets_go._probe_provider_availability") - def test_autodetect_uses_env_var_name(self, mock_probe: MagicMock, monkeypatch: pytest.MonkeyPatch): - from ogx.cli.stack.lets_go import _autodetect_providers + with patch("ogx.cli.stack.lets_go._probe_provider_availability", side_effect=side_effect): + parts = (await _autodetect_providers())[0].split(",") + assert "inference=remote::ollama" in parts + assert len(parts) == 6 # 1 inference + 5 inline + async def test_autodetect_uses_env_var_name(self, monkeypatch: pytest.MonkeyPatch): monkeypatch.setenv("OLLAMA_URL", "http://myhost:11434/v1") captured: list[str] = [] @@ -181,16 +160,11 @@ def side_effect( captured.append(base_url_env) return (_ProbeStatus.UNREACHABLE, [], "", "default", None) - mock_probe.side_effect = side_effect - _autodetect_providers() - assert captured[0] == "OLLAMA_URL" - - @patch("ogx.cli.stack.lets_go._probe_provider_availability") - def test_autodetect_result_order_matches_candidate_order( - self, mock_probe: MagicMock, monkeypatch: pytest.MonkeyPatch - ): - from ogx.cli.stack.lets_go import _autodetect_providers + with patch("ogx.cli.stack.lets_go._probe_provider_availability", side_effect=side_effect): + await _autodetect_providers() + assert captured[0] == "OLLAMA_URL" + async def test_autodetect_result_order_matches_candidate_order(self, monkeypatch: pytest.MonkeyPatch): monkeypatch.setenv("OPENAI_API_KEY", "sk-test") def side_effect( @@ -205,14 +179,11 @@ def side_effect( return (_ProbeStatus.OK, [], "http://test", "default", None) return (_ProbeStatus.UNREACHABLE, [], "", "default", None) - mock_probe.side_effect = side_effect - parts = _autodetect_providers()[0].split(",") - assert parts.index("inference=remote::ollama") < parts.index("inference=remote::openai") - - @patch("ogx.cli.stack.lets_go._probe_provider_availability") - def test_autodetect_includes_vllm_on_needs_key(self, mock_probe: MagicMock, monkeypatch: pytest.MonkeyPatch): - from ogx.cli.stack.lets_go import _autodetect_providers + with patch("ogx.cli.stack.lets_go._probe_provider_availability", side_effect=side_effect): + parts = (await _autodetect_providers())[0].split(",") + assert parts.index("inference=remote::ollama") < parts.index("inference=remote::openai") + async def test_autodetect_includes_vllm_on_needs_key(self, monkeypatch: pytest.MonkeyPatch): monkeypatch.delenv("VLLM_API_TOKEN", raising=False) def side_effect( @@ -227,176 +198,77 @@ def side_effect( return (_ProbeStatus.NEEDS_KEY, [], "http://localhost:8000/v1", "default", None) return (_ProbeStatus.UNREACHABLE, [], "", "default", None) - mock_probe.side_effect = side_effect - parts = _autodetect_providers()[0].split(",") - assert "inference=remote::vllm" in parts - + with patch("ogx.cli.stack.lets_go._probe_provider_availability", side_effect=side_effect): + parts = (await _autodetect_providers())[0].split(",") + assert "inference=remote::vllm" in parts -class TestRunCommand: - def test_no_inference_provider_exits(self, lets_go: StackLetsGo): - args = lets_go.parser.parse_args([]) - with ( - patch( - "ogx.cli.stack.lets_go._autodetect_providers", - return_value=( - "files=inline::localfs,vector_io=inline::faiss,tool_runtime=inline::file-search,responses=inline::builtin", - None, - ), - ), - warnings.catch_warnings(), - pytest.raises(SystemExit), - ): - warnings.simplefilter("ignore", FutureWarning) - lets_go._run_stack_lets_go_cmd(args) + async def test_autodetect_detects_embedding_when_no_key_env(self, monkeypatch: pytest.MonkeyPatch): + monkeypatch.delenv("OPENAI_API_KEY", raising=False) - def test_empty_spec_exits(self, lets_go: StackLetsGo): - args = lets_go.parser.parse_args([]) - with ( - patch("ogx.cli.stack.lets_go._autodetect_providers", return_value=("", None)), - warnings.catch_warnings(), - pytest.raises(SystemExit), - ): - warnings.simplefilter("ignore", FutureWarning) - lets_go._run_stack_lets_go_cmd(args) + def side_effect( + provider_type: str, + base_url_env: object, + default_base_url: str, + required_api_key_env: object, + optional_api_key_env: object = None, + debug: bool = False, + ) -> tuple: + if provider_type == "remote::openai": + # No key → NO_KEY status + return (_ProbeStatus.NO_KEY, [], "https://api.openai.com/v1", "default", None) + return (_ProbeStatus.UNREACHABLE, [], "", "default", None) - @patch("ogx.cli.stack.lets_go._uvicorn_run") - @patch("ogx.cli.stack.lets_go.get_provider_dependencies", return_value=([], [], [])) - @patch("ogx.cli.stack.lets_go.run_config_from_dynamic_config_spec") - def test_providers_override_skips_autodetect( - self, - mock_build_config: MagicMock, - mock_get_deps: MagicMock, - mock_uvicorn_run: MagicMock, - lets_go: StackLetsGo, - ): - args = lets_go.parser.parse_args(["--providers-override", "inference=remote::ollama"]) - mock_cfg = MagicMock() - mock_cfg.model_dump.return_value = {} - mock_build_config.return_value = mock_cfg + with patch("ogx.cli.stack.lets_go._probe_provider_availability", side_effect=side_effect): + spec, embedding = await _autodetect_providers() + assert embedding is None - with ( - patch("ogx.cli.stack.lets_go._autodetect_providers") as mock_detect, - patch("builtins.open", MagicMock()), - patch("ogx.cli.stack.lets_go.yaml.dump"), - warnings.catch_warnings(), - ): - warnings.simplefilter("ignore", FutureWarning) - lets_go._run_stack_lets_go_cmd(args) - mock_detect.assert_not_called() - @patch("ogx.cli.stack.lets_go._uvicorn_run") - @patch("ogx.cli.stack.lets_go.get_provider_dependencies", return_value=([], [], [])) - @patch("ogx.cli.stack.lets_go.run_config_from_dynamic_config_spec") - def test_run_command_uses_autodetected_providers( - self, - mock_build_config: MagicMock, - mock_get_deps: MagicMock, - mock_uvicorn_run: MagicMock, - lets_go: StackLetsGo, - ): - args = lets_go.parser.parse_args([]) - mock_cfg = MagicMock() - mock_cfg.model_dump.return_value = {} - mock_build_config.return_value = mock_cfg +class TestRunCommandSync: + """Tests that interact with the sync CLI entry point via _run_stack_lets_go_cmd. - with ( - patch("ogx.cli.stack.lets_go._autodetect_providers", return_value=("inference=remote::ollama", None)), - patch("builtins.open", MagicMock()), - patch("ogx.cli.stack.lets_go.yaml.dump"), - warnings.catch_warnings(), - ): - warnings.simplefilter("ignore", FutureWarning) - lets_go._run_stack_lets_go_cmd(args) + These patch `_autodetect_providers` with AsyncMock because it is now async. + run_letsgo_cmd internally calls asyncio.run(), so these tests must not use + the async test marker (which would have a running event loop already). + """ - mock_build_config.assert_called_once() - assert mock_build_config.call_args.kwargs["dynamic_config_spec"] == "inference=remote::ollama" - - @patch("ogx.cli.stack.lets_go._uvicorn_run") - @patch("ogx.cli.stack.lets_go.subprocess.run") - @patch("ogx.cli.stack.lets_go.get_provider_dependencies", return_value=(["httpx", "faiss-cpu"], [], [])) - @patch("ogx.cli.stack.lets_go.run_config_from_dynamic_config_spec") - def test_install_deps_called_by_default( - self, - mock_build_config: MagicMock, - mock_get_deps: MagicMock, - mock_subprocess: MagicMock, - mock_uvicorn_run: MagicMock, - lets_go: StackLetsGo, - ): + def test_no_inference_provider_exits(self, lets_go: StackLetsGo): args = lets_go.parser.parse_args([]) - mock_cfg = MagicMock() - mock_cfg.model_dump.return_value = {} - mock_build_config.return_value = mock_cfg - mock_subprocess.return_value = MagicMock(returncode=0) - - with ( - patch("ogx.cli.stack.lets_go._autodetect_providers", return_value=("inference=remote::ollama", None)), - patch("builtins.open", MagicMock()), - patch("ogx.cli.stack.lets_go.yaml.dump"), - warnings.catch_warnings(), - ): + with warnings.catch_warnings(): warnings.simplefilter("ignore", FutureWarning) - lets_go._run_stack_lets_go_cmd(args) - - mock_subprocess.assert_called_once() - call_args = mock_subprocess.call_args[0][0] - assert "httpx" in call_args - assert "faiss-cpu" in call_args - - @patch("ogx.cli.stack.lets_go._uvicorn_run") - @patch("ogx.cli.stack.lets_go.subprocess.run") - @patch("ogx.cli.stack.lets_go.get_provider_dependencies", return_value=(["httpx"], [], [])) - @patch("ogx.cli.stack.lets_go.run_config_from_dynamic_config_spec") - def test_install_deps_skipped_with_flag( - self, - mock_build_config: MagicMock, - mock_get_deps: MagicMock, - mock_subprocess: MagicMock, - mock_uvicorn_run: MagicMock, - lets_go: StackLetsGo, - ): - args = lets_go.parser.parse_args(["--skip-install-deps"]) - mock_cfg = MagicMock() - mock_cfg.model_dump.return_value = {} - mock_build_config.return_value = mock_cfg + with pytest.raises(SystemExit): + with patch( + "ogx.cli.stack.lets_go._autodetect_providers", + AsyncMock( + return_value=( + "files=inline::localfs,vector_io=inline::faiss,tool_runtime=inline::file-search,responses=inline::builtin", + None, + ) + ), + ): + lets_go._run_stack_lets_go_cmd(args) - with ( - patch("ogx.cli.stack.lets_go._autodetect_providers", return_value=("inference=remote::ollama", None)), - patch("builtins.open", MagicMock()), - patch("ogx.cli.stack.lets_go.yaml.dump"), - warnings.catch_warnings(), - ): + def test_empty_spec_exits(self, lets_go: StackLetsGo): + args = lets_go.parser.parse_args([]) + with warnings.catch_warnings(): warnings.simplefilter("ignore", FutureWarning) - lets_go._run_stack_lets_go_cmd(args) + with pytest.raises(SystemExit): + with patch("ogx.cli.stack.lets_go._autodetect_providers", AsyncMock(return_value=("", None))): + lets_go._run_stack_lets_go_cmd(args) - mock_subprocess.assert_not_called() - - @patch("ogx.cli.stack.lets_go._uvicorn_run") - @patch("ogx.cli.stack.lets_go.get_provider_dependencies", return_value=([], [], [])) - @patch("ogx.cli.stack.lets_go.run_config_from_dynamic_config_spec") - @patch("ogx.cli.stack.lets_go._detect_embedding_model") - def test_autodetected_embedding_model_is_registered_as_embedding( - self, - mock_detect_embedding_model: MagicMock, - mock_build_config: MagicMock, - mock_get_deps: MagicMock, - mock_uvicorn_run: MagicMock, - lets_go: StackLetsGo, - ): + def test_run_command_uses_autodetected_providers(self, lets_go: StackLetsGo): args = lets_go.parser.parse_args([]) mock_cfg = MagicMock() - mock_cfg.providers = {"inference": [MagicMock()], "vector_io": [MagicMock()]} - mock_cfg.vector_stores = None - mock_cfg.registered_resources.models = [] mock_cfg.model_dump.return_value = {} - mock_build_config.return_value = mock_cfg - mock_detect_embedding_model.return_value = ( - QualifiedModel(provider_id="openai", model_id="Qwen/Qwen3-Embedding-0.6B"), - 512, - ) with ( - patch("ogx.cli.stack.lets_go._autodetect_providers", return_value=("inference=remote::openai", None)), + patch("ogx.cli.stack.lets_go._uvicorn_run"), + patch("ogx.cli.stack.lets_go.get_provider_dependencies", return_value=([], [], [])), + patch("ogx.cli.stack.lets_go.subprocess.run"), + patch("ogx.cli.stack.lets_go.run_config_from_dynamic_config_spec", return_value=mock_cfg), + patch( + "ogx.cli.stack.lets_go._autodetect_providers", + AsyncMock(return_value=("inference=remote::ollama", None)), + ), patch("builtins.open", MagicMock()), patch("ogx.cli.stack.lets_go.yaml.dump"), warnings.catch_warnings(), @@ -404,56 +276,26 @@ def test_autodetected_embedding_model_is_registered_as_embedding( warnings.simplefilter("ignore", FutureWarning) lets_go._run_stack_lets_go_cmd(args) - matches = [ - model - for model in mock_cfg.registered_resources.models - if model.provider_id == "openai" - and model.model_id == "Qwen/Qwen3-Embedding-0.6B" - and model.provider_model_id == "Qwen/Qwen3-Embedding-0.6B" - and model.model_type == ModelType.embedding - and model.metadata.get("embedding_dimension") == 512 - ] - assert len(matches) == 1 - - @patch("ogx.cli.stack.lets_go._uvicorn_run") - @patch("ogx.cli.stack.lets_go.get_provider_dependencies", return_value=([], [], [])) - @patch("ogx.cli.stack.lets_go.run_config_from_dynamic_config_spec") - def test_default_embedding_model_sets_temp_embedding_dimension_metadata( - self, - mock_build_config: MagicMock, - mock_get_deps: MagicMock, - mock_uvicorn_run: MagicMock, - lets_go: StackLetsGo, - ): - args = lets_go.parser.parse_args( - ["--default-embedding-model", "openai/Qwen/Qwen3-Embedding-0.6B", "--default-embedding-dimension", "512"] - ) + assert mock_cfg.model_dump.called + + def test_providers_override_skips_autodetect(self, lets_go: StackLetsGo): + args = lets_go.parser.parse_args(["--providers-override", "inference=remote::ollama"]) mock_cfg = MagicMock() - mock_cfg.providers = {"inference": [MagicMock()], "vector_io": [MagicMock()]} - mock_cfg.vector_stores = None - mock_cfg.registered_resources.models = [] mock_cfg.model_dump.return_value = {} - mock_build_config.return_value = mock_cfg with ( - patch("ogx.cli.stack.lets_go._autodetect_providers", return_value=("inference=remote::openai", None)), + patch("ogx.cli.stack.lets_go._uvicorn_run"), + patch("ogx.cli.stack.lets_go.get_provider_dependencies", return_value=([], [], [])), + patch("ogx.cli.stack.lets_go.subprocess.run"), + patch("ogx.cli.stack.lets_go.run_config_from_dynamic_config_spec", return_value=mock_cfg), + patch("ogx.cli.stack.lets_go._autodetect_providers") as mock_detect, patch("builtins.open", MagicMock()), patch("ogx.cli.stack.lets_go.yaml.dump"), warnings.catch_warnings(), ): warnings.simplefilter("ignore", FutureWarning) lets_go._run_stack_lets_go_cmd(args) - - matches = [ - model - for model in mock_cfg.registered_resources.models - if model.provider_id == "openai" - and model.model_id == "Qwen/Qwen3-Embedding-0.6B" - and model.provider_model_id == "Qwen/Qwen3-Embedding-0.6B" - and model.model_type == ModelType.embedding - and model.metadata.get("embedding_dimension") == 512 - ] - assert len(matches) == 1 + mock_detect.assert_not_called() class TestDeprecation: From fb378fadc37a54b12447cfb41bae8544e40e68cd Mon Sep 17 00:00:00 2001 From: Artemy <7879901+Artemon-line@users.noreply.github.com> Date: Tue, 30 Jun 2026 10:53:22 +0100 Subject: [PATCH 16/32] fix(file_processors): allow owner-encrypted PDFs in pypdf processor (#6182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary The `is_encrypted` check in the pypdf file processor rejects all PDFs with any encryption metadata, including owner-encrypted documents that require no password to read. Many corporate PDFs (SEC filings, earnings press releases) use owner encryption to restrict printing/copying while keeping content freely readable. This PR attempts `reader.decrypt("")` and checks the return value — this succeeds for owner-encrypted PDFs (`PasswordType.OWNER_PASSWORD = 2`) and returns `PasswordType.NOT_DECRYPTED = 0` for truly password-protected ones. ### Why check the return value (not just catch exceptions) `pypdf`'s `decrypt()` uses a return-code pattern, not exceptions: | `decrypt("")` result | `PasswordType` | int | bool | Meaning | |---|---|---|---|---| | Owner-encrypted (no user password) | `OWNER_PASSWORD` | `2` | `True` | Readable — allow | | User password matches `""` | `USER_PASSWORD` | `1` | `True` | Readable — allow | | Wrong password | `NOT_DECRYPTED` | `0` | `False` | Cannot read — reject 422 | | Corrupted encryption metadata | raises `Exception` | — | — | Cannot read — reject 422 | ## Test Plan ```bash uv run pytest tests/unit/providers/file_processor/test_pypdf_validation.py -v ``` ### Condition coverage Three new tests cover every branch of the `if reader.is_encrypted` block: | Test | `decrypt("")` behavior | Expected | Verified against unfixed code | |---|---|---|---| | `test_rejects_password_protected_pdf` | returns `0` (`NOT_DECRYPTED`) | 422 | FAILS without fix (falls through) | | `test_rejects_corrupted_encrypted_pdf` | raises `Exception` | 422 | passes (caught by `except`) | | `test_allows_owner_encrypted_pdf` | returns `2` (`OWNER_PASSWORD`) | processes normally | passes (decrypt succeeds) | ``` tests/unit/providers/file_processor/test_pypdf_validation.py::test_rejects_docx_with_422 PASSED tests/unit/providers/file_processor/test_pypdf_validation.py::test_rejects_pptx_with_422 PASSED tests/unit/providers/file_processor/test_pypdf_validation.py::test_rejects_xlsx_with_422 PASSED tests/unit/providers/file_processor/test_pypdf_validation.py::test_allows_pdf PASSED tests/unit/providers/file_processor/test_pypdf_validation.py::test_allows_text_files PASSED tests/unit/providers/file_processor/test_pypdf_validation.py::test_allows_csv_files PASSED tests/unit/providers/file_processor/test_pypdf_validation.py::test_allows_markdown_files PASSED tests/unit/providers/file_processor/test_pypdf_validation.py::test_rejects_password_protected_pdf PASSED tests/unit/providers/file_processor/test_pypdf_validation.py::test_rejects_corrupted_encrypted_pdf PASSED tests/unit/providers/file_processor/test_pypdf_validation.py::test_allows_owner_encrypted_pdf PASSED 10 passed ``` Fixes #6181 Signed-off-by: Artemy Hladenko --------- Signed-off-by: Artemy Hladenko Signed-off-by: Artemy --- .../inline/file_processor/pypdf/pypdf.py | 8 ++- .../file_processor/test_pypdf_validation.py | 55 ++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/ogx/providers/inline/file_processor/pypdf/pypdf.py b/src/ogx/providers/inline/file_processor/pypdf/pypdf.py index d3780958473..7677890d0b0 100644 --- a/src/ogx/providers/inline/file_processor/pypdf/pypdf.py +++ b/src/ogx/providers/inline/file_processor/pypdf/pypdf.py @@ -103,7 +103,13 @@ def _process_pdf( reader = PdfReader(pdf_bytes) if reader.is_encrypted: - raise HTTPException(status_code=422, detail="Password-protected PDFs are not supported") + try: + if not reader.decrypt(""): + raise HTTPException(status_code=422, detail="Password-protected PDFs are not supported") + except HTTPException: + raise + except Exception: + raise HTTPException(status_code=422, detail="Password-protected PDFs are not supported") from None text_content, failed_pages = self._extract_pdf_text(reader) diff --git a/tests/unit/providers/file_processor/test_pypdf_validation.py b/tests/unit/providers/file_processor/test_pypdf_validation.py index 9f7106a0096..64bc4d911b2 100644 --- a/tests/unit/providers/file_processor/test_pypdf_validation.py +++ b/tests/unit/providers/file_processor/test_pypdf_validation.py @@ -5,10 +5,11 @@ # the root directory of this source tree. import io -from unittest.mock import MagicMock +from unittest.mock import MagicMock, patch import pytest from fastapi import HTTPException, UploadFile +from pypdf import PdfReader from ogx.providers.inline.file_processor.pypdf.config import PyPDFFileProcessorConfig from ogx.providers.inline.file_processor.pypdf.pypdf import PyPDFFileProcessor @@ -87,3 +88,55 @@ async def test_allows_markdown_files(pypdf_processor): result = await pypdf_processor.process_file(file=file) assert result is not None assert len(result.chunks) >= 1 + + +async def test_rejects_password_protected_pdf(pypdf_processor): + pdf_bytes = b"%PDF-1.4\n1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n2 0 obj\n<< /Type /Pages /Kids [] /Count 0 >>\nendobj\nxref\n0 3\n0000000000 65535 f \n0000000009 00000 n \n0000000058 00000 n \ntrailer\n<< /Size 3 /Root 1 0 R >>\nstartxref\n115\n%%EOF" + file = UploadFile(filename="secret.pdf", file=io.BytesIO(pdf_bytes)) + + mock_reader = MagicMock(spec=PdfReader) + mock_reader.is_encrypted = True + mock_reader.decrypt.return_value = 0 + + with patch("ogx.providers.inline.file_processor.pypdf.pypdf.PdfReader", return_value=mock_reader): + with pytest.raises(HTTPException) as exc_info: + await pypdf_processor.process_file(file=file) + + assert exc_info.value.status_code == 422 + assert "Password-protected" in exc_info.value.detail + + +async def test_rejects_corrupted_encrypted_pdf(pypdf_processor): + pdf_bytes = b"%PDF-1.4\n1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n2 0 obj\n<< /Type /Pages /Kids [] /Count 0 >>\nendobj\nxref\n0 3\n0000000000 65535 f \n0000000009 00000 n \n0000000058 00000 n \ntrailer\n<< /Size 3 /Root 1 0 R >>\nstartxref\n115\n%%EOF" + file = UploadFile(filename="corrupted.pdf", file=io.BytesIO(pdf_bytes)) + + mock_reader = MagicMock(spec=PdfReader) + mock_reader.is_encrypted = True + mock_reader.decrypt.side_effect = Exception("corrupted encryption metadata") + + with patch("ogx.providers.inline.file_processor.pypdf.pypdf.PdfReader", return_value=mock_reader): + with pytest.raises(HTTPException) as exc_info: + await pypdf_processor.process_file(file=file) + + assert exc_info.value.status_code == 422 + assert "Password-protected" in exc_info.value.detail + + +async def test_allows_owner_encrypted_pdf(pypdf_processor): + pdf_bytes = b"%PDF-1.4\n1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n2 0 obj\n<< /Type /Pages /Kids [] /Count 0 >>\nendobj\nxref\n0 3\n0000000000 65535 f \n0000000009 00000 n \n0000000058 00000 n \ntrailer\n<< /Size 3 /Root 1 0 R >>\nstartxref\n115\n%%EOF" + file = UploadFile(filename="ibm-earnings.pdf", file=io.BytesIO(pdf_bytes)) + + mock_page = MagicMock() + mock_page.extract_text.return_value = "IBM quarterly earnings results" + + mock_reader = MagicMock(spec=PdfReader) + mock_reader.is_encrypted = True + mock_reader.decrypt.return_value = 2 + mock_reader.pages = [mock_page] + mock_reader.metadata = None + + with patch("ogx.providers.inline.file_processor.pypdf.pypdf.PdfReader", return_value=mock_reader): + result = await pypdf_processor.process_file(file=file) + + assert result is not None + assert len(result.chunks) >= 1 From 8182d5b018784f5838b8eda82ab3ef3110a66955 Mon Sep 17 00:00:00 2001 From: Michael <104119185+Mykelxu@users.noreply.github.com> Date: Tue, 30 Jun 2026 05:57:25 -0400 Subject: [PATCH 17/32] fix: honor file_search ranking_options.weights (#6198) ## What does this PR do? Closes #6189. This PR makes `tools[].ranking_options.weights` take effect for Responses API `file_search` hybrid reranking. `ranking_options.weights` was already preserved through the Responses file_search request path, but the downstream reranking consumers ignored the explicit vector/keyword weights. This change: - applies explicit vector/keyword weights in in-memory weighted and RRF reranking - passes explicit weights into Milvus native weighted hybrid search - routes Milvus native RRF-with-weights through the in-memory hybrid path because Milvus `RRFRanker` does not support explicit weights - adds regression tests for Responses propagation, reranker behavior, along with Milvus handling ## Test Plan Relevant unit tests: `uv run pytest tests/unit/providers/utils/memory/test_reranking.py tests/unit/providers/responses/builtin/test_openai_responses_tools.py tests/unit/providers/test_milvus_weights.py -x --tb=short` Result: `38 passed` Lint: `uv run ruff check src/ogx/providers/utils/vector_io/vector_utils.py src/ogx/providers/remote/vector_io/milvus/milvus.py tests/unit/providers/utils/memory/test_reranking.py tests/unit/providers/responses/builtin/test_openai_responses_tools.py tests/unit/providers/test_milvus_weights.py` Result: `All checks passed` --------- Signed-off-by: Mykelxu --- .../remote/vector_io/milvus/milvus.py | 12 +- .../providers/utils/vector_io/vector_utils.py | 31 ++++- ...i_responses_file_search_ranking_options.py | 47 ++++++++ tests/unit/providers/test_milvus_weights.py | 110 ++++++++++++++++++ .../providers/utils/memory/test_reranking.py | 62 ++++++++++ 5 files changed, 259 insertions(+), 3 deletions(-) create mode 100644 tests/unit/providers/responses/builtin/test_openai_responses_file_search_ranking_options.py create mode 100644 tests/unit/providers/test_milvus_weights.py diff --git a/src/ogx/providers/remote/vector_io/milvus/milvus.py b/src/ogx/providers/remote/vector_io/milvus/milvus.py index 0ccb837e268..4a4c0a52309 100644 --- a/src/ogx/providers/remote/vector_io/milvus/milvus.py +++ b/src/ogx/providers/remote/vector_io/milvus/milvus.py @@ -318,7 +318,8 @@ async def query_hybrid( reranker_params: dict[str, Any] | None = None, filters: Filter | None = None, ) -> QueryChunksResponse: - if self.use_native_hybrid: + weighted_rrf = reranker_type != RERANKER_TYPE_WEIGHTED and bool((reranker_params or {}).get("weights")) + if self.use_native_hybrid and not weighted_rrf: return await self._query_hybrid_native( embedding, query_string, k, score_threshold, reranker_type, reranker_params, filters ) @@ -354,7 +355,14 @@ async def _query_hybrid_native( if reranker_type == RERANKER_TYPE_WEIGHTED: alpha = (reranker_params or {}).get("alpha", 0.5) - rerank = WeightedRanker(alpha, 1 - alpha) + weights = (reranker_params or {}).get("weights") + if isinstance(weights, dict): + vector_weight = float(weights.get("vector", 0.0)) + keyword_weight = float(weights.get("keyword", 0.0)) + else: + vector_weight = alpha + keyword_weight = 1 - alpha + rerank = WeightedRanker(vector_weight, keyword_weight) else: impact_factor = (reranker_params or {}).get("impact_factor", 60.0) rerank = RRFRanker(impact_factor) diff --git a/src/ogx/providers/utils/vector_io/vector_utils.py b/src/ogx/providers/utils/vector_io/vector_utils.py index 0808af263af..49506fa270b 100644 --- a/src/ogx/providers/utils/vector_io/vector_utils.py +++ b/src/ogx/providers/utils/vector_io/vector_utils.py @@ -135,7 +135,7 @@ def combine_search_results( vector_scores: dict[str, float], keyword_scores: dict[str, float], reranker_type: str = "rrf", - reranker_params: dict[str, float] | None = None, + reranker_params: dict[str, Any] | None = None, ) -> dict[str, float]: """ Combine vector and keyword search results using specified reranking strategy. @@ -152,12 +152,41 @@ def combine_search_results( if reranker_params is None: reranker_params = {} + weights = reranker_params.get("weights") if reranker_type == "weighted": alpha = reranker_params.get("alpha", 0.5) + if isinstance(weights, dict): + vector_weight = float(weights.get("vector", 0.0)) + keyword_weight = float(weights.get("keyword", 0.0)) + all_ids = set(vector_scores.keys()) | set(keyword_scores.keys()) + normalized_vector_scores = WeightedInMemoryAggregator._normalize_scores(vector_scores) + normalized_keyword_scores = WeightedInMemoryAggregator._normalize_scores(keyword_scores) + return { + doc_id: (keyword_weight * normalized_keyword_scores.get(doc_id, 0.0)) + + (vector_weight * normalized_vector_scores.get(doc_id, 0.0)) + for doc_id in all_ids + } return WeightedInMemoryAggregator.weighted_rerank(vector_scores, keyword_scores, alpha) else: # Default to RRF for None, RRF, or any unknown types impact_factor = reranker_params.get("impact_factor", 60.0) + if isinstance(weights, dict): + vector_weight = float(weights.get("vector", 0.0)) + keyword_weight = float(weights.get("keyword", 0.0)) + vector_ranks = { + doc_id: i + 1 + for i, (doc_id, _) in enumerate(sorted(vector_scores.items(), key=lambda x: x[1], reverse=True)) + } + keyword_ranks = { + doc_id: i + 1 + for i, (doc_id, _) in enumerate(sorted(keyword_scores.items(), key=lambda x: x[1], reverse=True)) + } + all_ids = set(vector_scores.keys()) | set(keyword_scores.keys()) + return { + doc_id: (vector_weight / (impact_factor + vector_ranks.get(doc_id, float("inf")))) + + (keyword_weight / (impact_factor + keyword_ranks.get(doc_id, float("inf")))) + for doc_id in all_ids + } return WeightedInMemoryAggregator.rrf_rerank(vector_scores, keyword_scores, impact_factor) diff --git a/tests/unit/providers/responses/builtin/test_openai_responses_file_search_ranking_options.py b/tests/unit/providers/responses/builtin/test_openai_responses_file_search_ranking_options.py new file mode 100644 index 00000000000..22ae942470a --- /dev/null +++ b/tests/unit/providers/responses/builtin/test_openai_responses_file_search_ranking_options.py @@ -0,0 +1,47 @@ +# Copyright (c) The OGX Contributors. +# All rights reserved. +# +# This source code is licensed under the terms described in the LICENSE file in +# the root directory of this source tree. + +from ogx.core.datatypes import VectorStoresConfig +from ogx.providers.inline.responses.builtin.responses.tool_executor import ToolExecutor +from ogx_api.openai_responses import OpenAIResponseInputToolFileSearch +from ogx_api.vector_io import SearchRankingOptions, VectorStoreSearchResponsePage + + +async def test_file_search_forwards_ranking_options_weights(mock_vector_io_api): + """Test that file_search forwards ranking_options.weights to vector store search.""" + query = "What is machine learning?" + vector_store_id = "test_vector_store" + ranking_options = SearchRankingOptions( + ranker="rrf", + weights={"vector": 1.0, "keyword": 0.0}, + ) + + mock_vector_io_api.openai_search_vector_store.return_value = VectorStoreSearchResponsePage( + search_query=[query], + has_more=False, + data=[], + ) + tool_executor = ToolExecutor( + tool_groups_api=None, # type: ignore + tool_runtime_api=None, # type: ignore + vector_io_api=mock_vector_io_api, + vector_stores_config=VectorStoresConfig(), + mcp_session_manager=None, + ) + + file_search_tool = OpenAIResponseInputToolFileSearch( + vector_store_ids=[vector_store_id], + ranking_options=ranking_options, + ) + await tool_executor._execute_file_search_via_vector_store( + query=query, + response_file_search_tool=file_search_tool, + ) + + call_kwargs = mock_vector_io_api.openai_search_vector_store.call_args + request = call_kwargs.kwargs["request"] + assert request.ranking_options == ranking_options + assert request.ranking_options.weights == {"vector": 1.0, "keyword": 0.0} diff --git a/tests/unit/providers/test_milvus_weights.py b/tests/unit/providers/test_milvus_weights.py new file mode 100644 index 00000000000..0fc95682340 --- /dev/null +++ b/tests/unit/providers/test_milvus_weights.py @@ -0,0 +1,110 @@ +# Copyright (c) The OGX Contributors. +# All rights reserved. +# +# This source code is licensed under the terms described in the LICENSE file in +# the root directory of this source tree. + +import sys +from types import ModuleType, SimpleNamespace +from typing import Any + +if "pymilvus" not in sys.modules: + pymilvus = ModuleType("pymilvus") + pymilvus.AnnSearchRequest = object + pymilvus.DataType = SimpleNamespace( + VARCHAR="VARCHAR", + FLOAT_VECTOR="FLOAT_VECTOR", + JSON="JSON", + SPARSE_FLOAT_VECTOR="SPARSE_FLOAT_VECTOR", + ) + pymilvus.Function = object + pymilvus.FunctionType = SimpleNamespace(BM25="BM25") + pymilvus.MilvusClient = object + pymilvus.RRFRanker = object + pymilvus.WeightedRanker = object + sys.modules["pymilvus"] = pymilvus + +from ogx.providers.remote.vector_io.milvus import milvus as milvus_module +from ogx.providers.remote.vector_io.milvus.milvus import MilvusIndex + + +class _FakeEmbedding: + def tolist(self) -> list[float]: + return [0.1, 0.2, 0.3] + + +class _FakeClient: + def __init__(self) -> None: + self.hybrid_search_kwargs: dict[str, Any] | None = None + + def hybrid_search(self, **kwargs: Any) -> list[list[Any]]: + self.hybrid_search_kwargs = kwargs + return [[]] + + +class _FakeAnnSearchRequest: + def __init__(self, **kwargs: Any) -> None: + self.kwargs = kwargs + + +async def test_milvus_native_weighted_hybrid_uses_ranking_option_weights(monkeypatch): + ranker_weights: list[tuple[float, float]] = [] + + class _FakeWeightedRanker: + def __init__(self, vector_weight: float, keyword_weight: float) -> None: + ranker_weights.append((vector_weight, keyword_weight)) + + monkeypatch.setattr(milvus_module, "AnnSearchRequest", _FakeAnnSearchRequest) + monkeypatch.setattr(milvus_module, "WeightedRanker", _FakeWeightedRanker) + + client = _FakeClient() + index = MilvusIndex( + client=client, # type: ignore[arg-type] + vector_store=SimpleNamespace(identifier="test-store", embedding_dimension=3), # type: ignore[arg-type] + use_native_hybrid=True, + ) + + await index._query_hybrid_native( + embedding=_FakeEmbedding(), # type: ignore[arg-type] + query_string="test query", + k=5, + score_threshold=0.0, + reranker_type="weighted", + reranker_params={"alpha": 0.5, "weights": {"vector": 0.2, "keyword": 0.8}}, + ) + + assert ranker_weights == [(0.2, 0.8)] + assert client.hybrid_search_kwargs is not None + assert isinstance(client.hybrid_search_kwargs["ranker"], _FakeWeightedRanker) + + +async def test_milvus_native_rrf_with_weights_uses_in_memory_hybrid(monkeypatch): + index = MilvusIndex( + client=_FakeClient(), # type: ignore[arg-type] + vector_store=SimpleNamespace(identifier="test-store", embedding_dimension=3), # type: ignore[arg-type] + use_native_hybrid=True, + ) + calls: list[str] = [] + + async def fake_native(*args: Any, **kwargs: Any) -> str: + calls.append("native") + return "native" + + async def fake_in_memory(*args: Any, **kwargs: Any) -> str: + calls.append("in_memory") + return "in_memory" + + monkeypatch.setattr(index, "_query_hybrid_native", fake_native) + monkeypatch.setattr(index, "_query_hybrid_in_memory", fake_in_memory) + + result = await index.query_hybrid( + embedding=_FakeEmbedding(), # type: ignore[arg-type] + query_string="test query", + k=5, + score_threshold=0.0, + reranker_type="rrf", + reranker_params={"weights": {"vector": 1.0, "keyword": 0.0}}, + ) + + assert result == "in_memory" + assert calls == ["in_memory"] diff --git a/tests/unit/providers/utils/memory/test_reranking.py b/tests/unit/providers/utils/memory/test_reranking.py index 4ff4ebe0f44..09850551044 100644 --- a/tests/unit/providers/utils/memory/test_reranking.py +++ b/tests/unit/providers/utils/memory/test_reranking.py @@ -5,8 +5,11 @@ # the root directory of this source tree. +from ogx.core.datatypes import VectorStoresConfig +from ogx.providers.utils.memory.openai_vector_store_mixin import OpenAIVectorStoreMixin from ogx.providers.utils.memory.vector_store import RERANKER_TYPE_RRF, RERANKER_TYPE_WEIGHTED from ogx.providers.utils.vector_io.vector_utils import WeightedInMemoryAggregator +from ogx_api.vector_io import SearchRankingOptions class TestNormalizeScores: @@ -207,6 +210,50 @@ def test_combine_search_results_weighted(self): assert len(combined) == 3 assert all(0 <= score <= 1 for score in combined.values()) + def test_combine_search_results_weighted_uses_weights(self): + """Test explicit vector/keyword weights override weighted alpha.""" + vector_scores = {"vector-doc": 1.0, "keyword-doc": 0.0} + keyword_scores = {"vector-doc": 0.0, "keyword-doc": 1.0} + + vector_only = WeightedInMemoryAggregator.combine_search_results( + vector_scores, + keyword_scores, + reranker_type=RERANKER_TYPE_WEIGHTED, + reranker_params={"alpha": 0.5, "weights": {"vector": 1.0, "keyword": 0.0}}, + ) + keyword_only = WeightedInMemoryAggregator.combine_search_results( + vector_scores, + keyword_scores, + reranker_type=RERANKER_TYPE_WEIGHTED, + reranker_params={"alpha": 0.5, "weights": {"vector": 0.0, "keyword": 1.0}}, + ) + + assert vector_only["vector-doc"] > vector_only["keyword-doc"] + assert keyword_only["keyword-doc"] > keyword_only["vector-doc"] + assert vector_only != keyword_only + + def test_combine_search_results_rrf_uses_weights(self): + """Test explicit vector/keyword weights affect RRF scoring.""" + vector_scores = {"vector-doc": 1.0, "keyword-doc": 0.0} + keyword_scores = {"vector-doc": 0.0, "keyword-doc": 1.0} + + vector_only = WeightedInMemoryAggregator.combine_search_results( + vector_scores, + keyword_scores, + reranker_type=RERANKER_TYPE_RRF, + reranker_params={"impact_factor": 60.0, "weights": {"vector": 1.0, "keyword": 0.0}}, + ) + keyword_only = WeightedInMemoryAggregator.combine_search_results( + vector_scores, + keyword_scores, + reranker_type=RERANKER_TYPE_RRF, + reranker_params={"impact_factor": 60.0, "weights": {"vector": 0.0, "keyword": 1.0}}, + ) + + assert vector_only["vector-doc"] > vector_only["keyword-doc"] + assert keyword_only["keyword-doc"] > keyword_only["vector-doc"] + assert vector_only != keyword_only + def test_combine_search_results_unknown_type(self): """Test combining with unknown reranker type defaults to RRF.""" vector_scores = {"doc1": 0.9} @@ -246,3 +293,18 @@ def test_combine_search_results_empty_scores(self): # Test with both empty combined = WeightedInMemoryAggregator.combine_search_results({}, {}) assert len(combined) == 0 + + +class TestBuildRerankerParams: + def test_build_reranker_params_preserves_weights(self): + """Test vector store request ranking options preserve weights for reranker inputs.""" + weights = {"vector": 0.2, "keyword": 0.8} + + params = OpenAIVectorStoreMixin._build_reranker_params( + object(), + SearchRankingOptions(ranker="rrf", weights=weights), + VectorStoresConfig(), + ) + + assert params["reranker_type"] == RERANKER_TYPE_RRF + assert params["reranker_params"]["weights"] == weights From 1de9fff734e05e86df70ac75d0c510be2bba71e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 10:02:24 +0000 Subject: [PATCH 18/32] chore(api-deps): bump opentelemetry-sdk from 1.42.1 to 1.43.0 in /src/ogx_api (#6203) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [opentelemetry-sdk](https://github.com/open-telemetry/opentelemetry-python) from 1.42.1 to 1.43.0.
Changelog

Sourced from opentelemetry-sdk's changelog.

Version 1.43.0/0.64b0 (2026-06-24)

Added

  • opentelemetry-sdk: add add_metric_reader / remove_metric_reader public APIs to register / unregister metric readers at runtime. (#4863)
  • opentelemetry-exporter-prometheus: add support for configuring metric scope labels (#5123)
  • opentelemetry-exporter-otlp-proto-grpc: Add grpc error details to the log message that's written when the grpc call fails. (#5143)
  • opentelemetry-exporter-http-transport: add 'opentelemetry-exporter-http-transport' package for HTTP exporters (#5194)
  • opentelemetry-sdk: Add composite/development samplers support to declarative file configuration (#5201)
  • opentelemetry-exporter-otlp-json-file: Add OTLP JSON File exporter implementation (#5207)
  • opentelemetry-sdk: add _resolve_component shared utility for declarative config plugin loading, reducing boilerplate in exporter factory functions (#5215)
  • opentelemetry-sdk: add pull metric reader support to declarative file configuration, including Prometheus metric reader via the prometheus_development config field (#5216)
  • opentelemetry-proto-json: update to use opentelemetry-proto v1.10.0 (#5224)
  • opentelemetry-proto: bump maximum supported protobuf version to 7.x.x (#5251)
  • opentelemetry-sdk: add ServiceInstanceIdResourceDetector for populating service.instance.id (#5259)
  • opentelemetry-sdk: declarative config loader now recursively converts parsed dicts into typed dataclass instances, including nested dataclasses, lists of dataclasses, and enum values. End-to-end YAML/JSON → SDK configuration now works via the factory functions. (#5269)
  • opentelemetry-sdk: add configure_sdk(config) to the declarative configuration API. Single entry point that takes a parsed OpenTelemetryConfiguration, builds the resource, and applies the tracer/meter/logger providers and propagator globally. Honors the top-level disabled flag. (#5270)
  • opentelemetry-sdk: the SDK configurator now honors the OTEL_CONFIG_FILE environment variable. When set, the SDK loads and applies the referenced declarative configuration file (YAML or JSON) in place of the env-var-based

... (truncated)

Commits
  • fcbbeb8 [release/v1.43.x-0.64bx] Prepare release 1.43.0/0.64b0 (#5349)
  • b40dcbc opentelemetry-exporter-http-transport: enable entry-point loading of transpor...
  • 10e8577 update to Sphinx to 8.1.3 in order to support Python 3.14 (#5278)
  • 6ac6895 docs: add declarative configuration guide and example (#5309)
  • 13ad4d5 opentelemetry-api: normalize empty environment propagation names to "_" in En...
  • 6a0ab84 opentelemetry-sdk: merge doesn't need a copy, dict already does this (#5326)
  • ac7a3df feat(config): support OTEL_CONFIG_FILE in the SDK configurator (#5271)
  • fa75422 Add support for composite samplers in declarative config (#5201)
  • 43f079f Update json and proto encoder to always accept None type, cleanup code / test...
  • 53c9d96 chore: cleanup typo found in test (#5324)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=opentelemetry-sdk&package-manager=uv&previous-version=1.42.1&new-version=1.43.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--------- Signed-off-by: dependabot[bot] Signed-off-by: github-actions[bot] Signed-off-by: Sébastien Han Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: Sébastien Han --- src/ogx_api/pyproject.toml | 2 +- src/ogx_api/uv.lock | 2 +- uv.lock | 48 +++++++++++++++++++------------------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/ogx_api/pyproject.toml b/src/ogx_api/pyproject.toml index e19ebde7cca..1fd45a21fe7 100644 --- a/src/ogx_api/pyproject.toml +++ b/src/ogx_api/pyproject.toml @@ -35,7 +35,7 @@ dependencies = [ "fastapi>=0.136.3,<1.0", "pydantic>=2.11.9", "jsonschema>=4.26.0", - "opentelemetry-sdk>=1.42.1", + "opentelemetry-sdk>=1.43.0", "opentelemetry-exporter-otlp-proto-http>=1.43.0", "opentelemetry-exporter-otlp-proto-grpc>=1.42.1", ] diff --git a/src/ogx_api/uv.lock b/src/ogx_api/uv.lock index 8618813208e..e11171bd455 100644 --- a/src/ogx_api/uv.lock +++ b/src/ogx_api/uv.lock @@ -374,7 +374,7 @@ requires-dist = [ { name = "openai", specifier = ">=2.41.1" }, { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.42.1" }, { name = "opentelemetry-exporter-otlp-proto-http", specifier = ">=1.43.0" }, - { name = "opentelemetry-sdk", specifier = ">=1.42.1" }, + { name = "opentelemetry-sdk", specifier = ">=1.43.0" }, { name = "pydantic", specifier = ">=2.11.9" }, ] diff --git a/uv.lock b/uv.lock index a7f7cde19c3..0acca65fdc0 100644 --- a/uv.lock +++ b/uv.lock @@ -4582,7 +4582,7 @@ requires-dist = [ { name = "openai", specifier = ">=2.41.1" }, { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.42.1" }, { name = "opentelemetry-exporter-otlp-proto-http", specifier = ">=1.43.0" }, - { name = "opentelemetry-sdk", specifier = ">=1.42.1" }, + { name = "opentelemetry-sdk", specifier = ">=1.43.0" }, { name = "pydantic", specifier = ">=2.11.9" }, ] @@ -5138,7 +5138,7 @@ name = "pexpect" version = "4.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "ptyprocess" }, + { name = "ptyprocess", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } wheels = [ @@ -7420,8 +7420,8 @@ name = "standard-aifc" version = "3.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "audioop-lts" }, - { name = "standard-chunk" }, + { name = "audioop-lts", marker = "python_full_version >= '3.13'" }, + { name = "standard-chunk", marker = "python_full_version >= '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c4/53/6050dc3dde1671eb3db592c13b55a8005e5040131f7509cef0215212cb84/standard_aifc-3.13.0.tar.gz", hash = "sha256:64e249c7cb4b3daf2fdba4e95721f811bde8bdfc43ad9f936589b7bb2fae2e43", size = 15240, upload-time = "2024-10-30T16:01:31.772Z" } wheels = [ @@ -7718,13 +7718,13 @@ resolution-markers = [ "python_full_version < '3.13' and sys_platform == 'darwin'", ] dependencies = [ - { name = "filelock" }, - { name = "fsspec" }, - { name = "jinja2" }, - { name = "networkx" }, - { name = "setuptools" }, - { name = "sympy" }, - { name = "typing-extensions" }, + { name = "filelock", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, + { name = "fsspec", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, + { name = "jinja2", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, + { name = "networkx", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, + { name = "setuptools", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, + { name = "sympy", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, + { name = "typing-extensions", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, ] wheels = [ { url = "https://download-r2.pytorch.org/whl/cpu/torch-2.12.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:b41339df93d491435e790ff8bcbae1c0ce777175889bfd1281d119862793e6a2", upload-time = "2026-05-12T16:20:12Z" }, @@ -7754,13 +7754,13 @@ resolution-markers = [ "python_full_version < '3.13' and sys_platform != 'darwin' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ - { name = "filelock" }, - { name = "fsspec" }, - { name = "jinja2" }, - { name = "networkx" }, - { name = "setuptools" }, - { name = "sympy" }, - { name = "typing-extensions" }, + { name = "filelock", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, + { name = "fsspec", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, + { name = "jinja2", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, + { name = "networkx", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, + { name = "setuptools", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, + { name = "sympy", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, ] wheels = [ { url = "https://download-r2.pytorch.org/whl/cpu/torch-2.12.0%2Bcpu-cp312-cp312-linux_s390x.whl", hash = "sha256:b9d0e8eed0af9321ffb12b75f4aca371b071254f12cf75875d5a8e7cc8f52b51", upload-time = "2026-05-12T23:16:33Z" }, @@ -7835,9 +7835,9 @@ resolution-markers = [ "python_full_version < '3.13' and sys_platform == 'darwin'", ] dependencies = [ - { name = "numpy" }, - { name = "pillow" }, - { name = "torch", version = "2.12.0", source = { registry = "https://download.pytorch.org/whl/cpu" } }, + { name = "numpy", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, + { name = "pillow", marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, + { name = "torch", version = "2.12.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "python_full_version < '3.15' and sys_platform == 'darwin'" }, ] wheels = [ { url = "https://download-r2.pytorch.org/whl/cpu/torchvision-0.27.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:1a6dd742a150645126df9e0b2e449874c1d635897c773b322c2e067e98382dfe", upload-time = "2026-05-12T16:20:37Z" }, @@ -7867,9 +7867,9 @@ resolution-markers = [ "python_full_version < '3.13' and sys_platform != 'darwin' and sys_platform != 'emscripten' and sys_platform != 'win32'", ] dependencies = [ - { name = "numpy" }, - { name = "pillow" }, - { name = "torch", version = "2.12.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" } }, + { name = "numpy", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, + { name = "pillow", marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, + { name = "torch", version = "2.12.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "python_full_version >= '3.15' or sys_platform != 'darwin'" }, ] wheels = [ { url = "https://download-r2.pytorch.org/whl/cpu/torchvision-0.27.0%2Bcpu-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:1b06f42d48b62098114923d8a3fe9fa864182715db06584a515155db0aa8eb30", upload-time = "2026-05-12T16:20:36Z" }, From 144536c8244c6dfd39a1239cdfd39f9e45139a3a Mon Sep 17 00:00:00 2001 From: E Geiger Date: Tue, 30 Jun 2026 14:17:55 +0300 Subject: [PATCH 19/32] ci(client-sdks): release locally-generated sdk as ogx-client Following comment https://github.com/ogx-ai/ogx/pull/6207#discussion_r3497494850 Building the locally-gnerated client SDK as `ogx-client`, moving back from the temporary `ogx-open-client` Signed-off-by: E Geiger --- .github/workflows/README.md | 2 +- .../openapi-generator-validation.yml | 12 ++--- .github/workflows/publish-openapi-sdk.yml | 14 +++--- .github/workflows/pypi.yml | 46 +++++-------------- 4 files changed, 25 insertions(+), 49 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index f1915853155..2150e66fb72 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -28,7 +28,7 @@ OGX uses GitHub Actions for Continuous Integration (CI). Below is a table detail | Pre-commit | [pre-commit.yml](pre-commit.yml) | Run pre-commit checks | | Prepare release | [prepare-release.yml](prepare-release.yml) | Prepare release | | Test OGX Build | [providers-build.yml](providers-build.yml) | Test ogx build and list-deps | -| Publish OpenAPI SDK to PyPI | [publish-openapi-sdk.yml](publish-openapi-sdk.yml) | Publish ogx-open-client to PyPI | +| Publish OpenAPI SDK to PyPI | [publish-openapi-sdk.yml](publish-openapi-sdk.yml) | Publish ogx-client to PyPI | | Build, test, and publish packages | [pypi.yml](pypi.yml) | Build, test, and publish packages | | Integration Tests (Record) | [record-integration-tests.yml](record-integration-tests.yml) | Auto-record missing test recordings for PR | | vLLM GPU Recording | [record-vllm-gpu-tests.yml](record-vllm-gpu-tests.yml) | GPU recording for gpt-oss:20b (${{ inputs.suite }} suite) | diff --git a/.github/workflows/openapi-generator-validation.yml b/.github/workflows/openapi-generator-validation.yml index e7eb537ad79..2efdc8bbb8a 100644 --- a/.github/workflows/openapi-generator-validation.yml +++ b/.github/workflows/openapi-generator-validation.yml @@ -187,7 +187,7 @@ jobs: - name: Generate Python SDK working-directory: client-sdks/openapi - run: make sdk OPEN=1 + run: make sdk OPEN=0 - name: Validate generated SDK working-directory: client-sdks/openapi @@ -217,14 +217,14 @@ jobs: - name: Install generated SDK run: | - echo "Reinstalling OpenAPI-generated SDK (ogx_open_client)..." - uv pip uninstall ogx-open-client || true + echo "Reinstalling OpenAPI-generated SDK (ogx_client)..." + uv pip uninstall ogx-client || true # Install SDK using uv pip uv pip install -e client-sdks/openapi/sdks/python echo "Verifying installation..." - uv run python -c "import ogx_open_client; print(f'Installed: {ogx_open_client.__name__}')" + uv run python -c "import ogx_client; print(f'Installed: {ogx_client.__name__}')" - name: Setup Ollama (for integration tests) if: runner.os == 'Linux' @@ -242,7 +242,7 @@ jobs: || echo "::warning::Some integration tests failed - this may indicate SDK compatibility issues" # Show which SDK is actually being used - uv run python -c "import ogx_open_client; import inspect; print(f'SDK location: {inspect.getfile(ogx_open_client)}')" + uv run python -c "import ogx_client; import inspect; print(f'SDK location: {inspect.getfile(ogx_client)}')" - name: Summary if: runner.os == 'Linux' @@ -255,5 +255,5 @@ jobs: echo "✅ Integration tests executed (check logs for results)" echo "" echo "**Platform**: ${{ matrix.os }}" - echo "**Package**: ogx_open_client (OpenAPI-generated)" + echo "**Package**: ogx_client (OpenAPI-generated)" } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/publish-openapi-sdk.yml b/.github/workflows/publish-openapi-sdk.yml index e200a13746b..325bd065ede 100644 --- a/.github/workflows/publish-openapi-sdk.yml +++ b/.github/workflows/publish-openapi-sdk.yml @@ -1,6 +1,6 @@ name: Publish OpenAPI SDK to PyPI -run-name: Publish ogx-open-client to PyPI +run-name: Publish ogx-client to PyPI on: workflow_dispatch: @@ -101,8 +101,8 @@ jobs: working-directory: client-sdks/openapi run: | VERSION="${{ needs.compute-version.outputs.version }}" - echo "Generating SDK with OPEN=1 (ogx_open_client) at version ${VERSION}..." - make sdk OPEN=1 VERSION="${VERSION}" + echo "Generating SDK with OPEN=0 (ogx_client) at version ${VERSION}..." + make sdk OPEN=0 VERSION="${VERSION}" - name: Verify SDK generation working-directory: client-sdks/openapi @@ -169,10 +169,10 @@ jobs: echo "" echo "- **Event**: ${{ github.event_name }}" echo "- **Target**: TestPyPI" - echo "- **Package**: ogx-open-client" + echo "- **Package**: ogx-client" echo "" echo "✅ Package published to TestPyPI" - echo "Install with: \`pip install --index-url https://test.pypi.org/simple/ ogx-open-client\`" + echo "Install with: \`pip install --index-url https://test.pypi.org/simple/ ogx-client\`" } >> "$GITHUB_STEP_SUMMARY" publish-pypi: @@ -204,8 +204,8 @@ jobs: echo "" echo "- **Event**: ${{ github.event_name }}" echo "- **Target**: PyPI (production)" - echo "- **Package**: ogx-open-client" + echo "- **Package**: ogx-client" echo "" echo "✅ Package published to PyPI" - echo "Install with: \`pip install ogx-open-client\`" + echo "Install with: \`pip install ogx-client\`" } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index d3902d68cb9..5ef2ff82de1 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -5,7 +5,7 @@ # This workflow builds, tests, and publishes all ogx packages: # - ogx (PyPI) # - ogx-api (PyPI) -# - ogx-client-python (PyPI, from external repo) +# - ogx-client (PyPI, OpenAPI-generated SDK) # - ogx-client-typescript (npm, from external repo) # # ============================================================================= @@ -226,15 +226,11 @@ jobs: type: local registry: pypi # OpenAPI-generated SDK (built from spec in this repo) - - package: ogx-open-client + - package: ogx-client path: client-sdks/openapi type: openapi-sdk registry: pypi # External packages (client SDKs from other repos) - - package: ogx-client-python - repo: ogx-ai/ogx-client-python - type: external - registry: pypi - package: ogx-client-typescript repo: ogx-ai/ogx-client-typescript type: external @@ -355,7 +351,7 @@ jobs: env: SETUPTOOLS_SCM_PRETEND_VERSION: ${{ needs.compute-version.outputs.version }} - # === OPENAPI SDK BUILD (ogx-open-client) === + # === OPENAPI SDK BUILD (ogx-client) === - name: Set up Java (openapi-sdk) if: steps.should-build.outputs.skip != 'true' && matrix.type == 'openapi-sdk' uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 @@ -378,8 +374,8 @@ jobs: working-directory: ${{ matrix.path }} run: | VERSION="${{ needs.compute-version.outputs.version }}" - echo "Generating SDK with OPEN=1 (ogx_open_client) at version ${VERSION}..." - make sdk OPEN=1 VERSION="${VERSION}" + echo "Generating SDK with OPEN=0 (ogx_client) at version ${VERSION}..." + make sdk OPEN=0 VERSION="${VERSION}" cd sdks/python echo "Building Python package..." @@ -658,14 +654,6 @@ jobs: path: dist-stack continue-on-error: true - - name: Download ogx-client-python artifacts - id: download-client-python - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: Packages-ogx-client-python - path: dist-client-python - continue-on-error: true - - name: Download ogx-client-typescript artifacts id: download-client-ts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 @@ -674,12 +662,12 @@ jobs: path: dist-client-ts continue-on-error: true - - name: Download ogx-open-client artifacts - id: download-open-client + - name: Download ogx-client artifacts (OpenAPI SDK) + id: download-client-python uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - name: Packages-ogx-open-client - path: dist-open-client + name: Packages-ogx-client + path: dist-client-python continue-on-error: true - name: Create venv and install Python packages @@ -703,11 +691,6 @@ jobs: uv pip install dist-stack/*.whl fi - if [ -d "dist-open-client" ] && ls dist-open-client/*.whl 1>/dev/null 2>&1; then - echo "Installing ogx-open-client..." - uv pip install dist-open-client/*.whl - fi - - name: List Wheel Contents (ogx-api) if: steps.download-api.outcome == 'success' run: | @@ -741,10 +724,6 @@ jobs: python -c "import ogx_client; print(f'ogx_client imported successfully from {ogx_client.__file__}')" fi - if [ -d "dist-open-client" ] && ls dist-open-client/*.whl 1>/dev/null 2>&1; then - python -c "import ogx_open_client; print(f'ogx_open_client imported successfully from {ogx_open_client.__file__}')" - fi - - name: Verify TypeScript package if: steps.download-client-ts.outcome == 'success' run: | @@ -764,7 +743,7 @@ jobs: fi # Publish packages to PyPI/npm - # Order: ogx-client-python, ogx-client-typescript, ogx-open-client, ogx-api, ogx + # Order: ogx-client-typescript, ogx-client, ogx-api, ogx publish-packages: name: Publish ${{ matrix.package }} if: | @@ -785,13 +764,10 @@ jobs: matrix: include: # Order matters! Dependencies are published first - - package: ogx-client-python - registry: pypi - type: external - package: ogx-client-typescript registry: npm type: external - - package: ogx-open-client + - package: ogx-client registry: pypi type: openapi-sdk - package: ogx-api From b51cbcea13b30d34a099b3e11e69cfb0c3369b49 Mon Sep 17 00:00:00 2001 From: Sumanth Kamenani Date: Tue, 30 Jun 2026 08:02:06 -0400 Subject: [PATCH 20/32] docs: add June 30 blog for `ogx connect codex` (#6118) ## Summary Adds a Codex CLI blog post that explains how OGX gives Codex one OpenAI-compatible connection to local models, hosted models, and secured deployments. The post keeps the first-run path local-first with Ollama, shows a vLLM-backed setup, and explains the generated Codex profile plus auth/provider-data forwarding. ## Test plan ```bash uv run --no-sync pre-commit run blacken-docs --files docs/blog/2026-06-15-codex-ogx-cli.md uv run --no-sync pre-commit run markdownlint --files docs/blog/2026-06-15-codex-ogx-cli.md ``` Output: ```text blacken-docs.................................................................Passed markdownlint.................................................................Passed ``` ## Checklist - [x] Docs-only change. - [x] No API, provider, or runtime behavior changes. - [x] No real credentials or deployment secrets included. ## Breaking changes None --------- Signed-off-by: Sumanth Kamenani --- docs/blog/2026-06-30-codex-ogx-cli.md | 201 ++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 docs/blog/2026-06-30-codex-ogx-cli.md diff --git a/docs/blog/2026-06-30-codex-ogx-cli.md b/docs/blog/2026-06-30-codex-ogx-cli.md new file mode 100644 index 00000000000..d5ea986da14 --- /dev/null +++ b/docs/blog/2026-06-30-codex-ogx-cli.md @@ -0,0 +1,201 @@ +--- +slug: ogx-codex-cli +title: "Connect Codex CLI to Local and Hosted Models with OGX" +authors: [skamenan7] +tags: [ogx, codex, responses-api, vllm, ollama, agents] +date: 2026-06-30 +--- + +Codex CLI brings an agent into the terminal, but teams often want that agent to use more than one model source. OGX gives Codex one OpenAI-compatible connection to local models, hosted models, and secured deployments. + +With `ogx connect codex`, you can launch Codex against the models exposed by a running OGX server without hand-editing your normal Codex configuration. OGX discovers the available models, writes a temporary Codex session home, forwards auth and provider data when needed, and starts Codex with a session that points at OGX. + +This post walks through the command, the generated Codex profile, and a local-first path with Ollama and vLLM. The result is a small but useful workflow: Codex gets a familiar Responses API endpoint, and teams keep model access, auth, and provider choice in OGX instead of hard-coding those details into every developer tool. + + + +## Why this is useful + +Launching Codex is easy. The harder part starts when you want the same tool to work across different model backends: a local Ollama model, a vLLM server, a hosted OpenAI model, or an internal deployment with its own auth rules. Each one has a different endpoint, model name, and credential story. With OGX, Codex points at one OpenAI-compatible endpoint while OGX smoothly takes care of the backend work: finding models, routing requests, forwarding auth, and adapting provider-specific details. + +OGX gives those tools a common front door: + +- Codex talks to an OpenAI-compatible `/v1/responses` API. +- OGX exposes the models already registered in the running server. +- The provider behind each model can change without rewriting the Codex workflow. +- Auth and provider data can be forwarded through OGX instead of stored in a long-lived local Codex config. +- The generated Codex session home is temporary, so your existing `~/.codex/config.toml` stays untouched. + +That makes OGX a good fit for agentic development across laptops, shared dev servers, and production-like environments. It is not just a proxy. It is a control plane for model access, auth shape, provider routing, and day-to-day debugging. + +Codex uses OGX through the Responses API, but the provider setup is useful beyond Codex. Once a model provider such as vLLM, Ollama, or OpenAI is registered in OGX, other OpenAI-compatible clients can use the same model access layer through chat completions or completions when those endpoints are enabled. That includes Python scripts using the OpenAI SDK, notebooks, OpenCode, LiteLLM or LangChain-style apps, and internal tools that already speak OpenAI-compatible APIs. Teams can configure routing and auth once in OGX, then reuse that setup from Codex and from simpler inference clients. + +## What the command does + +The command is intentionally small: + +```bash +ogx connect codex +``` + +Behind that command, OGX does the mechanical work that is easy to get wrong by hand: + +1. Queries `GET /v1/models` on the running OGX server. +2. Filters out embedding models. +3. Selects the requested model, or the first available LLM model. +4. Creates a temporary `CODEX_HOME`. +5. Writes `ogx.config.toml` and `ogx-model-catalog.json`. +6. Launches `codex -p ogx`, or `codex exec -p ogx` when `--exec` is used. + +The generated profile uses the Responses wire API: + +```toml +model_provider = "ogx" + +[features] +multi_agent = false + +[model_providers.ogx] +wire_api = "responses" +``` + +The `multi_agent` flag is disabled because current OGX Responses models do not accept the Codex `namespace` tool shape. That keeps the default connector path focused on the request shape OGX can handle today. + +The flow looks like this: + +```text +Codex CLI + | + | generated OGX profile + v +OGX /v1/responses + | + | provider routing + v +OpenAI, vLLM, Ollama, Bedrock, or another OGX-backed model provider +``` + +The important part is the boundary: Codex only needs to know about the OGX profile. OGX owns the provider mapping. + +## Try it with a running OGX server + +Start an OGX server that exposes at least one LLM model. The starter distribution enables providers from environment variables, so you can begin with a local provider instead of an OpenAI key. + +Start Ollama in one terminal: + +```bash +ollama serve +``` + +Then pull a model and start OGX in another terminal: + +```bash +ollama pull llama3.2:3b +export OLLAMA_URL="http://localhost:11434/v1" +uv run ogx run starter +``` + +If you do want to use an OpenAI-backed model instead, set `OPENAI_API_KEY` before starting the same starter distribution. + +Then launch Codex in another terminal: + +```bash +uv run ogx connect codex +``` + +If you want a specific model from the OGX model list: + +```bash +uv run ogx connect codex \ + --model ollama/llama3.2:3b +``` + +For a quick non-interactive run, use `--exec`: + +```bash +uv run ogx connect codex \ + --model ollama/llama3.2:3b \ + --exec "Explain in one sentence why OGX is useful with Codex CLI." +``` + +This is useful when you want a quick answer before opening an interactive Codex session. Codex sends the prompt through OGX, OGX routes it to the selected model, and the final answer comes back through the same Responses API path. + +## Auth and provider data + +The same setup works when OGX is running behind an authenticated endpoint. Codex still talks to one OGX URL, while OGX enforces the same access policy, provider routing, and credential handling that other clients use. + +That matters in shared environments. A team can let Codex use approved models without putting long-lived provider secrets in `~/.codex/config.toml`, and without teaching Codex every backend-specific auth shape. If the OGX server requires bearer auth, set `OGX_API_KEY`. If a provider path needs request-scoped data, such as a passthrough provider token, set `OGX_PROVIDER_DATA`. + +```bash +export OGX_API_KEY="your-ogx-access-token" +export OGX_PROVIDER_DATA='{"passthrough_api_key":"provider-token"}' + +uv run ogx connect codex \ + --url https://ogx.example.com/v1 +``` + +When `OGX_API_KEY` is set, Codex uses it to authenticate to OGX. When `OGX_PROVIDER_DATA` is set, OGX receives that JSON on each request and can use it for provider-specific needs such as passthrough credentials, tenant context, or other request-scoped routing data. + +Codex does not need to know what the backend provider expects. It only points at OGX for the current session; OGX decides how that request is authorized and how provider-specific data is applied before the request reaches the model. + +## Try it with a vLLM-backed OGX server + +vLLM is useful when you want Codex to use an open model served from your own environment. It exposes an OpenAI-compatible server that OGX can register as `remote::vllm`, so the same Codex workflow can run against a vLLM-backed model instead of a hosted provider. + +Start a vLLM OpenAI-compatible server: + +```bash +export VLLM_API_TOKEN="fake" + +vllm serve Qwen/Qwen3-8B \ + --api-key "$VLLM_API_TOKEN" +``` + +Then start OGX with the stock starter distribution pointed at that vLLM server in another terminal: + +```bash +export VLLM_URL="http://localhost:8000/v1" +export VLLM_API_TOKEN="fake" + +uv run ogx run starter +``` + +The starter distribution enables the vLLM provider when `VLLM_URL` is set. The relevant provider configuration is: + +```yaml +providers: + inference: + - provider_id: ${env.VLLM_URL:+vllm} + provider_type: remote::vllm + config: + base_url: ${env.VLLM_URL:=} + max_tokens: ${env.VLLM_MAX_TOKENS:=4096} + api_token: ${env.VLLM_API_TOKEN:=fake} + network: + tls: + verify: ${env.VLLM_TLS_VERIFY:=true} +``` + +Now connect Codex through OGX: + +```bash +uv run ogx connect codex \ + --model vllm/Qwen/Qwen3-8B \ + --exec "Explain in one sentence how this Codex request is reaching the vLLM model." +``` + +That is the main point: Codex still uses the same OGX command, while OGX changes the provider behind the model ID. Ollama is a good first local path for basic text flows. vLLM is useful when you want an OpenAI-compatible server for open models. Provider and model compatibility still matter, but those details stay behind the OGX boundary instead of becoming permanent Codex configuration. + +## Summary + +`ogx connect codex` makes Codex feel like a first-class OGX client: + +- It discovers models from the running OGX server. +- It generates a temporary Codex profile and model catalog. +- It keeps your normal Codex config untouched. +- It supports bearer auth and provider-data forwarding. +- It works for interactive Codex sessions and quick non-interactive runs. +- It works with local providers such as Ollama and vLLM as well as hosted providers. +- It keeps current alpha limits explicit, including no persistent Codex memory and disabled Codex multi-agent tools. + +The practical takeaway: OGX gives teams one place to manage model access while still letting developer tools like Codex move fast. If you can start OGX and see your model in `/v1/models`, you have a clear path to using that model from Codex and debugging each layer with concrete evidence. From b3d6a8a12f1125bcde83380530eff6fc5e42688e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 14:02:44 +0200 Subject: [PATCH 21/32] chore(github-deps): bump github/codeql-action from 4.36.0 to 4.36.2 (#6154) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.36.0 to 4.36.2.
Release notes

Sourced from github/codeql-action's releases.

v4.36.2

  • Cache CodeQL CLI version information across Actions steps. #3943
  • Reduce requests while waiting for analysis processing by using exponential backoff when polling SARIF processing status. #3937
  • Update default CodeQL bundle version to 2.25.6. #3948

v4.36.1

No user facing changes.

Changelog

Sourced from github/codeql-action's changelog.

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

[UNRELEASED]

No user facing changes.

4.36.2 - 04 Jun 2026

  • Cache CodeQL CLI version information across Actions steps. #3943
  • Reduce requests while waiting for analysis processing by using exponential backoff when polling SARIF processing status. #3937
  • Update default CodeQL bundle version to 2.25.6. #3948

4.36.1 - 02 Jun 2026

No user facing changes.

4.36.0 - 22 May 2026

  • Breaking change: Bump the minimum required CodeQL bundle version to 2.19.4. #3894
  • Add support for SHA-256 Git object IDs. #3893
  • Update default CodeQL bundle version to 2.25.5. #3926

4.35.5 - 15 May 2026

  • We have improved how the JavaScript bundles for the CodeQL Action are generated to avoid duplication across bundles and reduce the size of the repository by around 70%. This should have no effect on the runtime behaviour of the CodeQL Action. #3899
  • For performance and accuracy reasons, improved incremental analysis will now only be enabled on a pull request when diff-informed analysis is also enabled for that run. If diff-informed analysis is unavailable (for example, because the PR diff ranges could not be computed), the action will fall back to a full analysis. #3791
  • If multiple inputs are provided for the GitHub-internal analysis-kinds input, only code-scanning will be enabled. The analysis-kinds input is experimental, for GitHub-internal use only, and may change without notice at any time. #3892
  • Added an experimental change which, when running a Code Scanning analysis for a PR with improved incremental analysis enabled, prefers CodeQL CLI versions that have a cached overlay-base database for the configured languages. This speeds up analysis for a repository when there is not yet a cached overlay-base database for the latest CLI version. We expect to roll this change out to everyone in May. #3880

4.35.4 - 07 May 2026

  • Update default CodeQL bundle version to 2.25.4. #3881

4.35.3 - 01 May 2026

  • Upcoming breaking change: Add a deprecation warning for customers using CodeQL version 2.19.3 and earlier. These versions of CodeQL were discontinued on 9 April 2026 alongside GitHub Enterprise Server 3.15, and will be unsupported by the next minor release of the CodeQL Action. #3837
  • Configurations for private registries that use Cloudsmith or GCP OIDC are now accepted. #3850
  • Best-effort connection tests for private registries now use GET requests instead of HEAD for better compatibility with various registry implementations. For NuGet feeds, the test is now always performed against the service index. #3853
  • Fixed a bug where two diagnostics produced within the same millisecond could overwrite each other on disk, causing one of them to be lost. #3852
  • Update default CodeQL bundle version to 2.25.3. #3865

4.35.2 - 15 Apr 2026

  • The undocumented TRAP cache cleanup feature that could be enabled using the CODEQL_ACTION_CLEANUP_TRAP_CACHES environment variable is deprecated and will be removed in May 2026. If you are affected by this, we recommend disabling TRAP caching by passing the trap-caching: false input to the init Action. #3795
  • The Git version 2.36.0 requirement for improved incremental analysis now only applies to repositories that contain submodules. #3789
  • Python analysis on GHES no longer extracts the standard library, relying instead on models of the standard library. This should result in significantly faster extraction and analysis times, while the effect on alerts should be minimal. #3794
  • Fixed a bug in the validation of OIDC configurations for private registries that was added in CodeQL Action 4.33.0 / 3.33.0. #3807
  • Update default CodeQL bundle version to 2.25.2. #3823

... (truncated)

Commits
  • 8aad20d Merge pull request #3949 from github/update-v4.36.2-dcb947ce1
  • f521b08 Add additional changelog notes
  • 8aeff0f Update changelog for v4.36.2
  • dcb947c Merge pull request #3948 from github/update-bundle/codeql-bundle-v2.25.6
  • c251bce Add changelog note
  • 62953c1 Update default bundle to codeql-bundle-v2.25.6
  • 423b570 Merge pull request #3946 from github/dependabot/npm_and_yarn/npm-minor-5d507a...
  • c35d1b1 Merge pull request #3947 from github/dependabot/github_actions/dot-github/wor...
  • cb1a588 Merge pull request #3937 from github/robertbrignull/waitForProcessing_backoff
  • ba47406 Merge pull request #3943 from github/henrymercer/cache-cli-version-info
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.36.0&new-version=4.36.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-distributions.yml | 2 +- .github/workflows/pypi.yml | 2 +- .github/workflows/trivy-scheduled.yml | 8 ++++---- .github/workflows/trivy-security.yml | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-distributions.yml b/.github/workflows/build-distributions.yml index 64c55d1d162..80380f5b84b 100644 --- a/.github/workflows/build-distributions.yml +++ b/.github/workflows/build-distributions.yml @@ -154,7 +154,7 @@ jobs: output: 'trivy-container-${{ matrix.distro }}.sarif' - name: Upload container scan results to GitHub Security - uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v3 if: always() with: sarif_file: 'trivy-container-${{ matrix.distro }}.sarif' diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 8b09b9dab75..20b0a63b32e 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -1102,7 +1102,7 @@ jobs: trivy-config: 'trivy.yaml' - name: Upload Trivy image scan results to GitHub Security - uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v3 if: always() with: sarif_file: 'trivy-image-${{ matrix.distro }}.sarif' diff --git a/.github/workflows/trivy-scheduled.yml b/.github/workflows/trivy-scheduled.yml index 9bf23d9cf13..84dba4ee3bc 100644 --- a/.github/workflows/trivy-scheduled.yml +++ b/.github/workflows/trivy-scheduled.yml @@ -29,7 +29,7 @@ jobs: trivy-config: 'trivy.yaml' - name: Upload vulnerability results to GitHub Security - uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v3 if: always() with: sarif_file: 'trivy-scheduled-vuln.sarif' @@ -46,7 +46,7 @@ jobs: exit-code: '0' - name: Upload secret results to GitHub Security - uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v3 if: always() with: sarif_file: 'trivy-scheduled-secret.sarif' @@ -63,7 +63,7 @@ jobs: exit-code: '0' - name: Upload misconfiguration results to GitHub Security - uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v3 if: always() with: sarif_file: 'trivy-scheduled-misconfig.sarif' @@ -94,7 +94,7 @@ jobs: trivy-config: 'trivy.yaml' - name: Upload image scan results to GitHub Security - uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v3 if: always() with: sarif_file: 'trivy-image-${{ matrix.distro }}.sarif' diff --git a/.github/workflows/trivy-security.yml b/.github/workflows/trivy-security.yml index 794e84fc6c5..8d948965c25 100644 --- a/.github/workflows/trivy-security.yml +++ b/.github/workflows/trivy-security.yml @@ -61,7 +61,7 @@ jobs: trivy-config: 'trivy.yaml' - name: Upload vulnerability results to GitHub Security - uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v3 if: always() with: sarif_file: 'trivy-vuln.sarif' @@ -87,7 +87,7 @@ jobs: trivy-config: 'trivy.yaml' - name: Upload misconfiguration results to GitHub Security - uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v3 if: always() with: sarif_file: 'trivy-misconfig.sarif' @@ -112,7 +112,7 @@ jobs: trivy-config: 'trivy.yaml' - name: Upload secret detection results to GitHub Security - uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v3 if: always() with: sarif_file: 'trivy-secret.sarif' From a63ee620d8f4ac7004e6a5e63a17f5022a994302 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 14:02:53 +0200 Subject: [PATCH 22/32] chore(api-deps): bump openai from 2.41.1 to 2.43.0 in /src/ogx_api (#6153) Bumps [openai](https://github.com/openai/openai-python) from 2.41.1 to 2.43.0.
Release notes

Sourced from openai's releases.

v2.43.0

2.43.0 (2026-06-17)

Full Changelog: v2.42.0...v2.43.0

Features

  • api: update OpenAPI spec or Stainless config (2254235)

v2.42.0

2.42.0 (2026-06-16)

Full Changelog: v2.41.1...v2.42.0

Features

  • api: admin spend_alerts (6134198)
  • api: manual updates (f337bf4)
  • api: update OpenAPI spec or Stainless config (7015158)

Build System

Changelog

Sourced from openai's changelog.

2.43.0 (2026-06-17)

Full Changelog: v2.42.0...v2.43.0

Features

  • api: update OpenAPI spec or Stainless config (2254235)

2.42.0 (2026-06-16)

Full Changelog: v2.41.1...v2.42.0

Features

  • api: admin spend_alerts (6134198)
  • api: manual updates (f337bf4)
  • api: update OpenAPI spec or Stainless config (7015158)

Build System

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=openai&package-manager=uv&previous-version=2.41.1&new-version=2.43.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--------- Signed-off-by: dependabot[bot] Signed-off-by: github-actions[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] --- src/ogx_api/pyproject.toml | 2 +- src/ogx_api/uv.lock | 8 ++++---- uv.lock | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ogx_api/pyproject.toml b/src/ogx_api/pyproject.toml index 1fd45a21fe7..6763cf2bd7a 100644 --- a/src/ogx_api/pyproject.toml +++ b/src/ogx_api/pyproject.toml @@ -31,7 +31,7 @@ classifiers = [ "Topic :: Scientific/Engineering :: Information Analysis", ] dependencies = [ - "openai>=2.41.1", + "openai>=2.43.0", "fastapi>=0.136.3,<1.0", "pydantic>=2.11.9", "jsonschema>=4.26.0", diff --git a/src/ogx_api/uv.lock b/src/ogx_api/uv.lock index e11171bd455..fedc7c88a95 100644 --- a/src/ogx_api/uv.lock +++ b/src/ogx_api/uv.lock @@ -371,7 +371,7 @@ dependencies = [ requires-dist = [ { name = "fastapi", specifier = ">=0.136.3,<1.0" }, { name = "jsonschema", specifier = ">=4.26.0" }, - { name = "openai", specifier = ">=2.41.1" }, + { name = "openai", specifier = ">=2.43.0" }, { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.42.1" }, { name = "opentelemetry-exporter-otlp-proto-http", specifier = ">=1.43.0" }, { name = "opentelemetry-sdk", specifier = ">=1.43.0" }, @@ -380,7 +380,7 @@ requires-dist = [ [[package]] name = "openai" -version = "2.41.1" +version = "2.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -392,9 +392,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/40/36/4c926a91554483977608951360c18c2e911592785eb87a6437813f6123f7/openai-2.41.1.tar.gz", hash = "sha256:23d617a0432457ad844973bee8f540be9da90894f7c5686852d2d365da058f57", size = 783584, upload-time = "2026-06-10T16:10:37.667Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/fa/88d0c58a0c58df7e6758e66b99c5d028d5e0bb49f8812d7203940cd9dbf1/openai-2.43.0.tar.gz", hash = "sha256:e74d238200a26868977002190fb6631613480a93dfe0c9c982e77021ed60a017", size = 785369, upload-time = "2026-06-17T17:06:56.06Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/74/925d7b3892927e9804aaf58d374a45dc28e4420ff90e992272b77286343e/openai-2.41.1-py3-none-any.whl", hash = "sha256:a939565f350cb7443cb843b801b88c716ac8024b492fb94ca269d5f6b1bbefd6", size = 1353380, upload-time = "2026-06-10T16:10:35.756Z" }, + { url = "https://files.pythonhosted.org/packages/a3/d2/ba767f4bbb30776c03d40906a2d3afad716a165ffa1771fc23b8992f7920/openai-2.43.0-py3-none-any.whl", hash = "sha256:65a670b54fadf2268c9e1330133373c963eb779ee969e5cbad419ec2c21dce97", size = 1355077, upload-time = "2026-06-17T17:06:53.614Z" }, ] [[package]] diff --git a/uv.lock b/uv.lock index 0acca65fdc0..28cd08abe6e 100644 --- a/uv.lock +++ b/uv.lock @@ -4579,7 +4579,7 @@ dependencies = [ requires-dist = [ { name = "fastapi", specifier = ">=0.136.3,<1.0" }, { name = "jsonschema", specifier = ">=4.26.0" }, - { name = "openai", specifier = ">=2.41.1" }, + { name = "openai", specifier = ">=2.43.0" }, { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.42.1" }, { name = "opentelemetry-exporter-otlp-proto-http", specifier = ">=1.43.0" }, { name = "opentelemetry-sdk", specifier = ">=1.43.0" }, @@ -4692,7 +4692,7 @@ wheels = [ [[package]] name = "openai" -version = "2.41.1" +version = "2.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -4704,9 +4704,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/40/36/4c926a91554483977608951360c18c2e911592785eb87a6437813f6123f7/openai-2.41.1.tar.gz", hash = "sha256:23d617a0432457ad844973bee8f540be9da90894f7c5686852d2d365da058f57", size = 783584, upload-time = "2026-06-10T16:10:37.667Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/fa/88d0c58a0c58df7e6758e66b99c5d028d5e0bb49f8812d7203940cd9dbf1/openai-2.43.0.tar.gz", hash = "sha256:e74d238200a26868977002190fb6631613480a93dfe0c9c982e77021ed60a017", size = 785369, upload-time = "2026-06-17T17:06:56.06Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/74/925d7b3892927e9804aaf58d374a45dc28e4420ff90e992272b77286343e/openai-2.41.1-py3-none-any.whl", hash = "sha256:a939565f350cb7443cb843b801b88c716ac8024b492fb94ca269d5f6b1bbefd6", size = 1353380, upload-time = "2026-06-10T16:10:35.756Z" }, + { url = "https://files.pythonhosted.org/packages/a3/d2/ba767f4bbb30776c03d40906a2d3afad716a165ffa1771fc23b8992f7920/openai-2.43.0-py3-none-any.whl", hash = "sha256:65a670b54fadf2268c9e1330133373c963eb779ee969e5cbad419ec2c21dce97", size = 1355077, upload-time = "2026-06-17T17:06:53.614Z" }, ] [[package]] From 00e310752ea56c28ea4029807d20428432677618 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 12:03:46 +0000 Subject: [PATCH 23/32] chore(python-deps): bump msgpack from 1.1.2 to 1.2.1 (#6151) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [msgpack](https://github.com/msgpack/msgpack-python) from 1.1.2 to 1.2.1.
Release notes

Sourced from msgpack's releases.

v1.2.1

What's Changed

Full Changelog: https://github.com/msgpack/msgpack-python/compare/v1.2.0...v1.2.1

v1.2.0

What's Changed

New Contributors

... (truncated)

Changelog

Sourced from msgpack's changelog.

1.2.1

Release Date: 2026-06-19

Fix a segfault when calling Unpacker.unpack() or Unpacker.skip() after an unpacking failure. But note that reusing the same Unpacker instance after an unpacking failure is not supported. Please create a new Unpacker instance instead. GHSA-6v7p-g79w-8964

1.2.0

Release Date: 2026-06-11

  • Support free threaded Python. #654, #686
  • Dropped support for Python 3.9. #656
  • Fix missing error checks in C code. #665, #666, #667, #672
  • Fix strict_map_key option didn't work for object_pairs_hook. #673
  • Increase DEFAULT_RECURSE_LIMIT of Unpacker to 1024. #676
  • Fix memory leak when Unpacker returns error for invalid input. #671
  • Fix Packer.pack_ext_type() ignored autoreset option. #663
  • Fix Timestamp.from_datetime() returning wrong value for pre-epoch datetimes. #662
  • Fix use-after-free in unpackb() and Unpacker.unpack() for non-contiguous input. #677
  • Fix possible memory leak when calling Unpacker.__init__() several times. #687
Commits
  • 448d43f release v1.2.1 (#698)
  • 2c56ddb Merge commit from fork
  • 0f4f350 Bump pypa/cibuildwheel from 4.0.0 to 4.1.0 in the all-dependencies group (#694)
  • 11ed0a5 release v1.2.0 (#692)
  • c410a38 Bump pypa/cibuildwheel from 3.4.1 to 4.0.0 (#691)
  • 97ba6ca skip ci: remove unneeded CIBW_SKIP option
  • cdde1b0 Wheels CI hangs for MacOS Intel (#689)
  • 5eb57e1 release v1.2.0rc1 (#681)
  • 77395c1 Harden Unpacker.__init__ re-entry cleanup to prevent buffer/context leaks (...
  • 7df7136 Guard Packer buffer protocol hooks with Cython critical sections (#686)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=msgpack&package-manager=uv&previous-version=1.1.2&new-version=1.2.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ogx-ai/ogx/network/alerts).
--------- Signed-off-by: dependabot[bot] Signed-off-by: github-actions[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] --- pyproject.toml | 1 + uv.lock | 89 +++++++++++++++++++++++++++----------------------- 2 files changed, 50 insertions(+), 40 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0d5bc2abcad..d0f85217fd6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ constraint-dependencies = [ "idna>=3.15", "joserfc>=1.6.7", "lxml>=6.1.0", # CVE-2026-41066: XML entity expansion with default resolve_entities=True + "msgpack>=1.2.1", "pillow>=12.2.0", # CVE-2026-40192 + 4 more: heap overflow, OOB write, DoS "protobuf>=5.29.6", # CVE-2025-4565 + CVE-2026-0994: parsing vulnerabilities "pyasn1>=0.6.3", # CVE-2026-30922: DoS via unbounded recursion diff --git a/uv.lock b/uv.lock index 28cd08abe6e..ff73ba505b4 100644 --- a/uv.lock +++ b/uv.lock @@ -31,6 +31,7 @@ constraints = [ { name = "idna", specifier = ">=3.15" }, { name = "joserfc", specifier = ">=1.6.7" }, { name = "lxml", specifier = ">=6.1.0" }, + { name = "msgpack", specifier = ">=1.2.1" }, { name = "pillow", specifier = ">=12.2.0" }, { name = "protobuf", specifier = ">=5.29.6" }, { name = "pyasn1", specifier = ">=0.6.3" }, @@ -3677,46 +3678,54 @@ wheels = [ [[package]] name = "msgpack" -version = "1.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4d/f2/bfb55a6236ed8725a96b0aa3acbd0ec17588e6a2c3b62a93eb513ed8783f/msgpack-1.1.2.tar.gz", hash = "sha256:3b60763c1373dd60f398488069bcdc703cd08a711477b5d480eecc9f9626f47e", size = 173581, upload-time = "2025-10-08T09:15:56.596Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/bd/8b0d01c756203fbab65d265859749860682ccd2a59594609aeec3a144efa/msgpack-1.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:70a0dff9d1f8da25179ffcf880e10cf1aad55fdb63cd59c9a49a1b82290062aa", size = 81939, upload-time = "2025-10-08T09:15:01.472Z" }, - { url = "https://files.pythonhosted.org/packages/34/68/ba4f155f793a74c1483d4bdef136e1023f7bcba557f0db4ef3db3c665cf1/msgpack-1.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:446abdd8b94b55c800ac34b102dffd2f6aa0ce643c55dfc017ad89347db3dbdb", size = 85064, upload-time = "2025-10-08T09:15:03.764Z" }, - { url = "https://files.pythonhosted.org/packages/f2/60/a064b0345fc36c4c3d2c743c82d9100c40388d77f0b48b2f04d6041dbec1/msgpack-1.1.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c63eea553c69ab05b6747901b97d620bb2a690633c77f23feb0c6a947a8a7b8f", size = 417131, upload-time = "2025-10-08T09:15:05.136Z" }, - { url = "https://files.pythonhosted.org/packages/65/92/a5100f7185a800a5d29f8d14041f61475b9de465ffcc0f3b9fba606e4505/msgpack-1.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:372839311ccf6bdaf39b00b61288e0557916c3729529b301c52c2d88842add42", size = 427556, upload-time = "2025-10-08T09:15:06.837Z" }, - { url = "https://files.pythonhosted.org/packages/f5/87/ffe21d1bf7d9991354ad93949286f643b2bb6ddbeab66373922b44c3b8cc/msgpack-1.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2929af52106ca73fcb28576218476ffbb531a036c2adbcf54a3664de124303e9", size = 404920, upload-time = "2025-10-08T09:15:08.179Z" }, - { url = "https://files.pythonhosted.org/packages/ff/41/8543ed2b8604f7c0d89ce066f42007faac1eaa7d79a81555f206a5cdb889/msgpack-1.1.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be52a8fc79e45b0364210eef5234a7cf8d330836d0a64dfbb878efa903d84620", size = 415013, upload-time = "2025-10-08T09:15:09.83Z" }, - { url = "https://files.pythonhosted.org/packages/41/0d/2ddfaa8b7e1cee6c490d46cb0a39742b19e2481600a7a0e96537e9c22f43/msgpack-1.1.2-cp312-cp312-win32.whl", hash = "sha256:1fff3d825d7859ac888b0fbda39a42d59193543920eda9d9bea44d958a878029", size = 65096, upload-time = "2025-10-08T09:15:11.11Z" }, - { url = "https://files.pythonhosted.org/packages/8c/ec/d431eb7941fb55a31dd6ca3404d41fbb52d99172df2e7707754488390910/msgpack-1.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:1de460f0403172cff81169a30b9a92b260cb809c4cb7e2fc79ae8d0510c78b6b", size = 72708, upload-time = "2025-10-08T09:15:12.554Z" }, - { url = "https://files.pythonhosted.org/packages/c5/31/5b1a1f70eb0e87d1678e9624908f86317787b536060641d6798e3cf70ace/msgpack-1.1.2-cp312-cp312-win_arm64.whl", hash = "sha256:be5980f3ee0e6bd44f3a9e9dea01054f175b50c3e6cdb692bc9424c0bbb8bf69", size = 64119, upload-time = "2025-10-08T09:15:13.589Z" }, - { url = "https://files.pythonhosted.org/packages/6b/31/b46518ecc604d7edf3a4f94cb3bf021fc62aa301f0cb849936968164ef23/msgpack-1.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4efd7b5979ccb539c221a4c4e16aac1a533efc97f3b759bb5a5ac9f6d10383bf", size = 81212, upload-time = "2025-10-08T09:15:14.552Z" }, - { url = "https://files.pythonhosted.org/packages/92/dc/c385f38f2c2433333345a82926c6bfa5ecfff3ef787201614317b58dd8be/msgpack-1.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:42eefe2c3e2af97ed470eec850facbe1b5ad1d6eacdbadc42ec98e7dcf68b4b7", size = 84315, upload-time = "2025-10-08T09:15:15.543Z" }, - { url = "https://files.pythonhosted.org/packages/d3/68/93180dce57f684a61a88a45ed13047558ded2be46f03acb8dec6d7c513af/msgpack-1.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1fdf7d83102bf09e7ce3357de96c59b627395352a4024f6e2458501f158bf999", size = 412721, upload-time = "2025-10-08T09:15:16.567Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ba/459f18c16f2b3fc1a1ca871f72f07d70c07bf768ad0a507a698b8052ac58/msgpack-1.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fac4be746328f90caa3cd4bc67e6fe36ca2bf61d5c6eb6d895b6527e3f05071e", size = 424657, upload-time = "2025-10-08T09:15:17.825Z" }, - { url = "https://files.pythonhosted.org/packages/38/f8/4398c46863b093252fe67368b44edc6c13b17f4e6b0e4929dbf0bdb13f23/msgpack-1.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fffee09044073e69f2bad787071aeec727183e7580443dfeb8556cbf1978d162", size = 402668, upload-time = "2025-10-08T09:15:19.003Z" }, - { url = "https://files.pythonhosted.org/packages/28/ce/698c1eff75626e4124b4d78e21cca0b4cc90043afb80a507626ea354ab52/msgpack-1.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5928604de9b032bc17f5099496417f113c45bc6bc21b5c6920caf34b3c428794", size = 419040, upload-time = "2025-10-08T09:15:20.183Z" }, - { url = "https://files.pythonhosted.org/packages/67/32/f3cd1667028424fa7001d82e10ee35386eea1408b93d399b09fb0aa7875f/msgpack-1.1.2-cp313-cp313-win32.whl", hash = "sha256:a7787d353595c7c7e145e2331abf8b7ff1e6673a6b974ded96e6d4ec09f00c8c", size = 65037, upload-time = "2025-10-08T09:15:21.416Z" }, - { url = "https://files.pythonhosted.org/packages/74/07/1ed8277f8653c40ebc65985180b007879f6a836c525b3885dcc6448ae6cb/msgpack-1.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:a465f0dceb8e13a487e54c07d04ae3ba131c7c5b95e2612596eafde1dccf64a9", size = 72631, upload-time = "2025-10-08T09:15:22.431Z" }, - { url = "https://files.pythonhosted.org/packages/e5/db/0314e4e2db56ebcf450f277904ffd84a7988b9e5da8d0d61ab2d057df2b6/msgpack-1.1.2-cp313-cp313-win_arm64.whl", hash = "sha256:e69b39f8c0aa5ec24b57737ebee40be647035158f14ed4b40e6f150077e21a84", size = 64118, upload-time = "2025-10-08T09:15:23.402Z" }, - { url = "https://files.pythonhosted.org/packages/22/71/201105712d0a2ff07b7873ed3c220292fb2ea5120603c00c4b634bcdafb3/msgpack-1.1.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e23ce8d5f7aa6ea6d2a2b326b4ba46c985dbb204523759984430db7114f8aa00", size = 81127, upload-time = "2025-10-08T09:15:24.408Z" }, - { url = "https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6c15b7d74c939ebe620dd8e559384be806204d73b4f9356320632d783d1f7939", size = 84981, upload-time = "2025-10-08T09:15:25.812Z" }, - { url = "https://files.pythonhosted.org/packages/8e/a9/3536e385167b88c2cc8f4424c49e28d49a6fc35206d4a8060f136e71f94c/msgpack-1.1.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99e2cb7b9031568a2a5c73aa077180f93dd2e95b4f8d3b8e14a73ae94a9e667e", size = 411885, upload-time = "2025-10-08T09:15:27.22Z" }, - { url = "https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:180759d89a057eab503cf62eeec0aa61c4ea1200dee709f3a8e9397dbb3b6931", size = 419658, upload-time = "2025-10-08T09:15:28.4Z" }, - { url = "https://files.pythonhosted.org/packages/3b/ef/2b92e286366500a09a67e03496ee8b8ba00562797a52f3c117aa2b29514b/msgpack-1.1.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:04fb995247a6e83830b62f0b07bf36540c213f6eac8e851166d8d86d83cbd014", size = 403290, upload-time = "2025-10-08T09:15:29.764Z" }, - { url = "https://files.pythonhosted.org/packages/78/90/e0ea7990abea5764e4655b8177aa7c63cdfa89945b6e7641055800f6c16b/msgpack-1.1.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8e22ab046fa7ede9e36eeb4cfad44d46450f37bb05d5ec482b02868f451c95e2", size = 415234, upload-time = "2025-10-08T09:15:31.022Z" }, - { url = "https://files.pythonhosted.org/packages/72/4e/9390aed5db983a2310818cd7d3ec0aecad45e1f7007e0cda79c79507bb0d/msgpack-1.1.2-cp314-cp314-win32.whl", hash = "sha256:80a0ff7d4abf5fecb995fcf235d4064b9a9a8a40a3ab80999e6ac1e30b702717", size = 66391, upload-time = "2025-10-08T09:15:32.265Z" }, - { url = "https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl", hash = "sha256:9ade919fac6a3e7260b7f64cea89df6bec59104987cbea34d34a2fa15d74310b", size = 73787, upload-time = "2025-10-08T09:15:33.219Z" }, - { url = "https://files.pythonhosted.org/packages/6a/b0/9d9f667ab48b16ad4115c1935d94023b82b3198064cb84a123e97f7466c1/msgpack-1.1.2-cp314-cp314-win_arm64.whl", hash = "sha256:59415c6076b1e30e563eb732e23b994a61c159cec44deaf584e5cc1dd662f2af", size = 66453, upload-time = "2025-10-08T09:15:34.225Z" }, - { url = "https://files.pythonhosted.org/packages/16/67/93f80545eb1792b61a217fa7f06d5e5cb9e0055bed867f43e2b8e012e137/msgpack-1.1.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:897c478140877e5307760b0ea66e0932738879e7aa68144d9b78ea4c8302a84a", size = 85264, upload-time = "2025-10-08T09:15:35.61Z" }, - { url = "https://files.pythonhosted.org/packages/87/1c/33c8a24959cf193966ef11a6f6a2995a65eb066bd681fd085afd519a57ce/msgpack-1.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a668204fa43e6d02f89dbe79a30b0d67238d9ec4c5bd8a940fc3a004a47b721b", size = 89076, upload-time = "2025-10-08T09:15:36.619Z" }, - { url = "https://files.pythonhosted.org/packages/fc/6b/62e85ff7193663fbea5c0254ef32f0c77134b4059f8da89b958beb7696f3/msgpack-1.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5559d03930d3aa0f3aacb4c42c776af1a2ace2611871c84a75afe436695e6245", size = 435242, upload-time = "2025-10-08T09:15:37.647Z" }, - { url = "https://files.pythonhosted.org/packages/c1/47/5c74ecb4cc277cf09f64e913947871682ffa82b3b93c8dad68083112f412/msgpack-1.1.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:70c5a7a9fea7f036b716191c29047374c10721c389c21e9ffafad04df8c52c90", size = 432509, upload-time = "2025-10-08T09:15:38.794Z" }, - { url = "https://files.pythonhosted.org/packages/24/a4/e98ccdb56dc4e98c929a3f150de1799831c0a800583cde9fa022fa90602d/msgpack-1.1.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f2cb069d8b981abc72b41aea1c580ce92d57c673ec61af4c500153a626cb9e20", size = 415957, upload-time = "2025-10-08T09:15:40.238Z" }, - { url = "https://files.pythonhosted.org/packages/da/28/6951f7fb67bc0a4e184a6b38ab71a92d9ba58080b27a77d3e2fb0be5998f/msgpack-1.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d62ce1f483f355f61adb5433ebfd8868c5f078d1a52d042b0a998682b4fa8c27", size = 422910, upload-time = "2025-10-08T09:15:41.505Z" }, - { url = "https://files.pythonhosted.org/packages/f0/03/42106dcded51f0a0b5284d3ce30a671e7bd3f7318d122b2ead66ad289fed/msgpack-1.1.2-cp314-cp314t-win32.whl", hash = "sha256:1d1418482b1ee984625d88aa9585db570180c286d942da463533b238b98b812b", size = 75197, upload-time = "2025-10-08T09:15:42.954Z" }, - { url = "https://files.pythonhosted.org/packages/15/86/d0071e94987f8db59d4eeb386ddc64d0bb9b10820a8d82bcd3e53eeb2da6/msgpack-1.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:5a46bf7e831d09470ad92dff02b8b1ac92175ca36b087f904a0519857c6be3ff", size = 85772, upload-time = "2025-10-08T09:15:43.954Z" }, - { url = "https://files.pythonhosted.org/packages/81/f2/08ace4142eb281c12701fc3b93a10795e4d4dc7f753911d836675050f886/msgpack-1.1.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d99ef64f349d5ec3293688e91486c5fdb925ed03807f64d98d205d2713c60b46", size = 70868, upload-time = "2025-10-08T09:15:44.959Z" }, +version = "1.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/f9/c0a1c127f9049db9155afc316952ea571720dd01833ff5e4d7e8e6352dbb/msgpack-1.2.1.tar.gz", hash = "sha256:04c721c2c7448767e9e3f2520a475663d8ee0f09c31890f6d2bd70fd636a9647", size = 183960, upload-time = "2026-06-18T16:13:52.594Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/dd/9e8cbd8f5582ca4b590336f2b91ee5662f6a6ca562b565abaf696a0f81ff/msgpack-1.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2ef59c659f289eddf8aa6623823f19fa2f40a4029266889eac7a2505dd210c35", size = 83531, upload-time = "2026-06-18T16:12:58.249Z" }, + { url = "https://files.pythonhosted.org/packages/50/2e/ebdb85a8da151397a2790363676b7ed7c125924fe618e4c6d8befb0cc62c/msgpack-1.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d3567748a5107cb40cdf66a275430c2f87c07777698f4bfd25c35f44d533258c", size = 82657, upload-time = "2026-06-18T16:12:59.396Z" }, + { url = "https://files.pythonhosted.org/packages/26/aa/753ad8b007b464e1d8aa0c8e650b9c5f4f725e658fc5ac8a7635c55b7f6e/msgpack-1.2.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60926b75d00c8e816ef98f3034f484a8bc64242d66839cef4cf7e503142316a0", size = 410634, upload-time = "2026-06-18T16:13:00.383Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fd/6adabd4f6d5e686f97dd02ce7fce3fe4cf672cbac36b8f67ff4040e8ad8b/msgpack-1.2.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:020e881a764b20d8d7ca1a54fc01b8175519d108e3c3f194fddc200bda95951a", size = 419989, upload-time = "2026-06-18T16:13:01.776Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cc/85039b7b0eb168aaad7383a23c97e291a11f08351cb45a606ce865e4e3f1/msgpack-1.2.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4202c74688ca06591f78cb18988228bd4cca2cc75d57b60008372892d2f1e6e6", size = 377544, upload-time = "2026-06-18T16:13:03.637Z" }, + { url = "https://files.pythonhosted.org/packages/ed/bf/35963899493b32030c85fc513b723ae66144ac70c11ebc52e889e16e3d99/msgpack-1.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8b267ce94efb76fbd1b3373511420074ee3187f0f7811bf394531de13294735a", size = 400842, upload-time = "2026-06-18T16:13:05.012Z" }, + { url = "https://files.pythonhosted.org/packages/a6/df/8e2ac970c8f99264cd9997d1c73df5466bc19da3301d7dc5500862a9b089/msgpack-1.2.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e4f1d0f8f98ade9634e01fb704a408f9336c0a8f1117b369f5db83dc7551d8b1", size = 374108, upload-time = "2026-06-18T16:13:06.232Z" }, + { url = "https://files.pythonhosted.org/packages/17/dd/fa8bd265110dfa51c20cb529f9e6d240a16fafe7e645004c6af2d01353ba/msgpack-1.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f02cf17a6ca1abe29b5f980644f7551f94d71f2011509b26d8625ce038f0df64", size = 414939, upload-time = "2026-06-18T16:13:07.478Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b9/8377a5ad8953fc0437c70cc98d9ae29f27fe5ac5109fbec0812085865735/msgpack-1.2.1-cp312-cp312-win32.whl", hash = "sha256:0c0d9802354507bcba62af19c17918e3eb437cc25e6f50657d511b5856a77aac", size = 64504, upload-time = "2026-06-18T16:13:08.822Z" }, + { url = "https://files.pythonhosted.org/packages/57/7f/ce1e377df7e62461fefd9eb23bfb93a4a523f40a517b377b8f844d836828/msgpack-1.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:5c24aa15d5963051e1a5c62b12c50cd705992502b5ec1f3bece6046f33c9fc24", size = 71421, upload-time = "2026-06-18T16:13:09.828Z" }, + { url = "https://files.pythonhosted.org/packages/8f/32/ebfe84c9929f08f188d56c7a2fd913406a9ddad76a634697c1c43b8112e6/msgpack-1.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:4227224aaec8f7fbcbfbd4272319347b2bb4030366502600f8c45588c5187b07", size = 64775, upload-time = "2026-06-18T16:13:11.056Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ac/dcddcab6f6c20ecb387ca5e980371cdb3f87ff69aeca388be97eebc4c074/msgpack-1.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0a70e3cf2804a300d921bb0940426e35f4e489a23adfb77a808892241db0a064", size = 83151, upload-time = "2026-06-18T16:13:12.173Z" }, + { url = "https://files.pythonhosted.org/packages/64/71/fbcfa83a1d6a9c6091942d1cfd070962244664b87427a9a49a6897b1b219/msgpack-1.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:491cc39455ca765fad51fb451bf2915eb2cf41192ab5801ce8d67c1d614fe056", size = 82351, upload-time = "2026-06-18T16:13:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/e3/10/ddf7b06db879e8792d13934ddda09ff20bd2a583fd84c9b59aae9b0e650b/msgpack-1.2.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f310233ef7fb9c14e201c93639fe5f5260b005f56f0b29048e999c30935596cc", size = 407518, upload-time = "2026-06-18T16:13:14.233Z" }, + { url = "https://files.pythonhosted.org/packages/79/d3/36a46a8ed992b781acbc05928bd5bee3c810cb0c3563bf81a7b0c04a1a76/msgpack-1.2.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:787c9bebb5833e8f6fc8abca3c0597683d8d87f56a8842b6b89c75a5f3176e2d", size = 416405, upload-time = "2026-06-18T16:13:15.435Z" }, + { url = "https://files.pythonhosted.org/packages/f9/84/e8e9598b557c0ba6ddae901a73780a4c75ac667dddf59414b1e56a42fb34/msgpack-1.2.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dc871b997a9370d855b7394465f2f350e847a5b806dd38dcc9c989e7d87da155", size = 376257, upload-time = "2026-06-18T16:13:17.022Z" }, + { url = "https://files.pythonhosted.org/packages/40/16/738fe6d875ad7e2a9429c165322a4ec088f4f273cdfae63d96a89c467961/msgpack-1.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:85f57e960d877f2977f6430896191b04a21f8901b3b4baf2e4604329f4db5402", size = 397469, upload-time = "2026-06-18T16:13:18.287Z" }, + { url = "https://files.pythonhosted.org/packages/ca/be/6d5952df75a7f24f35833af764c3a6860780364cb3a0030beb8099e1b2b4/msgpack-1.2.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:1233ee2dd0cefba127583de50ea654677277047d238303521db35def3d7b2e7c", size = 372802, upload-time = "2026-06-18T16:13:19.685Z" }, + { url = "https://files.pythonhosted.org/packages/e1/39/e2ef7dbf0473bcb8dc7c50bf782a892d67414877b63e47fc88eb189ef5e6/msgpack-1.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e3dc2feb0876209d9c38aa56cb1de169bd6c4348f1aa48271f241226590993e6", size = 411273, upload-time = "2026-06-18T16:13:21.028Z" }, + { url = "https://files.pythonhosted.org/packages/ef/c5/133f4512a56e983a93445c836c9d94d88f3bc2e0980ff4b9e577bd8416ce/msgpack-1.2.1-cp313-cp313-win32.whl", hash = "sha256:6d09badf350af2be9d189184e04e64cf54ad93569ab3d96fca58bd3e84aad707", size = 64471, upload-time = "2026-06-18T16:13:22.293Z" }, + { url = "https://files.pythonhosted.org/packages/e2/98/577e10b055096a7dd40732358cabaf7180a20c79ed1dcdbb618e4b9deac7/msgpack-1.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:33f14fba63278b714efe6ad07e50ea5f03d91537aa6a1c5f1ceca4cf44013ca9", size = 71274, upload-time = "2026-06-18T16:13:23.455Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ee/0c0048e7cfbef23c6a94791b8959ab28155232e7956de8a305b5ff588f05/msgpack-1.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:afc5febcd4c99effbc02b528e49d6fd0760b2b7d48c05239e345a5fa6e743d9a", size = 64795, upload-time = "2026-06-18T16:13:24.687Z" }, + { url = "https://files.pythonhosted.org/packages/77/58/cce442852c6b9e1639c7c8ac8fd9143121cb32dab0f308df4d1426a8eb9c/msgpack-1.2.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:05f340e47e7e47d2da8db9b53e1bb1d294369e9ef45a747441309f6650b8351d", size = 83610, upload-time = "2026-06-18T16:13:25.724Z" }, + { url = "https://files.pythonhosted.org/packages/60/5c/15b4c7a0182f75ffa90751958ba36a9c01cafee367d49a3edc10ed140b01/msgpack-1.2.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:810b916696c86ef0deb3b74588480224df4c1b071136c34183e4a2a4284d7ac7", size = 83138, upload-time = "2026-06-18T16:13:26.781Z" }, + { url = "https://files.pythonhosted.org/packages/b8/a6/99e58722feaffc5f2fbcc0c8c0d1451ab9f84097f7af87291b46af2390f4/msgpack-1.2.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ca0dacff965c47afdc3749a8469d7302a8f801d6a28758d55120d75e66ce6889", size = 406090, upload-time = "2026-06-18T16:13:28.072Z" }, + { url = "https://files.pythonhosted.org/packages/19/03/8c63e8cf52958534ef688625965ab04c269a6cadd8caef16758b380a821a/msgpack-1.2.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e2bf9280bceb5efca998435904b5d3e9fdbcc11d90dc9df30aec7973252b720", size = 412106, upload-time = "2026-06-18T16:13:29.427Z" }, + { url = "https://files.pythonhosted.org/packages/63/d2/155d9e71b40e41fd934bc0c48b9b2770f22263e1ac20aad8e29fdca7be3f/msgpack-1.2.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6c4be5d1c02a42b066ca6ddb71adf36432868fdcdb6ee87e634e86e0674190", size = 374851, upload-time = "2026-06-18T16:13:30.631Z" }, + { url = "https://files.pythonhosted.org/packages/98/48/deaf2326262a8d5ea3295ce9649912ecd3f551ba7ec8e33c665d2ba583f3/msgpack-1.2.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec0e675d59150a6269ddc9139087c722292664a37d071a849c05c473350f1f2d", size = 396168, upload-time = "2026-06-18T16:13:31.977Z" }, + { url = "https://files.pythonhosted.org/packages/10/2a/b4410f906c2ec0008f1608d3ab5143afc3ad3f4e6da0fed3ea2231d0bef4/msgpack-1.2.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:dd3bfe82d53edfe4b7fc9a7ec9761e23a7a5b1dac22264505af428253c29ed24", size = 371959, upload-time = "2026-06-18T16:13:33.282Z" }, + { url = "https://files.pythonhosted.org/packages/59/86/1edc67270099a528fa2093ea60fe191233cd238e4bd30cfacf7db79fc959/msgpack-1.2.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5ad5467fc3f68b5468e06c5f788d712e9f8ffc8b0cd1bcb160c105c1ee92dae7", size = 408457, upload-time = "2026-06-18T16:13:34.567Z" }, + { url = "https://files.pythonhosted.org/packages/82/90/8b630fef07d8c5ab457b71ff2c217910c83d333c7a68472c186e87cc504a/msgpack-1.2.1-cp314-cp314-win32.whl", hash = "sha256:98b58bdb89c46190e4609bb36abe17c6d4105ad13f9c5f8f6f64d320f8ced3fb", size = 65942, upload-time = "2026-06-18T16:13:36.056Z" }, + { url = "https://files.pythonhosted.org/packages/16/f1/467b81e98b24dd3885d7b1857728797b4ffc76a7a7483af4fb321a07de3c/msgpack-1.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:74847557e28ce71bd3c438a447ca90e4b507e997ddbdef8a12a7b283b86c156b", size = 72627, upload-time = "2026-06-18T16:13:37.079Z" }, + { url = "https://files.pythonhosted.org/packages/a7/1d/5d8c4c89985feb6acefb82a09e501c60392261856d2408d20bfe4f0360b1/msgpack-1.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:b50b727bd652bdc37d950336c848ef20ec54a4cafc38dce19b1cd86ad625d0f7", size = 66908, upload-time = "2026-06-18T16:13:38.23Z" }, + { url = "https://files.pythonhosted.org/packages/1b/02/ad2afb678b4de94496cd432b581759b756a92c1192d8c767edd6b132efdc/msgpack-1.2.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:8d00f177ca88a77c1cf848d204a38f249751650b601cb6532acc68805d8a8273", size = 86000, upload-time = "2026-06-18T16:13:39.44Z" }, + { url = "https://files.pythonhosted.org/packages/54/74/0b797484013128837f3b1cbb6cea019277c4de4e377dc512b4d9a0f92940/msgpack-1.2.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5bb9c386f0a329c035ddbab4b72d1028bf9627add8dda41070288563d57ed1b1", size = 86544, upload-time = "2026-06-18T16:13:40.447Z" }, + { url = "https://files.pythonhosted.org/packages/a9/b4/b774d7eb95561739907fec675582f83203cf41c597a418c2589b4bfb8e9d/msgpack-1.2.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20466cca18c49c7292a8984bc15d65857b171e7264bdcb5f96baf8be238791fc", size = 427661, upload-time = "2026-06-18T16:13:41.574Z" }, + { url = "https://files.pythonhosted.org/packages/b2/f9/3243191dc9937e00756c8bc1b0272fed8f23758e43df2a3b46f533e5090f/msgpack-1.2.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:196300e7e5d6e74d50f1607ab9c06c4a1484c383cd22defd727902591f7e8dde", size = 426375, upload-time = "2026-06-18T16:13:42.936Z" }, + { url = "https://files.pythonhosted.org/packages/23/c7/1693111db9944ba4ad4b67a1e788400d78a0b6af7a6523dc7e4e58f8274b/msgpack-1.2.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:575957e79cd51903a4e8495a242442949641e08f1efd5197b43bebd3ea7682b4", size = 380495, upload-time = "2026-06-18T16:13:44.306Z" }, + { url = "https://files.pythonhosted.org/packages/3e/2b/92f86956a0c13e8662f7e2ad630c4eb4db07497b967589bd5245e018b2c1/msgpack-1.2.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8c2ed1e48cc0f460bf3c7780e7137ff21a4e18433451916f2442c1b21036cd7d", size = 410897, upload-time = "2026-06-18T16:13:45.629Z" }, + { url = "https://files.pythonhosted.org/packages/da/ea/1479f72d200313a76fc2f823a79d1e07ed052ab7b8a0280640aa7b95de42/msgpack-1.2.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5f6277e5f783c36786a145e0247fc189a03f35f84b251646e53592d2bc12b355", size = 378519, upload-time = "2026-06-18T16:13:46.998Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4d/fa006060ffa1011d32bfae826fe766fe73e02982183601633b7121058ab3/msgpack-1.2.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f9389552ecf4784886345ead0647e4edc96bee37cbab05b75540f542f766c48c", size = 419815, upload-time = "2026-06-18T16:13:48.205Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/aab6c946570496b78e67804721f3d5e2d62a93081b9b37df77764ef56347/msgpack-1.2.1-cp314-cp314t-win32.whl", hash = "sha256:c1c79a604a2969a868a78b6ebd27a887e00c624f14f66b3038e0590cb23332d1", size = 70914, upload-time = "2026-06-18T16:13:49.385Z" }, + { url = "https://files.pythonhosted.org/packages/13/0a/e608956488a2af014cfe6e3d665e090b8ee42aa14b07f8f95b8880d66b09/msgpack-1.2.1-cp314-cp314t-win_amd64.whl", hash = "sha256:f12038a35fabd52e56a3547bab42401af49a45caa6dd00b34c44de235bc93ee2", size = 77999, upload-time = "2026-06-18T16:13:50.467Z" }, + { url = "https://files.pythonhosted.org/packages/d2/8a/27e2e57055176e366a46b85d02d68e7a5bcfbdd8474c9706375d965f24d3/msgpack-1.2.1-cp314-cp314t-win_arm64.whl", hash = "sha256:0adcf06ffde0777c0e1a9b771a2b1c4226ba1bbf748c8efcc02fcdeca3299107", size = 71160, upload-time = "2026-06-18T16:13:51.498Z" }, ] [[package]] From 661d4dff83ca368a63d80b09819b5c913fa9e169 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 12:03:52 +0000 Subject: [PATCH 24/32] chore(python-deps): bump pydantic-settings from 2.14.1 to 2.14.2 (#6150) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [pydantic-settings](https://github.com/pydantic/pydantic-settings) from 2.14.1 to 2.14.2.
Release notes

Sourced from pydantic-settings's releases.

v2.14.2

What's Changed

This is a security patch release.

Security

Fixes GHSA-4xgf-cpjx-pc3j: NestedSecretsSettingsSource with secrets_nested_subdir=True could follow a symbolic link inside secrets_dir pointing outside it, reading out-of-tree files into settings values and bypassing the secrets_dir_max_size cap. Affected versions: >= 2.12.0, < 2.14.2.

Full Changelog: https://github.com/pydantic/pydantic-settings/compare/v2.14.1...v2.14.2

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pydantic-settings&package-manager=uv&previous-version=2.14.1&new-version=2.14.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ogx-ai/ogx/network/alerts).
--------- Signed-off-by: dependabot[bot] Signed-off-by: github-actions[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] --- pyproject.toml | 1 + uv.lock | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d0f85217fd6..1b13d27566a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ constraint-dependencies = [ "pillow>=12.2.0", # CVE-2026-40192 + 4 more: heap overflow, OOB write, DoS "protobuf>=5.29.6", # CVE-2025-4565 + CVE-2026-0994: parsing vulnerabilities "pyasn1>=0.6.3", # CVE-2026-30922: DoS via unbounded recursion + "pydantic-settings>=2.14.2", "python-multipart>=0.0.31", # CVE-2026-40347: header injection; CVE-2026-42561: DoS via oversized headers "python-socketio>=5.16.2", # CVE-2025-61765: RCE via pickle deserialization "requests>=2.34.2", diff --git a/uv.lock b/uv.lock index ff73ba505b4..f8c44ee7905 100644 --- a/uv.lock +++ b/uv.lock @@ -35,6 +35,7 @@ constraints = [ { name = "pillow", specifier = ">=12.2.0" }, { name = "protobuf", specifier = ">=5.29.6" }, { name = "pyasn1", specifier = ">=0.6.3" }, + { name = "pydantic-settings", specifier = ">=2.14.2" }, { name = "python-multipart", specifier = ">=0.0.31" }, { name = "python-socketio", specifier = ">=5.16.2" }, { name = "requests", specifier = ">=2.34.2" }, @@ -5876,16 +5877,16 @@ wheels = [ [[package]] name = "pydantic-settings" -version = "2.14.1" +version = "2.14.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/07/60/1d1e59c9c90d54591469ada7d268251f71c24bdb765f1a8a832cee8c6653/pydantic_settings-2.14.1.tar.gz", hash = "sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa", size = 235551, upload-time = "2026-05-08T13:40:06.542Z" } +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" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/8d/f1af3832f5e6eb13ba94ee809e72b8ecb5eef226d27ee0bef7d963d943c7/pydantic_settings-2.14.1-py3-none-any.whl", hash = "sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de", size = 60964, upload-time = "2026-05-08T13:40:04.958Z" }, + { 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" }, ] [[package]] From 5e7388521853546cf78b251f6bd4209bd6c80255 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 14:04:40 +0200 Subject: [PATCH 25/32] chore(python-deps): bump pypdf from 6.13.0 to 6.13.3 (#6142) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [pypdf](https://github.com/py-pdf/pypdf) from 6.13.0 to 6.13.3.
Release notes

Sourced from pypdf's releases.

Version 6.13.3, 2026-06-17

What's new

Security (SEC)

Performance Improvements (PI)

Robustness (ROB)

Maintenance (MAINT)

Full Changelog

Version 6.13.2, 2026-06-10

What's new

Security (SEC)

Robustness (ROB)

Full Changelog

Version 6.13.1, 2026-06-08

What's new

Security (SEC)

Full Changelog

Changelog

Sourced from pypdf's changelog.

Version 6.13.3, 2026-06-17

Security (SEC)

  • Apply MAX_DECLARED_STREAM_LENGTH to streams without length as well (#3871)

Performance Improvements (PI)

  • Avoid per-pixel getpixel loop for 1-bit indexed images (#3854)

Robustness (ROB)

  • Several fixes

Maintenance (MAINT)

  • Make mypy assert messages consistent (#3849)

Full Changelog

Version 6.13.2, 2026-06-10

Security (SEC)

  • Detect multi-hop cyclic /Pages trees in _flatten to prevent SIGSEGV (#3847)

Robustness (ROB)

  • Fix UnboundLocalError in _read_standard_xref_table on a malformed entry (#3841)
  • Raise PdfStreamError on non-hexadecimal bytes in hex readers (#3832)

Full Changelog

Version 6.13.1, 2026-06-08

Security (SEC)

  • Prevent infinite loops when processing threads/articles (#3839)

Full Changelog

Commits
  • 9aa05e7 REL: 6.13.3
  • bbd083d SEC: Apply MAX_DECLARED_STREAM_LENGTH to streams without length as well (#3871)
  • d5cd266 ROB: Guard text operators against missing operands in extract_text (#3861)
  • 82f1f90 ROB: Tolerate malformed /Limits in index2label (#3858)
  • 0276a6f PI: Avoid per-pixel getpixel loop for 1-bit indexed images (#3854)
  • 41a9c3c MAINT: Make mypy assert messages consistent (#3849)
  • d1bba60 MAINT: Increase readability of PdfDocCommon (#3834)
  • 53b6fbc DEV: Bump codecov/codecov-action from 6.0.1 to 7.0.0 (#3859)
  • e07c223 MAINT: Enforce G004 (no f-strings in logging) (#3845)
  • 5270f76 ROB: Guard zero unitsPerEm in from_truetype_font_file (#3846)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pypdf&package-manager=uv&previous-version=6.13.0&new-version=6.13.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ogx-ai/ogx/network/alerts).
--------- Signed-off-by: dependabot[bot] Signed-off-by: github-actions[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] --- pyproject.toml | 6 +++--- uv.lock | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1b13d27566a..e73178b528f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -114,7 +114,7 @@ starter = [ "pgvector>=0.3.0", "pymilvus[milvus-lite]>=2.4.10", "pymongo", - "pypdf>=6.13.0", + "pypdf>=6.13.3", "pythainlp", "qdrant-client", "redis>=8.0.0", @@ -162,7 +162,7 @@ type_checking = [ "types-setuptools", "types-jsonschema", "markitdown[all]", - "pypdf>=6.13.0", + "pypdf>=6.13.3", "pandas-stubs", "types-psutil>=7.2.2.20260518", "types-tqdm", @@ -200,7 +200,7 @@ test-common = [ "mcp>=1.23.0,<2.0", "pgvector>=0.3.0", "psycopg2-binary>=2.9.0", - "pypdf>=6.13.0", + "pypdf>=6.13.3", "sqlalchemy[asyncio]>=2.0.41", ] # These are the dependencies required for running unit tests. diff --git a/uv.lock b/uv.lock index f8c44ee7905..5e88aa54c57 100644 --- a/uv.lock +++ b/uv.lock @@ -4378,7 +4378,7 @@ requires-dist = [ { name = "pyjwt", extras = ["crypto"], specifier = ">=2.13.0" }, { name = "pymilvus", extras = ["milvus-lite"], marker = "extra == 'starter'", specifier = ">=2.4.10" }, { name = "pymongo", marker = "extra == 'starter'" }, - { name = "pypdf", marker = "extra == 'starter'", specifier = ">=6.13.0" }, + { name = "pypdf", marker = "extra == 'starter'", specifier = ">=6.13.3" }, { name = "pythainlp", marker = "extra == 'starter'" }, { name = "python-dotenv", specifier = ">=1.2.2" }, { name = "pyyaml", specifier = ">=6.0" }, @@ -4440,7 +4440,7 @@ dev = [ { name = "pgvector", specifier = ">=0.3.0" }, { name = "pre-commit", specifier = ">=4.4.0" }, { name = "psycopg2-binary", specifier = ">=2.9.0" }, - { name = "pypdf", specifier = ">=6.13.0" }, + { name = "pypdf", specifier = ">=6.13.3" }, { name = "pytest", specifier = ">=8.4" }, { name = "pytest-asyncio", specifier = ">=1.4.0" }, { name = "pytest-cov" }, @@ -4493,7 +4493,7 @@ test = [ { name = "pgvector", specifier = ">=0.3.0" }, { name = "psycopg2-binary", specifier = ">=2.9.0" }, { name = "pymilvus", specifier = ">=2.6.2" }, - { name = "pypdf", specifier = ">=6.13.0" }, + { name = "pypdf", specifier = ">=6.13.3" }, { name = "qdrant-client" }, { name = "requests" }, { name = "sqlalchemy", extras = ["asyncio"], specifier = ">=2.0.41" }, @@ -4510,7 +4510,7 @@ test-common = [ { name = "mcp", specifier = ">=1.23.0,<2.0" }, { name = "pgvector", specifier = ">=0.3.0" }, { name = "psycopg2-binary", specifier = ">=2.9.0" }, - { name = "pypdf", specifier = ">=6.13.0" }, + { name = "pypdf", specifier = ">=6.13.3" }, { name = "sqlalchemy", extras = ["asyncio"], specifier = ">=2.0.41" }, ] type-checking = [ @@ -4534,7 +4534,7 @@ type-checking = [ { name = "pandas-stubs" }, { name = "peft" }, { name = "pymongo" }, - { name = "pypdf", specifier = ">=6.13.0" }, + { name = "pypdf", specifier = ">=6.13.3" }, { name = "sqlite-vec" }, { name = "streamlit", specifier = ">=1.58.0" }, { name = "streamlit-option-menu" }, @@ -4565,7 +4565,7 @@ unit = [ { name = "ollama" }, { name = "pgvector", specifier = ">=0.3.0" }, { name = "psycopg2-binary", specifier = ">=2.9.0" }, - { name = "pypdf", specifier = ">=6.13.0" }, + { name = "pypdf", specifier = ">=6.13.3" }, { name = "sqlalchemy", extras = ["asyncio"], specifier = ">=2.0.41" }, { name = "sqlite-vec" }, { name = "together" }, @@ -6019,11 +6019,11 @@ wheels = [ [[package]] name = "pypdf" -version = "6.13.0" +version = "6.13.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/70/79/9fd087fbff8300e5c2a9b2bd0200b75c6ef8c1f9a7a2cfe3df0659aa4025/pypdf-6.13.0.tar.gz", hash = "sha256:558683ec9daf6b91c280c322c84c32f5cc216afd3eaa3a37de5ae88ae0c3b787", size = 6476995, upload-time = "2026-06-05T10:12:05.568Z" } +sdist = { url = "https://files.pythonhosted.org/packages/17/18/9947cc201af9ccf76720fd3347bf4f70eb882ce3fcf4cb05f7443e4cf871/pypdf-6.13.3.tar.gz", hash = "sha256:f3cb822769725f1bac658c406cfc9460399043f3750c2d3e4650e0a85eacabd7", size = 6484063, upload-time = "2026-06-17T15:22:00.898Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/70/16942ec95d32187d8679ce8419cee2d5c0dbe90fa3ac1b307daea4c86da9/pypdf-6.13.0-py3-none-any.whl", hash = "sha256:de1294ae49d6956edb4e5c41527fb9e8716ddd2b120f2185c68aab784d4ffe60", size = 345958, upload-time = "2026-06-05T10:12:03.453Z" }, + { url = "https://files.pythonhosted.org/packages/94/56/2967e621598987905fb8cdfadd8f8de6b5c68c9351f0523c4df8409f28f1/pypdf-6.13.3-py3-none-any.whl", hash = "sha256:c6e3f86afb625791510b02ad5480e94b63970bb957df75d44657c282ecc52224", size = 347288, upload-time = "2026-06-17T15:21:59.512Z" }, ] [[package]] From 0e81e86e49377a451616eaf71ead65ea723643ad Mon Sep 17 00:00:00 2001 From: Nathan Weinberg <31703736+nathan-weinberg@users.noreply.github.com> Date: Tue, 30 Jun 2026 08:05:58 -0400 Subject: [PATCH 26/32] chore: update `ogx stack run` references to `ogx run` (#6115) Signed-off-by: Nathan Weinberg Co-authored-by: Charlie Doern --- README.md | 2 +- client-sdks/openapi/USAGE_EXAMPLES.md | 2 +- docs/blog/2026-01-30-how-to-get-started.md | 2 +- docs/blog/2026-03-01-building-agentic-flows.md | 2 +- .../2026-03-20-open-responses-openai-compatibility.md | 2 +- docs/blog/2026-03-30-observability.md | 2 +- docs/blog/2026-04-06-mlflow-observability.md | 2 +- docs/blog/2026-05-19-codex-cli-integration.md | 4 ++-- docs/docs/building_applications/rag.mdx | 2 +- docs/docs/building_applications/telemetry.mdx | 2 +- docs/docs/concepts/distributions.mdx | 4 ++-- docs/docs/distributions/list_of_distributions.mdx | 2 +- docs/docs/distributions/self_hosted_distro/starter.md | 4 ++-- docs/docs/distributions/starting_ogx_server.mdx | 10 +++++----- docs/docs/getting_started/detailed_tutorial.mdx | 4 ++-- docs/docs/getting_started/quickstart.mdx | 8 ++++---- docs/src/components/InstallBlock/index.jsx | 2 +- docs/zero_to_hero_guide/README.md | 4 ++-- scripts/telemetry/README.md | 2 +- scripts/test_interactions_api.py | 2 +- src/ogx/distributions/README.md | 2 +- 21 files changed, 33 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 15a37621bb9..2e7d830405d 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ curl -LsSf https://github.com/ogx-ai/ogx/raw/main/scripts/install.sh | bash uv pip install ogx[starter] # Start the server (uses the starter distribution with Ollama) -uv run ogx stack run starter +uv run ogx run starter ``` Then connect with any OpenAI, Anthropic, or Google GenAI client — [Python](https://github.com/openai/openai-python), [TypeScript](https://github.com/openai/openai-node), [curl](https://platform.openai.com/docs/api-reference), or any framework that speaks these APIs. diff --git a/client-sdks/openapi/USAGE_EXAMPLES.md b/client-sdks/openapi/USAGE_EXAMPLES.md index 563c5f6d3e9..a3442decfd4 100644 --- a/client-sdks/openapi/USAGE_EXAMPLES.md +++ b/client-sdks/openapi/USAGE_EXAMPLES.md @@ -382,7 +382,7 @@ pip install ogx-open-client ```python # If you see: Connection refused # Solution: Ensure OGX server is running -# Start server: uv run ogx stack run starter +# Start server: uv run ogx run starter ``` ### Type Checking diff --git a/docs/blog/2026-01-30-how-to-get-started.md b/docs/blog/2026-01-30-how-to-get-started.md index 160c296cdd1..56d15c7f279 100644 --- a/docs/blog/2026-01-30-how-to-get-started.md +++ b/docs/blog/2026-01-30-how-to-get-started.md @@ -77,7 +77,7 @@ ollama serve > /dev/null 2>&1 & ollama run gpt-oss:20b --keepalive 60m # you can exit this once the model is running due to --keepalive uv run --with ogx ogx list-deps starter --format uv | sh export OLLAMA_URL=http://localhost:11434/v1 -uv run --with ogx ogx stack run starter +uv run --with ogx ogx run starter ``` diff --git a/docs/blog/2026-03-01-building-agentic-flows.md b/docs/blog/2026-03-01-building-agentic-flows.md index 4410d15352e..08e334d4569 100644 --- a/docs/blog/2026-03-01-building-agentic-flows.md +++ b/docs/blog/2026-03-01-building-agentic-flows.md @@ -245,7 +245,7 @@ First, pull the models and start Ollama, then run the OGX starter distribution p ```bash ollama pull llama3.1:8b ollama pull gpt-oss:20b -OLLAMA_URL=http://localhost:11434/v1 uv run --with ogx ogx stack run starter +OLLAMA_URL=http://localhost:11434/v1 uv run --with ogx ogx run starter ``` The `OLLAMA_URL` environment variable tells the starter distribution to use Ollama as its inference provider. The server starts on `http://localhost:8321` by default. diff --git a/docs/blog/2026-03-20-open-responses-openai-compatibility.md b/docs/blog/2026-03-20-open-responses-openai-compatibility.md index 1122b3bf79e..ca6c5795f9d 100644 --- a/docs/blog/2026-03-20-open-responses-openai-compatibility.md +++ b/docs/blog/2026-03-20-open-responses-openai-compatibility.md @@ -200,7 +200,7 @@ ollama run gpt-oss:20b # Launch OGX with the starter distribution -OLLAMA_URL=http://localhost:11434/v1 uv run ogx stack run starter +OLLAMA_URL=http://localhost:11434/v1 uv run ogx run starter ``` ```python diff --git a/docs/blog/2026-03-30-observability.md b/docs/blog/2026-03-30-observability.md index e0bddbaac66..bc2a2747056 100644 --- a/docs/blog/2026-03-30-observability.md +++ b/docs/blog/2026-03-30-observability.md @@ -188,7 +188,7 @@ export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf export OTEL_SERVICE_NAME=ogx-server -uv run opentelemetry-instrument ogx stack run starter +uv run opentelemetry-instrument ogx run starter ``` That's it. When `OTEL_EXPORTER_OTLP_ENDPOINT` is set, both auto and manual instrumentation activate. When it's not set, metrics are recorded in memory but never exported — no overhead, no errors. diff --git a/docs/blog/2026-04-06-mlflow-observability.md b/docs/blog/2026-04-06-mlflow-observability.md index a9c67eb6d8f..ff5b73175e1 100644 --- a/docs/blog/2026-04-06-mlflow-observability.md +++ b/docs/blog/2026-04-06-mlflow-observability.md @@ -316,7 +316,7 @@ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:5000/v1/traces \ OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf \ OTEL_EXPORTER_OTLP_TRACES_HEADERS="x-mlflow-experiment-id=1" \ OTEL_SERVICE_NAME=ogx-server \ -opentelemetry-instrument ogx stack run starter +opentelemetry-instrument ogx run starter ``` This gives you end-to-end visibility: client-side spans showing the request lifecycle, and server-side spans showing internal OGX processing. diff --git a/docs/blog/2026-05-19-codex-cli-integration.md b/docs/blog/2026-05-19-codex-cli-integration.md index 510e7a07264..8fe01ae263c 100644 --- a/docs/blog/2026-05-19-codex-cli-integration.md +++ b/docs/blog/2026-05-19-codex-cli-integration.md @@ -43,13 +43,13 @@ Three steps. Assumes you have OGX and Codex CLI already installed. ```bash export OPENAI_API_KEY="your-key-here" -ogx stack run starter +ogx run starter ``` For Ollama instead of OpenAI: ```bash -OLLAMA_URL=http://localhost:11434/v1 ogx stack run starter +OLLAMA_URL=http://localhost:11434/v1 ogx run starter ``` ### 2. Configure Codex CLI diff --git a/docs/docs/building_applications/rag.mdx b/docs/docs/building_applications/rag.mdx index b3b94f30026..e0621461129 100644 --- a/docs/docs/building_applications/rag.mdx +++ b/docs/docs/building_applications/rag.mdx @@ -21,7 +21,7 @@ In one terminal, start the OGX server: ```bash ogx list-deps starter | xargs -L1 uv pip install -ogx stack run starter +ogx run starter ``` ### 2. Choose Your Approach diff --git a/docs/docs/building_applications/telemetry.mdx b/docs/docs/building_applications/telemetry.mdx index 150f4f7b75d..7dcb6ed24d7 100644 --- a/docs/docs/building_applications/telemetry.mdx +++ b/docs/docs/building_applications/telemetry.mdx @@ -34,7 +34,7 @@ uv run opentelemetry-instrument \ --metrics_exporter otlp \ --service_name ogx-server \ -- \ - ogx stack run starter + ogx run starter ``` This sends traces and metrics to an OTLP collector on port 4318. The next section shows how to set up the full observability stack. diff --git a/docs/docs/concepts/distributions.mdx b/docs/docs/concepts/distributions.mdx index d8e24438719..5b7bb6f9ef0 100644 --- a/docs/docs/concepts/distributions.mdx +++ b/docs/docs/concepts/distributions.mdx @@ -15,10 +15,10 @@ Most users should start with `starter`. It includes all providers and auto-enabl ```bash # With Ollama (local inference) -OLLAMA_URL=http://localhost:11434 uv run ogx stack run starter +OLLAMA_URL=http://localhost:11434 uv run ogx run starter # With OpenAI (remote inference) -OPENAI_API_KEY=sk-xxx uv run ogx stack run starter +OPENAI_API_KEY=sk-xxx uv run ogx run starter ``` The starter distribution uses FAISS for vector storage, sentence-transformers for embeddings, and pypdf for file processing - all running locally with no external dependencies. diff --git a/docs/docs/distributions/list_of_distributions.mdx b/docs/docs/distributions/list_of_distributions.mdx index 9e8d2b5e7da..4c9027a8e9b 100644 --- a/docs/docs/distributions/list_of_distributions.mdx +++ b/docs/docs/distributions/list_of_distributions.mdx @@ -19,7 +19,7 @@ sidebar_position: 2 The starter distribution works for most use cases. It includes all providers and auto-enables them based on available environment variables: ```bash -uv run ogx stack run starter +uv run ogx run starter ``` It supports local inference (Ollama), cloud providers (OpenAI, Bedrock, Azure, etc.), and everything in between. See the [Starter Guide](self_hosted_distro/starter) for details. diff --git a/docs/docs/distributions/self_hosted_distro/starter.md b/docs/docs/distributions/self_hosted_distro/starter.md index 1e782acdf7e..2fa88f0084a 100644 --- a/docs/docs/distributions/self_hosted_distro/starter.md +++ b/docs/docs/distributions/self_hosted_distro/starter.md @@ -155,7 +155,7 @@ See [Starting a OGX Server](../starting_ogx_server) for all the ways to run (uv, Quick start: ```bash -uvx --from 'ogx[starter]' ogx stack run starter +uvx --from 'ogx[starter]' ogx run starter ``` Or run the pre-built container image from [Docker Hub](https://hub.docker.com/r/ogxai/distribution-starter): @@ -173,7 +173,7 @@ docker run -it \ By default, the starter distribution uses SQLite. For production, use PostgreSQL: ```bash -uvx --from 'ogx[starter]' ogx stack run starter::run-with-postgres-store.yaml +uvx --from 'ogx[starter]' ogx run starter::run-with-postgres-store.yaml ``` A pre-built container image with PostgreSQL storage is also available as [`ogxai/distribution-postgres-demo`](https://hub.docker.com/r/ogxai/distribution-postgres-demo). diff --git a/docs/docs/distributions/starting_ogx_server.mdx b/docs/docs/distributions/starting_ogx_server.mdx index 9f3a96baa9d..41e8747e571 100644 --- a/docs/docs/distributions/starting_ogx_server.mdx +++ b/docs/docs/distributions/starting_ogx_server.mdx @@ -16,13 +16,13 @@ import TabItem from '@theme/TabItem'; The fastest way to get started. No global install needed: ```bash -uvx --from 'ogx[starter]' ogx stack run starter +uvx --from 'ogx[starter]' ogx run starter ``` Or if you have a project with ogx as a dependency: ```bash -uv run ogx stack run starter +uv run ogx run starter ``` @@ -77,13 +77,13 @@ Control log output via environment variables: ```bash # Per-component levels -OGX_LOGGING=server=debug,core=info ogx stack run starter +OGX_LOGGING=server=debug,core=info ogx run starter # Global level -OGX_LOGGING=all=debug ogx stack run starter +OGX_LOGGING=all=debug ogx run starter # Log to file -OGX_LOG_FILE=/tmp/ogx.log ogx stack run starter +OGX_LOG_FILE=/tmp/ogx.log ogx run starter ``` Categories: `all`, `core`, `server`, `router`, `inference`, `tools`, `client`. diff --git a/docs/docs/getting_started/detailed_tutorial.mdx b/docs/docs/getting_started/detailed_tutorial.mdx index 1a980c56c80..3dc9efcd38c 100644 --- a/docs/docs/getting_started/detailed_tutorial.mdx +++ b/docs/docs/getting_started/detailed_tutorial.mdx @@ -179,7 +179,7 @@ The same code works with any backend. Just change the server config: ```bash export OLLAMA_URL=http://localhost:11434/v1 -uv run ogx stack run starter +uv run ogx run starter ``` @@ -187,7 +187,7 @@ uv run ogx stack run starter ```bash export OPENAI_API_KEY=sk-xxx -uv run ogx stack run starter +uv run ogx run starter ``` Your client code stays the same. Just update the model name: diff --git a/docs/docs/getting_started/quickstart.mdx b/docs/docs/getting_started/quickstart.mdx index 7570431d73e..13aac416593 100644 --- a/docs/docs/getting_started/quickstart.mdx +++ b/docs/docs/getting_started/quickstart.mdx @@ -20,7 +20,7 @@ Install [Ollama](https://ollama.com/download), then pull a model and start the s ```bash ollama pull llama3.2:3b export OLLAMA_URL=http://localhost:11434/v1 -uvx --from 'ogx[starter]' ogx stack run starter +uvx --from 'ogx[starter]' ogx run starter ``` @@ -28,7 +28,7 @@ uvx --from 'ogx[starter]' ogx stack run starter ```bash export OPENAI_API_KEY=sk-xxx -uvx --from 'ogx[starter]' ogx stack run starter +uvx --from 'ogx[starter]' ogx run starter ``` @@ -54,7 +54,7 @@ The `uvx` command above is great for trying things out. For a real project, inst uv init my-ai-app && cd my-ai-app uv add 'ogx[starter]' openai export OLLAMA_URL=http://localhost:11434/v1 -uv run ogx stack run starter +uv run ogx run starter ``` ::: @@ -166,7 +166,7 @@ That's it. Same OpenAI SDK, local model, your own vector store. If you see `Address already in use`, another process is using port 8321. Either stop it or run on a different port: ```bash -uvx --from 'ogx[starter]' ogx stack run starter --port 8322 +uvx --from 'ogx[starter]' ogx run starter --port 8322 ``` diff --git a/docs/src/components/InstallBlock/index.jsx b/docs/src/components/InstallBlock/index.jsx index 26b7e2738e8..8cb832d42c8 100644 --- a/docs/src/components/InstallBlock/index.jsx +++ b/docs/src/components/InstallBlock/index.jsx @@ -4,7 +4,7 @@ import styles from './styles.module.css'; const EXAMPLES = [ { label: 'Server', - command: "uvx --from 'ogx[starter]' ogx stack run starter", + command: "uvx --from 'ogx[starter]' ogx run starter", tokens: [ { text: 'uvx', style: 'tokenBinary' }, { text: '--from', style: 'tokenFlag' }, diff --git a/docs/zero_to_hero_guide/README.md b/docs/zero_to_hero_guide/README.md index b44a571bbad..f4a63277636 100644 --- a/docs/zero_to_hero_guide/README.md +++ b/docs/zero_to_hero_guide/README.md @@ -95,7 +95,7 @@ If you're looking for more specific topics, we have a [Zero to Hero Guide](#next 2. **Start the distribution**: ```bash - ogx stack run starter + ogx run starter ``` 3. **Set the ENV variables by exporting them to the terminal**: @@ -114,7 +114,7 @@ If you're looking for more specific topics, we have a [Zero to Hero Guide](#next INFERENCE_MODEL=$INFERENCE_MODEL \ MODERATION_ENDPOINT=$MODERATION_ENDPOINT \ OLLAMA_URL=$OLLAMA_URL \ - uv run --with ogx ogx stack run starter \ + uv run --with ogx ogx run starter \ --port $OGX_PORT ``` diff --git a/scripts/telemetry/README.md b/scripts/telemetry/README.md index 372cab55042..212e3e5fe73 100644 --- a/scripts/telemetry/README.md +++ b/scripts/telemetry/README.md @@ -87,7 +87,7 @@ export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf export OTEL_SERVICE_NAME=ogx-server -uv run opentelemetry-instrument ogx stack run starter +uv run opentelemetry-instrument ogx run starter ``` > **Note:** The `opentelemetry-instrument` wrapper automatically instruments the application and sends traces/metrics to the OTel Collector. diff --git a/scripts/test_interactions_api.py b/scripts/test_interactions_api.py index d1f70fbd55a..0764f5f5785 100755 --- a/scripts/test_interactions_api.py +++ b/scripts/test_interactions_api.py @@ -19,7 +19,7 @@ Usage: # Start a OGX server first: - OLLAMA_URL=http://localhost:11434/v1 uv run --extra starter ogx stack run starter --port 8321 + OLLAMA_URL=http://localhost:11434/v1 uv run --extra starter ogx run starter --port 8321 # Then run this script: uv run python scripts/test_interactions_api.py --base-url http://localhost:8321 --model ollama/llama3.2:3b diff --git a/src/ogx/distributions/README.md b/src/ogx/distributions/README.md index 11eaf6a8784..a474983b4b2 100644 --- a/src/ogx/distributions/README.md +++ b/src/ogx/distributions/README.md @@ -48,7 +48,7 @@ Distribution configs use `${env.VAR:=default}` syntax for environment-driven con Run a distribution with: ```bash -ogx stack run starter +ogx run starter # or ogx stack run --config path/to/config.yaml ``` From 6c39dd362af73657e68b98902557c6c09e545f11 Mon Sep 17 00:00:00 2001 From: Eleanor Hu <145939433+EleanorWho@users.noreply.github.com> Date: Tue, 30 Jun 2026 13:24:51 +0100 Subject: [PATCH 27/32] fix(deps): bump aiohttp and pyjwt constraints for CVE-2026-34993 and CVE-2026-48526 (#6183) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Bump minimum version constraints for aiohttp and pyjwt to address active CVEs: | Package | Old Constraint | New Constraint | CVE | |---|---|---|---| | `aiohttp` | `>=3.13.4` | `>=3.14.0` | CVE-2026-34993: arbitrary code execution via `CookieJar.load()` | | `pyjwt[crypto]` | `>=2.13.0` (comment only) | `>=2.13.0` (comment only) | CVE-2026-48526: authentication bypass via forged JWTs | ### Impact analysis - **aiohttp**: `CookieJar.load()` is not called anywhere in the codebase or transitive dependencies. Bump is defensive. - **pyjwt**: Already at `>=2.13.0` on main. Comment updated to reference CVE-2026-48526. ## Test plan - [x] `uv run pre-commit run --all-files` — all checks passed - [x] `uv run pytest tests/unit/ -x --tb=short` — 2576 passed, 0 failed - [ ] Verify updated package versions resolve in clean install Signed-off-by: Eleanor Hu Co-authored-by: Claude Opus 4.6 (1M context) --- pyproject.toml | 4 +- uv.lock | 159 +++++++++++++++++++++++++++---------------------- 2 files changed, 89 insertions(+), 74 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e73178b528f..9aa1a78c9e0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ fallback_version = "1.1.4.dev0" [tool.uv] required-version = ">=0.7.0" constraint-dependencies = [ - "aiohttp>=3.13.4", # CVE-2026-34514 + 9 more: CRLF injection, header leak, DoS + "aiohttp>=3.14.0", # CVE-2026-34993: CookieJar.load() RCE "authlib>=1.6.11", # CVE-2026-41425 + 7 more: account takeover, JWE padding oracle, sig bypass "cryptography>=48.0.1", # CVE-2026-39892: buffer overflow; CVE-2026-34073: DNS constraint bypass "fonttools>=4.60.2", @@ -60,7 +60,7 @@ dependencies = [ "ogx-api", # API and provider specifications (local dev via tool.uv.sources) "openai>=2.41.0", "python-dotenv>=1.2.2", # CVE-2026-28684: arbitrary file overwrite via symlink following - "pyjwt[crypto]>=2.13.0", # Pull crypto to support RS256 for jwt. Requires 2.12.0+ to fix CVE-2026-32597. + "pyjwt[crypto]>=2.13.0", # Pull crypto to support RS256 for jwt. CVE-2026-48526: auth bypass via forged JWTs. "pydantic>=2.11.9", "rich", "structlog>=24.1.0", diff --git a/uv.lock b/uv.lock index 5e88aa54c57..437f35fff87 100644 --- a/uv.lock +++ b/uv.lock @@ -22,7 +22,7 @@ resolution-markers = [ [manifest] constraints = [ - { name = "aiohttp", specifier = ">=3.13.4" }, + { name = "aiohttp", specifier = ">=3.14.0" }, { name = "authlib", specifier = ">=1.6.11" }, { name = "cryptography", specifier = ">=48.0.1" }, { name = "fonttools", specifier = ">=4.60.2" }, @@ -86,7 +86,7 @@ wheels = [ [[package]] name = "aiohttp" -version = "3.13.5" +version = "3.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohappyeyeballs" }, @@ -95,78 +95,93 @@ dependencies = [ { name = "frozenlist" }, { name = "multidict" }, { name = "propcache" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, { name = "yarl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/9a/152096d4808df8e4268befa55fba462f440f14beab85e8ad9bf990516918/aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", size = 7858271, upload-time = "2026-03-31T22:01:03.343Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/be/6f/353954c29e7dcce7cf00280a02c75f30e133c00793c7a2ed3776d7b2f426/aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9", size = 748876, upload-time = "2026-03-31T21:57:36.319Z" }, - { url = "https://files.pythonhosted.org/packages/f5/1b/428a7c64687b3b2e9cd293186695affc0e1e54a445d0361743b231f11066/aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416", size = 499557, upload-time = "2026-03-31T21:57:38.236Z" }, - { url = "https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2", size = 500258, upload-time = "2026-03-31T21:57:39.923Z" }, - { url = "https://files.pythonhosted.org/packages/67/84/c9ecc5828cb0b3695856c07c0a6817a99d51e2473400f705275a2b3d9239/aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4", size = 1749199, upload-time = "2026-03-31T21:57:41.938Z" }, - { url = "https://files.pythonhosted.org/packages/f0/d3/3c6d610e66b495657622edb6ae7c7fd31b2e9086b4ec50b47897ad6042a9/aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9", size = 1721013, upload-time = "2026-03-31T21:57:43.904Z" }, - { url = "https://files.pythonhosted.org/packages/49/a0/24409c12217456df0bae7babe3b014e460b0b38a8e60753d6cb339f6556d/aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5", size = 1781501, upload-time = "2026-03-31T21:57:46.285Z" }, - { url = "https://files.pythonhosted.org/packages/98/9d/b65ec649adc5bccc008b0957a9a9c691070aeac4e41cea18559fef49958b/aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e", size = 1878981, upload-time = "2026-03-31T21:57:48.734Z" }, - { url = "https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1", size = 1767934, upload-time = "2026-03-31T21:57:51.171Z" }, - { url = "https://files.pythonhosted.org/packages/31/04/d3f8211f273356f158e3464e9e45484d3fb8c4ce5eb2f6fe9405c3273983/aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286", size = 1566671, upload-time = "2026-03-31T21:57:53.326Z" }, - { url = "https://files.pythonhosted.org/packages/41/db/073e4ebe00b78e2dfcacff734291651729a62953b48933d765dc513bf798/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9", size = 1705219, upload-time = "2026-03-31T21:57:55.385Z" }, - { url = "https://files.pythonhosted.org/packages/48/45/7dfba71a2f9fd97b15c95c06819de7eb38113d2cdb6319669195a7d64270/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88", size = 1743049, upload-time = "2026-03-31T21:57:57.341Z" }, - { url = "https://files.pythonhosted.org/packages/18/71/901db0061e0f717d226386a7f471bb59b19566f2cae5f0d93874b017271f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3", size = 1749557, upload-time = "2026-03-31T21:57:59.626Z" }, - { url = "https://files.pythonhosted.org/packages/08/d5/41eebd16066e59cd43728fe74bce953d7402f2b4ddfdfef2c0e9f17ca274/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b", size = 1558931, upload-time = "2026-03-31T21:58:01.972Z" }, - { url = "https://files.pythonhosted.org/packages/30/e6/4a799798bf05740e66c3a1161079bda7a3dd8e22ca392481d7a7f9af82a6/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe", size = 1774125, upload-time = "2026-03-31T21:58:04.007Z" }, - { url = "https://files.pythonhosted.org/packages/84/63/7749337c90f92bc2cb18f9560d67aa6258c7060d1397d21529b8004fcf6f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14", size = 1732427, upload-time = "2026-03-31T21:58:06.337Z" }, - { url = "https://files.pythonhosted.org/packages/98/de/cf2f44ff98d307e72fb97d5f5bbae3bfcb442f0ea9790c0bf5c5c2331404/aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3", size = 433534, upload-time = "2026-03-31T21:58:08.712Z" }, - { url = "https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1", size = 460446, upload-time = "2026-03-31T21:58:10.945Z" }, - { url = "https://files.pythonhosted.org/packages/78/e9/d76bf503005709e390122d34e15256b88f7008e246c4bdbe915cd4f1adce/aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61", size = 742930, upload-time = "2026-03-31T21:58:13.155Z" }, - { url = "https://files.pythonhosted.org/packages/57/00/4b7b70223deaebd9bb85984d01a764b0d7bd6526fcdc73cca83bcbe7243e/aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832", size = 496927, upload-time = "2026-03-31T21:58:15.073Z" }, - { url = "https://files.pythonhosted.org/packages/9c/f5/0fb20fb49f8efdcdce6cd8127604ad2c503e754a8f139f5e02b01626523f/aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9", size = 497141, upload-time = "2026-03-31T21:58:17.009Z" }, - { url = "https://files.pythonhosted.org/packages/3b/86/b7c870053e36a94e8951b803cb5b909bfbc9b90ca941527f5fcafbf6b0fa/aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090", size = 1732476, upload-time = "2026-03-31T21:58:18.925Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e5/4e161f84f98d80c03a238671b4136e6530453d65262867d989bbe78244d0/aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b", size = 1706507, upload-time = "2026-03-31T21:58:21.094Z" }, - { url = "https://files.pythonhosted.org/packages/d4/56/ea11a9f01518bd5a2a2fcee869d248c4b8a0cfa0bb13401574fa31adf4d4/aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a", size = 1773465, upload-time = "2026-03-31T21:58:23.159Z" }, - { url = "https://files.pythonhosted.org/packages/eb/40/333ca27fb74b0383f17c90570c748f7582501507307350a79d9f9f3c6eb1/aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8", size = 1873523, upload-time = "2026-03-31T21:58:25.59Z" }, - { url = "https://files.pythonhosted.org/packages/f0/d2/e2f77eef1acb7111405433c707dc735e63f67a56e176e72e9e7a2cd3f493/aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665", size = 1754113, upload-time = "2026-03-31T21:58:27.624Z" }, - { url = "https://files.pythonhosted.org/packages/fb/56/3f653d7f53c89669301ec9e42c95233e2a0c0a6dd051269e6e678db4fdb0/aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540", size = 1562351, upload-time = "2026-03-31T21:58:29.918Z" }, - { url = "https://files.pythonhosted.org/packages/ec/a6/9b3e91eb8ae791cce4ee736da02211c85c6f835f1bdfac0594a8a3b7018c/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb", size = 1693205, upload-time = "2026-03-31T21:58:32.214Z" }, - { url = "https://files.pythonhosted.org/packages/98/fc/bfb437a99a2fcebd6b6eaec609571954de2ed424f01c352f4b5504371dd3/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46", size = 1730618, upload-time = "2026-03-31T21:58:34.728Z" }, - { url = "https://files.pythonhosted.org/packages/e4/b6/c8534862126191a034f68153194c389addc285a0f1347d85096d349bbc15/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8", size = 1745185, upload-time = "2026-03-31T21:58:36.909Z" }, - { url = "https://files.pythonhosted.org/packages/0b/93/4ca8ee2ef5236e2707e0fd5fecb10ce214aee1ff4ab307af9c558bda3b37/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d", size = 1557311, upload-time = "2026-03-31T21:58:39.38Z" }, - { url = "https://files.pythonhosted.org/packages/57/ae/76177b15f18c5f5d094f19901d284025db28eccc5ae374d1d254181d33f4/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6", size = 1773147, upload-time = "2026-03-31T21:58:41.476Z" }, - { url = "https://files.pythonhosted.org/packages/01/a4/62f05a0a98d88af59d93b7fcac564e5f18f513cb7471696ac286db970d6a/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c", size = 1730356, upload-time = "2026-03-31T21:58:44.049Z" }, - { url = "https://files.pythonhosted.org/packages/e4/85/fc8601f59dfa8c9523808281f2da571f8b4699685f9809a228adcc90838d/aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc", size = 432637, upload-time = "2026-03-31T21:58:46.167Z" }, - { url = "https://files.pythonhosted.org/packages/c0/1b/ac685a8882896acf0f6b31d689e3792199cfe7aba37969fa91da63a7fa27/aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83", size = 458896, upload-time = "2026-03-31T21:58:48.119Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ce/46572759afc859e867a5bc8ec3487315869013f59281ce61764f76d879de/aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c", size = 745721, upload-time = "2026-03-31T21:58:50.229Z" }, - { url = "https://files.pythonhosted.org/packages/13/fe/8a2efd7626dbe6049b2ef8ace18ffda8a4dfcbe1bcff3ac30c0c7575c20b/aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be", size = 497663, upload-time = "2026-03-31T21:58:52.232Z" }, - { url = "https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25", size = 499094, upload-time = "2026-03-31T21:58:54.566Z" }, - { url = "https://files.pythonhosted.org/packages/0a/33/a8362cb15cf16a3af7e86ed11962d5cd7d59b449202dc576cdc731310bde/aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56", size = 1726701, upload-time = "2026-03-31T21:58:56.864Z" }, - { url = "https://files.pythonhosted.org/packages/45/0c/c091ac5c3a17114bd76cbf85d674650969ddf93387876cf67f754204bd77/aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2", size = 1683360, upload-time = "2026-03-31T21:58:59.072Z" }, - { url = "https://files.pythonhosted.org/packages/23/73/bcee1c2b79bc275e964d1446c55c54441a461938e70267c86afaae6fba27/aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a", size = 1773023, upload-time = "2026-03-31T21:59:01.776Z" }, - { url = "https://files.pythonhosted.org/packages/c7/ef/720e639df03004fee2d869f771799d8c23046dec47d5b81e396c7cda583a/aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be", size = 1853795, upload-time = "2026-03-31T21:59:04.568Z" }, - { url = "https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b", size = 1730405, upload-time = "2026-03-31T21:59:07.221Z" }, - { url = "https://files.pythonhosted.org/packages/ce/75/ee1fd286ca7dc599d824b5651dad7b3be7ff8d9a7e7b3fe9820d9180f7db/aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94", size = 1558082, upload-time = "2026-03-31T21:59:09.484Z" }, - { url = "https://files.pythonhosted.org/packages/c3/20/1e9e6650dfc436340116b7aa89ff8cb2bbdf0abc11dfaceaad8f74273a10/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d", size = 1692346, upload-time = "2026-03-31T21:59:12.068Z" }, - { url = "https://files.pythonhosted.org/packages/d8/40/8ebc6658d48ea630ac7903912fe0dd4e262f0e16825aa4c833c56c9f1f56/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7", size = 1698891, upload-time = "2026-03-31T21:59:14.552Z" }, - { url = "https://files.pythonhosted.org/packages/d8/78/ea0ae5ec8ba7a5c10bdd6e318f1ba5e76fcde17db8275188772afc7917a4/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772", size = 1742113, upload-time = "2026-03-31T21:59:17.068Z" }, - { url = "https://files.pythonhosted.org/packages/8a/66/9d308ed71e3f2491be1acb8769d96c6f0c47d92099f3bc9119cada27b357/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5", size = 1553088, upload-time = "2026-03-31T21:59:19.541Z" }, - { url = "https://files.pythonhosted.org/packages/da/a6/6cc25ed8dfc6e00c90f5c6d126a98e2cf28957ad06fa1036bd34b6f24a2c/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1", size = 1757976, upload-time = "2026-03-31T21:59:22.311Z" }, - { url = "https://files.pythonhosted.org/packages/c1/2b/cce5b0ffe0de99c83e5e36d8f828e4161e415660a9f3e58339d07cce3006/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b", size = 1712444, upload-time = "2026-03-31T21:59:24.635Z" }, - { url = "https://files.pythonhosted.org/packages/6c/cf/9e1795b4160c58d29421eafd1a69c6ce351e2f7c8d3c6b7e4ca44aea1a5b/aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3", size = 438128, upload-time = "2026-03-31T21:59:27.291Z" }, - { url = "https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162", size = 464029, upload-time = "2026-03-31T21:59:29.429Z" }, - { url = "https://files.pythonhosted.org/packages/79/11/c27d9332ee20d68dd164dc12a6ecdef2e2e35ecc97ed6cf0d2442844624b/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a", size = 778758, upload-time = "2026-03-31T21:59:31.547Z" }, - { url = "https://files.pythonhosted.org/packages/04/fb/377aead2e0a3ba5f09b7624f702a964bdf4f08b5b6728a9799830c80041e/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254", size = 512883, upload-time = "2026-03-31T21:59:34.098Z" }, - { url = "https://files.pythonhosted.org/packages/bb/a6/aa109a33671f7a5d3bd78b46da9d852797c5e665bfda7d6b373f56bff2ec/aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36", size = 516668, upload-time = "2026-03-31T21:59:36.497Z" }, - { url = "https://files.pythonhosted.org/packages/79/b3/ca078f9f2fa9563c36fb8ef89053ea2bb146d6f792c5104574d49d8acb63/aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f", size = 1883461, upload-time = "2026-03-31T21:59:38.723Z" }, - { url = "https://files.pythonhosted.org/packages/b7/e3/a7ad633ca1ca497b852233a3cce6906a56c3225fb6d9217b5e5e60b7419d/aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800", size = 1747661, upload-time = "2026-03-31T21:59:41.187Z" }, - { url = "https://files.pythonhosted.org/packages/33/b9/cd6fe579bed34a906d3d783fe60f2fa297ef55b27bb4538438ee49d4dc41/aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf", size = 1863800, upload-time = "2026-03-31T21:59:43.84Z" }, - { url = "https://files.pythonhosted.org/packages/c0/3f/2c1e2f5144cefa889c8afd5cf431994c32f3b29da9961698ff4e3811b79a/aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b", size = 1958382, upload-time = "2026-03-31T21:59:46.187Z" }, - { url = "https://files.pythonhosted.org/packages/66/1d/f31ec3f1013723b3babe3609e7f119c2c2fb6ef33da90061a705ef3e1bc8/aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a", size = 1803724, upload-time = "2026-03-31T21:59:48.656Z" }, - { url = "https://files.pythonhosted.org/packages/0e/b4/57712dfc6f1542f067daa81eb61da282fab3e6f1966fca25db06c4fc62d5/aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8", size = 1640027, upload-time = "2026-03-31T21:59:51.284Z" }, - { url = "https://files.pythonhosted.org/packages/25/3c/734c878fb43ec083d8e31bf029daae1beafeae582d1b35da234739e82ee7/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be", size = 1806644, upload-time = "2026-03-31T21:59:53.753Z" }, - { url = "https://files.pythonhosted.org/packages/20/a5/f671e5cbec1c21d044ff3078223f949748f3a7f86b14e34a365d74a5d21f/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b", size = 1791630, upload-time = "2026-03-31T21:59:56.239Z" }, - { url = "https://files.pythonhosted.org/packages/0b/63/fb8d0ad63a0b8a99be97deac8c04dacf0785721c158bdf23d679a87aa99e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6", size = 1809403, upload-time = "2026-03-31T21:59:59.103Z" }, - { url = "https://files.pythonhosted.org/packages/59/0c/bfed7f30662fcf12206481c2aac57dedee43fe1c49275e85b3a1e1742294/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037", size = 1634924, upload-time = "2026-03-31T22:00:02.116Z" }, - { url = "https://files.pythonhosted.org/packages/17/d6/fd518d668a09fd5a3319ae5e984d4d80b9a4b3df4e21c52f02251ef5a32e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500", size = 1836119, upload-time = "2026-03-31T22:00:04.756Z" }, - { url = "https://files.pythonhosted.org/packages/78/b7/15fb7a9d52e112a25b621c67b69c167805cb1f2ab8f1708a5c490d1b52fe/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9", size = 1772072, upload-time = "2026-03-31T22:00:07.494Z" }, - { url = "https://files.pythonhosted.org/packages/7e/df/57ba7f0c4a553fc2bd8b6321df236870ec6fd64a2a473a8a13d4f733214e/aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8", size = 471819, upload-time = "2026-03-31T22:00:10.277Z" }, - { url = "https://files.pythonhosted.org/packages/62/29/2f8418269e46454a26171bfdd6a055d74febf32234e474930f2f60a17145/aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9", size = 505441, upload-time = "2026-03-31T22:00:12.791Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/82/78/8ea7308cac6934de8c74a14f3d5f65d1c89287426688be79538d0e5c013d/aiohttp-3.14.1.tar.gz", hash = "sha256:307f2cff90a764d329e77040603fa032db89c5c24fdad50c4c15334cba744035", size = 7955794, upload-time = "2026-06-07T21:09:35.529Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/21/151624b51cd92553d95424daf4bf19f19ce9be9002d19253e7e7ce67197b/aiohttp-3.14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d35143e27778b4bb0fb189562d7f275bff79c62ab8e98459717c0ea617ff2480", size = 757402, upload-time = "2026-06-07T21:06:40.311Z" }, + { url = "https://files.pythonhosted.org/packages/c2/82/280619e0bd7bf2454987e19282616e84762255dd9c8468f62382e8c191f1/aiohttp-3.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bcfb80a2cc36fba2534e5e5b5264dc7ae6fcd9bf15256da3e53d2f499e6fa29d", size = 512310, upload-time = "2026-06-07T21:06:42.207Z" }, + { url = "https://files.pythonhosted.org/packages/55/b2/2aac325583aaa1353045f96dffa586d8a34e8322e14a7ba49cffeb103ab4/aiohttp-3.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27fd7c91e51729b4f7e1577865fa6d34c9adccbc39aabe9000285b48af9f0ec2", size = 512448, upload-time = "2026-06-07T21:06:43.813Z" }, + { url = "https://files.pythonhosted.org/packages/8a/72/a60607cb849faa8af8a356c9329ea2eb6f395d49e82cc82ccba1fd8deb8f/aiohttp-3.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:64c567bf9eaf664280116a8688f63016e6b32db2505908e2bdaca1b6438142f2", size = 1766854, upload-time = "2026-06-07T21:06:45.391Z" }, + { url = "https://files.pythonhosted.org/packages/b5/d3/d9fe1c9ec7557ab4d0d82bebaa728c6418f0b93295ec2f4ab015f7710cc7/aiohttp-3.14.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f5e6ff2bdbb8f4cd3fbe41f99e25bbcd58e3bf9f13d3dd31a11e7917251cc77a", size = 1740884, upload-time = "2026-06-07T21:06:47.413Z" }, + { url = "https://files.pythonhosted.org/packages/c1/dc/f2cecfaf9337ba3e63f181500814ff502aa3d00d9c7ec93a9d23d10a27b2/aiohttp-3.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f73e01dc37122325caf079982621262f96d74823c179038a82fddfc50359264", size = 1810034, upload-time = "2026-06-07T21:06:50.165Z" }, + { url = "https://files.pythonhosted.org/packages/66/d7/2ff65c5e65c0d7476daf7e15c032e0805e36811185b9623e3238ad6c763e/aiohttp-3.14.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb2c0c80d431c0d03f2c7dbf125150fedd4f0de17366a7ca33f7ccb822391842", size = 1904054, upload-time = "2026-06-07T21:06:52.035Z" }, + { url = "https://files.pythonhosted.org/packages/20/9c/d445818389df371f56d141d881153ba23183c4735a03f7356ffb43f7757d/aiohttp-3.14.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e6fc1a85fa7194a1a7d19f44e8609180f4a8eb5fa4c7ed8b4355f080fad235c", size = 1790278, upload-time = "2026-06-07T21:06:54.049Z" }, + { url = "https://files.pythonhosted.org/packages/4d/aa/bf04cb4d865fc6101c2229a294ad744973b72e513fdc5a6b791e6983d72a/aiohttp-3.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:686b6c0d3911ec387b444ddf5dc62fb7f7c0a7d5186a7861626496a5ab4aff95", size = 1591795, upload-time = "2026-06-07T21:06:55.911Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b4/4dac0038960427ba832f6609dfb4ea5437d7fd80c72001b9e48f834f428b/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c6fa4dc7ad6f8109c70bb1499e589f76b0b792baf39f9b017eb92c8a81d0a199", size = 1728397, upload-time = "2026-06-07T21:06:57.777Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f9/7cd4e8ad7aa3b75f17d56bb5498dd604a93d4e6eece822ba0568c413fff0/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:87a5eea1b2a5e21e1ebdbb33ad4165359189327e63fc4e4894693e7f821ac817", size = 1766504, upload-time = "2026-06-07T21:07:00.009Z" }, + { url = "https://files.pythonhosted.org/packages/f9/df/fc01d9fcad0f73fed3f3d361f1f94f975947b50dff82919f6dc2bf4316cc/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1c1421eb01d4fd608d88cc8290211d177a58532b55ad94076fb349c5bf467f0a", size = 1777806, upload-time = "2026-06-07T21:07:02.064Z" }, + { url = "https://files.pythonhosted.org/packages/41/09/47e2d090bddcc8fb4ccb4c314aadc32d7c5d9bb55f50f6ad1c92fc15d501/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:34b257ec41345c1e8f2df68fa908a7952f5de932723871eb633ecbbff396c9a4", size = 1580707, upload-time = "2026-06-07T21:07:03.942Z" }, + { url = "https://files.pythonhosted.org/packages/3d/36/f1a4ce904ae0b6930cfe9afc96d0896f7ec1a620c400405d63783bb95a9c/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:de538791a80e5d862addbc183f70f0158ac9b9bb872bb147f1fd2a683691e087", size = 1798121, upload-time = "2026-06-07T21:07:05.987Z" }, + { url = "https://files.pythonhosted.org/packages/70/0a/e0075ce9ca0279ee1d4f0c0b85f54fea02ebc83c3007651a72bece658fec/aiohttp-3.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f71173be42d3241d428f760122febb748de0623f44308a6f120d0dd9ec572e3", size = 1767580, upload-time = "2026-06-07T21:07:07.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/a0c0a8f327a9c52095cdd8e312391b00d3ed64ab6c72bb5c33d8ec251cf7/aiohttp-3.14.1-cp312-cp312-win32.whl", hash = "sha256:ec8dc383ee57ea3e883477dcca3f11b65d58199f1080acaf4cd6ad9a99698be4", size = 452771, upload-time = "2026-06-07T21:07:09.669Z" }, + { url = "https://files.pythonhosted.org/packages/df/d9/ea367c75f16ac9c6cdc8febb25e8318fa21a2b1bc8d6514d4b2d890bface/aiohttp-3.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2aa92c87868cd13674989f9ee83e5f9f7ea4237589b728048e1f0c8f6caa3271", size = 479873, upload-time = "2026-06-07T21:07:11.538Z" }, + { url = "https://files.pythonhosted.org/packages/03/64/8d96784a7851156db8a4c6c3f6f91042fdf39fb15a4cc38c8b3c14833c45/aiohttp-3.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:2c840c90759922cb5e6dda94596e079a30fb5a5ba548e7e0dc00574703940847", size = 448073, upload-time = "2026-06-07T21:07:13.637Z" }, + { url = "https://files.pythonhosted.org/packages/bc/97/bd137012dd97e1649162b099135a80e1fd59aaa807b2430fc448d1029aff/aiohttp-3.14.1-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:b3a03285a7f9c7b016324574a6d92a1c895da6b978cb8f1deee3ac72bc6da178", size = 506882, upload-time = "2026-06-07T21:07:15.501Z" }, + { url = "https://files.pythonhosted.org/packages/ef/79/e5cc690e9d922a66887ceeaca53a8ffd5a7b0be3816142b7abc433742d89/aiohttp-3.14.1-cp313-cp313-android_21_x86_64.whl", hash = "sha256:2a73f487ab8ef5abbb24b7aa9b73e98eaba9e9e031804ff2416f02eca315ccaf", size = 515270, upload-time = "2026-06-07T21:07:17.53Z" }, + { url = "https://files.pythonhosted.org/packages/fe/22/a73ccbf9dbd6e26dda0b24d5fd5db7da92ee3383a79f47677ffb834c5c5b/aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:915fbb7b41b115192259f8c9ae58f3ddc444d2b5579917270211858e606a4afd", size = 485841, upload-time = "2026-06-07T21:07:19.555Z" }, + { url = "https://files.pythonhosted.org/packages/3b/b9/57ed8eaf596321c2ad747bd480fb1700dbd7177c60dfc9e4c187f629662e/aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:7fb4bdf95b0561a79f259f9d28fbc109728c5ee7f27aff6391f0ca703a329abe", size = 492088, upload-time = "2026-06-07T21:07:21.581Z" }, + { url = "https://files.pythonhosted.org/packages/78/c0/5ebe5270a7c140d7c6f79dcb018640225f14d406c149e4eec04a7d82fe71/aiohttp-3.14.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1b9748363260121d2927704f5d4fc498150669ca3ae93625986ee89c8f80dcd4", size = 501564, upload-time = "2026-06-07T21:07:23.388Z" }, + { url = "https://files.pythonhosted.org/packages/75/7f/8cdaa24fc7983865e0915153b96a9ac5bcdd3548d64c5a27d17cecccad2d/aiohttp-3.14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:86a6dab78b0e43e2897a3bbe15745aa60dc5423ca437b7b0b164c069bf91b876", size = 751998, upload-time = "2026-06-07T21:07:25.046Z" }, + { url = "https://files.pythonhosted.org/packages/b2/f4/c4227aacfacc5cb0cc2d119b65301d177912a6842cd64e120c47af76064f/aiohttp-3.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4dfd6e47d3c44c2279907607f73a4240b88c69eb8b90da7e2441a8045dfd21da", size = 510918, upload-time = "2026-06-07T21:07:27.28Z" }, + { url = "https://files.pythonhosted.org/packages/ab/01/a2d5f96cd4e74424864d30bc0a7e44d0a12dacdcfa91b5b2d1bd3dca6bf3/aiohttp-3.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:317acd9f8602858dc7d59679812c376c7f0b97bcbbf16e0d6237f54141d8a8a6", size = 508657, upload-time = "2026-06-07T21:07:29.252Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ed/3c0fb5c500fdd8e7ebc10d1889c04384fffa1a9163eac1356088ca9da1b1/aiohttp-3.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd869c427324e5cb15195793de951295710db28be7d818247f3097b4ab5d4b96", size = 1757907, upload-time = "2026-06-07T21:07:31.03Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ab/d4c924d9bd5be3050c226612413ce68cb54c70d2c31b661bfc8d9a5b6a70/aiohttp-3.14.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:93b032b5ec3255473c143627d21a69ac74ae12f7f33974cb587c564d11b1066f", size = 1737565, upload-time = "2026-06-07T21:07:33.031Z" }, + { url = "https://files.pythonhosted.org/packages/19/2a/37326821ff779084020cdc33224d20b19f42f4183a500ff92022a739eda7/aiohttp-3.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f234b4deb12f3ad59127e037bc57c40c21e45b45282df7d3a55a0f409f595296", size = 1799018, upload-time = "2026-06-07T21:07:35.003Z" }, + { url = "https://files.pythonhosted.org/packages/b3/4f/6e947ba73e4ce09070761c05ed3a8ceb7c21f5e46798671d8b2aac0e4626/aiohttp-3.14.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9af6779bfb46abf124068327abcdf9ce95c9ef8287a3e8da76ccf2d0f16c28fa", size = 1894416, upload-time = "2026-06-07T21:07:36.956Z" }, + { url = "https://files.pythonhosted.org/packages/9d/6e/dbf1d0625dc711fb2851f4f3c3055c39ed58bae92082d8c627dbe6013736/aiohttp-3.14.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:faccab372e66bc76d5731525e7f1143c922271725b9d38c9f97edcc66266b451", size = 1783881, upload-time = "2026-06-07T21:07:39.063Z" }, + { url = "https://files.pythonhosted.org/packages/44/c2/5e25098a67268ed369483ae7d1a58bd0a13d03aab860d2a0e4a6eb25b046/aiohttp-3.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f380468b09d2a81633ee863b0ec5648d364bd17bb8ecfb8c2f387f7ac1faf42c", size = 1587572, upload-time = "2026-06-07T21:07:41.058Z" }, + { url = "https://files.pythonhosted.org/packages/2a/bd/cf9cee17e140f942a3de73e658a543aa8fbf35a5fc67a9d2538d52d77f0b/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:97e704dcd26271f5bda3fa07c3ce0fb76d6d3f8659f4baa1a24442cc9ba177ca", size = 1722137, upload-time = "2026-06-07T21:07:43.014Z" }, + { url = "https://files.pythonhosted.org/packages/89/6d/5684f8c59045c96f81a18cefbc1fbbd79d25b88f1c622f2a5c5c08fcb632/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:269b76ac5394092b95bc4a098f4fc6c191c083c3bd12775d1e30e663132f6a09", size = 1755953, upload-time = "2026-06-07T21:07:45.933Z" }, + { url = "https://files.pythonhosted.org/packages/a8/40/35caf3170f8359760740a7d9aa0fff2e344bef98e1d1186f5a0f6dec17e6/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c0b3e614340c889d575451696374c9d17affd54cd607ca0babed8f8c37b9397", size = 1766479, upload-time = "2026-06-07T21:07:48.047Z" }, + { url = "https://files.pythonhosted.org/packages/6d/a1/b0c61e7a137f0d81de49a82023a6df73c3c16d6fefb0f8e4a93d21639002/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5663ee9257cfa1add7253a7da3035a02f31b6600ec48261585e1800a81533080", size = 1580077, upload-time = "2026-06-07T21:07:50.069Z" }, + { url = "https://files.pythonhosted.org/packages/0b/41/194ea4623693009fcefebef7aef63c141754f153e9cd0d39d3b9e36c175c/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:603a2c834142172ffddc054067f5ec0ca65d57a0aa98a71bc81952573208e345", size = 1791688, upload-time = "2026-06-07T21:07:52.106Z" }, + { url = "https://files.pythonhosted.org/packages/ba/45/4de841f005cfe1fd63e2a2fe011262c515e2a62aa6994b15947e7d717ac9/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cb21957bb8aca671c1765e32f58164cf0c50e6bf41c0bbbd16da20732ecaf588", size = 1761094, upload-time = "2026-06-07T21:07:54.113Z" }, + { url = "https://files.pythonhosted.org/packages/e4/ae/dbce10533d3896d544d5053939ed75b7dc31a1b0973d959b1b5ae21028d6/aiohttp-3.14.1-cp313-cp313-win32.whl", hash = "sha256:e509a55f681e6158c20f70f102f9cf61fb20fbc382272bc6d94b7343f2582780", size = 452662, upload-time = "2026-06-07T21:07:56.06Z" }, + { url = "https://files.pythonhosted.org/packages/7b/d9/0bf1a19362c32f06229da5e7ddfcec91f93474d6307f7a2d3135e9c674dc/aiohttp-3.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:1ac8531b638959718e18c2207fbfe297819875da46a740b29dfa29beba64355a", size = 479748, upload-time = "2026-06-07T21:07:58.319Z" }, + { url = "https://files.pythonhosted.org/packages/22/0a/62e7232dc9484fbec112ceb32efb6a624cc7994ec6e2b019286f17c4e8f2/aiohttp-3.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:250d14af67f6b6a1a4a811049b1afa69d61d617fca6bf33149b3ab1a6dbcf7b8", size = 447723, upload-time = "2026-06-07T21:08:00.154Z" }, + { url = "https://files.pythonhosted.org/packages/c4/a1/5fafa04e1ca91ddb47608699d60649c1c6db3cf41c99e78fc4056f9513db/aiohttp-3.14.1-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:7c106c26852ca1c2047c6b80384f17100b4e439af276f21ef3d4e2f450ae7e15", size = 508531, upload-time = "2026-06-07T21:08:02.093Z" }, + { url = "https://files.pythonhosted.org/packages/fa/2e/bfa02f699d87ffc86d5959270b28f1cb410add3ccaced8ed2e0b8a5238fc/aiohttp-3.14.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:20205f7f5ade7aaec9f4b500549bbc071b046453aed72f9c06dcab87896a83e8", size = 514718, upload-time = "2026-06-07T21:08:04.476Z" }, + { url = "https://files.pythonhosted.org/packages/85/a5/9594ad6289eebbc97d167c44213d557807f90e59115caad24de21ad2c3b1/aiohttp-3.14.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:62a759436b29e677181a9e76bab8b8f689a29cb9c535f45f7c48c9c830d3f8c3", size = 487918, upload-time = "2026-06-07T21:08:06.377Z" }, + { url = "https://files.pythonhosted.org/packages/b4/61/16a32c36c3c49edec122a3dc811f2057df2f94d3b14aa107c8017d981618/aiohttp-3.14.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:2964cbf553df4d7a57348da44d961d871895fc1ee4e8c322b2a95612c7b17fba", size = 494014, upload-time = "2026-06-07T21:08:08.263Z" }, + { url = "https://files.pythonhosted.org/packages/9b/89/3ebcf96ed99c05bec9c434aaac6963fd3cbab4a786ae739908a144d9ce44/aiohttp-3.14.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:237651caadc3a59badd39319c54642b5299e9cc98a3a194310e55d5bb9f5e397", size = 502398, upload-time = "2026-06-07T21:08:10.244Z" }, + { url = "https://files.pythonhosted.org/packages/fd/3d/b74870a0c2d40c355928cd5b96c7a11fa821b8a40fc41365e64479b151fb/aiohttp-3.14.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:896e12dfdbbab9d8f7e16d2b28c6769a60126fa92095d1ebf9473d02593a2448", size = 758018, upload-time = "2026-06-07T21:08:12.447Z" }, + { url = "https://files.pythonhosted.org/packages/d3/66/f42f5c984d99e49c6cff5f26f590750f2e2f7ef1fcfb99966ab5be1b632e/aiohttp-3.14.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d03f281ed22579314ba00821ce20115a7c0ac430660b4cc05704a3f818b3e004", size = 512462, upload-time = "2026-06-07T21:08:14.624Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a7/248e1aebe0c7810b0271e021a0f2a5eb6e78a051885b3c9df49f42a5802d/aiohttp-3.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07eabb979d236335fed927e137a928c9adfb7df3b9ec7aa31726f133a62be983", size = 512824, upload-time = "2026-06-07T21:08:16.572Z" }, + { url = "https://files.pythonhosted.org/packages/26/97/2aa0e5ba0727dc3bd5aaebb7ccbc510f7dfb7fb961ec87497cd496635ab1/aiohttp-3.14.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4fe1f1087cbadb280b5e1bb054a4f00d1423c74d6626c5e48400d871d34ecefe", size = 1749898, upload-time = "2026-06-07T21:08:18.635Z" }, + { url = "https://files.pythonhosted.org/packages/00/8d/e97f6c96c891d457c8479d92a514ba194d0412f981d72c70341ee18488ed/aiohttp-3.14.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:367a9314fdc79dab0fac96e216cb41dd73c85bdca85306ce8999118ba7e0f333", size = 1710114, upload-time = "2026-06-07T21:08:20.892Z" }, + { url = "https://files.pythonhosted.org/packages/6f/e6/aa8d7e863048c8fceb5cd6ce74017311cec3ead07847387e12265fb4444e/aiohttp-3.14.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a24f677ebe83749039e7bdf862ff0bbb16818ae4193d4ef96505e269375bcce0", size = 1802541, upload-time = "2026-06-07T21:08:23.044Z" }, + { url = "https://files.pythonhosted.org/packages/83/a8/72193137de57fda4ebfae4563182d082c8856e3b6e9871d0b46f028fb369/aiohttp-3.14.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c83afe0ba876be7e943d2e0ba645809ad441575d2840c895c21ee5de93b9377a", size = 1875776, upload-time = "2026-06-07T21:08:25.288Z" }, + { url = "https://files.pythonhosted.org/packages/a0/18/938441025db6769a3464596b2410af3afde0b21eb2f204c6f766f68af4bd/aiohttp-3.14.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:634e385930fb6d2d479cf3aa66515955863b77a5e3c2b5894ca259a25b308602", size = 1760329, upload-time = "2026-06-07T21:08:27.363Z" }, + { url = "https://files.pythonhosted.org/packages/60/29/bf2496b4065e76e09fe48015aaffe5ce161d8f089b06ac6982070f653076/aiohttp-3.14.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeea07c4397bbc57719c4eed8f9c284874d4f175f9b6d57f7a1546b976d455ca", size = 1587293, upload-time = "2026-06-07T21:08:29.805Z" }, + { url = "https://files.pythonhosted.org/packages/49/a2/2136674d52123b1354bd05dd5753c318db47dc0c927cc70b27bab3755456/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:335c0cc3e3545ce98dcb9cfcb836f40c3411f43fa03dab757597d80c89af8a35", size = 1714756, upload-time = "2026-06-07T21:08:32.094Z" }, + { url = "https://files.pythonhosted.org/packages/a7/b9/e5fd2e6f915503081c0f9b1e8540947037929c70c191da2e4d54b31a21a1/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ae6be797afdef264e8a84864a85b196ca06045586481b3df8a967322fd2fa844", size = 1721052, upload-time = "2026-06-07T21:08:34.167Z" }, + { url = "https://files.pythonhosted.org/packages/63/5a/2833e324a2263e104e31e2e91bc5bbee81bc499afd32203faee048a883f0/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:8560b4d712474335d08907db7973f71912d3a9a8f1dee992ec06b5d2fe359496", size = 1766888, upload-time = "2026-06-07T21:08:36.95Z" }, + { url = "https://files.pythonhosted.org/packages/57/fa/dea6511870913162f3b2e8c42a7614eb203a4540b8c2da43e0bfb0548f3c/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7edd08e0a5deb1e8564a2fcd8f4561014a3f05252334671bbf55ddd47db0e5", size = 1581679, upload-time = "2026-06-07T21:08:39.292Z" }, + { url = "https://files.pythonhosted.org/packages/14/bd/3cf0d55e71784b33534e9710a67d382d900598b4787fbce6cc7317f8c42a/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:b6ff7fcee63287ae57b5df3e4f5957ce032122802509246dec1a5bcc55904c95", size = 1782021, upload-time = "2026-06-07T21:08:41.407Z" }, + { url = "https://files.pythonhosted.org/packages/c1/af/14bb5843eccbe234f4dfb78ab73e549d99727247e62ae5d62cbd22eaf5b0/aiohttp-3.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6ffbb2f4ec1ceaff7e07d43922954da26b223d188bf30658e561b98e23089444", size = 1742574, upload-time = "2026-06-07T21:08:43.795Z" }, + { url = "https://files.pythonhosted.org/packages/f2/1e/fbeb7af9210a67ac0f9c9bec0f8f4568497924e33137a3d5b48e1cf85f3f/aiohttp-3.14.1-cp314-cp314-win32.whl", hash = "sha256:a9875b46d910cff3ea2f5962f9d266b465459fe634e22556ab9bd6fc1192eea0", size = 457773, upload-time = "2026-06-07T21:08:46.168Z" }, + { url = "https://files.pythonhosted.org/packages/f0/2b/13e8d741a9ec5db7d900c060554cf8352ab85e44e2a4469ebb9d377bda17/aiohttp-3.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:af8b4b81a960eeaf1234971ac3cd0ba5901f3cd42eae42a46b4d089a8b492719", size = 485001, upload-time = "2026-06-07T21:08:48.401Z" }, + { url = "https://files.pythonhosted.org/packages/df/30/491acfa2c4d6c3ff59c49a14fc1b50be3241e25bbb0c84c09e2da4d11395/aiohttp-3.14.1-cp314-cp314-win_arm64.whl", hash = "sha256:cf4491381b1b57425c315a56a439251b1bdac07b2275f19a8c44bc57744532ec", size = 453809, upload-time = "2026-06-07T21:08:50.7Z" }, + { url = "https://files.pythonhosted.org/packages/34/e3/19dbe1a1f4cc6230eb9e314de7fe68053b0992f9302b27d12141a0b5db53/aiohttp-3.14.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:819c054312f1af92947e6a55883d1b66feefab11531a7fc45e0fb9b63880b5c2", size = 793320, upload-time = "2026-06-07T21:08:52.775Z" }, + { url = "https://files.pythonhosted.org/packages/7f/20/1b7182219ba1b108430d6e4dc53d25ae02dcfcf5a045b33af4e8c5167527/aiohttp-3.14.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10ee9c1753a8f706345b22496c79fbddb5be0599e0823f3738b1534058e25340", size = 529077, upload-time = "2026-06-07T21:08:55Z" }, + { url = "https://files.pythonhosted.org/packages/b9/c8/14ce60ec31a2e5f5274bb17d383a6f7a3aabca31ac04eee05585bbadab16/aiohttp-3.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1601cc37baf5750ccacae618ec2daf020769581695550e3b654a911f859c563d", size = 532476, upload-time = "2026-06-07T21:08:57.176Z" }, + { url = "https://files.pythonhosted.org/packages/7e/02/9ac85e081e53da2e061b02fa7758fe0a12d17b8ce2d1f5e6c7cb76730328/aiohttp-3.14.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4d6e0ac9da31c9c04c84e1c0182ad8d6df35965a85cae29cd71d089621b3ae94", size = 1922347, upload-time = "2026-06-07T21:08:59.563Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3e/d3ba07a0ab38b5389e10bec4362d21e10a4f667cba2d79ba30837b3a5059/aiohttp-3.14.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9e8f2d660c350b3d0e259c7a7e3d9b7fc8b41210cbcc3d4a7076ff0a5e5c2fdc", size = 1786465, upload-time = "2026-06-07T21:09:01.909Z" }, + { url = "https://files.pythonhosted.org/packages/0b/cb/e2ee978a00cfb2df829704a69528b18154eba5939f45bc1efa8f33aee4c5/aiohttp-3.14.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4691802dda97be727f79d86818acaad7eb8e9252626a1d6b519fedbb92d5e251", size = 1909423, upload-time = "2026-06-07T21:09:04.357Z" }, + { url = "https://files.pythonhosted.org/packages/73/5d/1430334858b1022b58ae50399a918f0bd6fe8fa7fa183598d657ff61e040/aiohttp-3.14.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c389c482a7e9b9dc3ee2701ac46c4125297a3818875b9c305ddb603c04828fd1", size = 2001906, upload-time = "2026-06-07T21:09:06.722Z" }, + { url = "https://files.pythonhosted.org/packages/66/4e/560c7472d3d198a23aa5c8b19a5115bf6a9b77b7d3e4bb363da320430ad2/aiohttp-3.14.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fc0cacab7ba4e56f0f81c82a98c09bed2f39c940107b03a34b168bdf7597edd3", size = 1877095, upload-time = "2026-06-07T21:09:09.011Z" }, + { url = "https://files.pythonhosted.org/packages/0d/f1/4745806578d447db4a784a8591e2dae3afdfc2bcb96f8f81271b13df6543/aiohttp-3.14.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:979ed4717f59b8bb12e3963378fa285d93d367e15bcd66c721311826d3c44a6c", size = 1676222, upload-time = "2026-06-07T21:09:11.461Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c9/48255813cca749a229ef0ab476004ec623728ad79a9c0840616f6c076325/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:38e1e7daaea81df51c952e18483f323d878499a1e2bfe564790e0f9701d6f203", size = 1842922, upload-time = "2026-06-07T21:09:14.118Z" }, + { url = "https://files.pythonhosted.org/packages/3d/c0/bbd054e2bee909f529523a5af3891052606af5143c09f5f183ec3b234676/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:4132e72c608fe9fecb8f409113567605915b83e9bdd3ea56538d2f9cd35002f1", size = 1825035, upload-time = "2026-06-07T21:09:16.447Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ae/90395d4376deceb74e09ec26b6adf7d2015a6f8802d6d84446af860fef04/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:eefd9cc9b6d4a2db5f00a26bc3e4f9acf71926a6ec557cd56c9c6f27c290b665", size = 1849512, upload-time = "2026-06-07T21:09:18.742Z" }, + { url = "https://files.pythonhosted.org/packages/93/bd/fb25f3049957553d4ce0ba6ae480aa2f592a6985497fca590837d16c1be0/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b165790117eea512d7f3fb22f1f6dad3d55a7189571993eb015591c1401276d1", size = 1668571, upload-time = "2026-06-07T21:09:21.458Z" }, + { url = "https://files.pythonhosted.org/packages/3f/22/7f73303d64dd567ff3addca90b556690ed1233a47b8f55d242fb90af3681/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:ed09c7eb1c391271c2ed0314a51903e72a3acb653d5ccfc264cdf3ef11f8269d", size = 1881159, upload-time = "2026-06-07T21:09:23.813Z" }, + { url = "https://files.pythonhosted.org/packages/44/be/0474c5a8b5640e1e4aa1923430a91f4151be82e511373fe764189b89aef5/aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:99abd37084b82f5830c635fddd0b4993b9742a66eb746dacf433c8590e8f9e3c", size = 1841409, upload-time = "2026-06-07T21:09:26.207Z" }, + { url = "https://files.pythonhosted.org/packages/7b/3c/bb4a7cba26956cb3da4553cc2056cf67be5b5ff6e6d8fa4fbdff73bfb7ae/aiohttp-3.14.1-cp314-cp314t-win32.whl", hash = "sha256:47ddf841cdecc810749921d25606dee45857d12d2ad5ddb7b5bd7eab12e4b365", size = 494166, upload-time = "2026-06-07T21:09:28.505Z" }, + { url = "https://files.pythonhosted.org/packages/8a/84/ec80c2c1f66a952555a9f86df6b33af65108a6febfa0471b69013a12f807/aiohttp-3.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:5e78b522b7a6e27e0b25d19b247b75039ac4c94f99823e3c9e53ae1603a9f7e9", size = 530255, upload-time = "2026-06-07T21:09:30.843Z" }, + { url = "https://files.pythonhosted.org/packages/2a/71/6e22be134a4061ada85a92951b842f2657f17d926b727f3f94c56ae963d6/aiohttp-3.14.1-cp314-cp314t-win_arm64.whl", hash = "sha256:90d53f1609c29ccc2193945ef732428382a28f78d0456ae4d3daf0d48b74f0f6", size = 469640, upload-time = "2026-06-07T21:09:33.028Z" }, ] [[package]] From 6f981ba25356deb85b19ecd5ad416eb08837c0a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 12:24:57 +0000 Subject: [PATCH 28/32] chore(python-deps): bump langgraph-sdk from 0.3.14 to 0.3.15 (#6190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [langgraph-sdk](https://github.com/langchain-ai/langgraph) from 0.3.14 to 0.3.15.
Release notes

Sourced from langgraph-sdk's releases.

langgraph-sdk==0.3.15

Changes since sdk==0.3.14

  • release(checkpoint): 4.1.1 (#7890)
  • release(sdk-py): 0.3.15 (#7891)
  • fix(sdk-py): percent-encode caller-supplied identifiers in URL paths (#7893)
  • release(langgraph): 1.2.1 (#7883)
  • chore(deps): bump idna from 3.11 to 3.15 in /libs/sdk-py (#7863)
  • chore(deps): bump urllib3 from 2.6.3 to 2.7.0 in /libs/sdk-py (#7764)
  • chore(deps): bump langsmith from 0.7.31 to 0.8.0 in /libs/sdk-py (#7789)
  • release: bump alpha packages to official versions (#7775)
  • chore(langgraph): bump langchain-core to 1.4.0 (#7767)
  • feat(sdk-py): support metadata filter for crons search/count (#7737)
  • chore(deps): bump ty from 0.0.23 to 0.0.33 in /libs/sdk-py (#7666)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=langgraph-sdk&package-manager=uv&previous-version=0.3.14&new-version=0.3.15)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ogx-ai/ogx/network/alerts).
--------- Signed-off-by: dependabot[bot] Signed-off-by: github-actions[bot] Signed-off-by: Sébastien Han Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: Sébastien Han --- pyproject.toml | 1 + uv.lock | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9aa1a78c9e0..08d5c036423 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ constraint-dependencies = [ "h11>=0.16.0", "idna>=3.15", "joserfc>=1.6.7", + "langgraph-sdk>=0.3.15", "lxml>=6.1.0", # CVE-2026-41066: XML entity expansion with default resolve_entities=True "msgpack>=1.2.1", "pillow>=12.2.0", # CVE-2026-40192 + 4 more: heap overflow, OOB write, DoS diff --git a/uv.lock b/uv.lock index 437f35fff87..a71c35ae73c 100644 --- a/uv.lock +++ b/uv.lock @@ -30,6 +30,7 @@ constraints = [ { name = "h11", specifier = ">=0.16.0" }, { name = "idna", specifier = ">=3.15" }, { name = "joserfc", specifier = ">=1.6.7" }, + { name = "langgraph-sdk", specifier = ">=0.3.15" }, { name = "lxml", specifier = ">=6.1.0" }, { name = "msgpack", specifier = ">=1.2.1" }, { name = "pillow", specifier = ">=12.2.0" }, @@ -2995,15 +2996,15 @@ wheels = [ [[package]] name = "langgraph-sdk" -version = "0.3.14" +version = "0.3.15" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, { name = "orjson" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/02/f1/134046c20bc4a4a15d410d1d21c9e298a3e9923777b4cc867b8669bc636b/langgraph_sdk-0.3.14.tar.gz", hash = "sha256:acd1674c538e97f3cdaa610f6dd7e34bc9bad30167f0ccc482dcd563325e81f5", size = 198162, upload-time = "2026-05-05T18:40:03.524Z" } +sdist = { url = "https://files.pythonhosted.org/packages/66/af/cdd4d6f3c05b3c1112ed3f12ef830faf15951b21d22cbc622a4becbbe25c/langgraph_sdk-0.3.15.tar.gz", hash = "sha256:29e805003d2c6e296823dd71992610976fd0428cefaa8b3304fd91f2247037de", size = 201924, upload-time = "2026-05-22T16:54:27.678Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/34/96/1c9f9fbfe756ddd850a2585e7f1949d8ebb97fdaa7a5eff8f45ed1314670/langgraph_sdk-0.3.14-py3-none-any.whl", hash = "sha256:68935bf6f4924eda92617a9e5dfb4f4281197508c648cb9d62ff083907607f9d", size = 97028, upload-time = "2026-05-05T18:40:02.099Z" }, + { url = "https://files.pythonhosted.org/packages/be/a5/0196d9c05749c25bc198e4909d68c998bc3120297e14944921baf2f4c384/langgraph_sdk-0.3.15-py3-none-any.whl", hash = "sha256:3838773acf7456d158165385d49f48f1e856f28b56ccd99ea139a8f27004815d", size = 98166, upload-time = "2026-05-22T16:54:26.013Z" }, ] [[package]] From fc34cbbeba178f27f1562e2e5a04029ca08567b7 Mon Sep 17 00:00:00 2001 From: E Geiger Date: Tue, 30 Jun 2026 16:24:43 +0300 Subject: [PATCH 29/32] chore: remove publish-openapi-sdk.yml and update docs to use unified pypi.yml workflow Remove the standalone OpenAPI SDK publishing workflow now that ogx-client is published through the unified pypi.yml workflow alongside other packages. - Delete .github/workflows/publish-openapi-sdk.yml - Remove its CODEOWNERS and workflows README entries - Delete client-sdks/openapi/DEPLOYMENT.md (redundant with unified workflow) - Update client-sdks/openapi/README.md CD and publishing sections to reference pypi.yml, correct workflow name, package name (ogx-client), tag format (v*), and workflow_dispatch inputs Signed-off-by: E Geiger --- .github/CODEOWNERS | 1 - .github/workflows/README.md | 1 - .github/workflows/publish-openapi-sdk.yml | 211 ---------------- client-sdks/openapi/DEPLOYMENT.md | 289 ---------------------- client-sdks/openapi/README.md | 45 ++-- 5 files changed, 15 insertions(+), 532 deletions(-) delete mode 100644 .github/workflows/publish-openapi-sdk.yml delete mode 100644 client-sdks/openapi/DEPLOYMENT.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6f189b932c7..353ca7b8551 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,4 +7,3 @@ # OpenAPI SDK generation and publishing /client-sdks/openapi/ @ashwinb @leseb @bbrowning /.github/workflows/openapi-generator-validation.yml @ashwinb @leseb @bbrowning -/.github/workflows/publish-openapi-sdk.yml @ashwinb @leseb @bbrowning diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 2150e66fb72..1e4ece174d5 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -28,7 +28,6 @@ OGX uses GitHub Actions for Continuous Integration (CI). Below is a table detail | Pre-commit | [pre-commit.yml](pre-commit.yml) | Run pre-commit checks | | Prepare release | [prepare-release.yml](prepare-release.yml) | Prepare release | | Test OGX Build | [providers-build.yml](providers-build.yml) | Test ogx build and list-deps | -| Publish OpenAPI SDK to PyPI | [publish-openapi-sdk.yml](publish-openapi-sdk.yml) | Publish ogx-client to PyPI | | Build, test, and publish packages | [pypi.yml](pypi.yml) | Build, test, and publish packages | | Integration Tests (Record) | [record-integration-tests.yml](record-integration-tests.yml) | Auto-record missing test recordings for PR | | vLLM GPU Recording | [record-vllm-gpu-tests.yml](record-vllm-gpu-tests.yml) | GPU recording for gpt-oss:20b (${{ inputs.suite }} suite) | diff --git a/.github/workflows/publish-openapi-sdk.yml b/.github/workflows/publish-openapi-sdk.yml deleted file mode 100644 index 325bd065ede..00000000000 --- a/.github/workflows/publish-openapi-sdk.yml +++ /dev/null @@ -1,211 +0,0 @@ -name: Publish OpenAPI SDK to PyPI - -run-name: Publish ogx-client to PyPI - -on: - workflow_dispatch: - inputs: - publish_to: - description: 'Publish to PyPI or TestPyPI' - required: true - default: 'testpypi' - type: choice - options: - - testpypi - - pypi - version: - description: 'Version override (e.g., "1.2.0"). Leave empty to auto-detect from tag or fallback_version.' - required: false - type: string - dry_run: - description: 'Dry run (build only, no publish)' - type: boolean - default: false - push: - tags: - - 'openapi-sdk-v*' # Tags like openapi-sdk-v0.5.0 - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: false - -permissions: - contents: read - -jobs: - compute-version: - name: Compute version - runs-on: ubuntu-latest - outputs: - version: ${{ steps.version.outputs.version }} - steps: - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Compute SDK version - id: version - run: | - if [ -n "${{ inputs.version }}" ]; then - # Explicit override from workflow_dispatch - VERSION="${{ inputs.version }}" - elif [[ "$GITHUB_REF" == refs/tags/openapi-sdk-v* ]]; then - # Extract version from tag: openapi-sdk-v1.2.0 -> 1.2.0 - VERSION="${GITHUB_REF#refs/tags/openapi-sdk-v}" - else - # Fall back to fallback_version from pyproject.toml - VERSION=$(python3 -c " - import tomllib, pathlib - p = tomllib.loads(pathlib.Path('pyproject.toml').read_text()) - print(p.get('tool', {}).get('setuptools_scm', {}).get('fallback_version', '0.0.0.dev0')) - ") - fi - echo "version=${VERSION}" >> "$GITHUB_OUTPUT" - echo "Computed version: ${VERSION}" - - build-sdk: - needs: compute-version - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Setup Python environment - uses: ./.github/actions/setup-runner - with: - python-version: '3.12' - - - name: Set up Java - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 - with: - distribution: 'temurin' - java-version: '11' - - - name: Install openapi-generator-cli - run: npm install -g @openapitools/openapi-generator-cli - - - name: Verify installations - working-directory: client-sdks/openapi - run: | - set -e - echo "=== Java version ===" - java -version - - echo "=== OpenAPI Generator version ===" - openapi-generator-cli version - - echo "=== SDK version ===" - echo "${{ needs.compute-version.outputs.version }}" - - - name: Generate OpenAPI SDK - working-directory: client-sdks/openapi - run: | - VERSION="${{ needs.compute-version.outputs.version }}" - echo "Generating SDK with OPEN=0 (ogx_client) at version ${VERSION}..." - make sdk OPEN=0 VERSION="${VERSION}" - - - name: Verify SDK generation - working-directory: client-sdks/openapi - run: | - if [ ! -d sdks/python ]; then - echo "Error: SDK directory was not generated" - exit 1 - fi - - PY_FILE_COUNT=$(find sdks/python -name "*.py" | wc -l) - echo "Generated Python files: $PY_FILE_COUNT" - - if [ "$PY_FILE_COUNT" -le 10 ]; then - echo "Error: Too few Python files generated" - exit 1 - fi - - echo "SDK generated successfully" - ls -lh sdks/python/ - - - name: Build package - working-directory: client-sdks/openapi/sdks/python - run: | - echo "Building Python package..." - uv build - - echo "Built distribution files:" - ls -lh dist/ - - - name: Upload build artifacts - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: python-sdk-dist - path: client-sdks/openapi/sdks/python/dist/ - retention-days: 30 - - publish-testpypi: - if: | - (github.event_name == 'workflow_dispatch' && inputs.publish_to == 'testpypi' && inputs.dry_run == false) || - (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/openapi-sdk-v') && !contains(github.ref, '-rc') && !contains(github.ref, '-alpha') && !contains(github.ref, '-beta')) - needs: build-sdk - runs-on: ubuntu-latest - environment: testpypi - permissions: - id-token: write - steps: - - name: Download build artifacts - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: python-sdk-dist - path: dist - - - name: Publish to TestPyPI - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 - with: - repository-url: https://test.pypi.org/legacy/ - packages-dir: dist/ - verbose: true - - - name: Summary - run: | - { - echo "## SDK Publishing Summary" - echo "" - echo "- **Event**: ${{ github.event_name }}" - echo "- **Target**: TestPyPI" - echo "- **Package**: ogx-client" - echo "" - echo "✅ Package published to TestPyPI" - echo "Install with: \`pip install --index-url https://test.pypi.org/simple/ ogx-client\`" - } >> "$GITHUB_STEP_SUMMARY" - - publish-pypi: - if: | - github.event_name == 'workflow_dispatch' && - inputs.publish_to == 'pypi' && - inputs.dry_run == false - needs: build-sdk - runs-on: ubuntu-latest - permissions: - id-token: write - steps: - - name: Download build artifacts - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: python-sdk-dist - path: dist - - - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 - with: - packages-dir: dist/ - verbose: true - - - name: Summary - run: | - { - echo "## SDK Publishing Summary" - echo "" - echo "- **Event**: ${{ github.event_name }}" - echo "- **Target**: PyPI (production)" - echo "- **Package**: ogx-client" - echo "" - echo "✅ Package published to PyPI" - echo "Install with: \`pip install ogx-client\`" - } >> "$GITHUB_STEP_SUMMARY" diff --git a/client-sdks/openapi/DEPLOYMENT.md b/client-sdks/openapi/DEPLOYMENT.md deleted file mode 100644 index 0afcd01d817..00000000000 --- a/client-sdks/openapi/DEPLOYMENT.md +++ /dev/null @@ -1,289 +0,0 @@ -# Deployment Guide for ogx-open-client - -This document outlines the deployment configuration and requirements for publishing the `ogx-open-client` SDK to PyPI. - -## Required GitHub Configurations - -### 1. Environments - -The publishing workflow requires two GitHub environments with different protection rules: - -#### `testpypi` Environment - -- **Purpose**: For testing releases and automated tag-triggered publishes -- **Protection rules**: None (auto-approve) -- **Secrets**: - - `TEST_PYPI_API_TOKEN` — TestPyPI API token - -#### `pypi-production` Environment - -- **Purpose**: For production releases to PyPI -- **Protection rules**: **Required reviewers** (at least 1) -- **Secrets**: - - `PYPI_API_TOKEN` — Production PyPI API token -- **Deployment branches**: Limit to `main` or specific release branches - -**Setup Instructions:** - -1. Go to Repository Settings → Environments -2. Create `testpypi` environment (no protection) -3. Create `pypi-production` environment -4. Add required reviewers: @ashwinb, @leseb, or @bbrowning -5. Configure deployment branch restrictions (recommended: `main` only) - -### 2. Secrets - -Configure the following secrets at Repository Settings → Secrets and variables → Actions: - -| Secret Name | Purpose | How to Get | -|-------------|---------|-----------| -| `TEST_PYPI_API_TOKEN` | TestPyPI publishing | [Create token at test.pypi.org](https://test.pypi.org/manage/account/token/) | -| `PYPI_API_TOKEN` | Production PyPI publishing | [Create token at pypi.org](https://pypi.org/manage/account/token/) | - -**Token Scope**: Set to "Entire account" or limit to `ogx-open-client` package once it exists. - -**Security Notes**: - -- Use token authentication (not username/password) -- Enable 2FA on PyPI accounts -- Rotate tokens annually -- Prefer Trusted Publishing (OIDC) when available - -### 3. PyPI Package Setup - -Before first publish, claim the package name: - -1. **Register package on TestPyPI first**: - - ```bash - # Build locally - cd client-sdks/openapi - make sdk OPEN=1 - cd sdks/python - uv build - - # Publish to TestPyPI - uv publish --publish-url https://test.pypi.org/legacy/ dist/* - ``` - -2. **Verify on TestPyPI**: - -3. **Register on production PyPI**: - - Use workflow_dispatch with `publish_to: pypi` - - Requires approval from configured reviewers - -4. **Configure PyPI project** (post-first-publish): - - Add project description/README - - Configure Trusted Publishing (GitHub Actions OIDC) - - Add maintainers: - -## Publishing Workflows - -### Automatic Publishing (Tag-Triggered) - -Stable releases automatically publish to TestPyPI: - -```bash -# Tag format: openapi-sdk-v{VERSION} -git tag openapi-sdk-v1.0.0 -git push origin openapi-sdk-v1.0.0 -``` - -**What happens:** - -1. Workflow triggers on tag push -2. Builds SDK from OpenAPI spec -3. Publishes to **TestPyPI** (testpypi environment) -4. Uploads artifacts to GitHub - -**Pre-release tags** (`-rc`, `-alpha`, `-beta`) are built but **not published**. - -### Manual Publishing (Workflow Dispatch) - -For production PyPI or on-demand builds: - -1. Go to Actions → "Publish OpenAPI SDK to PyPI" -2. Click "Run workflow" -3. Configure: - - **publish_to**: `testpypi` or `pypi` - - **dry_run**: `true` (build only) or `false` (publish) - -**Production publish** (`publish_to: pypi`): - -- Requires approval from environment reviewers -- Notifies reviewers via GitHub -- Reviewer approves/rejects in Actions tab - -### Manual Local Publishing - -For emergency releases or testing: - -```bash -# Generate SDK -cd client-sdks/openapi -make sdk OPEN=1 - -# Build package -cd sdks/python -uv build - -# Publish to TestPyPI -uv publish --publish-url https://test.pypi.org/legacy/ dist/* -# Token: paste TEST_PYPI_API_TOKEN when prompted - -# Publish to PyPI (production) -uv publish dist/* -# Token: paste PYPI_API_TOKEN when prompted -``` - -## Versioning - -SDK versions follow semantic versioning and track OGX server versions: - -- **Stable**: `1.0.0`, `1.1.0`, `1.2.3` -- **Pre-release**: `1.0.0-rc1`, `1.1.0-alpha.2`, `1.2.0-beta.1` - -Version is extracted from `../../pyproject.toml` (`fallback_version` field). - -To release a new version: - -```bash -# Update version in root pyproject.toml -vim pyproject.toml # Change fallback_version = "1.1.0" - -# Commit version bump -git add pyproject.toml -git commit -s -m "chore: bump version to 1.1.0" - -# Tag and push -git tag openapi-sdk-v1.1.0 -git push origin main -git push origin openapi-sdk-v1.1.0 -``` - -## Rollback Procedure - -If a bad version is published: - -### 1. Yank the Release - -```bash -# TestPyPI -uv publish --yank ogx-open-client==1.0.0 --publish-url https://test.pypi.org/legacy/ - -# Production PyPI -uv publish --yank ogx-open-client==1.0.0 -``` - -**Effect**: Marks release as unavailable for new installs. Existing installs unaffected. - -### 2. Publish Hotfix - -```bash -# Fix the issue in code -git commit -s -m "fix: critical bug in 1.0.0" - -# Bump to patch version -vim pyproject.toml # Change to 1.0.1 - -# Tag and publish -git tag openapi-sdk-v1.0.1 -git push origin openapi-sdk-v1.0.1 -``` - -### 3. Notify Users - -- Create GitHub Release with changelog -- Post to Discord #announcements -- Update PyPI description if critical security issue - -## Monitoring - -### Success Indicators - -- ✅ Workflow completes with green checkmark -- ✅ Package appears on PyPI/TestPyPI -- ✅ Installation works: `pip install ogx-open-client` -- ✅ Import works: `python -c "from ogx_open_client import OgxClient"` - -### Failure Scenarios - -| Error | Cause | Solution | -|-------|-------|----------| -| `HTTP 403: Invalid or non-existent authentication` | Bad API token | Rotate secret, update in GitHub | -| `HTTP 400: File already exists` | Version already published | Bump version, cannot overwrite | -| `No such file or directory: dist/` | Build failed | Check `make sdk` step logs | -| `ModuleNotFoundError: ogx_open_client` | Package name typo | Check `packageName` in openapi-config.json | -| Environment approval timeout | No reviewer available | Add more reviewers to environment | - -### Debug Workflow - -```bash -# Run workflow with dry-run to test build without publishing -# GitHub Actions → Publish OpenAPI SDK to PyPI → Run workflow -# Set: dry_run = true -``` - -## Security Considerations - -1. **Token Rotation**: Rotate PyPI tokens annually -2. **2FA Enforcement**: All PyPI account owners must use 2FA -3. **Environment Protection**: Production requires reviewer approval -4. **Audit Trail**: All publishes logged in GitHub Actions -5. **Package Signing**: Consider adding GPG signatures (future enhancement) - -## Trusted Publishing (Future) - -Once the package exists on PyPI, migrate to Trusted Publishing: - -1. PyPI Project Settings → Publishing -2. Add GitHub publisher: - - Owner: `ogx-ai` - - Repository: `ogx` - - Workflow: `publish-openapi-sdk.yml` - - Environment: `pypi-production` - -3. Remove `PYPI_API_TOKEN` secret (no longer needed) - -**Benefits**: - -- No long-lived API tokens -- OIDC-based authentication -- Automatic token rotation -- Better security posture - -## Troubleshooting - -### Package Not Found After Publish - -Wait 5-10 minutes for PyPI's CDN to propagate. Then: - -```bash -pip install --upgrade --force-reinstall ogx-open-client -``` - -### Version Conflict - -If local environment has old version cached: - -```bash -pip cache purge -pip install ogx-open-client==1.0.0 # Specify exact version -``` - -### Build Artifacts Missing - -If build step succeeds but publish fails: - -1. Download artifacts from workflow run -2. Manually publish: `uv publish path/to/downloaded/dist/*` - -## Contacts - -- **Primary Maintainers**: @ashwinb, @leseb, @bbrowning -- **Emergency Contact**: -- **GitHub Issues**: - ---- - -Last updated: 2026-05-31 diff --git a/client-sdks/openapi/README.md b/client-sdks/openapi/README.md index a477afa92b8..16f998d7639 100644 --- a/client-sdks/openapi/README.md +++ b/client-sdks/openapi/README.md @@ -92,73 +92,58 @@ The CI workflow (`.github/workflows/openapi-generator-validation.yml`) automatic ### Continuous Delivery -The CD workflow (`.github/workflows/publish-openapi-sdk.yml`) automatically publishes SDK to PyPI: +The `ogx-client` package is published through the unified PyPI/NPM release workflow (`.github/workflows/pypi.yml`) alongside other ogx packages. **Automatic publishing (via tags):** -- Tags matching `openapi-sdk-v*` trigger builds -- Stable versions (e.g., `openapi-sdk-v1.0.0`) → Published to TestPyPI -- Pre-release versions (e.g., `openapi-sdk-v1.0.0-rc1`) → Built only, not published +- Tags matching `v*` trigger the unified workflow +- The workflow builds all packages including `ogx-client` **Manual publishing (via GitHub UI):** -- Go to Actions → "Publish OpenAPI SDK to PyPI" -- Choose target (TestPyPI/PyPI) and dry-run mode +- Go to Actions → "Build, test, and publish packages" +- Choose `packages: clients-only` (or `all`) and the desired `dry_run` mode ## Publishing to PyPI -The SDK can be published to PyPI using the GitHub Actions workflow at `.github/workflows/publish-openapi-sdk.yml`. +The SDK is published as `ogx-client` via the unified workflow at `.github/workflows/pypi.yml`. ### Manual Publishing (via GitHub UI) -1. Go to Actions → "Publish OpenAPI SDK to PyPI" +1. Go to Actions → "Build, test, and publish packages" 2. Click "Run workflow" 3. Select options: - - **publish_to**: `testpypi` (for testing) or `pypi` (production) - - **dry_run**: `true` to build only without publishing + - **packages**: `clients-only` or `all` + - **dry_run**: `test-pypi` (default), `build-only`, or `off` (production) ### Automatic Publishing (via Git Tags) -Push a tag matching `openapi-sdk-v*` to trigger automatic builds: +Push a version tag to trigger the unified workflow: ```bash -# Stable release → Published to TestPyPI -git tag openapi-sdk-v1.0.0 -git push origin openapi-sdk-v1.0.0 - -# Pre-release → Built only, not published -git tag openapi-sdk-v1.0.0-rc1 -git push origin openapi-sdk-v1.0.0-rc1 +# Release → triggers unified workflow for all packages +git tag v1.0.0 +git push origin v1.0.0 ``` -**Note:** Pre-release tags (containing `-rc`, `-alpha`, or `-beta`) are built for validation but not published to avoid cluttering the package index. - -### Required Secrets - -Configure these GitHub secrets for the repository: - -- `TEST_PYPI_API_TOKEN` - TestPyPI API token -- `PYPI_API_TOKEN` - Production PyPI API token - ### Testing the Published Package After publishing to TestPyPI: ```bash -pip install --index-url https://test.pypi.org/simple/ ogx-open-client +pip install --index-url https://test.pypi.org/simple/ ogx-client ``` After publishing to PyPI: ```bash -pip install ogx-open-client +pip install ogx-client ``` ## Documentation - **[USAGE_EXAMPLES.md](USAGE_EXAMPLES.md)** - End-to-end code examples for all major API features - **[STRATEGY.md](STRATEGY.md)** - Long-term strategy, ownership, versioning, and deprecation policy -- **[DEPLOYMENT.md](DEPLOYMENT.md)** - Production deployment guide, environment setup, rollback procedures ## Files From 0a386e94cbda00c091dd8941165197d0366a6870 Mon Sep 17 00:00:00 2001 From: Nathan Weinberg <31703736+nathan-weinberg@users.noreply.github.com> Date: Tue, 30 Jun 2026 09:51:45 -0400 Subject: [PATCH 30/32] fix(cli): resolve env var templates before validation in list-deps (#5914) # What does this PR do? `ogx stack list-deps` passed raw YAML directly to `StackConfig()`, causing Pydantic validation errors for non-string fields using env var syntax (e.g. `registry_refresh_interval_seconds` set to `${env.REGISTRY_REFRESH_INTERVAL_SECONDS:=300}`). Use `replace_env_vars()` before validation, matching the server startup path. This also subsumes the manual `auth` `provider_config` nulling workaround since `replace_env_vars` already handles that. Distributions like `nvidia` and `postgres-demo` use bare `${env.INFERENCE_MODEL}` (no default value) in `registered_resources`. Since these env vars are not set at build/CI time, `replace_env_vars()` would raise `EnvVarError`. The new `ignore_unresolved` parameter makes `list-deps` tolerant of these by resolving bare unset env vars to empty strings, which triggers the existing resource-skip logic. Server startup behavior is unchanged (still raises on missing env vars). ## Test plan - [x] Unit tests for `replace_env_vars` pass (37 tests including 4 new `ignore_unresolved` tests) - [x] Unit tests for `list-deps` pass (14 tests) - [x] `ogx stack list-deps nvidia` succeeds without `INFERENCE_MODEL` set - [x] `ogx stack list-deps postgres-demo` succeeds without `INFERENCE_MODEL` set - [x] Pre-commit checks pass on all changed files - [x] `mypy` passes **Upstream issue**: https://github.com/opendatahub-io/ogx-distribution/issues/429 --------- Signed-off-by: Nathan Weinberg Co-authored-by: Claude Opus 4.6 (1M context) --- src/ogx/cli/stack/_list_deps.py | 12 ++------ src/ogx/core/stack.py | 31 +++++++++++++++----- tests/unit/server/test_replace_env_vars.py | 34 ++++++++++++++++++++++ 3 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/ogx/cli/stack/_list_deps.py b/src/ogx/cli/stack/_list_deps.py index fb9701d6362..5df613d51e1 100644 --- a/src/ogx/cli/stack/_list_deps.py +++ b/src/ogx/cli/stack/_list_deps.py @@ -14,7 +14,7 @@ from ogx.core.build import get_provider_dependencies from ogx.core.datatypes import StackConfig from ogx.core.distribution import get_provider_registry -from ogx.core.stack import run_config_from_dynamic_config_spec +from ogx.core.stack import replace_env_vars, run_config_from_dynamic_config_spec from ogx.log import get_logger from .utils import add_dependent_providers @@ -90,15 +90,7 @@ def run_stack_list_deps_command(args: argparse.Namespace) -> None: with open(config_file) as f: try: contents = yaml.safe_load(f) - # Remove auth provider_config to avoid validation errors with env var syntax. - # We only need provider dependencies, not auth config (auth has no pip_packages). - # This is simpler than modifying the schema to accept type="" which would require - # removing discriminated union and adding custom validation logic and modifying - # all 4 auth provider config classes (a very invasive change) - if "server" in contents and "auth" in contents["server"]: - if "provider_config" in contents["server"]["auth"]: - contents["server"]["auth"]["provider_config"] = None - config = StackConfig(**contents) + config = StackConfig(**replace_env_vars(contents, ignore_unresolved=True)) except Exception as e: cprint( f"Could not parse config file {config_file}: {e}", diff --git a/src/ogx/core/stack.py b/src/ogx/core/stack.py index ec364e9b0a7..4a5e8a5ce32 100644 --- a/src/ogx/core/stack.py +++ b/src/ogx/core/stack.py @@ -482,8 +482,15 @@ def _collect(obj: Any, acc: list[str]) -> None: return result -def replace_env_vars(config: Any, path: str = "") -> Any: - """Recursively replace environment variable references in a configuration object.""" +def replace_env_vars(config: Any, path: str = "", ignore_unresolved: bool = False) -> Any: + """Recursively replace environment variable references in a configuration object. + + When *ignore_unresolved* is True, bare ``${env.VAR}`` references that cannot + be resolved (env var not set, no default) are replaced with an empty string + instead of raising :class:`EnvVarError`. This is used by ``list-deps`` which + only needs the structural shape of the config (provider types), not actual + runtime values. + """ if isinstance(config, dict): # Special handling for auth provider_config with conditional type field # This allows auth to be enabled/disabled via environment variables @@ -493,7 +500,9 @@ def replace_env_vars(config: Any, path: str = "") -> Any: if isinstance(provider_cfg, dict) and "type" in provider_cfg: try: # Resolve the type field first to check if auth should be enabled - resolved_type = replace_env_vars(provider_cfg["type"], f"{path}.provider_config.type") + resolved_type = replace_env_vars( + provider_cfg["type"], f"{path}.provider_config.type", ignore_unresolved + ) # If type is empty/None, disable auth by setting provider_config to None # This prevents validation errors on the discriminated union @@ -501,7 +510,7 @@ def replace_env_vars(config: Any, path: str = "") -> Any: # Process rest of config normally but exclude provider_config from expansion # to avoid EnvVarError from bare env vars (e.g., ${env.KEYCLOAK_URL}) result = { - k: replace_env_vars(v, f"{path}.{k}" if path else k) + k: replace_env_vars(v, f"{path}.{k}" if path else k, ignore_unresolved) for k, v in config.items() if k != "provider_config" } @@ -518,7 +527,7 @@ def replace_env_vars(config: Any, path: str = "") -> Any: result = {} for k, v in config.items(): try: - result[k] = replace_env_vars(v, f"{path}.{k}" if path else k) + result[k] = replace_env_vars(v, f"{path}.{k}" if path else k, ignore_unresolved) except EnvVarError as e: raise EnvVarError(e.var_name, e.path) from None return result @@ -533,7 +542,9 @@ def replace_env_vars(config: Any, path: str = "") -> Any: # is disabled so that we can skip config env variable expansion and avoid validation errors if isinstance(v, dict) and "provider_id" in v: try: - resolved_provider_id = replace_env_vars(v["provider_id"], f"{path}[{i}].provider_id") + resolved_provider_id = replace_env_vars( + v["provider_id"], f"{path}[{i}].provider_id", ignore_unresolved + ) if resolved_provider_id == "__disabled__": logger.debug( "Skipping config env variable expansion for disabled provider", @@ -551,7 +562,9 @@ def replace_env_vars(config: Any, path: str = "") -> Any: for id_field in RESOURCE_ID_FIELDS: if id_field in v: try: - resolved_id = replace_env_vars(v[id_field], f"{path}[{i}].{id_field}") + resolved_id = replace_env_vars( + v[id_field], f"{path}[{i}].{id_field}", ignore_unresolved + ) if resolved_id is None or resolved_id == "": logger.debug( "Skipping [] with empty (conditional env var not set)", @@ -575,7 +588,7 @@ def replace_env_vars(config: Any, path: str = "") -> Any: # Normal processing # result is a list here, but mypy sees it could be dict/str - result.append(replace_env_vars(v, f"{path}[{i}]")) # type: ignore[attr-defined] + result.append(replace_env_vars(v, f"{path}[{i}]", ignore_unresolved)) # type: ignore[attr-defined] except EnvVarError as e: raise EnvVarError(e.var_name, e.path) from None return result @@ -620,6 +633,8 @@ def get_env_var(match: re.Match): value = "" else: # No operator case: ${env.FOO} if not env_value: + if ignore_unresolved: + return "" raise EnvVarError(env_var, path) value = env_value diff --git a/tests/unit/server/test_replace_env_vars.py b/tests/unit/server/test_replace_env_vars.py index 6c5ac5d6f33..0e202de9dec 100644 --- a/tests/unit/server/test_replace_env_vars.py +++ b/tests/unit/server/test_replace_env_vars.py @@ -42,6 +42,40 @@ def test_simple_replacement_raises_when_not_set(setup_env_vars): assert exc_info.value.var_name == "NOT_SET" +def test_ignore_unresolved_returns_empty_for_bare_env_var(setup_env_vars): + result = replace_env_vars("${env.NOT_SET}", ignore_unresolved=True) + assert result is None + + +def test_ignore_unresolved_still_resolves_set_vars(setup_env_vars): + assert replace_env_vars("${env.TEST_VAR}", ignore_unresolved=True) == "test_value" + + +def test_ignore_unresolved_skips_resource_with_bare_env_var(setup_env_vars): + """Bare ${env.VAR} in a model_id should skip the item when ignore_unresolved=True.""" + data = { + "models": [ + {"model_id": "${env.INFERENCE_MODEL}", "provider_id": "nvidia"}, + {"model_id": "always-present", "provider_id": "other"}, + ] + } + result = replace_env_vars(data, ignore_unresolved=True) + assert len(result["models"]) == 1 + assert result["models"][0]["model_id"] == "always-present" + + +def test_ignore_unresolved_preserves_defaults_and_conditionals(setup_env_vars): + data = { + "url": "${env.BASE_URL:=https://example.com}", + "key": "${env.API_KEY:=}", + "opt": "${env.OPTIONAL:+enabled}", + } + result = replace_env_vars(data, ignore_unresolved=True) + assert result["url"] == "https://example.com" + assert result["key"] is None + assert result["opt"] is None + + def test_default_value_when_not_set(setup_env_vars): assert replace_env_vars("${env.NOT_SET:=default}") == "default" From 9ebdb571e88e97723634dc9082b57a3ed38478af Mon Sep 17 00:00:00 2001 From: Derek Higgins Date: Tue, 30 Jun 2026 15:12:15 +0100 Subject: [PATCH 31/32] feat(cli): support OGX_WORKERS env var to override worker count (#6221) ## Summary - Add `OGX_WORKERS` environment variable to override the configured worker count, matching the existing `OGX_PORT` pattern. ## Test plan - Set `OGX_WORKERS=4` and verify uvicorn starts with 4 workers - Unset `OGX_WORKERS` and verify the config value is used Signed-off-by: Derek Higgins Co-authored-by: Claude Opus 4.6 --- src/ogx/cli/stack/run.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ogx/cli/stack/run.py b/src/ogx/cli/stack/run.py index 2690fffebcf..09ed1a3776a 100644 --- a/src/ogx/cli/stack/run.py +++ b/src/ogx/cli/stack/run.py @@ -153,7 +153,8 @@ def _uvicorn_run(config_file: Path | None, args: argparse.Namespace, parser: arg env_port = os.getenv("OGX_PORT") port = args.port or (int(env_port) if env_port else None) or config.server.port - workers = config.server.workers + env_workers = os.getenv("OGX_WORKERS") + workers = (int(env_workers) if env_workers else None) or config.server.workers host = "" if config.server.host: From bb94d7c6db5ff3b3b2395046fab8a9230420f22c Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Tue, 30 Jun 2026 09:58:43 -0700 Subject: [PATCH 32/32] fix(ci): Include OpenAPI SDK in clients-only release mode. Signed-off-by: Francisco Javier Arceo --- .github/workflows/pypi.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 5f61da36355..32dfec5f8cb 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -249,7 +249,7 @@ jobs: echo "skip=false" >> "$GITHUB_OUTPUT" elif [ "$PACKAGES" == "ogx-only" ] && { [ "$TYPE" == "local" ] || [ "$TYPE" == "openapi-sdk" ]; }; then echo "skip=false" >> "$GITHUB_OUTPUT" - elif [ "$PACKAGES" == "clients-only" ] && [ "$TYPE" == "external" ]; then + elif [ "$PACKAGES" == "clients-only" ] && { [ "$TYPE" == "external" ] || [ "$TYPE" == "openapi-sdk" ]; }; then echo "skip=false" >> "$GITHUB_OUTPUT" else echo "skip=true" >> "$GITHUB_OUTPUT" @@ -790,7 +790,7 @@ jobs: echo "skip=false" >> "$GITHUB_OUTPUT" elif [ "$PACKAGES" == "ogx-only" ] && { [ "$TYPE" == "local" ] || [ "$TYPE" == "openapi-sdk" ]; }; then echo "skip=false" >> "$GITHUB_OUTPUT" - elif [ "$PACKAGES" == "clients-only" ] && [ "$TYPE" == "external" ]; then + elif [ "$PACKAGES" == "clients-only" ] && { [ "$TYPE" == "external" ] || [ "$TYPE" == "openapi-sdk" ]; }; then echo "skip=false" >> "$GITHUB_OUTPUT" else echo "skip=true" >> "$GITHUB_OUTPUT"