fred-runtime 3.3.5__tar.gz → 3.3.6__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-3.3.5 → fred_runtime-3.3.6}/PKG-INFO +1 -1
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/deep/deep_runtime.py +46 -8
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime.egg-info/PKG-INFO +1 -1
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime.egg-info/SOURCES.txt +1 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/pyproject.toml +1 -1
- fred_runtime-3.3.6/tests/test_deep_agent_middleware.py +182 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/README.md +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/__main__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/app/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/app/_catalogs.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/app/agent_app.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/app/config.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/app/config_loader.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/app/container.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/app/context.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/app/dependencies.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/app/mcp_config.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/app/observability_factory.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/app/openai_compat_router.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/assembly.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/assets.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/demo.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/demo_migrations/env.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/demo_migrations/versions/d1e2m0a0b0c0_create_demo_echo_notes.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/document_access/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/document_access/capability.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/errors.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/mcp.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/openapi_dump.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/registry.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/cli/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/cli/completion.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/cli/entrypoint.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/cli/history_display.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/cli/kpi_display.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/cli/pod_client.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/cli/repl.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/cli/repl_helpers.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/cli/url_helpers.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/client.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/context_aware_tool.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/kf_base_client.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/kf_fast_text_client.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/kf_http_client.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/kf_markdown_media_client.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/kf_vectorsearch_client.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/kf_workspace_client.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/mcp_interceptors.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/mcp_runtime.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/mcp_toolkit.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/mcp_utils.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/structures.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/token_expiry.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/common/tool_node_utils.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/deep/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/eval/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/eval/collector.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/graph/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/graph/graph_runtime.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/integrations/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/integrations/inprocess_toolkit_registry.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/integrations/kf_vector_search/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/integrations/kf_vector_search/toolkit.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/integrations/v2_runtime/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/integrations/v2_runtime/adapters.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/migrations.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/model_routing/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/model_routing/catalog.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/model_routing/contracts.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/model_routing/provider.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/model_routing/resolver.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/middleware/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/middleware/checkpoint_hygiene.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/middleware/dynamic_prompt.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/middleware/frame.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/middleware/hitl.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/middleware/model_routing.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/middleware/shared.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/middleware/tool_observability.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/middleware/tracing_kpi.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/react_langchain_adapter.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/react_message_codec.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/react_model_adapter.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/react_prompting.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/react_runtime.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/react_stream_adapter.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/react_tool_binding.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/react_tool_loop.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/react_tool_rendering.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/react_tool_resolution.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/react_tool_utils.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/react_tracing.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/runtime_context.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/runtime_support/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/runtime_support/checkpoints.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/runtime_support/model_metadata.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/runtime_support/request_context_helpers.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/runtime_support/sql_checkpointer.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/runtime_support/user_token_refresher.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/support/__init__.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/support/filesystem_context.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/support/thinking.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/support/tool_loop.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime.egg-info/dependency_links.txt +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime.egg-info/entry_points.txt +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime.egg-info/requires.txt +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime.egg-info/top_level.txt +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/setup.cfg +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_agent_app.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_capability_agent_1973.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_capability_chat_controls_1976.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_capability_chat_parts_1977.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_capability_document_access_1906.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_capability_endpoints_1974.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_capability_registry_1973.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_capability_routes_tables_1979.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_capability_selection_1974.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_client.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_config_loader.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_context.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_context_aware_tool.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_conversational_memory.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_eval_collector.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_eval_trace.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_fred_workspace_fs.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_graph_runtime_invoke_agent.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_graph_runtime_observability.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_history.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_kf_vector_search_toolkit.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_kf_workspace_client.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_knowledge_search_tool_invoker_sources.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_kpi_display.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_mcp_config.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_model_routing.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_openai_compat_router.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_pod_client.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_react_loop_regressions_1972.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_react_middleware_frame.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_react_prompting.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_react_thinking.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_repl_helpers.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_runtime_context_prompt_injection.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_smoke.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_spike_capability_state_1971.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_sql_checkpointer_owner.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_token_expiry.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_tool_observability_middleware.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_tracing_kpi_content_confinement.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_url_helpers.py +0 -0
- {fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_user_token_refresher.py +0 -0
|
@@ -29,14 +29,25 @@ from __future__ import annotations
|
|
|
29
29
|
from collections.abc import Sequence
|
|
30
30
|
from typing import cast
|
|
31
31
|
|
|
32
|
+
from fred_core.kpi import BaseKPIWriter
|
|
32
33
|
from fred_sdk.contracts.context import BoundRuntimeContext
|
|
33
|
-
from fred_sdk.contracts.runtime import Executor
|
|
34
|
+
from fred_sdk.contracts.runtime import Executor, TracerPort
|
|
34
35
|
from langchain.agents.middleware import AgentMiddleware
|
|
35
36
|
from langchain.agents.middleware.tool_call_limit import ToolCallLimitMiddleware
|
|
36
37
|
from langchain_core.language_models.chat_models import BaseChatModel
|
|
37
38
|
from langchain_core.tools import BaseTool
|
|
38
39
|
from langgraph.types import Checkpointer
|
|
39
40
|
|
|
41
|
+
from fred_runtime.react.middleware.tool_observability import (
|
|
42
|
+
ToolObservabilityMiddleware,
|
|
43
|
+
)
|
|
44
|
+
from fred_runtime.react.middleware.tracing_kpi import TracingKpiMiddleware
|
|
45
|
+
from fred_runtime.react.react_model_adapter import (
|
|
46
|
+
REACT_MODEL_OPERATION_ROUTING,
|
|
47
|
+
)
|
|
48
|
+
from fred_runtime.react.react_model_adapter import (
|
|
49
|
+
infer_react_model_operation_from_messages as _infer_react_model_operation_from_messages,
|
|
50
|
+
)
|
|
40
51
|
from fred_runtime.react.react_prompting import (
|
|
41
52
|
compose_system_prompt as _compose_system_prompt,
|
|
42
53
|
)
|
|
@@ -53,6 +64,7 @@ from fred_runtime.react.react_runtime import (
|
|
|
53
64
|
)
|
|
54
65
|
from fred_runtime.react.react_tool_binding import ReActToolBinder
|
|
55
66
|
from fred_runtime.react.react_tool_resolution import ReActRuntimeToolResolver
|
|
67
|
+
from fred_runtime.runtime_context import get_runtime_context
|
|
56
68
|
|
|
57
69
|
_FILESYSTEM_TOOL_NAMES: tuple[str, ...] = (
|
|
58
70
|
"ls",
|
|
@@ -135,7 +147,10 @@ class DeepAgentRuntime(ReActRuntime):
|
|
|
135
147
|
system_prompt=system_prompt,
|
|
136
148
|
checkpointer=cast(Checkpointer, self.services.checkpointer),
|
|
137
149
|
middleware=_build_deepagent_runtime_middleware(
|
|
138
|
-
filesystem_tools_enabled=filesystem_tools_enabled
|
|
150
|
+
filesystem_tools_enabled=filesystem_tools_enabled,
|
|
151
|
+
tracer=self.services.tracer,
|
|
152
|
+
kpi=get_runtime_context().get_kpi_writer(),
|
|
153
|
+
binding=binding,
|
|
139
154
|
),
|
|
140
155
|
)
|
|
141
156
|
return _TransportBackedReActExecutor(
|
|
@@ -229,12 +244,26 @@ def _filesystem_prompt_suffix(*, filesystem_tools_enabled: bool) -> str:
|
|
|
229
244
|
|
|
230
245
|
|
|
231
246
|
def _build_deepagent_runtime_middleware(
|
|
232
|
-
*,
|
|
247
|
+
*,
|
|
248
|
+
filesystem_tools_enabled: bool,
|
|
249
|
+
tracer: TracerPort | None,
|
|
250
|
+
kpi: BaseKPIWriter | None,
|
|
251
|
+
binding: BoundRuntimeContext,
|
|
233
252
|
) -> list[AgentMiddleware]:
|
|
234
253
|
"""
|
|
235
|
-
Build Deep runtime middleware
|
|
254
|
+
Build Deep runtime middleware: platform observability first, then the
|
|
255
|
+
filesystem-tool policy guard.
|
|
236
256
|
|
|
237
257
|
Why this exists:
|
|
258
|
+
- Deep used to bypass `build_react_platform_middleware_frame()` entirely
|
|
259
|
+
(it overrides `build_executor`, so it never went through
|
|
260
|
+
`_create_compiled_react_agent`), which meant a Deep turn emitted no
|
|
261
|
+
`[LLM][CALL]`/`[LLM][RESPONSE]` logs, no `llm.call_latency_ms` KPI, and
|
|
262
|
+
no `agent.tool.invocation.*` audit events — the same
|
|
263
|
+
`TracingKpiMiddleware`/`ToolObservabilityMiddleware` pair ReAct always
|
|
264
|
+
gets. `create_deep_agent` accepts a plain `middleware=` list, so the
|
|
265
|
+
fix is to hand it the same two middleware instances, same order, no
|
|
266
|
+
new machinery.
|
|
238
267
|
- when the standard filesystem MCP tools are absent, Deep should block
|
|
239
268
|
accidental filesystem calls explicitly
|
|
240
269
|
- when those tools are present, Deep should not add special blocking and
|
|
@@ -243,15 +272,24 @@ def _build_deepagent_runtime_middleware(
|
|
|
243
272
|
How to use it:
|
|
244
273
|
- call once while creating the compiled deep agent
|
|
245
274
|
- pass whether standard filesystem tools are available in the resolved tool
|
|
246
|
-
list
|
|
275
|
+
list, plus the same tracer/kpi/binding used to build the tool bindings
|
|
247
276
|
|
|
248
277
|
Example:
|
|
249
|
-
- `middleware = _build_deepagent_runtime_middleware(filesystem_tools_enabled=True)`
|
|
278
|
+
- `middleware = _build_deepagent_runtime_middleware(filesystem_tools_enabled=True, tracer=tracer, kpi=kpi, binding=binding)`
|
|
250
279
|
"""
|
|
280
|
+
middleware: list[AgentMiddleware] = [
|
|
281
|
+
TracingKpiMiddleware(
|
|
282
|
+
tracer=tracer,
|
|
283
|
+
kpi=kpi,
|
|
284
|
+
binding=binding,
|
|
285
|
+
infer_operation_from_messages=_infer_react_model_operation_from_messages,
|
|
286
|
+
default_operation=REACT_MODEL_OPERATION_ROUTING,
|
|
287
|
+
),
|
|
288
|
+
ToolObservabilityMiddleware(kpi=kpi, binding=binding),
|
|
289
|
+
]
|
|
251
290
|
if filesystem_tools_enabled:
|
|
252
|
-
return
|
|
291
|
+
return middleware
|
|
253
292
|
|
|
254
|
-
middleware: list[AgentMiddleware] = []
|
|
255
293
|
for tool_name in _FILESYSTEM_TOOL_NAMES:
|
|
256
294
|
middleware.append(
|
|
257
295
|
cast(
|
|
@@ -121,6 +121,7 @@ tests/test_config_loader.py
|
|
|
121
121
|
tests/test_context.py
|
|
122
122
|
tests/test_context_aware_tool.py
|
|
123
123
|
tests/test_conversational_memory.py
|
|
124
|
+
tests/test_deep_agent_middleware.py
|
|
124
125
|
tests/test_eval_collector.py
|
|
125
126
|
tests/test_eval_trace.py
|
|
126
127
|
tests/test_fred_workspace_fs.py
|
|
@@ -0,0 +1,182 @@
|
|
|
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
|
+
"""
|
|
16
|
+
Tests proving DeepAgentRuntime gets the same observability guarantees as
|
|
17
|
+
ReActRuntime.
|
|
18
|
+
|
|
19
|
+
Deep overrides `build_executor` and never goes through
|
|
20
|
+
`build_react_platform_middleware_frame()`, so it used to silently skip
|
|
21
|
+
`TracingKpiMiddleware`/`ToolObservabilityMiddleware` — no `[LLM][CALL]` logs,
|
|
22
|
+
no `llm.call_latency_ms`/`agent.tool_latency_ms` KPI, no
|
|
23
|
+
`agent.tool.invocation.*` audit events for any Deep turn. These tests cover
|
|
24
|
+
both the middleware-list builder in isolation (mirrors
|
|
25
|
+
`test_react_middleware_frame.py::test_frame_order_is_fixed`) and the real
|
|
26
|
+
`build_executor` wiring (mirrors
|
|
27
|
+
`test_runtime_context_prompt_injection.py`'s stubbed-compile pattern).
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
from types import SimpleNamespace
|
|
33
|
+
from typing import Any, cast
|
|
34
|
+
|
|
35
|
+
import fred_runtime.deep.deep_runtime as deep_mod
|
|
36
|
+
import pytest
|
|
37
|
+
from fred_runtime.react.middleware.tool_observability import (
|
|
38
|
+
ToolObservabilityMiddleware,
|
|
39
|
+
)
|
|
40
|
+
from fred_runtime.react.middleware.tracing_kpi import TracingKpiMiddleware
|
|
41
|
+
from fred_runtime.runtime_context import RuntimeConfig, set_runtime_context
|
|
42
|
+
from fred_runtime.runtime_context import RuntimeContext as ProcessRuntimeContext
|
|
43
|
+
from fred_sdk.contracts.context import (
|
|
44
|
+
BoundRuntimeContext,
|
|
45
|
+
PortableContext,
|
|
46
|
+
PortableEnvironment,
|
|
47
|
+
RuntimeContext,
|
|
48
|
+
)
|
|
49
|
+
from fred_sdk.contracts.models import ReActAgentDefinition
|
|
50
|
+
from fred_sdk.contracts.runtime import RuntimeServices
|
|
51
|
+
from langchain.agents.middleware import ToolCallLimitMiddleware
|
|
52
|
+
from langchain_core.language_models.chat_models import BaseChatModel
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _binding() -> BoundRuntimeContext:
|
|
56
|
+
return BoundRuntimeContext(
|
|
57
|
+
runtime_context=RuntimeContext(),
|
|
58
|
+
portable_context=PortableContext(
|
|
59
|
+
request_id="request-1",
|
|
60
|
+
correlation_id="correlation-1",
|
|
61
|
+
actor="user-1",
|
|
62
|
+
tenant="team-1",
|
|
63
|
+
environment=PortableEnvironment.DEV,
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# ---------------------------------------------------------------------------
|
|
69
|
+
# _build_deepagent_runtime_middleware — list composition
|
|
70
|
+
# ---------------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_middleware_leads_with_observability_when_filesystem_enabled() -> None:
|
|
74
|
+
middleware = deep_mod._build_deepagent_runtime_middleware(
|
|
75
|
+
filesystem_tools_enabled=True,
|
|
76
|
+
tracer=None,
|
|
77
|
+
kpi=None,
|
|
78
|
+
binding=_binding(),
|
|
79
|
+
)
|
|
80
|
+
assert [type(m) for m in middleware] == [
|
|
81
|
+
TracingKpiMiddleware,
|
|
82
|
+
ToolObservabilityMiddleware,
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_middleware_keeps_observability_first_then_filesystem_guards() -> None:
|
|
87
|
+
middleware = deep_mod._build_deepagent_runtime_middleware(
|
|
88
|
+
filesystem_tools_enabled=False,
|
|
89
|
+
tracer=None,
|
|
90
|
+
kpi=None,
|
|
91
|
+
binding=_binding(),
|
|
92
|
+
)
|
|
93
|
+
assert type(middleware[0]) is TracingKpiMiddleware
|
|
94
|
+
assert type(middleware[1]) is ToolObservabilityMiddleware
|
|
95
|
+
assert all(type(m) is ToolCallLimitMiddleware for m in middleware[2:])
|
|
96
|
+
# One guard per disabled filesystem tool name (ls/read_file/write_file/
|
|
97
|
+
# edit_file/glob/grep/execute).
|
|
98
|
+
assert len(middleware) == 2 + 7
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# ---------------------------------------------------------------------------
|
|
102
|
+
# build_executor — the real wiring, stubbed compile step
|
|
103
|
+
# ---------------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class _FakePolicy:
|
|
107
|
+
def __init__(self) -> None:
|
|
108
|
+
self.system_prompt_template = "BASE-TEMPLATE"
|
|
109
|
+
self.guardrails: list[object] = []
|
|
110
|
+
self.tool_approval = SimpleNamespace(enabled=False)
|
|
111
|
+
self.tool_selection = SimpleNamespace(
|
|
112
|
+
max_tool_calls_per_turn=None, allow_parallel_calls=False
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class _FakeDefinition:
|
|
117
|
+
agent_id = "agent-1"
|
|
118
|
+
declared_tool_refs: tuple[object, ...] = ()
|
|
119
|
+
tuning_values: dict[str, str] = {}
|
|
120
|
+
|
|
121
|
+
def policy(self) -> _FakePolicy:
|
|
122
|
+
return _FakePolicy()
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class _FakeResolver:
|
|
126
|
+
def __init__(self, **_: object) -> None:
|
|
127
|
+
pass
|
|
128
|
+
|
|
129
|
+
def resolve_tools(self) -> list[object]:
|
|
130
|
+
return []
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class _FakeBinder:
|
|
134
|
+
def __init__(self, **_: object) -> None:
|
|
135
|
+
pass
|
|
136
|
+
|
|
137
|
+
def build_tools(self) -> list[object]:
|
|
138
|
+
return []
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class _FakeExecutor:
|
|
142
|
+
def __init__(self, **kwargs: object) -> None:
|
|
143
|
+
self.kwargs = kwargs
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _fake_definition() -> ReActAgentDefinition:
|
|
147
|
+
return cast(ReActAgentDefinition, _FakeDefinition())
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@pytest.mark.asyncio
|
|
151
|
+
async def test_deep_build_executor_wires_observability_middleware(
|
|
152
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
153
|
+
) -> None:
|
|
154
|
+
captured: dict[str, Any] = {}
|
|
155
|
+
|
|
156
|
+
def _fake_compile(**kwargs: object) -> object:
|
|
157
|
+
captured["middleware"] = list(cast(list, kwargs["middleware"]))
|
|
158
|
+
return object()
|
|
159
|
+
|
|
160
|
+
# build_executor reads the KPI writer off the process-wide runtime
|
|
161
|
+
# context (mirrors `test_kf_workspace_client.py`'s `_make_client`
|
|
162
|
+
# helper) — a NoOpKPIWriter is enough, no real config needed.
|
|
163
|
+
set_runtime_context(
|
|
164
|
+
ProcessRuntimeContext(RuntimeConfig(knowledge_flow_url="http://test"))
|
|
165
|
+
)
|
|
166
|
+
monkeypatch.setattr(deep_mod, "ReActRuntimeToolResolver", _FakeResolver)
|
|
167
|
+
monkeypatch.setattr(deep_mod, "ReActToolBinder", _FakeBinder)
|
|
168
|
+
monkeypatch.setattr(deep_mod, "_TransportBackedReActExecutor", _FakeExecutor)
|
|
169
|
+
monkeypatch.setattr(deep_mod, "_create_compiled_deep_agent", _fake_compile)
|
|
170
|
+
|
|
171
|
+
runtime = deep_mod.DeepAgentRuntime(
|
|
172
|
+
definition=_fake_definition(), services=RuntimeServices()
|
|
173
|
+
)
|
|
174
|
+
runtime._model = cast(BaseChatModel, SimpleNamespace())
|
|
175
|
+
|
|
176
|
+
await runtime.build_executor(_binding())
|
|
177
|
+
|
|
178
|
+
# The fake tool pipeline resolves no tools, so the filesystem guard
|
|
179
|
+
# clause also fires — this test only cares that observability leads.
|
|
180
|
+
wired = captured["middleware"]
|
|
181
|
+
assert type(wired[0]) is TracingKpiMiddleware
|
|
182
|
+
assert type(wired[1]) is ToolObservabilityMiddleware
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/document_access/__init__.py
RENAMED
|
File without changes
|
{fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/capabilities/document_access/capability.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/integrations/inprocess_toolkit_registry.py
RENAMED
|
File without changes
|
{fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/integrations/kf_vector_search/__init__.py
RENAMED
|
File without changes
|
{fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/integrations/kf_vector_search/toolkit.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/middleware/checkpoint_hygiene.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/react/middleware/tool_observability.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/runtime_support/request_context_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{fred_runtime-3.3.5 → fred_runtime-3.3.6}/fred_runtime/runtime_support/user_token_refresher.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fred_runtime-3.3.5 → fred_runtime-3.3.6}/tests/test_knowledge_search_tool_invoker_sources.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|