by-framework-langgraph 0.0.3.dev2__tar.gz → 0.0.3.dev3__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.
- {by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/PKG-INFO +1 -1
- {by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/pyproject.toml +1 -1
- {by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/src/by_framework_langgraph/adapter.py +22 -0
- {by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/tests/test_adapter.py +59 -0
- {by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/.gitignore +0 -0
- {by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/README.md +0 -0
- {by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/src/by_framework_langgraph/__init__.py +0 -0
- {by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/src/by_framework_langgraph/_utils.py +0 -0
- {by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/src/by_framework_langgraph/tools.py +0 -0
- {by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/src/by_framework_langgraph/worker.py +0 -0
- {by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/tests/test_tools.py +0 -0
- {by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/tests/test_utils.py +0 -0
|
@@ -525,6 +525,7 @@ class LangGraphAdapter:
|
|
|
525
525
|
self._context, "parent_message_id", ""
|
|
526
526
|
),
|
|
527
527
|
"by_framework_agent_id": getattr(self._context, "current_agent_id", ""),
|
|
528
|
+
"worker_id": getattr(self._context, "worker_id", ""),
|
|
528
529
|
"langgraph_thread_id": self._thread_id,
|
|
529
530
|
}
|
|
530
531
|
return {
|
|
@@ -538,10 +539,31 @@ class LangGraphAdapter:
|
|
|
538
539
|
|
|
539
540
|
with (
|
|
540
541
|
self._phoenix_context_manager(),
|
|
542
|
+
self._langfuse_attribute_propagation_context_manager(),
|
|
541
543
|
self._langfuse_callback_manager(callbacks),
|
|
542
544
|
):
|
|
543
545
|
yield callbacks
|
|
544
546
|
|
|
547
|
+
@contextmanager
|
|
548
|
+
def _langfuse_attribute_propagation_context_manager(self) -> Iterator[None]:
|
|
549
|
+
"""Propagate stable framework metadata to Langfuse child observations."""
|
|
550
|
+
worker_id = str(getattr(self._context, "worker_id", "") or "")
|
|
551
|
+
if not worker_id:
|
|
552
|
+
yield
|
|
553
|
+
return
|
|
554
|
+
|
|
555
|
+
try:
|
|
556
|
+
propagate_attributes = getattr(
|
|
557
|
+
import_module("langfuse"),
|
|
558
|
+
"propagate_attributes",
|
|
559
|
+
)
|
|
560
|
+
except (ImportError, AttributeError):
|
|
561
|
+
yield
|
|
562
|
+
return
|
|
563
|
+
|
|
564
|
+
with propagate_attributes(metadata={"worker_id": worker_id}):
|
|
565
|
+
yield
|
|
566
|
+
|
|
545
567
|
@contextmanager
|
|
546
568
|
def _phoenix_context_manager(self) -> Iterator[None]:
|
|
547
569
|
"""Prepare OpenTelemetry context for Phoenix tracing."""
|
{by_framework_langgraph-0.0.3.dev2 → by_framework_langgraph-0.0.3.dev3}/tests/test_adapter.py
RENAMED
|
@@ -23,6 +23,7 @@ def _make_mock_context(session_id: str = "test-session"):
|
|
|
23
23
|
ctx.message_id = "msg-ctx"
|
|
24
24
|
ctx.parent_message_id = "parent-ctx"
|
|
25
25
|
ctx.current_agent_id = "planner"
|
|
26
|
+
ctx.worker_id = "worker-langgraph-1"
|
|
26
27
|
ctx.redis = AsyncMock()
|
|
27
28
|
ctx.emit_chunk = AsyncMock()
|
|
28
29
|
ctx.ask_user = AsyncMock()
|
|
@@ -225,6 +226,7 @@ class TestAdapterRun:
|
|
|
225
226
|
assert config["metadata"]["langfuse_session_id"] == "test-session"
|
|
226
227
|
assert config["metadata"]["langfuse_user_id"] == "user-1"
|
|
227
228
|
assert config["metadata"]["by_framework_message_id"] == "msg-ctx"
|
|
229
|
+
assert config["metadata"]["worker_id"] == "worker-langgraph-1"
|
|
228
230
|
assert config["metadata"]["langgraph_thread_id"] == "test-session"
|
|
229
231
|
# Callbacks list includes the Langfuse handler(s) plus the token accumulator.
|
|
230
232
|
assert callback_handler in config["callbacks"]
|
|
@@ -239,6 +241,63 @@ class TestAdapterRun:
|
|
|
239
241
|
}
|
|
240
242
|
]
|
|
241
243
|
|
|
244
|
+
@pytest.mark.asyncio
|
|
245
|
+
async def test_propagates_worker_id_to_langfuse_child_observations(
|
|
246
|
+
self, monkeypatch
|
|
247
|
+
):
|
|
248
|
+
"""Langfuse attribute propagation covers nested LangGraph observations."""
|
|
249
|
+
ctx = _make_mock_context()
|
|
250
|
+
graph = MagicMock()
|
|
251
|
+
snapshot = MagicMock()
|
|
252
|
+
snapshot.next = ()
|
|
253
|
+
graph.get_state.return_value = snapshot
|
|
254
|
+
|
|
255
|
+
propagation_events: list[tuple[str, dict[str, str]]] = []
|
|
256
|
+
propagation_active = False
|
|
257
|
+
|
|
258
|
+
class FakePropagation:
|
|
259
|
+
|
|
260
|
+
def __init__(self, metadata):
|
|
261
|
+
self.metadata = metadata
|
|
262
|
+
|
|
263
|
+
def __enter__(self):
|
|
264
|
+
nonlocal propagation_active
|
|
265
|
+
propagation_active = True
|
|
266
|
+
propagation_events.append(("enter", self.metadata))
|
|
267
|
+
|
|
268
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
269
|
+
nonlocal propagation_active
|
|
270
|
+
propagation_events.append(("exit", self.metadata))
|
|
271
|
+
propagation_active = False
|
|
272
|
+
|
|
273
|
+
def fake_propagate_attributes(**kwargs):
|
|
274
|
+
return FakePropagation(metadata=kwargs["metadata"])
|
|
275
|
+
|
|
276
|
+
async def fake_ainvoke(input_data, *, config):
|
|
277
|
+
del input_data
|
|
278
|
+
assert config["metadata"]["worker_id"] == "worker-langgraph-1"
|
|
279
|
+
assert propagation_active is True
|
|
280
|
+
return {"messages": [MagicMock(content="hello")]}
|
|
281
|
+
|
|
282
|
+
graph.ainvoke = fake_ainvoke
|
|
283
|
+
monkeypatch.setitem(
|
|
284
|
+
sys.modules,
|
|
285
|
+
"langfuse",
|
|
286
|
+
SimpleNamespace(propagate_attributes=fake_propagate_attributes),
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
adapter = LangGraphAdapter(graph, ctx, stream=False)
|
|
290
|
+
|
|
291
|
+
result = await adapter.run(
|
|
292
|
+
AskAgentCommand(header=_make_header(), content="write a poem")
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
assert result == "hello"
|
|
296
|
+
assert propagation_events == [
|
|
297
|
+
("enter", {"worker_id": "worker-langgraph-1"}),
|
|
298
|
+
("exit", {"worker_id": "worker-langgraph-1"}),
|
|
299
|
+
]
|
|
300
|
+
|
|
242
301
|
@pytest.mark.asyncio
|
|
243
302
|
async def test_skips_langfuse_callback_when_provider_package_missing(
|
|
244
303
|
self, monkeypatch
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|