agent-api-server 2.2.1a3__tar.gz → 2.2.1a4__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.
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/PKG-INFO +1 -1
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/adapters/openclaw_adapter/openclaw_adapter.py +26 -11
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/api/thread.py +29 -7
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/pyproject.toml +1 -1
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/sdk/client.py +12 -6
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/README.md +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/adapters/__init__.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/adapters/langgraph_adapter/__init__.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/adapters/langgraph_adapter/formatter.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/adapters/langgraph_adapter/langgraph_adapter.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/adapters/openclaw_adapter/__init__.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/agent_api_server.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/api/__init__.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/api/config.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/api/graph.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/api/router.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/api/schema.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/client/css/styles.css +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/client/favicon.ico +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/client/index.html +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/client/js/app.js +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/client/js/index.umd.js +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/common/__init__.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/common/config.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/common/crypto.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/common/formatting.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/common/logging.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/common/nats.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/common/postgres.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/common/redis.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/__init__.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/loader.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/model/__init__.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/model/agent_models.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/model/base_model.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/model/detect_message.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/model/dynamic_llm.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/model/input_normalization.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/model/middleware.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/model/model_info.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/model/schema_utils.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/model/streaming.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/runtime/__init__.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/runtime/base.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/core/runtime/manager.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/demo.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/integration/__init__.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/integration/listener.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/integration/registry.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/logging.json +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/sdk/__init__.py +0 -0
- {agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/service.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-api-server
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1a4
|
|
4
4
|
Summary: A Langgraph agent API server that implements Langgraph agent's web capabilities and can interact with chatbot
|
|
5
5
|
Keywords: fastapi,langgraph,agent,api-server
|
|
6
6
|
Requires-Python: >=3.11,<3.14
|
{agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/adapters/openclaw_adapter/openclaw_adapter.py
RENAMED
|
@@ -694,7 +694,7 @@ class OpenClawAgentAdapter(BaseAgentAdapter):
|
|
|
694
694
|
content_parts: list[str] = []
|
|
695
695
|
tool_calls: list[dict[str, Any]] = []
|
|
696
696
|
last_message: ChatMessage | None = None
|
|
697
|
-
|
|
697
|
+
last_real_tool_message: ChatMessage | None = None
|
|
698
698
|
event_iterator = agent.execute_stream_typed(query, options=options).__aiter__()
|
|
699
699
|
|
|
700
700
|
while True:
|
|
@@ -708,12 +708,12 @@ class OpenClawAgentAdapter(BaseAgentAdapter):
|
|
|
708
708
|
break
|
|
709
709
|
except asyncio.TimeoutError:
|
|
710
710
|
logger.warning(
|
|
711
|
-
"OpenClaw run stream idle timeout without DoneEvent; agent=%s session=%s timeout_s=%s last_message_type=%s
|
|
711
|
+
"OpenClaw run stream idle timeout without DoneEvent; agent=%s session=%s timeout_s=%s last_message_type=%s last_real_tool_message=%s",
|
|
712
712
|
self.agent_id,
|
|
713
713
|
session_name,
|
|
714
714
|
timeout,
|
|
715
715
|
last_message.type if last_message is not None else None,
|
|
716
|
-
|
|
716
|
+
last_real_tool_message is not None,
|
|
717
717
|
)
|
|
718
718
|
break
|
|
719
719
|
|
|
@@ -750,8 +750,8 @@ class OpenClawAgentAdapter(BaseAgentAdapter):
|
|
|
750
750
|
session_name=session_name,
|
|
751
751
|
)
|
|
752
752
|
last_message = tool_message
|
|
753
|
-
if self.
|
|
754
|
-
|
|
753
|
+
if self._is_real_tool_message(tool_message):
|
|
754
|
+
last_real_tool_message = tool_message
|
|
755
755
|
continue
|
|
756
756
|
|
|
757
757
|
if isinstance(event, DoneEvent):
|
|
@@ -773,7 +773,7 @@ class OpenClawAgentAdapter(BaseAgentAdapter):
|
|
|
773
773
|
session_name=session_name,
|
|
774
774
|
tool_calls=tool_calls,
|
|
775
775
|
last_message=last_message,
|
|
776
|
-
|
|
776
|
+
last_real_tool_message=last_real_tool_message,
|
|
777
777
|
extra_metadata={"token_usage": serialize_data(event.token_usage), "stop_reason": event.stop_reason},
|
|
778
778
|
)
|
|
779
779
|
|
|
@@ -785,7 +785,7 @@ class OpenClawAgentAdapter(BaseAgentAdapter):
|
|
|
785
785
|
session_name=session_name,
|
|
786
786
|
tool_calls=tool_calls,
|
|
787
787
|
last_message=last_message,
|
|
788
|
-
|
|
788
|
+
last_real_tool_message=last_real_tool_message,
|
|
789
789
|
)
|
|
790
790
|
|
|
791
791
|
def _build_ai_message(
|
|
@@ -817,12 +817,12 @@ class OpenClawAgentAdapter(BaseAgentAdapter):
|
|
|
817
817
|
session_name: str,
|
|
818
818
|
tool_calls: list[dict[str, Any]],
|
|
819
819
|
last_message: ChatMessage | None,
|
|
820
|
-
|
|
820
|
+
last_real_tool_message: ChatMessage | None,
|
|
821
821
|
extra_metadata: dict[str, Any] | None = None,
|
|
822
822
|
) -> ChatMessage:
|
|
823
|
-
if
|
|
824
|
-
return
|
|
825
|
-
update={"response_metadata": {**
|
|
823
|
+
if last_real_tool_message is not None:
|
|
824
|
+
return last_real_tool_message.model_copy(
|
|
825
|
+
update={"response_metadata": {**last_real_tool_message.response_metadata, **(extra_metadata or {})}}
|
|
826
826
|
)
|
|
827
827
|
|
|
828
828
|
if last_message is not None and last_message.type == "ai":
|
|
@@ -854,6 +854,21 @@ class OpenClawAgentAdapter(BaseAgentAdapter):
|
|
|
854
854
|
)
|
|
855
855
|
return not any(re.match(pattern, content) for pattern in low_signal_patterns)
|
|
856
856
|
|
|
857
|
+
@staticmethod
|
|
858
|
+
def _is_real_tool_message(message: ChatMessage) -> bool:
|
|
859
|
+
content = message.content.strip()
|
|
860
|
+
if not OpenClawAgentAdapter._is_semantic_tool_message(message):
|
|
861
|
+
return False
|
|
862
|
+
if message.content_type != "text":
|
|
863
|
+
return True
|
|
864
|
+
|
|
865
|
+
low_value_status_patterns = (
|
|
866
|
+
r"^(done|ok|success|completed)\.?$",
|
|
867
|
+
r"^(analysis|task|job) (done|completed|finished)\.?$",
|
|
868
|
+
r"^(saved|written) successfully\.?$",
|
|
869
|
+
)
|
|
870
|
+
return not any(re.match(pattern, content, re.IGNORECASE) for pattern in low_value_status_patterns)
|
|
871
|
+
|
|
857
872
|
@staticmethod
|
|
858
873
|
def _resolve_run_completion_idle_timeout_seconds(
|
|
859
874
|
settings: dict[str, Any],
|
|
@@ -57,15 +57,34 @@ def _ensure_thread_ready(state: ThreadState, thread_id: str) -> None:
|
|
|
57
57
|
)
|
|
58
58
|
|
|
59
59
|
|
|
60
|
+
def _thread_agent_conflict(thread_id: str, existing_graph_name: str, requested_graph_name: str) -> HTTPException:
|
|
61
|
+
return HTTPException(
|
|
62
|
+
status_code=status.HTTP_409_CONFLICT,
|
|
63
|
+
detail={
|
|
64
|
+
"error": "thread_agent_conflict",
|
|
65
|
+
"message": "Thread is already bound to a different agent",
|
|
66
|
+
"thread_id": thread_id,
|
|
67
|
+
"existing_graph_name": existing_graph_name,
|
|
68
|
+
"requested_graph_name": requested_graph_name,
|
|
69
|
+
},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _ensure_thread_matches_graph(
|
|
74
|
+
state: ThreadState,
|
|
75
|
+
*,
|
|
76
|
+
thread_id: str,
|
|
77
|
+
requested_graph_name: str | None = None,
|
|
78
|
+
) -> None:
|
|
79
|
+
if requested_graph_name and state.graph_name != requested_graph_name:
|
|
80
|
+
raise _thread_agent_conflict(thread_id, state.graph_name, requested_graph_name)
|
|
81
|
+
|
|
82
|
+
|
|
60
83
|
async def _resolve_thread_for_execution(thread_id: str, request: Request) -> ThreadState:
|
|
61
84
|
graph_name = request.headers.get("X-Agent-Name", "")
|
|
62
85
|
state = await _get_or_create_thread(thread_id, graph_name)
|
|
63
86
|
_ensure_thread_ready(state, thread_id)
|
|
64
|
-
|
|
65
|
-
if graph_name:
|
|
66
|
-
logger.info("Graph name overridden by header: %s", graph_name)
|
|
67
|
-
state.graph_name = graph_name
|
|
68
|
-
|
|
87
|
+
_ensure_thread_matches_graph(state, thread_id=thread_id, requested_graph_name=graph_name or None)
|
|
69
88
|
return state
|
|
70
89
|
|
|
71
90
|
|
|
@@ -114,6 +133,7 @@ async def _get_or_create_thread(thread_id: str, graph_name: Optional[str] = "")
|
|
|
114
133
|
storage = AsyncRedisThreadStorage.get_worker_instance()
|
|
115
134
|
thread_data = await storage.get_thread(thread_id)
|
|
116
135
|
if thread_data:
|
|
136
|
+
_ensure_thread_matches_graph(thread_data, thread_id=thread_id, requested_graph_name=graph_name or None)
|
|
117
137
|
return thread_data
|
|
118
138
|
|
|
119
139
|
if not graph_name:
|
|
@@ -248,10 +268,12 @@ async def create_thread(graph_name: str, thread_id: Optional[str] = None) -> Thr
|
|
|
248
268
|
if thread_id:
|
|
249
269
|
try:
|
|
250
270
|
state = await _get_existing_thread_or_404(thread_id)
|
|
271
|
+
_ensure_thread_matches_graph(state, thread_id=thread_id, requested_graph_name=graph_name)
|
|
251
272
|
logger.info("%s already exists, returning existing thread", thread_id)
|
|
252
273
|
return _thread_info(state)
|
|
253
|
-
except HTTPException:
|
|
254
|
-
|
|
274
|
+
except HTTPException as exc:
|
|
275
|
+
if exc.status_code != status.HTTP_404_NOT_FOUND:
|
|
276
|
+
raise
|
|
255
277
|
|
|
256
278
|
storage = None
|
|
257
279
|
thread_state = None
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from typing import Any, AsyncIterator, Iterator
|
|
2
|
+
from uuid import uuid4
|
|
2
3
|
|
|
3
4
|
from core import AgentDefinition, AgentExecutionContext, AgentFramework, AgentManager, get_agent_manager
|
|
4
5
|
from core import BaseAgentAdapter
|
|
@@ -177,6 +178,10 @@ class AgentSDK:
|
|
|
177
178
|
await self.manager.get_definition(resolved_agent_name)
|
|
178
179
|
return {}
|
|
179
180
|
|
|
181
|
+
@staticmethod
|
|
182
|
+
def _resolve_thread_id(thread_id: str | None) -> str:
|
|
183
|
+
return thread_id or f"sdk-{uuid4().hex}"
|
|
184
|
+
|
|
180
185
|
@staticmethod
|
|
181
186
|
def _build_context(
|
|
182
187
|
agent_name: str,
|
|
@@ -201,7 +206,7 @@ class AgentSDK:
|
|
|
201
206
|
self,
|
|
202
207
|
agent_name: str,
|
|
203
208
|
query: str | dict[str, Any],
|
|
204
|
-
thread_id: str,
|
|
209
|
+
thread_id: str | None,
|
|
205
210
|
ts_tenant: str | None,
|
|
206
211
|
ei_token: str | None,
|
|
207
212
|
attachments: list[dict[str, Any]] | None,
|
|
@@ -209,9 +214,10 @@ class AgentSDK:
|
|
|
209
214
|
use_system_llm: bool | str | None,
|
|
210
215
|
) -> tuple[dict[str, Any], AgentExecutionContext]:
|
|
211
216
|
inputs, normalized_attachments = normalize_agent_query(query, attachments)
|
|
217
|
+
resolved_thread_id = self._resolve_thread_id(thread_id)
|
|
212
218
|
context = self._build_context(
|
|
213
219
|
agent_name=agent_name,
|
|
214
|
-
thread_id=
|
|
220
|
+
thread_id=resolved_thread_id,
|
|
215
221
|
ts_tenant=ts_tenant,
|
|
216
222
|
ei_token=ei_token,
|
|
217
223
|
attachments=normalized_attachments,
|
|
@@ -225,7 +231,7 @@ class AgentSDK:
|
|
|
225
231
|
agent_name: str | dict[str, Any] | None = None,
|
|
226
232
|
query: str | dict[str, Any] | None = None,
|
|
227
233
|
*,
|
|
228
|
-
thread_id: str =
|
|
234
|
+
thread_id: str | None = None,
|
|
229
235
|
ts_tenant: str | None = None,
|
|
230
236
|
ei_token: str | None = None,
|
|
231
237
|
attachments: list[dict[str, Any]] | None = None,
|
|
@@ -251,7 +257,7 @@ class AgentSDK:
|
|
|
251
257
|
agent_name: str | dict[str, Any] | None = None,
|
|
252
258
|
query: str | dict[str, Any] | None = None,
|
|
253
259
|
*,
|
|
254
|
-
thread_id: str =
|
|
260
|
+
thread_id: str | None = None,
|
|
255
261
|
ts_tenant: str | None = None,
|
|
256
262
|
ei_token: str | None = None,
|
|
257
263
|
attachments: list[dict[str, Any]] | None = None,
|
|
@@ -277,7 +283,7 @@ class AgentSDK:
|
|
|
277
283
|
agent_name: str | dict[str, Any] | None = None,
|
|
278
284
|
query: str | dict[str, Any] | None = None,
|
|
279
285
|
*,
|
|
280
|
-
thread_id: str =
|
|
286
|
+
thread_id: str | None = None,
|
|
281
287
|
ts_tenant: str | None = None,
|
|
282
288
|
ei_token: str | None = None,
|
|
283
289
|
attachments: list[dict[str, Any]] | None = None,
|
|
@@ -304,7 +310,7 @@ class AgentSDK:
|
|
|
304
310
|
agent_name: str | dict[str, Any] | None = None,
|
|
305
311
|
query: str | dict[str, Any] | None = None,
|
|
306
312
|
*,
|
|
307
|
-
thread_id: str =
|
|
313
|
+
thread_id: str | None = None,
|
|
308
314
|
ts_tenant: str | None = None,
|
|
309
315
|
ei_token: str | None = None,
|
|
310
316
|
attachments: list[dict[str, Any]] | None = None,
|
|
File without changes
|
|
File without changes
|
{agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/adapters/langgraph_adapter/__init__.py
RENAMED
|
File without changes
|
{agent_api_server-2.2.1a3 → agent_api_server-2.2.1a4}/adapters/langgraph_adapter/formatter.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|