Skip to content

Commit bd27b88

Browse files
committed
Merge remote-tracking branch 'upstream/main' into improving-ci-coverage-and-configuring-.coveragerc
2 parents bd6ab2e + bcc2566 commit bd27b88

17 files changed

Lines changed: 386 additions & 48 deletions

File tree

client-sdks/stainless/openapi.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3329,6 +3329,7 @@ paths:
33293329
$ref: '#/components/responses/DefaultError'
33303330
tags:
33313331
- Admin
3332+
- Connectors
33323333
summary: List all connectors.
33333334
description: List all configured connectors.
33343335
operationId: list_connectors_v1alpha_admin_connectors_get
@@ -3355,6 +3356,7 @@ paths:
33553356
description: Default Response
33563357
tags:
33573358
- Admin
3359+
- Connectors
33583360
summary: Get a tool by name from a connector.
33593361
description: Get a tool definition by its name from a connector.
33603362
operationId: get_connector_tool_v1alpha_admin_connectors__connector_id__tools__tool_name__get
@@ -3408,6 +3410,7 @@ paths:
34083410
description: Default Response
34093411
tags:
34103412
- Admin
3413+
- Connectors
34113414
summary: List tools from a connector.
34123415
description: List all tools available from a connector.
34133416
operationId: list_connector_tools_v1alpha_admin_connectors__connector_id__tools_get
@@ -3453,6 +3456,7 @@ paths:
34533456
description: Default Response
34543457
tags:
34553458
- Admin
3459+
- Connectors
34563460
summary: Get a connector by its ID.
34573461
description: Get a connector by its ID.
34583462
operationId: get_connector_v1alpha_admin_connectors__connector_id__get

docs/docs/providers/responses/inline_builtin.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ Metadata: {metadata}
7676
| `vector_stores_config.contextual_retrieval_params.default_timeout_seconds` | `int` | No | 120 | Default timeout in seconds for each LLM contextualization call. |
7777
| `vector_stores_config.contextual_retrieval_params.default_max_concurrency` | `int` | No | 3 | Default maximum concurrent LLM calls for contextualization. |
7878
| `vector_stores_config.contextual_retrieval_params.max_document_tokens` | `int` | No | 100000 | Maximum document size in tokens. Documents exceeding this are rejected for contextual retrieval. |
79-
| `compaction_config` | `CompactionConfig` | No | summarization_prompt='You are performing a CONTEXT CHECKPOINT COMPACTION. Create a handoff summary for another LLM that will resume the task.\n\nInclude:\n- Current progress and key decisions made\n- Important context, constraints, or user preferences\n- What remains to be done (clear next steps)\n- Any critical data, examples, or references needed to continue\n\nBe concise, structured, and focused on helping the next LLM seamlessly continue the work.' summary_prefix='Another language model started to solve this problem and produced a summary of its thinking process. You also have access to the state of the tools that were used by that language model. Use this to build on the work that has already been done and avoid duplicating work. Here is the summary produced by the other language model, use the information in this summary to assist with your own analysis:' summarization_model=None default_compact_threshold=None tokenizer_encoding=None | Configuration for conversation compaction behavior and prompt templates |
79+
| `compaction_config` | `CompactionConfig` | No | summarization_prompt='You are performing a CONTEXT CHECKPOINT COMPACTION. Create a handoff summary for another LLM that will resume the task.\n\nInclude:\n- Current progress and key decisions made\n- Important context, constraints, or user preferences\n- What remains to be done (clear next steps)\n- Any critical data, examples, or references needed to continue\n\nBe concise, structured, and focused on helping the next LLM seamlessly continue the work.' summary_prefix='Another language model started to solve this problem and produced a summary of its thinking process. You also have access to the state of the tools that were used by that language model. Use this to build on the work that has already been done and avoid duplicating work. Here is the summary produced by the other language model, use the information in this summary to assist with your own analysis:' summarization_model=None default_compact_threshold=None tokenizer_encoding=None model_tokenizer_mappings={'llama': 'cl100k_base', 'mistral': 'cl100k_base', 'claude': 'cl100k_base', 'gemma': 'cl100k_base', 'qwen': 'cl100k_base', 'phi': 'cl100k_base', 'deepseek': 'cl100k_base'} | Configuration for conversation compaction behavior and prompt templates |
8080
| `compaction_config.summarization_prompt` | `str` | No | You are performing a CONTEXT CHECKPOINT COMPACTION. Create a handoff summary for another LLM that will resume the task.
8181

8282
Include:
@@ -89,7 +89,8 @@ Be concise, structured, and focused on helping the next LLM seamlessly continue
8989
| `compaction_config.summary_prefix` | `str` | No | Another language model started to solve this problem and produced a summary of its thinking process. You also have access to the state of the tools that were used by that language model. Use this to build on the work that has already been done and avoid duplicating work. Here is the summary produced by the other language model, use the information in this summary to assist with your own analysis: | Text prepended to the compaction summary to frame it as a handoff for the next LLM. |
9090
| `compaction_config.summarization_model` | `str \| None` | No | | Model to use for generating compaction summaries. If not set, uses the same model as the conversation. |
9191
| `compaction_config.default_compact_threshold` | `int \| None` | No | | Default token threshold for auto-compaction via context_management. If set, conversations exceeding this token count will be automatically compacted. |
92-
| `compaction_config.tokenizer_encoding` | `str \| None` | No | | Tiktoken encoding name for token counting (e.g. 'o200k_base', 'cl100k_base'). If not set, the encoding is resolved from the model name via tiktoken.encoding_for_model(). |
92+
| `compaction_config.tokenizer_encoding` | `str \| None` | No | | Default tiktoken encoding name for token counting (e.g. 'o200k_base', 'cl100k_base'). Applied as a server-level default after any per-request override via extra_body. If not set, encoding is resolved from the model name via tiktoken, then model-family prefix mappings, then character-based estimation. |
93+
| `compaction_config.model_tokenizer_mappings` | `dict[str, str]` | No | {'llama': 'cl100k_base', 'mistral': 'cl100k_base', 'claude': 'cl100k_base', 'gemma': 'cl100k_base', 'qwen': 'cl100k_base', 'phi': 'cl100k_base', 'deepseek': 'cl100k_base'} | Map model name prefixes to tiktoken encoding names. Used as a heuristic fallback when tiktoken cannot resolve the model name directly. Matching is case-insensitive on the model name after stripping any provider prefix (e.g., 'ollama/llama3.2:3b' matches the 'llama' prefix). Admins can extend this to support custom or fine-tuned models. |
9394
| `moderation_endpoint` | `str \| None` | No | | URL of an OpenAI-compatible /v1/moderations endpoint for guardrails. The endpoint must accept POST {"input": "text"} and return {"results": [{"flagged": bool, "categories": {...}}]}. |
9495

9596
## Sample Configuration

docs/static/experimental-ogx-spec.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ paths:
225225
$ref: '#/components/responses/DefaultError'
226226
tags:
227227
- Admin
228+
- Connectors
228229
summary: List all connectors.
229230
description: List all configured connectors.
230231
operationId: list_connectors_v1alpha_admin_connectors_get
@@ -251,6 +252,7 @@ paths:
251252
description: Default Response
252253
tags:
253254
- Admin
255+
- Connectors
254256
summary: Get a tool by name from a connector.
255257
description: Get a tool definition by its name from a connector.
256258
operationId: get_connector_tool_v1alpha_admin_connectors__connector_id__tools__tool_name__get
@@ -304,6 +306,7 @@ paths:
304306
description: Default Response
305307
tags:
306308
- Admin
309+
- Connectors
307310
summary: List tools from a connector.
308311
description: List all tools available from a connector.
309312
operationId: list_connector_tools_v1alpha_admin_connectors__connector_id__tools_get
@@ -349,6 +352,7 @@ paths:
349352
description: Default Response
350353
tags:
351354
- Admin
355+
- Connectors
352356
summary: Get a connector by its ID.
353357
description: Get a connector by its ID.
354358
operationId: get_connector_v1alpha_admin_connectors__connector_id__get

docs/static/stainless-ogx-spec.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3329,6 +3329,7 @@ paths:
33293329
$ref: '#/components/responses/DefaultError'
33303330
tags:
33313331
- Admin
3332+
- Connectors
33323333
summary: List all connectors.
33333334
description: List all configured connectors.
33343335
operationId: list_connectors_v1alpha_admin_connectors_get
@@ -3355,6 +3356,7 @@ paths:
33553356
description: Default Response
33563357
tags:
33573358
- Admin
3359+
- Connectors
33583360
summary: Get a tool by name from a connector.
33593361
description: Get a tool definition by its name from a connector.
33603362
operationId: get_connector_tool_v1alpha_admin_connectors__connector_id__tools__tool_name__get
@@ -3408,6 +3410,7 @@ paths:
34083410
description: Default Response
34093411
tags:
34103412
- Admin
3413+
- Connectors
34113414
summary: List tools from a connector.
34123415
description: List all tools available from a connector.
34133416
operationId: list_connector_tools_v1alpha_admin_connectors__connector_id__tools_get
@@ -3453,6 +3456,7 @@ paths:
34533456
description: Default Response
34543457
tags:
34553458
- Admin
3459+
- Connectors
34563460
summary: Get a connector by its ID.
34573461
description: Get a connector by its ID.
34583462
operationId: get_connector_v1alpha_admin_connectors__connector_id__get

src/ogx/core/datatypes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from typing import Annotated, Any, Literal, Self
1111
from urllib.parse import urlparse
1212

13-
from pydantic import BaseModel, Field, field_validator, model_validator
13+
from pydantic import BaseModel, Field, SecretStr, field_validator, model_validator
1414

1515
from ogx.core.access_control.datatypes import AccessRule, RouteAccessRule
1616
from ogx.core.storage.datatypes import (
@@ -193,7 +193,7 @@ class OAuth2IntrospectionConfig(BaseModel):
193193

194194
url: str
195195
client_id: str
196-
client_secret: str
196+
client_secret: SecretStr
197197
send_secret_in_body: bool = False
198198

199199

src/ogx/core/resolver.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ def additional_protocols_map() -> dict[Api, Any]:
132132
}
133133

134134

135-
# TODO: make all this naming far less atrocious. Provider. ProviderSpec. ProviderWithSpec. WTF!
136135
class ProviderWithSpec(Provider):
137136
"""A Provider paired with its resolved ProviderSpec for instantiation."""
138137

src/ogx/core/routers/inference.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@
6565
logger = get_logger(name=__name__, category="core::routers")
6666

6767

68+
def _log_background_task_error(task: asyncio.Task) -> None:
69+
if not task.cancelled() and (exc := task.exception()):
70+
logger.error("Failed to store chat completion in background", error=str(exc))
71+
72+
6873
class InferenceRouter(Inference):
6974
"""Routes to an provider based on the model"""
7075

@@ -268,7 +273,8 @@ async def openai_chat_completion(
268273

269274
# Store the response with the ID that will be returned to the client
270275
if self.store:
271-
asyncio.create_task(self.store.store_chat_completion(response, params.messages))
276+
task = asyncio.create_task(self.store.store_chat_completion(response, params.messages))
277+
task.add_done_callback(_log_background_task_error)
272278

273279
return response
274280

@@ -555,4 +561,5 @@ async def stream_tokens_and_compute_metrics_openai_chat(
555561
object="chat.completion",
556562
)
557563
logger.debug("InferenceRouter.completion_response", final_response=final_response)
558-
asyncio.create_task(self.store.store_chat_completion(final_response, messages))
564+
task = asyncio.create_task(self.store.store_chat_completion(final_response, messages))
565+
task.add_done_callback(_log_background_task_error)

src/ogx/core/routers/vector_io.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,7 @@ def _get_provider_id(self, vector_store_id: str) -> str:
103103
return "unknown"
104104
return obj.provider_id
105105
except Exception:
106-
logger.warning(
107-
"Could not resolve provider for vector store", vector_store_id=vector_store_id, exc_info=True
108-
)
106+
logger.exception("Could not resolve provider for vector store", vector_store_id=vector_store_id)
109107
return "unknown"
110108

111109
async def _rewrite_query_for_search(self, query: str) -> str:

src/ogx/core/server/auth_providers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,12 @@ async def introspect_token(self, token: str, scope: Scope | None = None) -> User
246246

247247
if self.config.introspection.send_secret_in_body:
248248
form["client_id"] = self.config.introspection.client_id
249-
form["client_secret"] = self.config.introspection.client_secret
249+
form["client_secret"] = self.config.introspection.client_secret.get_secret_value()
250250
else:
251251
# httpx auth parameter expects tuple[str | bytes, str | bytes]
252252
post_kwargs["auth"] = (
253253
self.config.introspection.client_id,
254-
self.config.introspection.client_secret,
254+
self.config.introspection.client_secret.get_secret_value(),
255255
)
256256

257257
try:

src/ogx/core/storage/kvstore/redis/redis.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ async def get(self, key: str) -> str | None:
4646
value = await client.get(key)
4747
if value is None:
4848
return None
49-
await client.ttl(key)
5049
if isinstance(value, bytes):
5150
return value.decode("utf-8")
5251
if isinstance(value, str):

0 commit comments

Comments
 (0)