Commit Graph

1511 Commits

Author SHA1 Message Date
Mason Daugherty
557eddfd51 refactor(core): add warning for fallback GPT-2 tokenizer usage (#34621) 2026-01-06 19:11:10 -05:00
Mason Daugherty
8aeff95341 fix(core,langchain): use get_buffer_string for message summarization (#34607)
Fixes #34517

Supersedes #34557, #34570

Fixes token inflation in `SummarizationMiddleware` that caused context
window overflow during summarization.

**Root cause:** When formatting messages for the summary prompt,
`str(messages)` was implicitly called, which includes all Pydantic
metadata fields (`usage_metadata`, `response_metadata`,
`additional_kwargs`, etc.). This caused the stringified representation
to use ~2.5x more tokens than `count_tokens_approximately` estimates.

**Problem:**
- Summarization triggers at 85% of context window based on
`count_tokens_approximately`
- But `str(messages)` in the prompt uses 2.5x more tokens
- Results in `ContextLengthExceeded`

**Fix:** Use `get_buffer_string()` to format messages, which produces
compact output:

```
Human: What's the weather?
AI: Let me check...[tool_calls]
Tool: 72°F and sunny
```

Instead of verbose Pydantic repr:

```python
[HumanMessage(content='What's the weather?', additional_kwargs={}, response_metadata={}), ...]
```
2026-01-06 19:05:03 -05:00
ゆり
be2c7f1aa8 test(core): add tests for formatting utils and merge functions (#34511)
## Summary
Add comprehensive test coverage for previously untested utilities in
`langchain-core`.

## Changes

### New file: `test_formatting.py` (18 tests)

Tests for `StrictFormatter` class:
- `test_vformat_with_keyword_args` - basic functionality
- `test_vformat_with_multiple_keyword_args` - multiple placeholders
- `test_vformat_with_empty_string` - edge case
- `test_vformat_with_no_placeholders` - literal strings
- `test_vformat_raises_on_positional_args` - error handling
- `test_vformat_raises_on_multiple_positional_args` - error handling
- `test_vformat_with_special_characters` - newlines, tabs
- `test_vformat_with_unicode` - emoji, CJK characters
- `test_vformat_with_format_spec` - format specifications
- `test_vformat_with_nested_braces` - escaped braces

Tests for `validate_input_variables`:
- `test_validate_input_variables_success` - valid input
- `test_validate_input_variables_with_extra_variables` - extra vars
allowed
- `test_validate_input_variables_with_missing_variable` - KeyError
- `test_validate_input_variables_empty_format` - edge case
- `test_validate_input_variables_no_placeholders` - edge case

Tests for `formatter` singleton:
- `test_formatter_is_strict_formatter` - type check
- `test_formatter_format_works` - functionality
- `test_formatter_rejects_positional_args` - error handling

### Extended `test_utils.py` (14 new tests)

Tests for `merge_lists`:
- Parametrized tests covering None handling, simple merge, empty lists,
index-based merging
- `test_merge_lists_multiple_others` - merging 3+ lists
- `test_merge_lists_all_none` - all None inputs

Tests for `merge_obj`:
- Parametrized tests for None, strings, dicts, lists, equal values
- `test_merge_obj_type_mismatch` - TypeError on type mismatch
- `test_merge_obj_unmergeable_values` - ValueError on different values
- `test_merge_obj_tuple_raises` - ValueError for tuples

## Test plan
- [x] Tests follow existing patterns in the codebase
- [x] All tests are unit tests (no network calls)
- [x] Tests cover happy paths and error conditions
- [x] Tests verify no mutation of input data

## AI Disclosure
This contribution was developed with AI assistance (Claude Code).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: yurekami <yurekami@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2026-01-05 14:20:11 -05:00
aroun-coumar
730a3676f8 fix(core): strip message IDs from cache keys using model_copy (#33915)
**Description:**  

*Closes
#[33883](https://github.com/langchain-ai/langchain/issues/33883)*

Chat model cache keys are generated by serializing messages via
`dumps(messages)`. The optional `BaseMessage.id` field (a UUID used
solely for tracing/threading) is included in this serialization, causing
functionally identical messages to produce different cache keys. This
results in repeated API calls, cache bloat, and degraded performance in
production workloads (e.g., agents, RAG chains, long conversations).

This change normalizes messages **only for cache key generation** by
stripping the nonsemantic `id` field using Pydantic V2’s
`model_copy(update={"id": None})`. The normalization is applied in both
synchronous and asynchronous cache paths (`_generate_with_cache` /
`_agenerate_with_cache`) immediately before `dumps()`.

```python
normalized_messages = [
    msg.model_copy(update={"id": None})
    if getattr(msg, "id", None) is not None
    else msg
    for msg in messages
]
prompt = dumps(normalized_messages)

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
2026-01-05 10:37:10 -05:00
Mohan Kumar S
13cfdf1676 fix(core): exclude injected args from tool schema (#34582) 2026-01-05 09:59:59 -05:00
Andre Roelofs
c25f3847d0 refactor(core): select chunk_id via ranking and remove extra allocation (#34588) 2026-01-05 09:13:05 -05:00
ccurme
659eab2607 release(core): 1.2.6 (#34586) 2026-01-02 16:20:20 -05:00
Angus Jelinek
458a186540 chore(core): Update LangChainTracer to use Pydantic v2 methods (#34541) 2026-01-02 16:02:13 -05:00
weiii668
5517ef37fb docs(core): add docstrings to internal helper functions (#34525)
Co-authored-by: weiii668 <your-email@example.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-12-30 21:58:00 -06:00
Mason Daugherty
2bbe4216e0 docs(core): refresh content.py docstrings (#34546)
minor formatting improvements and increased disambiguation between `id`
and `file_id` for `FileContentBlock` in response to
https://github.com/langchain-ai/langchain-google/pull/1477
2025-12-30 20:44:47 -06:00
Christophe Bornet
e03d6b80d5 chore(deps): bump mypy to v1.19 and ruff to v1.14 (#34521)
* Set mypy to >=1.19.1,<1.20
* Set ruff to >=0.14.10,<0.15
2025-12-29 18:07:55 -06:00
Christophe Bornet
03ae39747b refactor(core): fix some missing generic types (#31658)
See
https://mypy.readthedocs.io/en/stable/config_file.html#confval-disallow_any_generics

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
2025-12-27 16:53:08 -06:00
Christophe Bornet
5ef9f6e036 style(core): add ruff RUF012 rule (#34492)
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-12-27 02:36:28 -06:00
Connor Hyatt
e3939ade5a fix(core): support (message class, template) tuples in ChatPromptTemplate.from_messages (#33989)
### Description

`ChatPromptTemplate.from_messages` supports multiple tuple formats for
defining message templates. One documented format is `(message class,
template)`, which allows users to specify the message type using the
class directly:

```python
ChatPromptTemplate.from_messages([
    (SystemMessage, "You are a helpful assistant named {name}."),
    (HumanMessage, "{input}"),
])
```

However, this syntax was broken. Passing a tuple like `(HumanMessage,
"{input}")` would raise a Pydantic validation error because the
conversion logic in `_convert_to_message_template` didn't handle
`BaseMessage` subclasses—it only recognized string-based role
identifiers like `"human"` or `"system"`.

This PR adds the missing branch to detect when the first element of a
tuple is a message class (by checking for the `type` class attribute)
and routes it through `_create_template_from_message_type`, which
already knows how to create the appropriate `MessagePromptTemplate` for
each message type.

### Changes

- Updated `_convert_to_message_template` to properly support `(message
class, template)` tuples

### Testing

Added 16 comprehensive unit tests covering:

- Basic usage with `HumanMessage`, `AIMessage`, and `SystemMessage`
classes
- Integration with `invoke()` method
- Mixed syntax (message class tuples alongside string tuples)
- Multiple template variables
- Edge cases: empty templates, static text (no variables)
- Correct extraction of `input_variables`
- Partial variables support
- Combination with `MessagesPlaceholder`
- Mustache template format
- Template operations: `append()`, `extend()`, concatenation, and
slicing
- Special characters and unicode in templates

### Issue

Fixes #33791

### Dependencies

None

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-12-27 02:20:33 -06:00
Miguel Athie
b0e4ef3158 test(core): add regression test for list-index $ref resolution (#34097)
This PR adds a regression test covering the JSON Schema `$ref` pattern
found in
MCP-style schemas, where a `$ref` points into a list-based structure
such as:


#/properties/body/anyOf/1/properties/Message/properties/bccRecipients/items

This pattern historically failed due to incorrect handling of numeric
list
components in `_retrieve_ref`. The underlying bug has since been fixed,
and
this test ensures coverage so we don't regress on list-index `$ref`
resolution.

The new test (`test_dereference_refs_list_index_items_ref_mcp_like`)
verifies:

- correct traversal into `anyOf[1]`
- proper dereferencing of `items.$ref`
- no errors thrown
- `ccRecipients.items` is identical to the resolved schema of
`bccRecipients.items`

No code changes are included, just the one test — this PR adds coverage
to preserve the expected
behavior and documents support for this real-world MCP schema pattern.

Related to #32012.

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-12-27 02:18:51 -06:00
gjeltep
ca7790f895 fix(core): fix callback manager merge mixing handlers (#32028) (#33617)
## Description
Fixed `BaseCallbackManager.merge()` method to correctly preserve the
distinction between `handlers` and `inheritable_handlers` during merge
operations.

Previously, the merge method was using `add_handler()` which incorrectly
added handlers to both lists when `inherit=True`, causing
cross-contamination between regular and inheritable handlers.

The fix directly passes the combined handler lists to the constructor
instead of using `add_handler()`, ensuring proper separation is
maintained.

## Issue
Fixes #32028

## Dependencies
None

## Testing
- Modified existing test `test_merge_preserves_handler_distinction()` to
verify handlers remain properly separated after merge

## Checklist
- [x] **Breaking Changes**: No breaking changes - only fixes incorrect
behavior
- [x] **Type Hints**: All functions have complete type annotations
- [x] **Tests**: Fix is fully tested with existing unit test
- [x] **Security**: No security implications
- [x] **Documentation**: No documentation changes needed - bug fix only
- [x] **Code Quality**: Passes lint and format checks
- [x] **Commit Message**: Follows Conventional Commits format

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-12-27 02:01:59 -06:00
Christophe Bornet
d46187201d style: add ruff ISC001 rule (#34493)
ISC001 doesn't conflict anymore with the formatter. See
https://github.com/astral-sh/ruff/issues/8272

Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-12-26 21:39:56 -06:00
Christophe Bornet
a92c032ff6 style(core): fix mypy no-any-return violations (#34204)
* FIxed where possible
* Used `cast` when not possible to fix

---------

Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-12-26 21:35:27 -06:00
Mason Daugherty
78b2d51edc docs(core): image url docstring enhancement (#34488) 2025-12-25 23:10:48 -06:00
Harikrishna KP
294dda8df2 test(core): URL-encode bgColor parameter in mermaid.ink API calls (#34466)
## Problem

The `draw_mermaid_png()` function fails with HTTP 400 when using named
background colors like `white`. This is because named colors get
prefixed with `!` (e.g., `!white`) but this special character is not
URL-encoded before being added to the API URL.

As reported in #34444, the URL parameter `bgColor=!white` causes
mermaid.ink to return a 400 Bad Request error.

## Solution

URL-encode the `background_color` parameter using `urllib.parse.quote()`
before constructing the API URL. This ensures special characters like
`!` are properly encoded as `%21`.

## Changes

- Added `import urllib.parse` 
- URL-encode `background_color` value with
`urllib.parse.quote(str(background_color), safe="")`
- Added 2 unit tests:
- `test_mermaid_bgcolor_url_encoding`: Verifies named colors are
properly encoded
- `test_mermaid_bgcolor_hex_not_encoded`: Verifies hex colors work
correctly

## Testing

```bash
pytest tests/unit_tests/runnables/test_graph.py::test_mermaid_bgcolor_url_encoding -v
pytest tests/unit_tests/runnables/test_graph.py::test_mermaid_bgcolor_hex_not_encoded -v
```

Both tests pass.

Fixes #34444

---
*This contribution was made with AI assistance (Claude).*

Co-authored-by: Mr-Neutr0n <mrneutron@users.noreply.github.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-12-25 21:41:46 -06:00
Christophe Bornet
2212137931 style(core): fix some noqa: ARG rules (#34437) 2025-12-25 21:31:02 -06:00
Nhan Nguyen
e99ccbc126 fix(core): URL-encode bgColor in mermaid API calls (#34461)
URL-encode the bgColor parameter to fix 400 errors from mermaid.ink API.

The `!` character in `!white` was not encoded, causing API failures.

Fixes #34444
2025-12-25 21:30:09 -06:00
Rudra Tiwari
75e237643a perf(core): move origin type map to module level in function_calling.py (#34481)
Moves `_ORIGIN_MAP` dict from inside `_py_38_safe_origin()` to module
level constant. This avoids dict allocation on every function call,
reducing garbage collection pressure during frequent tool conversions.

The function is called during typed dict to pydantic model conversion
which happens during tool binding and invocation - a hot path in
LangChain.

**Testing:** `make lint` passes

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
2025-12-25 21:29:31 -06:00
Christophe Bornet
1f403cf612 style(core): add ruff rules TC (#34476)
* Fixed a few TC
* Added a few Pydantic classes to
`flake8-type-checking.runtime-evaluated-base-classes` (not as much as I
would have imagined)
* Added a few `noqa: TC`
* Activated TC rules
2025-12-25 21:23:31 -06:00
Rudra Tiwari
451e8496e7 perf(core): precompile hex color regex pattern at module level (#34480)
Moves hex color validation regex from inside
`_render_mermaid_using_api()` to module-level constant
`_HEX_COLOR_PATTERN`. This avoids recompiling the regex on every
function call, improving performance when rendering multiple Mermaid
graphs.


**Testing:**
- `make lint` passes
- `make test` passes

---------

Co-authored-by: Mason Daugherty <github@mdrxy.com>
2025-12-25 21:22:08 -06:00
Mason Daugherty
75b07b3d4e docs(core): update to indicate betas (#34457) 2025-12-22 17:54:37 -06:00
Mason Daugherty
2e0bed6a21 release(core): 1.2.5 (#34456) 2025-12-22 17:37:44 -06:00
ccurme
5ec0fa69de fix(core): serialization patch (#34455)
- `allowed_objects` kwarg in `load`
- escape lc-ser formatted dicts on `dump`
- fix for jinja2

---------

Co-authored-by: Mason Daugherty <github@mdrxy.com>
2025-12-22 17:33:31 -06:00
Christophe Bornet
d3e9c4d29d fix(core): RunnablePick method return types (#34208)
Following https://github.com/langchain-ai/langchain/pull/31321, the
`Output` type of `RunnablePick` is `Any`.
2025-12-19 23:47:46 -06:00
rari404
1cc4dc7cc9 fix(core): preserve Field(description=...) in @tool decorator (#34354)
## Summary

Fixes #34247

When using `Annotated[type, Field(description="...")]` syntax with the
`@tool` decorator, field descriptions were being lost during schema
generation. The `_get_annotation_description()` function only checked
for string annotations but not for Pydantic `FieldInfo` objects.

## Changes

- Extended `_get_annotation_description()` to also extract descriptions
from `FieldInfo` objects within `Annotated` types
- Added import for `pydantic.fields.FieldInfo`
- Added unit test to verify `Field(description=...)` is preserved

## Why this approach

The fix is minimal and targeted - it extends the existing description
extraction logic rather than restructuring the schema generation. This
maintains backward compatibility while supporting both annotation
styles:

```python
# Both now work correctly:
topic: Annotated[str, "The research topic"]           # existing
topic: Annotated[str, Field(description="...")]       # now fixed
```

## Known limitation

This fix only handles `pydantic.fields.FieldInfo` (Pydantic v2). The v1
compatibility layer (`pydantic.v1.fields.FieldInfo`) is a different
class and will not have descriptions extracted. This is intentional:

- Pydantic v1 is deprecated; users should migrate to v2
- The v1 compat layer exists for legacy model migration, not new tool
definitions
- Duck-typing on `description` attribute could match unintended objects

If v1 `Field` support is needed, it can be addressed in a follow-up PR
with explicit handling.

## Testing

- Added `test_tool_field_description_preserved()` covering required and
optional params
- Verified existing `test_tool_annotated_descriptions` still passes
- Lint and type checks pass

---

> [!NOTE]
> This PR was developed with AI agent assistance (Factory/Droid).

---------

Co-authored-by: Mason Daugherty <github@mdrxy.com>
2025-12-19 23:14:23 -06:00
Nhan Nguyen
398c067f30 fix(core): populate default args from tool's args_schema (#34399)
## Summary
- Fixes issue where Pydantic default values from `args_schema` were not
passed to tool functions when the caller omits optional arguments
- Modified `_parse_input()` in `libs/core/langchain_core/tools/base.py`
to include fields with non-None defaults
- Added unit tests to verify default args behavior for both sync and
async tools

## Problem
When a tool has an `args_schema` with default values:
```python
class SearchArgs(BaseModel):
    query: str = Field(..., description="Search query")
    page: int = Field(default=1, description="Page number")
    size: int = Field(default=10, description="Results per page")

@tool("search", args_schema=SearchArgs)
def search_tool(query: str, page: int, size: int) -> str:
    return f"query={query}, page={page}, size={size}"

# This threw: TypeError: search_tool() missing 2 required positional arguments
search_tool.invoke({"query": "test"})
```

The defaults from `args_schema` were being discarded because
`_parse_input()` filtered validated results to only include keys from
the original input.

## Solution
Changed the filtering logic to:
1. Include all fields that were in the original input (validated)
2. Also include fields with non-None defaults from the Pydantic schema

This applies user-defined defaults (like `Field(default=1)`) while
excluding synthetic fields from `*args`/`**kwargs` which have
`default=None`.

## Test plan
- [x] Added `test_tool_args_schema_default_values` - tests sync tool
with defaults
- [x] Added `test_tool_args_schema_default_values_async` - tests async
tool with defaults
- [x] All existing tests pass (150 passed, 4 skipped)
- [x] Lint passes

Fixes #34384

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
2025-12-19 23:14:13 -06:00
rari404
d84eef667a fix(core): use tool_calls instead of deprecated function_call in get_buffer_string (#34355)
## Summary

Fixes #33970

`get_buffer_string` was only checking for the deprecated `function_call`
field in `additional_kwargs`, which modern LLM providers no longer
return. This fix updates the function to check for the modern
`tool_calls` field first, falling back to `function_call` for legacy
compatibility.

## Changes

- Check `AIMessage.tool_calls` first (modern standard)
- Fall back to `additional_kwargs["function_call"]` (legacy support)
- Added 3 unit tests covering tool_calls, empty content, and precedence
behavior

## Testing

```python
# Before fix: tool_calls info was lost
msg = AIMessage(content="Hi", tool_calls=[{"name": "search", ...}])
get_buffer_string([msg])  # "AI: Hi" (no tool info)

# After fix: tool_calls are included
get_buffer_string([msg])  # "AI: Hi[{\"name\": \"search\", ...}]"
```

- All existing `get_buffer_string` tests pass
- Legacy `function_call` behavior preserved

---

> [!NOTE]
> This PR was developed with AI agent assistance (Factory/Droid).

---------

Co-authored-by: Mason Daugherty <github@mdrxy.com>
2025-12-19 22:37:56 -06:00
Mason Daugherty
85c401f648 feat(core): add PEP 702 __deprecated__ attribute support to @deprecated (#34257)
Adds [PEP 702](https://peps.python.org/pep-0702/) `__deprecated__`
attribute support to the `@deprecated` decorator, enabling IDE and type
checker integration for deprecation warnings.

---

PEP 702 introduced the `__deprecated__` attribute convention, which type
checkers (Pyright, mypy) and IDEs (VS Code with Pylance, PyCharm) can
use to surface deprecations directly in the editor. This PR sets
`__deprecated__` on all objects decorated with `@deprecated`.

With this change, developers using supported IDEs will see:

- **Strikethrough text** on deprecated symbols
- **Hover messages** showing the deprecation reason and suggested
alternative
- **Diagnostic warnings** during type checking (e.g., `pyright`, `mypy`)

### References

- [PEP 702 – Marking deprecations using the type
system](https://peps.python.org/pep-0702/)
- [`typing.deprecated`
specification](https://typing.python.org/en/latest/spec/directives.html#deprecated)
2025-12-19 21:07:37 -06:00
Mason Daugherty
04ec6cacaf fix(core): ensure tool_call_count is never null (#34431)
add truthiness check to guard against `None`
2025-12-19 21:04:01 -06:00
Mason Daugherty
ed9bd6e3ad feat(core): automatically count and store meta for tool call count (#33756)
Adds automatic tool call counting to tracing by means of a new
`store_tool_call_count_in_run()`, which calls on newly added
`count_tool_calls_in_run()`.

Runs on successful LLM completion. Does not run on errored runs.
2025-12-19 20:41:57 -06:00
James
4fbeffcfee feat(core): add 'approximate' alias in place of count_tokens_approximately (#33045)
### Description: 
earlier we have to use like below:
```python
from langchain_core.messages import trim_messages
from langchain_core.messages.utils import count_tokens_approximately

trim_messages(..., token_counter=count_tokens_approximately)
```
Now can be used as like this also
```python
from langchain_core.messages import trim_messages

trim_messages(..., token_counter="approximate")
```
- [x] **Added tests**
- [x] **Lint and test**: Run this as I made change in langchain/core, uv
run --group test pytest tests/unit_tests/messages/test_utils.py -v
<img width="1006" height="66" alt="image"
src="https://github.com/user-attachments/assets/c6938c29-a781-4e7f-871b-8e888ee764b7"
/>

---------

Co-authored-by: Mason Daugherty <mason@langchain.dev>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
2025-12-19 19:25:29 -06:00
Christophe Bornet
72f1d79022 chore(core): fix some ruff preview rules (#34425)
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-12-19 14:33:42 -06:00
Mason Daugherty
10087ac024 release(core): 1.2.4 (#34429) 2025-12-19 13:05:17 -06:00
Hunter Lovell
7902fa3238 feat(core): add usage_metadata to metadata in LangChainTracer (#34414)
Adds `usage_metadata` (token counts, etc.) to the run metadata in
`LangChainTracer`.

When an LLM run ends, usage metadata is extracted from all generations
and aggregated using the existing `add_usage` helper, then stored in
`run.extra["metadata"]["usage_metadata"]`.

The original data in outputs remains unchanged.

Also, see #34415

---------

Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
2025-12-19 12:59:52 -06:00
Hunter Lovell
9225bff326 fix(core): defer persisting traces for iterator inputs (#34416)
ref https://github.com/langchain-ai/langchainjs/pull/9665

Fixes trace persistence for iterator/generator inputs (like
`RunnableGenerator`) where the full input isn't available at chain
start. Instead of POSTing a run with incomplete inputs on start and
PATCHing later, this defers the POST until chain end when inputs are
fully realized.

---------

Co-authored-by: Mason Daugherty <github@mdrxy.com>
2025-12-19 12:45:22 -06:00
Christophe Bornet
8bca31f8c4 chore(core): fix some docstrings (#34426) 2025-12-19 13:08:10 -05:00
ccurme
795e746ca7 release(core): 1.2.3 (#34421) 2025-12-18 15:06:32 -05:00
ccurme
6519a5675b fix(core): allow unknown blocks in convert_to_openai_messages (#34420) 2025-12-18 14:22:53 -05:00
Mason Daugherty
71778cb721 feat(infra): add CI check for out of date lockfiles (#34397) 2025-12-16 22:23:25 -05:00
Mason Daugherty
c1f66611fc chore(core): bump lockfile (#34392) 2025-12-16 14:21:11 -05:00
Mason Daugherty
f93bc48915 release(core): 1.2.2 (#34391) 2025-12-16 14:17:47 -05:00
Mason Daugherty
516d74b6df fix(core): use get_type_hints for Python 3.14 TypedDict compatibility (#34390)
Replace direct `__annotations__` access with `get_type_hints()` in
`_convert_any_typed_dicts_to_pydantic` to handle [PEP
649](https://peps.python.org/pep-0649/) deferred annotations in Python
3.14:

> [`Changed in version 3.14: Annotations are now lazily evaluated by
default`](https://docs.python.org/3/reference/compound_stmts.html#annotations)

Before:

```python
class MyTool(TypedDict):
    name: str

MyTool.__annotations__  # {'name': 'str'} - string, not type
issubclass('str', ...)  # TypeError: arg 1 must be a class
```

After:

```python
get_type_hints(MyTool)  # {'name': <class 'str'>} - actual type
```

Fixes #34291
2025-12-16 14:08:01 -05:00
ccurme
6cff82d02e release(core): 1.2.1 (#34370) 2025-12-15 09:28:46 -05:00
rari404
15cc090e52 fix(core): handle None arguments in parse_tool_call (#34242) 2025-12-12 13:57:34 -05:00
Christophe Bornet
914730cf8d chore(core): fix some types related to ToolCallChunk (#34283) 2025-12-12 13:15:57 -05:00