Skip to content

Commit 58ab2bc

Browse files
authored
chore: bump v0.16.1 (#3107)
2 parents 6f48d4b + 5646be7 commit 58ab2bc

File tree

87 files changed

+1067
-787
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+1067
-787
lines changed

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ RUN set -eux; \
5757
esac; \
5858
apt-get update && \
5959
# Install curl, Python, and PostgreSQL client libraries
60-
apt-get install -y curl python3 python3-venv libpq-dev && \
60+
apt-get install -y curl python3 python3-venv libpq-dev redis-server && \
6161
# Install Node.js
6262
curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - && \
6363
apt-get install -y nodejs && \
@@ -95,7 +95,7 @@ COPY --from=builder /app .
9595
# Copy initialization SQL if it exists
9696
COPY init.sql /docker-entrypoint-initdb.d/
9797

98-
EXPOSE 8283 5432 4317 4318
98+
EXPOSE 8283 5432 6379 4317 4318
9999

100100
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
101101
CMD ["./letta/server/startup.sh"]
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""add project constraint on tools
2+
3+
Revision ID: 39577145c45d
4+
Revises: d0880aae6cee
5+
Create Date: 2025-12-17 15:46:06.184858
6+
7+
"""
8+
9+
from typing import Sequence, Union
10+
11+
import sqlalchemy as sa
12+
13+
from alembic import op
14+
15+
# revision identifiers, used by Alembic.
16+
revision: str = "39577145c45d"
17+
down_revision: Union[str, None] = "d0880aae6cee"
18+
branch_labels: Union[str, Sequence[str], None] = None
19+
depends_on: Union[str, Sequence[str], None] = None
20+
21+
22+
def upgrade() -> None:
23+
# ### commands auto generated by Alembic - please adjust! ###
24+
op.create_unique_constraint(
25+
"uix_organization_project_name", "tools", ["organization_id", "project_id", "name"], postgresql_nulls_not_distinct=True
26+
)
27+
# ### end Alembic commands ###
28+
29+
30+
def downgrade() -> None:
31+
# ### commands auto generated by Alembic - please adjust! ###
32+
op.drop_constraint("uix_organization_project_name", "tools", type_="unique")
33+
# ### end Alembic commands ###

fern/openapi.json

Lines changed: 119 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19638,6 +19638,97 @@
1963819638
}
1963919639
}
1964019640
},
19641+
"/v1/metadata/balance": {
19642+
"get": {
19643+
"description": "Retrieve the current usage balances for the organization.",
19644+
"summary": "Retrieve current organization balance",
19645+
"tags": ["metadata"],
19646+
"parameters": [],
19647+
"operationId": "metadata.retrieveCurrentBalances",
19648+
"responses": {
19649+
"200": {
19650+
"description": "200",
19651+
"content": {
19652+
"application/json": {
19653+
"schema": {
19654+
"type": "object",
19655+
"properties": {
19656+
"total_balance": {
19657+
"type": "number"
19658+
},
19659+
"monthly_credit_balance": {
19660+
"type": "number"
19661+
},
19662+
"purchased_credit_balance": {
19663+
"type": "number"
19664+
},
19665+
"billing_tier": {
19666+
"type": "string"
19667+
}
19668+
},
19669+
"required": [
19670+
"total_balance",
19671+
"monthly_credit_balance",
19672+
"purchased_credit_balance",
19673+
"billing_tier"
19674+
]
19675+
}
19676+
}
19677+
}
19678+
}
19679+
}
19680+
}
19681+
},
19682+
"/v1/metadata/feedback": {
19683+
"post": {
19684+
"description": "Send feedback from users to improve our services.",
19685+
"summary": "Send user feedback",
19686+
"tags": ["metadata"],
19687+
"parameters": [],
19688+
"operationId": "metadata.sendFeedback",
19689+
"requestBody": {
19690+
"description": "Body",
19691+
"content": {
19692+
"application/json": {
19693+
"schema": {
19694+
"type": "object",
19695+
"properties": {
19696+
"message": {
19697+
"type": "string",
19698+
"minLength": 1,
19699+
"maxLength": 10000
19700+
},
19701+
"feature": {
19702+
"default": "letta-code",
19703+
"type": "string",
19704+
"enum": ["letta-code", "sdk"]
19705+
}
19706+
},
19707+
"required": ["message"]
19708+
}
19709+
}
19710+
}
19711+
},
19712+
"responses": {
19713+
"200": {
19714+
"description": "200",
19715+
"content": {
19716+
"application/json": {
19717+
"schema": {
19718+
"type": "object",
19719+
"properties": {
19720+
"success": {
19721+
"type": "boolean"
19722+
}
19723+
},
19724+
"required": ["success"]
19725+
}
19726+
}
19727+
}
19728+
}
19729+
}
19730+
}
19731+
},
1964119732
"/v1/scheduled-messages/{scheduled_message_id}": {
1964219733
"delete": {
1964319734
"description": "Delete a scheduled message by its ID for a specific agent.",
@@ -21952,6 +22043,11 @@
2195222043
"title": "Content",
2195322044
"description": "The message content sent by the assistant (can be a string or an array of content parts)"
2195422045
},
22046+
"message_id": {
22047+
"type": "string",
22048+
"title": "Message Id",
22049+
"description": "The unique identifier of the message."
22050+
},
2195522051
"agent_id": {
2195622052
"anyOf": [
2195722053
{
@@ -21972,9 +22068,9 @@
2197222068
}
2197322069
},
2197422070
"type": "object",
21975-
"required": ["content", "created_at"],
22071+
"required": ["content", "message_id", "created_at"],
2197622072
"title": "AssistantMessageListResult",
21977-
"description": "Assistant message list result with agent context.\n\nShape is identical to UpdateAssistantMessage but includes the owning agent_id."
22073+
"description": "Assistant message list result with agent context.\n\nShape is identical to UpdateAssistantMessage but includes the owning agent_id and message id."
2197822074
},
2197922075
"Audio": {
2198022076
"properties": {
@@ -34376,6 +34472,11 @@
3437634472
"title": "Message Type",
3437734473
"default": "reasoning_message"
3437834474
},
34475+
"message_id": {
34476+
"type": "string",
34477+
"title": "Message Id",
34478+
"description": "The unique identifier of the message."
34479+
},
3437934480
"agent_id": {
3438034481
"anyOf": [
3438134482
{
@@ -34396,9 +34497,9 @@
3439634497
}
3439734498
},
3439834499
"type": "object",
34399-
"required": ["reasoning", "created_at"],
34500+
"required": ["reasoning", "message_id", "created_at"],
3440034501
"title": "ReasoningMessageListResult",
34401-
"description": "Reasoning message list result with agent context.\n\nShape is identical to UpdateReasoningMessage but includes the owning agent_id."
34502+
"description": "Reasoning message list result with agent context.\n\nShape is identical to UpdateReasoningMessage but includes the owning agent_id and message id."
3440234503
},
3440334504
"RedactedReasoningContent": {
3440434505
"properties": {
@@ -36870,6 +36971,11 @@
3687036971
"title": "Content",
3687136972
"description": "The message content sent by the system (can be a string or an array of multi-modal content parts)"
3687236973
},
36974+
"message_id": {
36975+
"type": "string",
36976+
"title": "Message Id",
36977+
"description": "The unique identifier of the message."
36978+
},
3687336979
"agent_id": {
3687436980
"anyOf": [
3687536981
{
@@ -36890,9 +36996,9 @@
3689036996
}
3689136997
},
3689236998
"type": "object",
36893-
"required": ["content", "created_at"],
36999+
"required": ["content", "message_id", "created_at"],
3689437000
"title": "SystemMessageListResult",
36895-
"description": "System message list result with agent context.\n\nShape is identical to UpdateSystemMessage but includes the owning agent_id."
37001+
"description": "System message list result with agent context.\n\nShape is identical to UpdateSystemMessage but includes the owning agent_id and message id."
3689637002
},
3689737003
"TagSchema": {
3689837004
"properties": {
@@ -39541,6 +39647,11 @@
3954139647
"title": "Content",
3954239648
"description": "The message content sent by the user (can be a string or an array of multi-modal content parts)"
3954339649
},
39650+
"message_id": {
39651+
"type": "string",
39652+
"title": "Message Id",
39653+
"description": "The unique identifier of the message."
39654+
},
3954439655
"agent_id": {
3954539656
"anyOf": [
3954639657
{
@@ -39561,9 +39672,9 @@
3956139672
}
3956239673
},
3956339674
"type": "object",
39564-
"required": ["content", "created_at"],
39675+
"required": ["content", "message_id", "created_at"],
3956539676
"title": "UserMessageListResult",
39566-
"description": "User message list result with agent context.\n\nShape is identical to UpdateUserMessage but includes the owning agent_id."
39677+
"description": "User message list result with agent context.\n\nShape is identical to UpdateUserMessage but includes the owning agent_id and message id."
3956739678
},
3956839679
"UserUpdate": {
3956939680
"properties": {

letta/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
__version__ = version("letta")
66
except PackageNotFoundError:
77
# Fallback for development installations
8-
__version__ = "0.16.0"
8+
__version__ = "0.16.1"
99

1010
if os.environ.get("LETTA_VERSION"):
1111
__version__ = os.environ["LETTA_VERSION"]

letta/agents/helpers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ def validate_approval_tool_call_ids(approval_request_message: Message, approval_
109109
)
110110

111111
approval_responses = approval_response_message.approvals
112+
if not approval_responses:
113+
raise ValueError("Invalid approval response. Approval response message does not contain any approvals.")
112114
approval_response_tool_call_ids = [approval_response.tool_call_id for approval_response in approval_responses]
113115

114116
request_response_diff = set(approval_request_tool_call_ids).symmetric_difference(set(approval_response_tool_call_ids))

letta/agents/letta_agent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,8 +1902,8 @@ async def _execute_tool(
19021902
start_time = get_utc_timestamp_ns()
19031903
agent_step_span.add_event(name="tool_execution_started")
19041904

1905-
# Decrypt environment variable values
1906-
sandbox_env_vars = {var.key: var.value_enc.get_plaintext() if var.value_enc else None for var in agent_state.secrets}
1905+
# Use pre-decrypted environment variable values (populated in from_orm_async)
1906+
sandbox_env_vars = {var.key: var.value or "" for var in agent_state.secrets}
19071907
tool_execution_manager = ToolExecutionManager(
19081908
agent_state=agent_state,
19091909
message_manager=self.message_manager,

letta/agents/letta_agent_v2.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,8 +1184,8 @@ async def _execute_tool(
11841184
start_time = get_utc_timestamp_ns()
11851185
agent_step_span.add_event(name="tool_execution_started")
11861186

1187-
# Decrypt environment variable values
1188-
sandbox_env_vars = {var.key: var.value_enc.get_plaintext() if var.value_enc else None for var in agent_state.secrets}
1187+
# Use pre-decrypted environment variable values (populated in from_orm_async)
1188+
sandbox_env_vars = {var.key: var.value or "" for var in agent_state.secrets}
11891189
tool_execution_manager = ToolExecutionManager(
11901190
agent_state=agent_state,
11911191
message_manager=self.message_manager,

letta/agents/letta_agent_v3.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,9 @@ async def stream(
368368
# Cleanup and finalize (only runs if no exception occurred)
369369
try:
370370
if run_id:
371-
result = LettaResponse(messages=response_letta_messages, stop_reason=self.stop_reason, usage=self.usage)
371+
# Filter out LettaStopReason from messages (only valid in LettaStreamingResponse, not LettaResponse)
372+
filtered_messages = [m for m in response_letta_messages if not isinstance(m, LettaStopReason)]
373+
result = LettaResponse(messages=filtered_messages, stop_reason=self.stop_reason, usage=self.usage)
372374
if self.job_update_metadata is None:
373375
self.job_update_metadata = {}
374376
self.job_update_metadata["result"] = result.model_dump(mode="json")

letta/agents/voice_agent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,8 @@ async def _execute_tool(self, user_query: str, tool_name: str, tool_args: dict,
438438
)
439439

440440
# Use ToolExecutionManager for modern tool execution
441-
# Decrypt environment variable values
442-
sandbox_env_vars = {var.key: var.value_enc.get_plaintext() if var.value_enc else None for var in agent_state.secrets}
441+
# Use pre-decrypted environment variable values (populated in from_orm_async)
442+
sandbox_env_vars = {var.key: var.value or "" for var in agent_state.secrets}
443443
tool_execution_manager = ToolExecutionManager(
444444
agent_state=agent_state,
445445
message_manager=self.message_manager,

letta/constants.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,14 @@ def FUNCTION_RETURN_VALUE_TRUNCATED(return_str, return_char: int, return_char_li
226226

227227
# Constants to do with summarization / conversation length window
228228
# The max amount of tokens supported by the underlying model (eg 8k for gpt-4 and Mistral 7B)
229-
LLM_MAX_TOKENS = {
229+
LLM_MAX_CONTEXT_WINDOW = {
230230
"DEFAULT": 30000,
231231
# deepseek
232232
"deepseek-chat": 64000,
233233
"deepseek-reasoner": 64000,
234+
# glm (Z.AI)
235+
"glm-4.6": 200000,
236+
"glm-4.5": 128000,
234237
## OpenAI models: https://platform.openai.com/docs/models/overview
235238
# gpt-5
236239
"gpt-5": 272000,
@@ -357,6 +360,9 @@ def FUNCTION_RETURN_VALUE_TRUNCATED(return_str, return_char: int, return_char_li
357360
"gemini-2.5-flash-preview-09-2025": 1048576,
358361
"gemini-2.5-flash-lite-preview-09-2025": 1048576,
359362
"gemini-2.5-computer-use-preview-10-2025": 1048576,
363+
# gemini 3
364+
"gemini-3-pro-preview": 1048576,
365+
"gemini-3-flash-preview": 1048576,
360366
# gemini latest aliases
361367
"gemini-flash-latest": 1048576,
362368
"gemini-flash-lite-latest": 1048576,

0 commit comments

Comments
 (0)