fred-runtime 2.0.7__tar.gz → 2.0.10__tar.gz
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.
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/PKG-INFO +5 -2
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/app/agent_app.py +127 -49
- fred_runtime-2.0.10/fred_runtime/app/container.py +27 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/app/context.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/app/dependencies.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/app/mcp_config.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/cli/__init__.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/cli/completion.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/cli/entrypoint.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/cli/history_display.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/cli/kpi_display.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/cli/pod_client.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/cli/repl.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/cli/repl_helpers.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/cli/url_helpers.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/client.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/context_aware_tool.py +21 -5
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/token_expiry.py +14 -0
- fred_runtime-2.0.10/fred_runtime/deep/__init__.py +15 -0
- fred_runtime-2.0.10/fred_runtime/graph/__init__.py +15 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/graph/graph_runtime.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/integrations/v2_runtime/adapters.py +19 -1
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/model_routing/__init__.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/model_routing/catalog.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/model_routing/provider.py +14 -0
- fred_runtime-2.0.10/fred_runtime/react/__init__.py +15 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/react/react_message_codec.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/react/react_model_adapter.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/react/react_tool_rendering.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/react/react_tool_utils.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/runtime_support/checkpoints.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/runtime_support/sql_checkpointer.py +14 -0
- fred_runtime-2.0.10/fred_runtime/support/__init__.py +15 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/support/filesystem_context.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/support/tool_approval.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/support/tool_loop.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime.egg-info/PKG-INFO +5 -2
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime.egg-info/SOURCES.txt +1 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime.egg-info/requires.txt +4 -1
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/pyproject.toml +10 -2
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_agent_app.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_client.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_config_loader.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_context.py +14 -0
- fred_runtime-2.0.10/tests/test_context_aware_tool.py +78 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_conversational_memory.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_eval_collector.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_eval_trace.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_graph_runtime_observability.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_history.py +184 -2
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_kpi_display.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_mcp_config.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_model_routing.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_openai_compat_router.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_pod_client.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_repl_helpers.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_smoke.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_token_expiry.py +14 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_url_helpers.py +14 -0
- fred_runtime-2.0.7/fred_runtime/app/container.py +0 -13
- fred_runtime-2.0.7/fred_runtime/deep/__init__.py +0 -1
- fred_runtime-2.0.7/fred_runtime/graph/__init__.py +0 -1
- fred_runtime-2.0.7/fred_runtime/react/__init__.py +0 -1
- fred_runtime-2.0.7/fred_runtime/support/__init__.py +0 -1
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/README.md +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/__init__.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/app/__init__.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/app/_catalogs.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/app/config.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/app/config_loader.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/app/observability_factory.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/app/openai_compat_router.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/__init__.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/kf_base_client.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/kf_fast_text_client.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/kf_http_client.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/kf_logs_client.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/kf_markdown_media_client.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/kf_vectorsearch_client.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/kf_workspace_client.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/mcp_interceptors.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/mcp_runtime.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/mcp_toolkit.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/mcp_utils.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/structures.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/common/tool_node_utils.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/deep/deep_runtime.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/eval/__init__.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/eval/collector.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/integrations/__init__.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/integrations/v2_runtime/__init__.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/model_routing/contracts.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/model_routing/resolver.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/react/react_langchain_adapter.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/react/react_prompting.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/react/react_runtime.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/react/react_stream_adapter.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/react/react_tool_binding.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/react/react_tool_loop.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/react/react_tool_resolution.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/react/react_tracing.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/runtime_context.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/runtime_support/__init__.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/runtime_support/model_metadata.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/runtime_support/request_context_helpers.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime/runtime_support/user_token_refresher.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime.egg-info/dependency_links.txt +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime.egg-info/entry_points.txt +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/fred_runtime.egg-info/top_level.txt +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/setup.cfg +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_kf_workspace_client.py +0 -0
- {fred_runtime-2.0.7 → fred_runtime-2.0.10}/tests/test_user_token_refresher.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fred-runtime
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.10
|
|
4
4
|
Summary: Runtime adapters and infrastructure wiring for Fred v2 agents.
|
|
5
5
|
Author-email: Thales <noreply@thalesgroup.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -12,8 +12,9 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
12
12
|
Classifier: Operating System :: OS Independent
|
|
13
13
|
Requires-Python: <3.13,>=3.12
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
|
-
Requires-Dist: fred-core>=
|
|
15
|
+
Requires-Dist: fred-core>=2.0.5
|
|
16
16
|
Requires-Dist: fred-sdk>=0.1.11
|
|
17
|
+
Requires-Dist: alembic>=1.18.4
|
|
17
18
|
Requires-Dist: deepagents>=0.4.11
|
|
18
19
|
Requires-Dist: httpx>=0.28.1
|
|
19
20
|
Requires-Dist: langchain-mcp-adapters>=0.2.1
|
|
@@ -30,7 +31,9 @@ Requires-Dist: bandit>=1.8.6; extra == "dev"
|
|
|
30
31
|
Requires-Dist: basedpyright==1.31.0; extra == "dev"
|
|
31
32
|
Requires-Dist: detect-secrets>=1.5.0; extra == "dev"
|
|
32
33
|
Requires-Dist: pytest>=8.4.2; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=1.2.0; extra == "dev"
|
|
33
35
|
Requires-Dist: pytest-cov>=6.2.1; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-socket>=0.7.0; extra == "dev"
|
|
34
37
|
Requires-Dist: ruff>=0.12.5; extra == "dev"
|
|
35
38
|
|
|
36
39
|
# fred-runtime
|
|
@@ -814,6 +814,7 @@ class _AgentTemplateSummary(BaseModel):
|
|
|
814
814
|
template_agent_id: str
|
|
815
815
|
title: str
|
|
816
816
|
description: str
|
|
817
|
+
description_by_lang: dict[str, str] | None = None
|
|
817
818
|
kind: ExecutionCategory
|
|
818
819
|
default_tuning: AgentTuning
|
|
819
820
|
available_mcp_servers: list[MCPServerConfiguration] = Field(default_factory=list)
|
|
@@ -2060,6 +2061,7 @@ def _build_agent_router(
|
|
|
2060
2061
|
template_agent_id=definition.agent_id,
|
|
2061
2062
|
title=definition.role,
|
|
2062
2063
|
description=definition.description,
|
|
2064
|
+
description_by_lang=getattr(definition, "description_by_lang", None),
|
|
2063
2065
|
kind=definition.execution_category,
|
|
2064
2066
|
default_tuning=_definition_to_agent_tuning(definition),
|
|
2065
2067
|
available_mcp_servers=_available_mcp_servers_for_definition(definition),
|
|
@@ -2101,22 +2103,20 @@ def _build_agent_router(
|
|
|
2101
2103
|
]
|
|
2102
2104
|
)
|
|
2103
2105
|
|
|
2104
|
-
@router.get("/sessions"
|
|
2105
|
-
async def list_sessions(
|
|
2106
|
+
@router.get("/sessions")
|
|
2107
|
+
async def list_sessions(
|
|
2108
|
+
caller: KeycloakUser | None = Depends(_authenticated_user),
|
|
2109
|
+
user_id: str | None = None,
|
|
2110
|
+
) -> list[str]:
|
|
2106
2111
|
"""
|
|
2107
|
-
Return the session IDs for
|
|
2112
|
+
Return the session IDs for the authenticated user, most recent first.
|
|
2108
2113
|
|
|
2109
|
-
GET <configured base_url>/agents/sessions
|
|
2110
|
-
Authorization: Bearer <user JWT>
|
|
2111
|
-
Response: JSON array of session_id strings
|
|
2112
|
-
|
|
2113
|
-
Why this endpoint exists:
|
|
2114
|
-
- the UI needs to list past conversations for a returning user
|
|
2115
|
-
- the checkpointer has no user_id index; only the history store does
|
|
2114
|
+
GET <configured base_url>/agents/sessions
|
|
2115
|
+
Authorization: Bearer <user JWT>
|
|
2116
2116
|
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2117
|
+
Security: user identity is always extracted from the JWT token.
|
|
2118
|
+
The user_id query parameter is accepted only in dev mode (security
|
|
2119
|
+
disabled) for CLI convenience; it is ignored when security is enabled.
|
|
2120
2120
|
"""
|
|
2121
2121
|
history_store = get_runtime_context().config.history_store
|
|
2122
2122
|
if history_store is None:
|
|
@@ -2124,29 +2124,30 @@ def _build_agent_router(
|
|
|
2124
2124
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
2125
2125
|
detail="No history store configured — session listing is unavailable.",
|
|
2126
2126
|
)
|
|
2127
|
-
|
|
2127
|
+
effective_uid = caller.uid if caller is not None else user_id
|
|
2128
|
+
if effective_uid is None:
|
|
2129
|
+
return []
|
|
2130
|
+
return await history_store.list_sessions(user_id=effective_uid)
|
|
2128
2131
|
|
|
2129
2132
|
@router.get(
|
|
2130
2133
|
"/sessions/{session_id}/messages",
|
|
2131
|
-
dependencies=_auth_deps,
|
|
2132
2134
|
response_model=list[ChatMessage],
|
|
2133
2135
|
)
|
|
2134
|
-
async def get_session_messages(
|
|
2136
|
+
async def get_session_messages(
|
|
2137
|
+
session_id: str,
|
|
2138
|
+
caller: KeycloakUser | None = Depends(_authenticated_user),
|
|
2139
|
+
) -> list[ChatMessage]:
|
|
2135
2140
|
"""
|
|
2136
2141
|
Return the conversation history for a session as a flat message list.
|
|
2137
2142
|
|
|
2138
2143
|
GET <configured base_url>/agents/sessions/{session_id}/messages
|
|
2139
|
-
Authorization: Bearer <user JWT>
|
|
2140
|
-
Response: JSON array of ChatMessage objects (role/channel/parts/metadata).
|
|
2144
|
+
Authorization: Bearer <user JWT>
|
|
2141
2145
|
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
- the checkpointer (former source) only works for agents with a ``messages``
|
|
2146
|
-
channel in state and is not queryable per user_id
|
|
2146
|
+
Security: only rows belonging to the authenticated user are returned.
|
|
2147
|
+
Returns [] when the session does not exist or belongs to another user —
|
|
2148
|
+
callers cannot distinguish the two cases by design.
|
|
2147
2149
|
|
|
2148
2150
|
Returns 503 when no history store is configured (stateless pod mode).
|
|
2149
|
-
Returns [] when the session exists but has no rows yet.
|
|
2150
2151
|
"""
|
|
2151
2152
|
history_store = get_runtime_context().config.history_store
|
|
2152
2153
|
if history_store is None:
|
|
@@ -2154,27 +2155,29 @@ def _build_agent_router(
|
|
|
2154
2155
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
2155
2156
|
detail="No history store configured — session history is unavailable.",
|
|
2156
2157
|
)
|
|
2157
|
-
|
|
2158
|
+
caller_uid = caller.uid if caller is not None else None
|
|
2159
|
+
return await history_store.get(session_id=session_id, user_id=caller_uid)
|
|
2158
2160
|
|
|
2159
2161
|
@router.delete(
|
|
2160
2162
|
"/sessions/{session_id}",
|
|
2161
|
-
dependencies=_auth_deps,
|
|
2162
2163
|
status_code=status.HTTP_200_OK,
|
|
2163
2164
|
)
|
|
2164
|
-
async def delete_session_history(
|
|
2165
|
+
async def delete_session_history(
|
|
2166
|
+
session_id: str,
|
|
2167
|
+
caller: KeycloakUser | None = Depends(_authenticated_user),
|
|
2168
|
+
) -> dict[str, int]:
|
|
2165
2169
|
"""
|
|
2166
|
-
Permanently delete
|
|
2170
|
+
Permanently delete history rows for a session.
|
|
2167
2171
|
|
|
2168
2172
|
DELETE <base_url>/agents/sessions/{session_id}
|
|
2169
2173
|
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2174
|
+
Security: only rows belonging to the authenticated user are deleted.
|
|
2175
|
+
Returns {"deleted": 0} when the session does not exist or belongs to
|
|
2176
|
+
another user — callers cannot distinguish the two cases by design.
|
|
2177
|
+
|
|
2178
|
+
Checkpoint state is NOT touched; delete separately via
|
|
2179
|
+
DELETE /agents/checkpoints/{session_id} if required.
|
|
2176
2180
|
|
|
2177
|
-
Returns {"deleted": N} where N is the number of rows removed.
|
|
2178
2181
|
Returns 503 when no history store is configured.
|
|
2179
2182
|
"""
|
|
2180
2183
|
history_store = get_runtime_context().config.history_store
|
|
@@ -2183,7 +2186,10 @@ def _build_agent_router(
|
|
|
2183
2186
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
2184
2187
|
detail="No history store configured — session history is unavailable.",
|
|
2185
2188
|
)
|
|
2186
|
-
|
|
2189
|
+
caller_uid = caller.uid if caller is not None else None
|
|
2190
|
+
count = await history_store.delete_session(
|
|
2191
|
+
session_id=session_id, user_id=caller_uid
|
|
2192
|
+
)
|
|
2187
2193
|
return {"deleted": count}
|
|
2188
2194
|
|
|
2189
2195
|
# ------------------------------------------------------------------
|
|
@@ -2199,8 +2205,36 @@ def _build_agent_router(
|
|
|
2199
2205
|
)
|
|
2200
2206
|
return cp
|
|
2201
2207
|
|
|
2202
|
-
|
|
2208
|
+
def _get_history_store_for_owned_access(
|
|
2209
|
+
caller: KeycloakUser | None,
|
|
2210
|
+
) -> HistoryStorePort | None:
|
|
2211
|
+
"""Return the history store used as ownership oracle, failing closed.
|
|
2212
|
+
|
|
2213
|
+
Why this helper exists:
|
|
2214
|
+
- checkpoint tables do not carry user_id, so ownership checks depend on
|
|
2215
|
+
the history store
|
|
2216
|
+
- when security is enabled, proceeding without that oracle would leak
|
|
2217
|
+
checkpoint visibility across users
|
|
2218
|
+
|
|
2219
|
+
How to use it:
|
|
2220
|
+
- call from checkpoint endpoints before listing or mutating per-session
|
|
2221
|
+
checkpoint data
|
|
2222
|
+
"""
|
|
2223
|
+
if caller is None:
|
|
2224
|
+
return None
|
|
2225
|
+
history_store = get_runtime_context().config.history_store
|
|
2226
|
+
if history_store is None:
|
|
2227
|
+
raise HTTPException(
|
|
2228
|
+
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
2229
|
+
detail=(
|
|
2230
|
+
"No history store configured — ownership checks are unavailable."
|
|
2231
|
+
),
|
|
2232
|
+
)
|
|
2233
|
+
return history_store
|
|
2234
|
+
|
|
2235
|
+
@router.get("/checkpoints")
|
|
2203
2236
|
async def list_checkpoint_threads(
|
|
2237
|
+
caller: KeycloakUser | None = Depends(_authenticated_user),
|
|
2204
2238
|
limit: int = 100,
|
|
2205
2239
|
) -> list[_CheckpointThreadSummary]:
|
|
2206
2240
|
"""
|
|
@@ -2271,6 +2305,15 @@ def _build_agent_router(
|
|
|
2271
2305
|
.limit(limit)
|
|
2272
2306
|
)
|
|
2273
2307
|
rows = (await conn.execute(stmt)).fetchall()
|
|
2308
|
+
|
|
2309
|
+
# Scope to the caller's own sessions using the history store as the
|
|
2310
|
+
# ownership oracle (checkpoint tables carry no user_id column).
|
|
2311
|
+
caller_uid = caller.uid if caller is not None else None
|
|
2312
|
+
history_store = _get_history_store_for_owned_access(caller)
|
|
2313
|
+
if caller_uid is not None and history_store is not None:
|
|
2314
|
+
owned = set(await history_store.list_sessions(user_id=caller_uid))
|
|
2315
|
+
rows = [r for r in rows if str(r.thread_id) in owned]
|
|
2316
|
+
|
|
2274
2317
|
return [
|
|
2275
2318
|
_CheckpointThreadSummary(
|
|
2276
2319
|
session_id=str(row.thread_id),
|
|
@@ -2338,8 +2381,11 @@ def _build_agent_router(
|
|
|
2338
2381
|
blob_bytes_approx=int(blob_bytes),
|
|
2339
2382
|
)
|
|
2340
2383
|
|
|
2341
|
-
@router.get("/checkpoints/{session_id}"
|
|
2342
|
-
async def get_checkpoint_thread(
|
|
2384
|
+
@router.get("/checkpoints/{session_id}")
|
|
2385
|
+
async def get_checkpoint_thread(
|
|
2386
|
+
session_id: str,
|
|
2387
|
+
caller: KeycloakUser | None = Depends(_authenticated_user),
|
|
2388
|
+
) -> _CheckpointThreadDetail:
|
|
2343
2389
|
"""
|
|
2344
2390
|
Return all checkpoints for one session, newest first.
|
|
2345
2391
|
|
|
@@ -2360,7 +2406,20 @@ def _build_agent_router(
|
|
|
2360
2406
|
|
|
2361
2407
|
Returns 503 when no checkpointer is configured.
|
|
2362
2408
|
Returns an empty checkpoints list when the session has no rows.
|
|
2409
|
+
Returns 403 when the session does not belong to the authenticated user.
|
|
2363
2410
|
"""
|
|
2411
|
+
caller_uid = caller.uid if caller is not None else None
|
|
2412
|
+
history_store = _get_history_store_for_owned_access(caller)
|
|
2413
|
+
if (
|
|
2414
|
+
caller_uid is not None
|
|
2415
|
+
and history_store is not None
|
|
2416
|
+
and not await history_store.session_belongs_to_user(session_id, caller_uid)
|
|
2417
|
+
):
|
|
2418
|
+
raise HTTPException(
|
|
2419
|
+
status_code=status.HTTP_403_FORBIDDEN,
|
|
2420
|
+
detail="Access denied.",
|
|
2421
|
+
)
|
|
2422
|
+
|
|
2364
2423
|
from sqlalchemy import desc, func, select
|
|
2365
2424
|
|
|
2366
2425
|
cp = _get_checkpointer()
|
|
@@ -2429,25 +2488,38 @@ def _build_agent_router(
|
|
|
2429
2488
|
|
|
2430
2489
|
@router.delete(
|
|
2431
2490
|
"/checkpoints/{session_id}",
|
|
2432
|
-
dependencies=_auth_deps,
|
|
2433
2491
|
status_code=status.HTTP_204_NO_CONTENT,
|
|
2434
2492
|
response_model=None,
|
|
2435
2493
|
)
|
|
2436
|
-
async def delete_checkpoint_thread(
|
|
2494
|
+
async def delete_checkpoint_thread(
|
|
2495
|
+
session_id: str,
|
|
2496
|
+
caller: KeycloakUser | None = Depends(_authenticated_user),
|
|
2497
|
+
) -> None:
|
|
2437
2498
|
"""
|
|
2438
2499
|
Purge all checkpoint data for one session.
|
|
2439
2500
|
|
|
2440
2501
|
DELETE <base_url>/agents/checkpoints/{session_id}
|
|
2441
2502
|
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
to resume from any prior HITL pause or conversation state for this session.
|
|
2503
|
+
Security: the session must belong to the authenticated user.
|
|
2504
|
+
Returns 403 when ownership cannot be confirmed via the history store.
|
|
2445
2505
|
|
|
2446
|
-
|
|
2447
|
-
|
|
2506
|
+
Deletes all rows in the checkpoints, blobs, and writes tables.
|
|
2507
|
+
History store rows are NOT deleted — use DELETE /sessions/{session_id}
|
|
2508
|
+
to remove those separately.
|
|
2448
2509
|
|
|
2449
|
-
Returns 204 on success, 503 when no checkpointer
|
|
2510
|
+
Returns 204 on success, 403 when not owned, 503 when no checkpointer.
|
|
2450
2511
|
"""
|
|
2512
|
+
caller_uid = caller.uid if caller is not None else None
|
|
2513
|
+
history_store = _get_history_store_for_owned_access(caller)
|
|
2514
|
+
if (
|
|
2515
|
+
caller_uid is not None
|
|
2516
|
+
and history_store is not None
|
|
2517
|
+
and not await history_store.session_belongs_to_user(session_id, caller_uid)
|
|
2518
|
+
):
|
|
2519
|
+
raise HTTPException(
|
|
2520
|
+
status_code=status.HTTP_403_FORBIDDEN,
|
|
2521
|
+
detail="Access denied.",
|
|
2522
|
+
)
|
|
2451
2523
|
cp = _get_checkpointer()
|
|
2452
2524
|
await cp.adelete_thread(session_id)
|
|
2453
2525
|
|
|
@@ -2850,6 +2922,12 @@ def create_agent_app(
|
|
|
2850
2922
|
await container.initialize_sql()
|
|
2851
2923
|
container.start_metrics_exporter()
|
|
2852
2924
|
await container.start_kpi_tasks()
|
|
2925
|
+
checkpointer = container.get_checkpointer()
|
|
2926
|
+
history_store = container.get_history_store()
|
|
2927
|
+
if (checkpointer is None) != (history_store is None):
|
|
2928
|
+
raise RuntimeError(
|
|
2929
|
+
"Invalid runtime storage state: checkpointer and history store must be configured together."
|
|
2930
|
+
)
|
|
2853
2931
|
set_runtime_context(
|
|
2854
2932
|
FredRuntimeContext(
|
|
2855
2933
|
RuntimeConfig(
|
|
@@ -2857,8 +2935,8 @@ def create_agent_app(
|
|
|
2857
2935
|
service_name=config.app.name,
|
|
2858
2936
|
timeouts=config.ai.timeout,
|
|
2859
2937
|
chat_model_factory=chat_factory,
|
|
2860
|
-
checkpointer=
|
|
2861
|
-
history_store=
|
|
2938
|
+
checkpointer=checkpointer,
|
|
2939
|
+
history_store=history_store,
|
|
2862
2940
|
mcp_configuration=config.get_mcp_configuration(),
|
|
2863
2941
|
control_plane_url=config.platform.control_plane_url,
|
|
2864
2942
|
kpi_writer=container.get_kpi_writer(),
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Pod container factory — single composition-root entry point."""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from fred_runtime.app.config import AgentPodConfig
|
|
20
|
+
from fred_runtime.app.context import PodApplicationContext
|
|
21
|
+
|
|
22
|
+
PodContainer = PodApplicationContext
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def build_pod_container(configuration: AgentPodConfig) -> PodContainer:
|
|
26
|
+
"""Create a fresh PodApplicationContext with no side effects."""
|
|
27
|
+
return PodApplicationContext(configuration)
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
"""PodApplicationContext — single composition root for a fred-runtime agent pod."""
|
|
2
16
|
|
|
3
17
|
from __future__ import annotations
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
"""FastAPI dependency helpers for pod container injection."""
|
|
2
16
|
|
|
3
17
|
from __future__ import annotations
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
"""Typed representation of the mcp_catalog.yaml loaded by an agent pod."""
|
|
2
16
|
|
|
3
17
|
from __future__ import annotations
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
from .completion import completion_candidates
|
|
2
16
|
from .entrypoint import build_parser, main
|
|
3
17
|
from .history_display import (
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
from __future__ import annotations
|
|
2
16
|
|
|
3
17
|
from collections.abc import Sequence
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
from __future__ import annotations
|
|
2
16
|
|
|
3
17
|
import argparse
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
from __future__ import annotations
|
|
2
16
|
|
|
3
17
|
import json
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
from __future__ import annotations
|
|
2
16
|
|
|
3
17
|
import re
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
from __future__ import annotations
|
|
2
16
|
|
|
3
17
|
import json
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
from __future__ import annotations
|
|
2
16
|
|
|
3
17
|
import getpass
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
from __future__ import annotations
|
|
2
16
|
|
|
3
17
|
import uuid
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
from __future__ import annotations
|
|
2
16
|
|
|
3
17
|
import os
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# Copyright Thales 2026
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
1
15
|
"""
|
|
2
16
|
Compatibility shim — all implementation has moved to fred_runtime.cli.*
|
|
3
17
|
|
|
@@ -6,6 +6,7 @@ from typing import Any, Callable, Optional
|
|
|
6
6
|
|
|
7
7
|
import httpx # ← we log/inspect HTTP errors coming from MCP adapters
|
|
8
8
|
from fred_core.common import OwnerFilter
|
|
9
|
+
from fred_core.common.team_id import is_personal_team_id
|
|
9
10
|
from fred_core.kpi.kpi_writer_structures import KPIActor
|
|
10
11
|
from fred_sdk.support.mcp_utils import normalize_mcp_content
|
|
11
12
|
from langchain_core.tools import BaseTool
|
|
@@ -20,6 +21,7 @@ from fred_runtime.runtime_context import get_runtime_context
|
|
|
20
21
|
from fred_runtime.runtime_support import (
|
|
21
22
|
RuntimeContextProvider,
|
|
22
23
|
get_document_library_tags_ids,
|
|
24
|
+
get_document_uids,
|
|
23
25
|
get_vector_search_scopes,
|
|
24
26
|
)
|
|
25
27
|
|
|
@@ -170,6 +172,15 @@ class ContextAwareTool(BaseTool):
|
|
|
170
172
|
library_ids,
|
|
171
173
|
)
|
|
172
174
|
|
|
175
|
+
document_uids = get_document_uids(context)
|
|
176
|
+
if document_uids and "document_uids" in tool_properties:
|
|
177
|
+
kwargs["document_uids"] = document_uids
|
|
178
|
+
logger.info(
|
|
179
|
+
"ContextAwareTool(%s) injecting document filter: %s",
|
|
180
|
+
self.name,
|
|
181
|
+
document_uids,
|
|
182
|
+
)
|
|
183
|
+
|
|
173
184
|
session_id = context.session_id
|
|
174
185
|
if (
|
|
175
186
|
session_id
|
|
@@ -183,19 +194,24 @@ class ContextAwareTool(BaseTool):
|
|
|
183
194
|
session_id,
|
|
184
195
|
)
|
|
185
196
|
|
|
186
|
-
# Force team_id depending on agent settings
|
|
187
|
-
|
|
188
|
-
|
|
197
|
+
# Force team_id depending on agent settings.
|
|
198
|
+
# Personal-space IDs ("personal-<uuid>") are not real ReBAC teams;
|
|
199
|
+
# don't forward them to tools that look up team membership.
|
|
200
|
+
effective_team_id = (
|
|
201
|
+
settings.team_id if not is_personal_team_id(settings.team_id) else None
|
|
202
|
+
)
|
|
203
|
+
if "team_id" in tool_properties and effective_team_id:
|
|
204
|
+
kwargs["team_id"] = effective_team_id
|
|
189
205
|
logger.info(
|
|
190
206
|
"ContextAwareTool(%s) injecting team_id: %s",
|
|
191
207
|
self.name,
|
|
192
|
-
|
|
208
|
+
effective_team_id,
|
|
193
209
|
)
|
|
194
210
|
|
|
195
211
|
# Force owner_filter depending on agent settings
|
|
196
212
|
if "owner_filter" in tool_properties:
|
|
197
213
|
owner_filter = (
|
|
198
|
-
OwnerFilter.TEAM if
|
|
214
|
+
OwnerFilter.TEAM if effective_team_id else OwnerFilter.PERSONAL
|
|
199
215
|
)
|
|
200
216
|
kwargs["owner_filter"] = owner_filter.value
|
|
201
217
|
logger.info(
|