remdb 0.3.181__py3-none-any.whl → 0.3.200__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of remdb might be problematic. Click here for more details.
- rem/agentic/context.py +101 -0
- rem/agentic/context_builder.py +12 -2
- rem/api/main.py +1 -1
- rem/api/mcp_router/server.py +4 -0
- rem/api/mcp_router/tools.py +395 -159
- rem/api/routers/chat/completions.py +51 -9
- rem/api/routers/chat/sse_events.py +2 -2
- rem/api/routers/chat/streaming.py +146 -21
- rem/api/routers/messages.py +96 -23
- rem/auth/middleware.py +42 -28
- rem/cli/README.md +62 -0
- rem/cli/commands/db.py +33 -19
- rem/cli/commands/process.py +171 -43
- rem/services/content/service.py +18 -5
- rem/services/postgres/__init__.py +28 -3
- rem/services/postgres/diff_service.py +57 -5
- rem/services/postgres/programmable_diff_service.py +635 -0
- rem/services/postgres/pydantic_to_sqlalchemy.py +2 -2
- rem/services/postgres/register_type.py +11 -10
- rem/services/session/__init__.py +7 -1
- rem/services/session/pydantic_messages.py +210 -0
- rem/sql/migrations/001_install.sql +115 -7
- rem/sql/migrations/002_install_models.sql +117 -105
- rem/sql/migrations/004_cache_system.sql +7 -275
- rem/utils/schema_loader.py +6 -6
- {remdb-0.3.181.dist-info → remdb-0.3.200.dist-info}/METADATA +1 -1
- {remdb-0.3.181.dist-info → remdb-0.3.200.dist-info}/RECORD +29 -27
- {remdb-0.3.181.dist-info → remdb-0.3.200.dist-info}/WHEEL +0 -0
- {remdb-0.3.181.dist-info → remdb-0.3.200.dist-info}/entry_points.txt +0 -0
rem/agentic/context.py
CHANGED
|
@@ -22,14 +22,81 @@ Key Design Pattern:
|
|
|
22
22
|
- Enables session tracking across API, CLI, and test execution
|
|
23
23
|
- Supports header-based configuration override (model, schema URI)
|
|
24
24
|
- Clean separation: context (who/what) vs agent (how)
|
|
25
|
+
|
|
26
|
+
Multi-Agent Context Propagation:
|
|
27
|
+
- ContextVar (_current_agent_context) threads context through nested agent calls
|
|
28
|
+
- Parent context is automatically available to child agents via get_current_context()
|
|
29
|
+
- Use agent_context_scope() context manager for scoped context setting
|
|
30
|
+
- Child agents inherit user_id, tenant_id, session_id, is_eval from parent
|
|
25
31
|
"""
|
|
26
32
|
|
|
33
|
+
from contextlib import contextmanager
|
|
34
|
+
from contextvars import ContextVar
|
|
35
|
+
from typing import Generator
|
|
36
|
+
|
|
27
37
|
from loguru import logger
|
|
28
38
|
from pydantic import BaseModel, Field
|
|
29
39
|
|
|
30
40
|
from ..settings import settings
|
|
31
41
|
|
|
32
42
|
|
|
43
|
+
# Thread-local context for current agent execution
|
|
44
|
+
# This enables context propagation through nested agent calls (multi-agent)
|
|
45
|
+
_current_agent_context: ContextVar["AgentContext | None"] = ContextVar(
|
|
46
|
+
"current_agent_context", default=None
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_current_context() -> "AgentContext | None":
|
|
51
|
+
"""
|
|
52
|
+
Get the current agent context from context var.
|
|
53
|
+
|
|
54
|
+
Used by MCP tools (like ask_agent) to inherit context from parent agent.
|
|
55
|
+
Returns None if no context is set (e.g., direct CLI invocation without context).
|
|
56
|
+
|
|
57
|
+
Example:
|
|
58
|
+
# In an MCP tool
|
|
59
|
+
parent_context = get_current_context()
|
|
60
|
+
if parent_context:
|
|
61
|
+
# Inherit user_id, session_id, etc. from parent
|
|
62
|
+
child_context = parent_context.child_context(agent_schema_uri="child-agent")
|
|
63
|
+
"""
|
|
64
|
+
return _current_agent_context.get()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def set_current_context(ctx: "AgentContext | None") -> None:
|
|
68
|
+
"""
|
|
69
|
+
Set the current agent context.
|
|
70
|
+
|
|
71
|
+
Called by streaming layer before agent execution.
|
|
72
|
+
Should be cleared (set to None) after execution completes.
|
|
73
|
+
"""
|
|
74
|
+
_current_agent_context.set(ctx)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@contextmanager
|
|
78
|
+
def agent_context_scope(ctx: "AgentContext") -> Generator["AgentContext", None, None]:
|
|
79
|
+
"""
|
|
80
|
+
Context manager for scoped context setting.
|
|
81
|
+
|
|
82
|
+
Automatically restores previous context when exiting scope.
|
|
83
|
+
Safe for nested agent calls - each level preserves its parent's context.
|
|
84
|
+
|
|
85
|
+
Example:
|
|
86
|
+
context = AgentContext(user_id="user-123")
|
|
87
|
+
with agent_context_scope(context):
|
|
88
|
+
# Context is available via get_current_context()
|
|
89
|
+
result = await agent.run(...)
|
|
90
|
+
# Previous context (or None) is restored
|
|
91
|
+
"""
|
|
92
|
+
previous = _current_agent_context.get()
|
|
93
|
+
_current_agent_context.set(ctx)
|
|
94
|
+
try:
|
|
95
|
+
yield ctx
|
|
96
|
+
finally:
|
|
97
|
+
_current_agent_context.set(previous)
|
|
98
|
+
|
|
99
|
+
|
|
33
100
|
class AgentContext(BaseModel):
|
|
34
101
|
"""
|
|
35
102
|
Session and configuration context for agent execution.
|
|
@@ -85,6 +152,40 @@ class AgentContext(BaseModel):
|
|
|
85
152
|
|
|
86
153
|
model_config = {"populate_by_name": True}
|
|
87
154
|
|
|
155
|
+
def child_context(
|
|
156
|
+
self,
|
|
157
|
+
agent_schema_uri: str | None = None,
|
|
158
|
+
model_override: str | None = None,
|
|
159
|
+
) -> "AgentContext":
|
|
160
|
+
"""
|
|
161
|
+
Create a child context for nested agent calls.
|
|
162
|
+
|
|
163
|
+
Inherits user_id, tenant_id, session_id, is_eval from parent.
|
|
164
|
+
Allows overriding agent_schema_uri and default_model for the child.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
agent_schema_uri: Agent schema for the child agent (required for lineage)
|
|
168
|
+
model_override: Optional model override for child agent
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
New AgentContext for the child agent
|
|
172
|
+
|
|
173
|
+
Example:
|
|
174
|
+
parent_context = get_current_context()
|
|
175
|
+
child_context = parent_context.child_context(
|
|
176
|
+
agent_schema_uri="sentiment-analyzer"
|
|
177
|
+
)
|
|
178
|
+
agent = await create_agent(context=child_context)
|
|
179
|
+
"""
|
|
180
|
+
return AgentContext(
|
|
181
|
+
user_id=self.user_id,
|
|
182
|
+
tenant_id=self.tenant_id,
|
|
183
|
+
session_id=self.session_id,
|
|
184
|
+
default_model=model_override or self.default_model,
|
|
185
|
+
agent_schema_uri=agent_schema_uri or self.agent_schema_uri,
|
|
186
|
+
is_eval=self.is_eval,
|
|
187
|
+
)
|
|
188
|
+
|
|
88
189
|
@staticmethod
|
|
89
190
|
def get_user_id_or_default(
|
|
90
191
|
user_id: str | None,
|
rem/agentic/context_builder.py
CHANGED
|
@@ -217,11 +217,21 @@ class ContextBuilder:
|
|
|
217
217
|
)
|
|
218
218
|
|
|
219
219
|
# Convert to ContextMessage format
|
|
220
|
+
# For tool messages, wrap content with clear markers so the agent
|
|
221
|
+
# can see previous tool results when the prompt is concatenated
|
|
220
222
|
for msg_dict in session_history:
|
|
223
|
+
role = msg_dict["role"]
|
|
224
|
+
content = msg_dict["content"]
|
|
225
|
+
|
|
226
|
+
if role == "tool":
|
|
227
|
+
# Wrap tool results with clear markers for visibility
|
|
228
|
+
tool_name = msg_dict.get("tool_name", "unknown")
|
|
229
|
+
content = f"[TOOL RESULT: {tool_name}]\n{content}\n[/TOOL RESULT]"
|
|
230
|
+
|
|
221
231
|
messages.append(
|
|
222
232
|
ContextMessage(
|
|
223
|
-
role=
|
|
224
|
-
content=
|
|
233
|
+
role=role,
|
|
234
|
+
content=content,
|
|
225
235
|
)
|
|
226
236
|
)
|
|
227
237
|
|
rem/api/main.py
CHANGED
|
@@ -322,7 +322,7 @@ def create_app() -> FastAPI:
|
|
|
322
322
|
|
|
323
323
|
app.add_middleware(
|
|
324
324
|
AuthMiddleware,
|
|
325
|
-
protected_paths=["/api/v1"],
|
|
325
|
+
protected_paths=["/api/v1", "/api/admin"],
|
|
326
326
|
excluded_paths=["/api/auth", "/api/dev", "/api/v1/mcp/auth", "/api/v1/slack"],
|
|
327
327
|
# Allow anonymous when auth is disabled, otherwise use setting
|
|
328
328
|
allow_anonymous=(not settings.auth.enabled) or settings.auth.allow_anonymous,
|
rem/api/mcp_router/server.py
CHANGED
|
@@ -34,6 +34,7 @@ from .resources import (
|
|
|
34
34
|
register_status_resources,
|
|
35
35
|
)
|
|
36
36
|
from .tools import (
|
|
37
|
+
ask_agent,
|
|
37
38
|
ask_rem_agent,
|
|
38
39
|
get_schema,
|
|
39
40
|
ingest_into_rem,
|
|
@@ -203,6 +204,9 @@ def create_mcp_server(is_local: bool = False) -> FastMCP:
|
|
|
203
204
|
mcp.tool()(get_schema)
|
|
204
205
|
mcp.tool()(save_agent)
|
|
205
206
|
|
|
207
|
+
# Register multi-agent tools
|
|
208
|
+
mcp.tool()(ask_agent)
|
|
209
|
+
|
|
206
210
|
# Register test tool only in development environment (not staging/production)
|
|
207
211
|
if settings.environment not in ("staging", "production"):
|
|
208
212
|
mcp.tool()(test_error_handling)
|