Commit Graph

6998 Commits

Author SHA1 Message Date
cthomas
ca40eff7bc fix: ensure stop_reason is always set when marking runs as failed (#9045)
**Problem:**
Production error showed runs being marked as failed with stop_reason=None,
which violates LettaStopReason's Pydantic schema (requires valid enum value).
This caused cascading validation errors that got stored in metadata.

Example error:
```
Run is already in a terminal state failed with stop reason None, but is being
updated with data {'status': 'failed', 'stop_reason': None, 'metadata':
{'error': "1 validation error for LettaStopReason\nstop_reason Input should
be 'end_turn', 'error', ... [type=enum, input_value=None]"}}
```

**Root Causes:**
1. routers/v1/agents.py had 3 exception handlers creating RunUpdate(status=failed)
   without stop_reason
2. Success path assumed result.stop_reason always exists (AttributeError if None)
3. run_manager.py tried to create LettaStopReason(stop_reason=None) when
   refreshing result messages

**Fixes:**
1. Added stop_reason=StopReasonType.error to 3 exception handlers
2. Added defensive None checks before accessing result.stop_reason.stop_reason
3. Added fallback to StopReasonType.error when pydantic_run.stop_reason is None

**Trigger:**
OpenAI BadRequestError for invalid tool schema → exception handlers marked
run as failed without stop_reason → validation error when constructing response

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
Ari Webb
5533c723df fix: bedrock third time (#9043) 2026-01-29 12:44:04 -08:00
Ari Webb
e5afbd0972 fix: base url wrong (#9040) 2026-01-29 12:44:04 -08:00
cthomas
57ab117437 feat: dedupe approval response retries on server (#9038) 2026-01-29 12:44:04 -08:00
Sarah Wooders
25e9539a6e feat: add batch passage create and optional search query (#8866) 2026-01-29 12:44:04 -08:00
github-actions[bot]
179a1df524 feat: add conversation compact endpoint to SDK and add integration tests (#9025) 2026-01-29 12:44:04 -08:00
Shubham Naik
8ced2e0c82 Shub/let 7138 support custom feeds that recieve data via an endpoint [LET-7138] (#9027)
* feat: support custom endpoint

* feat: support custom endpoint

* chore: add webhook

* chore: add webhook

* chore: fix types

* chore: fix types

* chore: docs
2026-01-29 12:44:04 -08:00
cthomas
c162de5127 fix: use shared event + .athrow() to properly set stream_was_cancelle… (#9019)
fix: use shared event + .athrow() to properly set stream_was_cancelled flag

**Problem:**
When a run is cancelled via /cancel endpoint, `stream_was_cancelled` remained
False because `RunCancelledException` was raised in the consumer code (wrapper),
which closes the generator from outside. This causes Python to skip the
generator's except blocks and jump directly to finally with the wrong flag value.

**Solution:**
1. Shared `asyncio.Event` registry for cross-layer cancellation signaling
2. `cancellation_aware_stream_wrapper` sets the event when cancellation detected
3. Wrapper uses `.athrow()` to inject exception INTO generator (not consumer-side raise)
4. All streaming interfaces check event in `finally` block to set flag correctly
5. `streaming_service.py` handles `RunCancelledException` gracefully, yields [DONE]

**Changes:**
- streaming_response.py: Event registry + .athrow() injection + graceful handling
- openai_streaming_interface.py: 3 classes check event in finally
- gemini_streaming_interface.py: Check event in finally
- anthropic_*.py: Catch RunCancelledException
- simple_llm_stream_adapter.py: Create & pass event to interfaces
- streaming_service.py: Handle RunCancelledException, yield [DONE], skip double-update
- routers/v1/{conversations,runs}.py: Pass event to wrapper
- integration_test_human_in_the_loop.py: New test for approval + cancellation

**Tests:**
- test_tool_call with cancellation (OpenAI models) 
- test_approve_with_cancellation (approval flow + concurrent cancel) 

**Known cosmetic warnings (pre-existing):**
- "Run already in terminal state" - agent loop tries to update after /cancel
- "Stream ended without terminal event" - background streaming timing race

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
Ari Webb
5ca0f55079 fix: fix bedrock again (#9021) 2026-01-29 12:44:04 -08:00
Kian Jones
e3fb00f970 feat(crouton): add orgId, userId, Compaction_Settings and LLM_Config (#9022)
* LC one shot?

* api changes

* fix summarizer nameerror
2026-01-29 12:44:04 -08:00
Kian Jones
194fa7d1c6 fix: anthropic message packing bugs (#9017)
* fix: anthroppic message packing bugs - traling whitespace and final assistant message missing thinking

* revert bug Caren will fix upstream?
2026-01-29 12:44:04 -08:00
Ari Webb
5c06918042 fix: don't need embedding model for self hosted [LET-7009] (#8935)
* fix: don't need embedding model for self hosted

* stage publish api

* passes tests

* add test

* remove unnecessary upgrades

* update revision order db migrations

* add timeout for ci
2026-01-29 12:44:04 -08:00
Shubham Naik
16e3f10a56 Shub/let 7147 improved channel selector [LET-7147] (#9002)
* feat; improve selector

* chore: next

* chore: next

* wah

* wah

* wah

* chore: next

* chore: fix

* chore: noverify

* chroe; imporve selctor

* chore: update api
2026-01-29 12:44:04 -08:00
Shubham Naik
6d453ea586 feat: fix template creation bogs [LET-7165] (#9015)
feat: fix template creation bogs
2026-01-29 12:44:02 -08:00
Kian Jones
2bb4caffc3 fix: remove unused embedding generation (#9013)
* remove unused embedding generation

* prevent double embed

* fix embedding dimension comparison and valueerror
2026-01-29 12:43:53 -08:00
Shubham Naik
dbc4f88701 chore: add better error logging (#8981) 2026-01-29 12:43:53 -08:00
Shelley Pham
4353df683e Shelley/let 7155 favorites tagged should be user scoped [LET-7155] (#9003)
* make favorite tag a const

* add favorite:user:{userId} for favorites

* favorite agent upon initial creation

* rename const

* add eslint ignore

* expect favorite tag
2026-01-29 12:43:53 -08:00
Ari Webb
b5e93ab6d1 fix: bedrock config state (#9005) 2026-01-29 12:43:53 -08:00
Kian Jones
273ca9ec44 feat(tests): add crouton telemetry tests (#9000)
* test: add comprehensive provider trace telemetry tests

Add two test files for provider trace telemetry:

1. test_provider_trace.py - Integration tests for:
   - Basic agent steps (streaming and non-streaming)
   - Tool calls
   - Telemetry context fields (agent_id, agent_tags, step_id, run_id)
   - Multi-step conversations
   - Request/response JSON content

2. test_provider_trace_summarization.py - Unit tests for:
   - simple_summary() telemetry context passing
   - summarize_all() telemetry pass-through
   - summarize_via_sliding_window() telemetry pass-through
   - Summarizer class runtime vs constructor telemetry
   - LLMClient.set_telemetry_context() method

🤖 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* test: add telemetry tests for tool generation, adapters, and agent versions

Add comprehensive unit tests for provider trace telemetry:

- TestToolGenerationTelemetry: Verify /generate-tool endpoint sets
  call_type="tool_generation" and has no agent context
- TestLLMClientTelemetryContext: Verify LLMClient.set_telemetry_context
  accepts all telemetry fields
- TestAdapterTelemetryAttributes: Verify base adapter and subclasses
  (LettaLLMRequestAdapter, LettaLLMStreamAdapter) support telemetry attrs
- TestSummarizerTelemetry: Verify Summarizer stores and passes telemetry
- TestAgentAdapterInstantiation: Verify LettaAgentV2 creates Summarizer
  with correct agent_id

🤖 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* ci: add provider trace telemetry tests to unit test workflow

Add the new provider trace test files to the CI matrix:
- test_provider_trace_backends.py
- test_provider_trace_summarization.py
- test_provider_trace_agents.py

🤖 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix: update socket backend test to match new record structure

The socket backend record structure changed - step_id/run_id are now
at top level, and model/usage are nested in request/response objects.

🤖 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix: add step_id to V1 agent telemetry context

Pass step_id to set_telemetry_context in both streaming and non-streaming
paths in LettaAgent (v1). The step_id is available via step_metrics.id
in the non-streaming path and passed explicitly in the streaming path.

🤖 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

---------

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:43:53 -08:00
Ari Webb
5c1512237f fix: restore deleted provider session conflicts (#9001) 2026-01-29 12:43:53 -08:00
Kian Jones
4d256b3399 feat: add agent_id, run_id, step_id to summarization provider traces (#8996)
* feat: add agent_id, run_id, step_id to summarization provider traces

Summarization LLM calls were missing telemetry context (agent_id,
agent_tags, run_id, step_id), making it impossible to attribute
summarization costs to specific agents or trace them back to the
step that triggered compaction.

Changes:
- Add step_id param to simple_summary() and set_telemetry_context()
- Add agent_id, agent_tags, run_id, step_id to summarize_all() and
  summarize_via_sliding_window()
- Update Summarizer class to accept and pass telemetry context
- Update LettaAgentV3.compact() to pass full telemetry context
- Update LettaAgentV2.summarize_conversation_history() with run_id/step_id
- Update LettaAgent (v1) streaming methods with run_id param
- Add run_id/step_id to SummarizeParams for Temporal activities

🤖 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix: update test mock to accept new summarization params

🤖 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

---------

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:43:53 -08:00
Kian Jones
1ab21af725 fix: safer type coersion for tools (#8990)
* mvp

* perfrom type coercion in sandbox

* fix: safely resolve typing annotations on host

Use an AST whitelist for generic annotations to avoid eval while keeping list/dict coercion working.

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

---------

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:43:53 -08:00
Ari Webb
2e826577d9 fix: fix zai and others byok (#8991)
* fix: fix zai and other byok providers

* fix test

* get endpoint from typed provider and add test

* also add base_url on provider create
2026-01-29 12:43:53 -08:00
Kian Jones
7133083b81 fix: agent_tags for provider traces (#8989)
* add include tags

* include agent_tags and pass them into the adapter
2026-01-29 12:43:53 -08:00
Charles Packer
2fc592e0b6 feat(core): add image support in tool returns [LET-7140] (#8985)
* feat(core): add image support in tool returns [LET-7140]

Enable tool_return to support both string and ImageContent content parts,
matching the pattern used for user message inputs. This allows tools
executed client-side to return images back to the agent.

Changes:
- Add LettaToolReturnContentUnion type for text/image content parts
- Update ToolReturn schema to accept Union[str, List[content parts]]
- Update converters for each provider:
  - OpenAI Chat Completions: placeholder text for images
  - OpenAI Responses API: full image support
  - Anthropic: full image support with base64
  - Google: placeholder text for images
- Add resolve_tool_return_images() for URL-to-base64 conversion
- Make create_approval_response_message_from_input() async

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix(core): support images in Google tool returns as sibling parts

Following the gemini-cli pattern: images in tool returns are sent as
sibling inlineData parts alongside the functionResponse, rather than
inside it.

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* test(core): add integration tests for multi-modal tool returns [LET-7140]

Tests verify that:
- Models with image support (Anthropic, OpenAI Responses API) can see
  images in tool returns and identify the secret text
- Models without image support (Chat Completions) get placeholder text
  and cannot see the actual image content
- Tool returns with images persist correctly in the database

Uses secret.png test image containing hidden text "FIREBRAWL" that
models must identify to pass the test.

Also fixes misleading comment about Anthropic only supporting base64
images - they support URLs too, we just pre-resolve for consistency.

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* refactor: simplify tool return image support implementation

Reduce code verbosity while maintaining all functionality:
- Extract _resolve_url_to_base64() helper in message_helper.py (eliminates duplication)
- Add _get_text_from_part() helper for text extraction
- Add _get_base64_image_data() helper for image data extraction
- Add _tool_return_to_google_parts() to simplify Google implementation
- Add _image_dict_to_data_url() for OpenAI Responses format
- Use walrus operator and list comprehensions where appropriate
- Add integration_test_multi_modal_tool_returns.py to CI workflow

Net change: -120 lines while preserving all features and test coverage.

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix(tests): improve prompt for multi-modal tool return tests

Make prompts more direct to reduce LLM flakiness:
- Simplify tool description: "Retrieves a secret image with hidden text. Call this function to get the image."
- Change user prompt from verbose request to direct command: "Call the get_secret_image function now."
- Apply to both test methods

This reduces ambiguity and makes tool calling more reliable across different LLM models.

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix bugs

* test(core): add google_ai/gemini-2.0-flash-exp to multi-modal tests

Add Gemini model to test coverage for multi-modal tool returns. Google AI already supports images in tool returns via sibling inlineData parts.

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix(ui): handle multi-modal tool_return type in frontend components

Convert Union<string, LettaToolReturnContentUnion[]> to string for display:
- ViewRunDetails: Convert array to '[Image here]' placeholder
- ToolCallMessageComponent: Convert array to '[Image here]' placeholder

Fixes TypeScript errors in web, desktop-ui, and docker-ui type-checks.

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

---------

Co-authored-by: Letta <noreply@letta.com>
Co-authored-by: Caren Thomas <carenthomas@gmail.com>
2026-01-29 12:43:53 -08:00
Ari Webb
4ec6649caf feat: byok provider models in db also (#8317)
* feat: byok provider models in db also

* make tests and sync api

* fix inconsistent state with recreating provider of same name

* fix sync on byok creation

* update revision

* move stripe code for testing purposes

* revert

* add refresh byok models endpoint

* just stage publish api

* add tests

* reorder revision

* add test for name clashes
2026-01-29 12:43:53 -08:00
Christina Tong
fa92f711fe add conversation_id to message obj before persisting (#8984) 2026-01-29 12:43:53 -08:00
Kevin Lin
b5519f02fb feat: make tool return messages more explicit [LET-7145] (#8986)
prompt
2026-01-29 12:43:53 -08:00
cthomas
3f8f2e622a fix: filter our reasoning for groq client [LET-7135] (#8982)
fix: filter our reasoning for groq client
2026-01-29 12:43:53 -08:00
Christina Tong
0333ff0614 fix: max tokens and context window size [LET-6481] (#8298)
* fix: max tokens [LET-6481]

* remove print statements

* update

* simplofy fallback

* address comments async

* update other helpers

* update pyproject,.toml

* update pyproject w async lru

* oopen ai internal async methods

* update

* update uv lock
2026-01-29 12:43:53 -08:00
Charles Packer
238894eebd fix(core): disable MCP stdio servers by default (#8969)
* fix(core): disable MCP stdio servers by default

Stdio MCP servers spawn local processes on the host, which is not
suitable for multi-tenant or shared server deployments. This change:

- Changes `mcp_disable_stdio` default from False to True
- Enforces the setting in `get_mcp_client()` and `create_mcp_server_from_config()`
- Users running local/single-user deployments can set MCP_DISABLE_STDIO=false
  to enable stdio-based MCP servers (e.g., for npx/uvx tools)

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* update ci

* push

---------

Co-authored-by: Letta <noreply@letta.com>
Co-authored-by: jnjpng <jin@letta.com>
Co-authored-by: Letta Bot <jinjpeng@gmail.com>
2026-01-29 12:43:53 -08:00
Ari Webb
5645ca8107 fix: use labels for error messages for builtin memory tools [LET-7095] (#8941)
* fix: use labels for error messages for builtin memory tools

* catch specific error
2026-01-29 12:43:53 -08:00
Devansh Jain
dfa6ee0c23 feat: add SGLang support (#8838)
* add sglang support

* add tests

* normalize base url

* cleanup

* chore: regenerate autogenerated API files for sglang support
2026-01-29 12:43:51 -08:00
cthomas
5f58819bbf fix: false positives for token markers (#8942) 2026-01-29 12:43:23 -08:00
Sarah Wooders
7544027cd9 chore: release 0.16.3 (#3158) 2026-01-19 16:01:53 -08:00
Sarah Wooders
2200993b3d chore: remove .letta/skills-hash.json
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 15:59:35 -08:00
Sarah Wooders
21396099d5 chore: bump version to 0.16.3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 15:57:32 -08:00
Ari Webb
7a104a74fe fix: allow conversation_search time only queries [LET-7094] (#8939)
fix: allow conversation_search time only queries
2026-01-19 15:54:44 -08:00
cthomas
b3a213a56f revert: fix: include assistant response in sliding window summarizati… (#8929)
revert: fix: include assistant response in sliding window summarization slice
2026-01-19 15:54:44 -08:00
Ari Webb
9dbf428c1f feat: enable bedrock for anthropic models (#8847)
* feat: enable bedrock for anthropic models

* parallel tool calls in ade

* attempt add to ci

* update tests

* add env vars

* hardcode region

* get it working

* debugging

* add bedrock extra

* default env var [skip ci]

* run ci

* reasoner model update

* secrets

* clean up log

* clean up
2026-01-19 15:54:44 -08:00
cthomas
4be366470b fix: summarizer cutoff bug (#8928)
* fix: summarizer cutoff bug

* update comment with context
2026-01-19 15:54:44 -08:00
github-actions[bot]
90f3ab9184 fix: validate URL scheme in fetch_webpage to reject file:// URLs (#8889)
Adds validation to the fetch_webpage tool to ensure only HTTP/HTTPS URLs
are accepted. Previously, passing a file:// URL would cause an unhandled
requests.exceptions.InvalidSchema error. Now it raises a clear ValueError
with a helpful error message.

Fixes: requests.exceptions.InvalidSchema: No connection adapters were found for 'file://...'

🤖 Generated with [Letta Code](https://letta.com)

Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: datadog-official[bot] <datadog-official[bot]@users.noreply.github.com>
Co-authored-by: Letta <noreply@letta.com>
Co-authored-by: Kian Jones <11655409+kianjones9@users.noreply.github.com>
2026-01-19 15:54:44 -08:00
github-actions[bot]
cb2db18b1f fix: add Claude Haiku 4.5 model to MODEL_LIST and add defensive prefix stripping (#8908)
- Added `claude-haiku-4-5-20251001` and `claude-haiku-4-5-latest` to MODEL_LIST
  in anthropic.py to fix context window lookup for the newly released model
- Added prefix stripping in anthropic_client.py to handle cases where the
  model name incorrectly includes the `anthropic/` provider prefix

Fixes the production error:
anthropic.NotFoundError: Error code: 404 - model: anthropic/claude-haiku-4-5-20251001

Fixes #8907

🤖 Generated with [Letta Code](https://letta.com)

Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: datadog-official[bot] <datadog-official[bot]@users.noreply.github.com>
Co-authored-by: Kian Jones <11655409+kianjones9@users.noreply.github.com>
2026-01-19 15:54:44 -08:00
Kian Jones
2ee28c3264 feat: add telemetry source identifier (#8918)
* add telemetry source

* add source to provider trave
2026-01-19 15:54:44 -08:00
github-actions[bot]
15de765876 fix: downgrade MCP tool error logs from warning to debug (#8846)
Change the log level for expected MCP tool execution failures (ToolError,
McpError) from warning to debug in fastmcp_client.py to match base_client.py.

These errors occur when an LLM calls an MCP tool with missing/invalid
arguments - they are expected user-facing issues from external MCP servers,
not system errors that should trigger production alerts.

Fixes #8845

🤖 Generated with [Letta Code](https://letta.com)

Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: datadog-official[bot] <datadog-official[bot]@users.noreply.github.com>
Co-authored-by: Kian Jones <11655409+kianjones9@users.noreply.github.com>
2026-01-19 15:54:43 -08:00
github-actions[bot]
940d648d42 fix(mcp): handle MCP tool errors gracefully to prevent Datadog alerts (#8687)
MCP tool errors (ToolError, McpError) are expected user-facing errors
from external MCP servers (e.g., "No connected account found"). These
were propagating through @trace_method decorator and being recorded
as errors in Datadog APM.

Changes:
- Add try/except to catch expected MCP errors in ExternalMCPToolExecutor
- Return ToolExecutionResult with status="error" instead of re-raising
- Log expected errors at INFO level instead of letting them trace as ERROR
- Remove stray 'pass' statement that was a no-op

Fixes #8685

🤖 Generated with [Letta Code](https://letta.com)

Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: datadog-official[bot] <datadog-official[bot]@users.noreply.github.com>
Co-authored-by: Kian Jones <11655409+kianjones9@users.noreply.github.com>
2026-01-19 15:54:43 -08:00
Kian Jones
81b5d71889 feat: add agents and log error properly (#8914)
* add agents and log error properly

* fix llm stream adapter
2026-01-19 15:54:43 -08:00
Charles Packer
6472834130 fix(core): add default value for OllamaProvider.default_prompt_formatter (#8911)
When Ollama providers are synced to DB via sync_base_providers(), the
default_prompt_formatter field is lost because ProviderCreate doesn't
include it. When loading from DB and calling cast_to_subtype(), Pydantic
validation fails because the field is required.

This was a latent bug exposed when provider models persistence was
re-enabled in 0.16.2. The field was always required but never persisted.

Adding a default value ("chatml") fixes the issue. The field isn't
actually used in the current implementation - the model_wrapper line
is commented out in list_llm_models_async() since Ollama now uses
OpenAI-compatible endpoints.

Fixes: letta-ai/letta-code#587

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-19 15:54:43 -08:00
Kian Jones
b0dfdd2725 fix commas in justfile helm secret setting and bug with missing metadata (#8874) 2026-01-19 15:54:43 -08:00
Kian Jones
a92e868ee6 feat: centralize telemetry logging at LLM client level (#8815)
* feat: centralize telemetry logging at LLM client level

Moves telemetry logging from individual adapters to LLMClientBase:
- Add TelemetryStreamWrapper for streaming telemetry on stream close
- Add request_async_with_telemetry() for non-streaming requests
- Add stream_async_with_telemetry() for streaming requests
- Add set_telemetry_context() to configure agent_id, run_id, step_id

Updates adapters and agents to use new pattern:
- LettaLLMAdapter now accepts agent_id/run_id in constructor
- Adapters call set_telemetry_context() before LLM requests
- Removes duplicate telemetry logging from adapters
- Enriches traces with agent_id, run_id, call_type metadata

🐙 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix: accumulate streaming response content for telemetry

TelemetryStreamWrapper now extracts actual response data from chunks:
- Content text (concatenated from deltas)
- Tool calls (id, name, arguments)
- Model name, finish reason, usage stats

🐙 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* refactor: move streaming telemetry to caller (option 3)

- Remove TelemetryStreamWrapper class
- Add log_provider_trace_async() helper to LLMClientBase
- stream_async_with_telemetry() now just returns raw stream
- Callers log telemetry after processing with rich interface data

Updated callers:
- summarizer.py: logs content + usage after stream processing
- letta_agent.py: logs tool_call, reasoning, model, usage

🐙 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

* fix: pass agent_id and run_id to parent adapter class

LettaLLMStreamAdapter was not passing agent_id/run_id to parent,
causing "unexpected keyword argument" errors.

🐙 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

---------

Co-authored-by: Letta <noreply@letta.com>
2026-01-19 15:54:43 -08:00