copilotkit 0.1.76__tar.gz → 0.1.78a0__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.
Files changed (26) hide show
  1. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/PKG-INFO +2 -2
  2. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/copilotkit_lg_middleware.py +96 -1
  3. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/pyproject.toml +2 -2
  4. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/README.md +0 -0
  5. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/__init__.py +0 -0
  6. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/action.py +0 -0
  7. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/agent.py +0 -0
  8. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/crewai/__init__.py +0 -0
  9. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/crewai/copilotkit_integration.py +0 -0
  10. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/crewai/crewai_agent.py +0 -0
  11. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/crewai/crewai_sdk.py +0 -0
  12. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/exc.py +0 -0
  13. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/html.py +0 -0
  14. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/integrations/__init__.py +0 -0
  15. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/integrations/fastapi.py +0 -0
  16. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/langchain.py +0 -0
  17. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/langgraph.py +0 -0
  18. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/langgraph_agent.py +0 -0
  19. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/langgraph_agui_agent.py +0 -0
  20. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/logging.py +0 -0
  21. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/parameter.py +0 -0
  22. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/protocol.py +0 -0
  23. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/runloop.py +0 -0
  24. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/sdk.py +0 -0
  25. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/types.py +0 -0
  26. {copilotkit-0.1.76 → copilotkit-0.1.78a0}/copilotkit/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: copilotkit
3
- Version: 0.1.76
3
+ Version: 0.1.78a0
4
4
  Summary: CopilotKit python SDK
5
5
  License: MIT
6
6
  Keywords: copilot,copilotkit,langgraph,langchain,ai,langsmith,langserve
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3.10
13
13
  Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Provides-Extra: crewai
16
- Requires-Dist: ag-ui-langgraph[fastapi] (>=0.0.23)
16
+ Requires-Dist: ag-ui-langgraph[fastapi] (>=0.0.24)
17
17
  Requires-Dist: crewai (==0.118.0) ; extra == "crewai"
18
18
  Requires-Dist: fastapi (>=0.115.0,<0.116.0)
19
19
  Requires-Dist: langchain (>=0.3.0)
@@ -14,9 +14,10 @@ Example:
14
14
  )
15
15
  """
16
16
 
17
+ import json
17
18
  from typing import Any, Callable, Awaitable, ClassVar, List
18
19
 
19
- from langchain_core.messages import AIMessage
20
+ from langchain_core.messages import AIMessage, SystemMessage
20
21
  from langchain.agents.middleware import (
21
22
  AgentMiddleware,
22
23
  AgentState,
@@ -75,6 +76,100 @@ class CopilotKitMiddleware(AgentMiddleware[StateSchema, Any]):
75
76
 
76
77
  return await handler(request.override(tools=merged_tools))
77
78
 
79
+ # Inject app context before agent runs
80
+ def before_agent(
81
+ self,
82
+ state: StateSchema,
83
+ runtime: Runtime[Any],
84
+ ) -> dict[str, Any] | None:
85
+ messages = state.get("messages", [])
86
+
87
+ if not messages:
88
+ return None
89
+
90
+ # Get app context from state or runtime
91
+ copilotkit_state = state.get("copilotkit", {})
92
+ app_context = copilotkit_state.get("context") or getattr(runtime, "context", None)
93
+
94
+ # Check if app_context is missing or empty
95
+ if not app_context:
96
+ return None
97
+ if isinstance(app_context, str) and app_context.strip() == "":
98
+ return None
99
+ if isinstance(app_context, dict) and len(app_context) == 0:
100
+ return None
101
+
102
+ # Create the context content
103
+ if isinstance(app_context, str):
104
+ context_content = app_context
105
+ else:
106
+ context_content = json.dumps(app_context, indent=2)
107
+
108
+ context_message_content = f"App Context:\n{context_content}"
109
+ context_message_prefix = "App Context:\n"
110
+
111
+ # Helper to get message content as string
112
+ def get_content_string(msg: Any) -> str | None:
113
+ content = getattr(msg, "content", None)
114
+ if isinstance(content, str):
115
+ return content
116
+ if isinstance(content, list) and content and isinstance(content[0], dict):
117
+ return content[0].get("text")
118
+ return None
119
+
120
+ # Find the first system/developer message (not our context message)
121
+ # to determine where to insert our context message (right after it)
122
+ first_system_index = -1
123
+
124
+ for i, msg in enumerate(messages):
125
+ msg_type = getattr(msg, "type", None)
126
+ if msg_type in ("system", "developer"):
127
+ content = get_content_string(msg)
128
+ # Skip if this is our own context message
129
+ if content and content.startswith(context_message_prefix):
130
+ continue
131
+ first_system_index = i
132
+ break
133
+
134
+ # Check if our context message already exists
135
+ existing_context_index = -1
136
+ for i, msg in enumerate(messages):
137
+ msg_type = getattr(msg, "type", None)
138
+ if msg_type in ("system", "developer"):
139
+ content = get_content_string(msg)
140
+ if content and content.startswith(context_message_prefix):
141
+ existing_context_index = i
142
+ break
143
+
144
+ # Create the context message
145
+ context_message = SystemMessage(content=context_message_content)
146
+
147
+ if existing_context_index != -1:
148
+ # Replace existing context message
149
+ updated_messages = list(messages)
150
+ updated_messages[existing_context_index] = context_message
151
+ else:
152
+ # Insert after the first system message, or at position 0 if no system message
153
+ insert_index = first_system_index + 1 if first_system_index != -1 else 0
154
+ updated_messages = [
155
+ *messages[:insert_index],
156
+ context_message,
157
+ *messages[insert_index:],
158
+ ]
159
+
160
+ return {
161
+ **state,
162
+ "messages": updated_messages,
163
+ }
164
+
165
+ async def abefore_agent(
166
+ self,
167
+ state: StateSchema,
168
+ runtime: Runtime[Any],
169
+ ) -> dict[str, Any] | None:
170
+ # Delegate to sync implementation
171
+ return self.before_agent(state, runtime)
172
+
78
173
  # Intercept frontend tool calls after model returns, before ToolNode executes
79
174
  def after_model(
80
175
  self,
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "copilotkit"
3
- version = "0.1.76"
3
+ version = "0.1.78-alpha.0"
4
4
  description = "CopilotKit python SDK"
5
5
  authors = ["Markus Ecker <markus.ecker@gmail.com>"]
6
6
  license = "MIT"
@@ -14,7 +14,7 @@ python = ">=3.10,<3.13"
14
14
  langgraph = {version = ">=0.3.25,<1.1.0"}
15
15
  langchain = {version = ">=0.3.0"}
16
16
  crewai = { version = "0.118.0", optional = true }
17
- ag-ui-langgraph = { version = ">=0.0.23", extras = ["fastapi"] }
17
+ ag-ui-langgraph = { version = ">=0.0.24", extras = ["fastapi"] }
18
18
  fastapi = "^0.115.0"
19
19
  partialjson = "^0.0.8"
20
20
  toml = "^0.10.2"
File without changes