copilotkit 0.1.90__tar.gz → 0.1.91__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.
- {copilotkit-0.1.90 → copilotkit-0.1.91}/PKG-INFO +2 -2
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/copilotkit_lg_middleware.py +97 -2
- {copilotkit-0.1.90 → copilotkit-0.1.91}/pyproject.toml +1 -1
- {copilotkit-0.1.90 → copilotkit-0.1.91}/README.md +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/__init__.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/a2ui.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/action.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/agent.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/crewai/__init__.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/crewai/copilotkit_integration.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/crewai/crewai_agent.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/crewai/crewai_sdk.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/exc.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/header_propagation.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/html.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/integrations/__init__.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/integrations/fastapi.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/langchain.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/langgraph.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/langgraph_agui_agent.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/logging.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/parameter.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/protocol.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/py.typed +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/runloop.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/sdk.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/types.py +0 -0
- {copilotkit-0.1.90 → copilotkit-0.1.91}/copilotkit/utils.py +0 -0
|
@@ -16,7 +16,7 @@ Example:
|
|
|
16
16
|
|
|
17
17
|
import json
|
|
18
18
|
import re
|
|
19
|
-
from typing import Any, Callable, Awaitable, ClassVar, Iterable,
|
|
19
|
+
from typing import Any, Callable, Awaitable, ClassVar, Iterable, Union
|
|
20
20
|
|
|
21
21
|
from langchain_core.messages import AIMessage, SystemMessage, ToolMessage
|
|
22
22
|
from langchain.agents.middleware import (
|
|
@@ -27,7 +27,7 @@ from langchain.agents.middleware import (
|
|
|
27
27
|
)
|
|
28
28
|
from langgraph.runtime import Runtime
|
|
29
29
|
|
|
30
|
-
from .header_propagation import install_httpx_hook
|
|
30
|
+
from .header_propagation import install_httpx_hook, set_forwarded_headers
|
|
31
31
|
from .langgraph import CopilotKitProperties
|
|
32
32
|
|
|
33
33
|
# Track which httpx clients already have the header-propagation hook installed
|
|
@@ -35,6 +35,99 @@ from .langgraph import CopilotKitProperties
|
|
|
35
35
|
_hooked_clients: set[int] = set()
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
def _extract_forwarded_headers_from_config() -> None:
|
|
39
|
+
"""Extract raw ``x-*`` headers from the current LangGraph RunnableConfig and
|
|
40
|
+
push them into the header-propagation ContextVar so the httpx hook can
|
|
41
|
+
forward them on outgoing LLM requests.
|
|
42
|
+
|
|
43
|
+
When an agent runs inside **langgraph-api** with
|
|
44
|
+
``LANGGRAPH_HTTP={"configurable_headers":{"include":["x-*"]}}``,
|
|
45
|
+
the server copies inbound HTTP ``x-*`` headers into
|
|
46
|
+
``config["configurable"]`` as individual keys (e.g.
|
|
47
|
+
``configurable["x-aimock-context"] = "value"``). This function reads those
|
|
48
|
+
keys and calls :func:`set_forwarded_headers` so they propagate to the
|
|
49
|
+
underlying LLM provider SDK via the httpx event hook.
|
|
50
|
+
|
|
51
|
+
Precedence: the wrapper dict ``copilotkit_forwarded_headers`` (if present)
|
|
52
|
+
takes priority over raw ``x-*`` keys. Raw keys are only used when the
|
|
53
|
+
wrapper dict is absent or does not contain a given header.
|
|
54
|
+
|
|
55
|
+
Safe to call outside a runnable context (e.g. in unit tests) — silently
|
|
56
|
+
returns without doing anything if ``get_config()`` raises.
|
|
57
|
+
"""
|
|
58
|
+
try:
|
|
59
|
+
from langgraph.config import (
|
|
60
|
+
get_config,
|
|
61
|
+
) # local import to avoid hard dep at module level
|
|
62
|
+
|
|
63
|
+
config = get_config()
|
|
64
|
+
except ImportError:
|
|
65
|
+
return
|
|
66
|
+
except RuntimeError:
|
|
67
|
+
# No active runnable context — clear the ContextVar so stale headers
|
|
68
|
+
# from a prior request in the same async context do not leak through.
|
|
69
|
+
set_forwarded_headers({})
|
|
70
|
+
return
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
headers: dict[str, str] = {}
|
|
74
|
+
|
|
75
|
+
# Sources to scan: config["context"] (LangGraph >=0.6.0) and
|
|
76
|
+
# config["configurable"] (all versions).
|
|
77
|
+
context = config.get("context") or {}
|
|
78
|
+
configurable = config.get("configurable") or {}
|
|
79
|
+
|
|
80
|
+
# 1) Wrapper-dict path (highest priority): these are headers that
|
|
81
|
+
# CopilotKit explicitly bundled under a known key. Process context
|
|
82
|
+
# first with first-write-wins so context takes precedence over
|
|
83
|
+
# configurable (LangGraph >=0.6.0 introduced context as the newer
|
|
84
|
+
# preferred mechanism).
|
|
85
|
+
for src in (context, configurable):
|
|
86
|
+
if not isinstance(src, dict):
|
|
87
|
+
continue
|
|
88
|
+
wrapper = src.get("copilotkit_forwarded_headers")
|
|
89
|
+
if isinstance(wrapper, dict):
|
|
90
|
+
for k, v in wrapper.items():
|
|
91
|
+
lk = k.lower() if isinstance(k, str) else k
|
|
92
|
+
if isinstance(k, str) and isinstance(v, str) and lk not in headers:
|
|
93
|
+
headers[lk] = v
|
|
94
|
+
|
|
95
|
+
# 2) Raw x-* keys directly on context and configurable. These appear
|
|
96
|
+
# when langgraph-api's configurable_headers mechanism forwards inbound
|
|
97
|
+
# HTTP headers as individual configurable entries.
|
|
98
|
+
for src in (context, configurable):
|
|
99
|
+
if not isinstance(src, dict):
|
|
100
|
+
continue
|
|
101
|
+
for k, v in src.items():
|
|
102
|
+
if (
|
|
103
|
+
isinstance(k, str)
|
|
104
|
+
and k.lower().startswith("x-")
|
|
105
|
+
and isinstance(v, str)
|
|
106
|
+
):
|
|
107
|
+
# Don't overwrite wrapper-dict values (wrapper > raw).
|
|
108
|
+
# Lowercase at insertion so precedence checks are
|
|
109
|
+
# deterministic regardless of source casing.
|
|
110
|
+
lk = k.lower()
|
|
111
|
+
if lk not in headers:
|
|
112
|
+
headers[lk] = v
|
|
113
|
+
|
|
114
|
+
# Always set the ContextVar — even with an empty dict — so stale
|
|
115
|
+
# headers from previous calls in the same async context do not leak
|
|
116
|
+
# into this one.
|
|
117
|
+
set_forwarded_headers(headers)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
# Header forwarding is best-effort. Never block the LLM call.
|
|
120
|
+
# Clear the ContextVar so stale headers from a prior request do not
|
|
121
|
+
# leak through on failure.
|
|
122
|
+
set_forwarded_headers({})
|
|
123
|
+
import logging
|
|
124
|
+
|
|
125
|
+
logging.getLogger(__name__).debug(
|
|
126
|
+
"Header forwarding extraction failed; continuing without forwarded headers: %s",
|
|
127
|
+
e,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
38
131
|
def _ensure_httpx_hook(model: Any) -> None:
|
|
39
132
|
"""Install the header-propagation httpx hook on a LangChain chat model's
|
|
40
133
|
underlying HTTP client(s), if present. No-op for models that don't expose
|
|
@@ -172,6 +265,7 @@ class CopilotKitMiddleware(AgentMiddleware[StateSchema, Any]):
|
|
|
172
265
|
request: ModelRequest,
|
|
173
266
|
handler: Callable[[ModelRequest], ModelResponse],
|
|
174
267
|
) -> ModelResponse:
|
|
268
|
+
_extract_forwarded_headers_from_config()
|
|
175
269
|
_ensure_httpx_hook(request.model)
|
|
176
270
|
request = self._apply_state_note(request)
|
|
177
271
|
frontend_tools = request.state.get("copilotkit", {}).get("actions", [])
|
|
@@ -361,6 +455,7 @@ class CopilotKitMiddleware(AgentMiddleware[StateSchema, Any]):
|
|
|
361
455
|
request: ModelRequest,
|
|
362
456
|
handler: Callable[[ModelRequest], Awaitable[ModelResponse]],
|
|
363
457
|
) -> ModelResponse:
|
|
458
|
+
_extract_forwarded_headers_from_config()
|
|
364
459
|
_ensure_httpx_hook(request.model)
|
|
365
460
|
self._fix_messages_for_bedrock(request.messages)
|
|
366
461
|
request = self._apply_state_note(request)
|
|
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
|