agent-api-server 2.2.1a2__tar.gz → 2.2.1a3__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.1a2 → agent_api_server-2.2.1a3}/PKG-INFO +2 -2
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/adapters/openclaw_adapter/openclaw_adapter.py +220 -21
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/pyproject.toml +1 -1
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/README.md +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/adapters/__init__.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/adapters/langgraph_adapter/__init__.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/adapters/langgraph_adapter/formatter.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/adapters/langgraph_adapter/langgraph_adapter.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/adapters/openclaw_adapter/__init__.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/agent_api_server.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/api/__init__.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/api/config.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/api/graph.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/api/router.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/api/schema.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/api/thread.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/client/css/styles.css +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/client/favicon.ico +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/client/index.html +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/client/js/app.js +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/client/js/index.umd.js +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/common/__init__.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/common/config.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/common/crypto.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/common/formatting.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/common/logging.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/common/nats.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/common/postgres.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/common/redis.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/__init__.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/loader.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/model/__init__.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/model/agent_models.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/model/base_model.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/model/detect_message.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/model/dynamic_llm.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/model/input_normalization.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/model/middleware.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/model/model_info.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/model/schema_utils.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/model/streaming.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/runtime/__init__.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/runtime/base.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/core/runtime/manager.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/demo.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/integration/__init__.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/integration/listener.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/integration/registry.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/logging.json +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/sdk/__init__.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/sdk/client.py +0 -0
- {agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/service.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-api-server
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1a3
|
|
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.1a2 → agent_api_server-2.2.1a3}/adapters/openclaw_adapter/openclaw_adapter.py
RENAMED
|
@@ -3,6 +3,7 @@ import hashlib
|
|
|
3
3
|
import json
|
|
4
4
|
import logging
|
|
5
5
|
import platform
|
|
6
|
+
import re
|
|
6
7
|
import shlex
|
|
7
8
|
import time
|
|
8
9
|
from pathlib import Path
|
|
@@ -317,6 +318,10 @@ class OpenClawAgentAdapter(BaseAgentAdapter):
|
|
|
317
318
|
self.session_name = self.settings.get("session_name", "main")
|
|
318
319
|
self.query_field = self.settings.get("query_field")
|
|
319
320
|
self.execution_settings = dict(self.settings.get("execution_options") or {})
|
|
321
|
+
self.run_completion_idle_timeout_seconds = self._resolve_run_completion_idle_timeout_seconds(
|
|
322
|
+
self.settings,
|
|
323
|
+
self.execution_settings,
|
|
324
|
+
)
|
|
320
325
|
self.workspace = self._resolve_workspace(self.settings.get("workspace"))
|
|
321
326
|
self.agent_config = dict(self.settings.get("agent_config") or {})
|
|
322
327
|
|
|
@@ -381,8 +386,11 @@ class OpenClawAgentAdapter(BaseAgentAdapter):
|
|
|
381
386
|
session_name = self._resolve_session_name(context=context)
|
|
382
387
|
try:
|
|
383
388
|
agent = await self._load_agent(client, context=context)
|
|
384
|
-
|
|
385
|
-
|
|
389
|
+
return await self._collect_run_result(
|
|
390
|
+
agent=agent,
|
|
391
|
+
query=self._resolve_query(inputs),
|
|
392
|
+
context=context,
|
|
393
|
+
session_name=session_name,
|
|
386
394
|
options=self._build_execution_options(context),
|
|
387
395
|
)
|
|
388
396
|
except Exception as exc:
|
|
@@ -390,25 +398,6 @@ class OpenClawAgentAdapter(BaseAgentAdapter):
|
|
|
390
398
|
finally:
|
|
391
399
|
await client.close()
|
|
392
400
|
|
|
393
|
-
if not result.success and result.error_message:
|
|
394
|
-
raise RuntimeError(result.error_message)
|
|
395
|
-
|
|
396
|
-
return ChatMessage(
|
|
397
|
-
type="ai",
|
|
398
|
-
content_type=detect_content_type(result.content),
|
|
399
|
-
content=result.content,
|
|
400
|
-
tool_calls=[self._normalize_tool_call(tool_call) for tool_call in result.tool_calls],
|
|
401
|
-
response_metadata={
|
|
402
|
-
"latency_ms": result.latency_ms,
|
|
403
|
-
"stop_reason": result.stop_reason,
|
|
404
|
-
"token_usage": serialize_data(result.token_usage),
|
|
405
|
-
"completed_at": serialize_data(result.completed_at),
|
|
406
|
-
"conversation_id": self._resolve_conversation_id(context),
|
|
407
|
-
"session_name": session_name,
|
|
408
|
-
},
|
|
409
|
-
references=[],
|
|
410
|
-
)
|
|
411
|
-
|
|
412
401
|
async def stream(self, inputs: dict[str, Any], context: AgentExecutionContext) -> AsyncIterator[str]:
|
|
413
402
|
client = await self._connect_client()
|
|
414
403
|
content_parts: list[str] = []
|
|
@@ -693,6 +682,216 @@ class OpenClawAgentAdapter(BaseAgentAdapter):
|
|
|
693
682
|
options["attachments"] = attachments
|
|
694
683
|
return ExecutionOptions(**options)
|
|
695
684
|
|
|
685
|
+
async def _collect_run_result(
|
|
686
|
+
self,
|
|
687
|
+
*,
|
|
688
|
+
agent,
|
|
689
|
+
query: str,
|
|
690
|
+
context: AgentExecutionContext,
|
|
691
|
+
session_name: str,
|
|
692
|
+
options,
|
|
693
|
+
) -> ChatMessage:
|
|
694
|
+
content_parts: list[str] = []
|
|
695
|
+
tool_calls: list[dict[str, Any]] = []
|
|
696
|
+
last_message: ChatMessage | None = None
|
|
697
|
+
last_tool_message: ChatMessage | None = None
|
|
698
|
+
event_iterator = agent.execute_stream_typed(query, options=options).__aiter__()
|
|
699
|
+
|
|
700
|
+
while True:
|
|
701
|
+
timeout = self.run_completion_idle_timeout_seconds if last_message is not None else None
|
|
702
|
+
try:
|
|
703
|
+
if timeout is None:
|
|
704
|
+
event = await anext(event_iterator)
|
|
705
|
+
else:
|
|
706
|
+
event = await asyncio.wait_for(anext(event_iterator), timeout=timeout)
|
|
707
|
+
except StopAsyncIteration:
|
|
708
|
+
break
|
|
709
|
+
except asyncio.TimeoutError:
|
|
710
|
+
logger.warning(
|
|
711
|
+
"OpenClaw run stream idle timeout without DoneEvent; agent=%s session=%s timeout_s=%s last_message_type=%s last_tool_message=%s",
|
|
712
|
+
self.agent_id,
|
|
713
|
+
session_name,
|
|
714
|
+
timeout,
|
|
715
|
+
last_message.type if last_message is not None else None,
|
|
716
|
+
last_tool_message is not None,
|
|
717
|
+
)
|
|
718
|
+
break
|
|
719
|
+
|
|
720
|
+
if isinstance(event, ContentEvent):
|
|
721
|
+
if event.text:
|
|
722
|
+
content_parts.append(event.text)
|
|
723
|
+
last_message = self._build_ai_message(
|
|
724
|
+
content="".join(content_parts),
|
|
725
|
+
tool_calls=tool_calls,
|
|
726
|
+
context=context,
|
|
727
|
+
session_name=session_name,
|
|
728
|
+
)
|
|
729
|
+
continue
|
|
730
|
+
|
|
731
|
+
if ThinkingEvent is not None and isinstance(event, ThinkingEvent):
|
|
732
|
+
continue
|
|
733
|
+
|
|
734
|
+
if isinstance(event, ToolCallEvent):
|
|
735
|
+
tool_calls = [*tool_calls, self._normalize_tool_call({"tool": event.tool, "input": event.input})]
|
|
736
|
+
last_message = self._build_ai_message(
|
|
737
|
+
content="".join(content_parts),
|
|
738
|
+
tool_calls=tool_calls,
|
|
739
|
+
context=context,
|
|
740
|
+
session_name=session_name,
|
|
741
|
+
)
|
|
742
|
+
continue
|
|
743
|
+
|
|
744
|
+
if isinstance(event, ToolResultEvent):
|
|
745
|
+
tool_message = self._build_tool_message(
|
|
746
|
+
output=event.output,
|
|
747
|
+
tool=event.tool,
|
|
748
|
+
duration_ms=event.duration_ms,
|
|
749
|
+
context=context,
|
|
750
|
+
session_name=session_name,
|
|
751
|
+
)
|
|
752
|
+
last_message = tool_message
|
|
753
|
+
if self._is_semantic_tool_message(tool_message):
|
|
754
|
+
last_tool_message = tool_message
|
|
755
|
+
continue
|
|
756
|
+
|
|
757
|
+
if isinstance(event, DoneEvent):
|
|
758
|
+
final_content = event.content or "".join(content_parts)
|
|
759
|
+
if final_content:
|
|
760
|
+
return self._build_ai_message(
|
|
761
|
+
content=final_content,
|
|
762
|
+
tool_calls=[],
|
|
763
|
+
context=context,
|
|
764
|
+
session_name=session_name,
|
|
765
|
+
extra_metadata={
|
|
766
|
+
"token_usage": serialize_data(event.token_usage),
|
|
767
|
+
"stop_reason": event.stop_reason,
|
|
768
|
+
},
|
|
769
|
+
)
|
|
770
|
+
|
|
771
|
+
return self._build_terminal_fallback_message(
|
|
772
|
+
context=context,
|
|
773
|
+
session_name=session_name,
|
|
774
|
+
tool_calls=tool_calls,
|
|
775
|
+
last_message=last_message,
|
|
776
|
+
last_tool_message=last_tool_message,
|
|
777
|
+
extra_metadata={"token_usage": serialize_data(event.token_usage), "stop_reason": event.stop_reason},
|
|
778
|
+
)
|
|
779
|
+
|
|
780
|
+
if isinstance(event, ErrorEvent):
|
|
781
|
+
raise RuntimeError(event.message)
|
|
782
|
+
|
|
783
|
+
return self._build_terminal_fallback_message(
|
|
784
|
+
context=context,
|
|
785
|
+
session_name=session_name,
|
|
786
|
+
tool_calls=tool_calls,
|
|
787
|
+
last_message=last_message,
|
|
788
|
+
last_tool_message=last_tool_message,
|
|
789
|
+
)
|
|
790
|
+
|
|
791
|
+
def _build_ai_message(
|
|
792
|
+
self,
|
|
793
|
+
*,
|
|
794
|
+
content: str,
|
|
795
|
+
tool_calls: list[dict[str, Any]],
|
|
796
|
+
context: AgentExecutionContext,
|
|
797
|
+
session_name: str,
|
|
798
|
+
extra_metadata: dict[str, Any] | None = None,
|
|
799
|
+
) -> ChatMessage:
|
|
800
|
+
return ChatMessage(
|
|
801
|
+
type="ai",
|
|
802
|
+
content_type=detect_content_type(content),
|
|
803
|
+
content=content,
|
|
804
|
+
tool_calls=list(tool_calls),
|
|
805
|
+
response_metadata={
|
|
806
|
+
"conversation_id": self._resolve_conversation_id(context),
|
|
807
|
+
"session_name": session_name,
|
|
808
|
+
**(extra_metadata or {}),
|
|
809
|
+
},
|
|
810
|
+
references=[],
|
|
811
|
+
)
|
|
812
|
+
|
|
813
|
+
def _build_terminal_fallback_message(
|
|
814
|
+
self,
|
|
815
|
+
*,
|
|
816
|
+
context: AgentExecutionContext,
|
|
817
|
+
session_name: str,
|
|
818
|
+
tool_calls: list[dict[str, Any]],
|
|
819
|
+
last_message: ChatMessage | None,
|
|
820
|
+
last_tool_message: ChatMessage | None,
|
|
821
|
+
extra_metadata: dict[str, Any] | None = None,
|
|
822
|
+
) -> ChatMessage:
|
|
823
|
+
if last_tool_message is not None:
|
|
824
|
+
return last_tool_message.model_copy(
|
|
825
|
+
update={"response_metadata": {**last_tool_message.response_metadata, **(extra_metadata or {})}}
|
|
826
|
+
)
|
|
827
|
+
|
|
828
|
+
if last_message is not None and last_message.type == "ai":
|
|
829
|
+
return last_message.model_copy(
|
|
830
|
+
update={"response_metadata": {**last_message.response_metadata, **(extra_metadata or {})}}
|
|
831
|
+
)
|
|
832
|
+
|
|
833
|
+
return self._build_ai_message(
|
|
834
|
+
content="",
|
|
835
|
+
tool_calls=tool_calls,
|
|
836
|
+
context=context,
|
|
837
|
+
session_name=session_name,
|
|
838
|
+
extra_metadata=extra_metadata,
|
|
839
|
+
)
|
|
840
|
+
|
|
841
|
+
@staticmethod
|
|
842
|
+
def _is_semantic_tool_message(message: ChatMessage) -> bool:
|
|
843
|
+
content = message.content.strip()
|
|
844
|
+
if not content:
|
|
845
|
+
return False
|
|
846
|
+
if message.content_type != "text":
|
|
847
|
+
return True
|
|
848
|
+
|
|
849
|
+
low_signal_patterns = (
|
|
850
|
+
r"^Successfully wrote \d+ bytes to .+",
|
|
851
|
+
r"^Wrote \d+ bytes to .+",
|
|
852
|
+
r"^File written to .+",
|
|
853
|
+
r"^Saved to .+",
|
|
854
|
+
)
|
|
855
|
+
return not any(re.match(pattern, content) for pattern in low_signal_patterns)
|
|
856
|
+
|
|
857
|
+
@staticmethod
|
|
858
|
+
def _resolve_run_completion_idle_timeout_seconds(
|
|
859
|
+
settings: dict[str, Any],
|
|
860
|
+
execution_settings: dict[str, Any],
|
|
861
|
+
) -> float | None:
|
|
862
|
+
for source in (settings, execution_settings):
|
|
863
|
+
raw_value = source.get("run_completion_idle_timeout_seconds")
|
|
864
|
+
if raw_value is None:
|
|
865
|
+
continue
|
|
866
|
+
timeout = float(raw_value)
|
|
867
|
+
return timeout if timeout > 0 else None
|
|
868
|
+
return 5.0
|
|
869
|
+
|
|
870
|
+
def _build_tool_message(
|
|
871
|
+
self,
|
|
872
|
+
*,
|
|
873
|
+
output: str,
|
|
874
|
+
tool: str,
|
|
875
|
+
duration_ms: Any,
|
|
876
|
+
context: AgentExecutionContext,
|
|
877
|
+
session_name: str,
|
|
878
|
+
extra_metadata: dict[str, Any] | None = None,
|
|
879
|
+
) -> ChatMessage:
|
|
880
|
+
return ChatMessage(
|
|
881
|
+
type="tool",
|
|
882
|
+
content_type=detect_content_type(output),
|
|
883
|
+
content=output,
|
|
884
|
+
tool_calls=[],
|
|
885
|
+
response_metadata={
|
|
886
|
+
"duration_ms": duration_ms,
|
|
887
|
+
"tool": tool,
|
|
888
|
+
"conversation_id": self._resolve_conversation_id(context),
|
|
889
|
+
"session_name": session_name,
|
|
890
|
+
**(extra_metadata or {}),
|
|
891
|
+
},
|
|
892
|
+
references=[],
|
|
893
|
+
)
|
|
894
|
+
|
|
696
895
|
@staticmethod
|
|
697
896
|
def _build_attachments(items: list[dict[str, Any]]):
|
|
698
897
|
attachments = []
|
|
File without changes
|
|
File without changes
|
{agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/adapters/langgraph_adapter/__init__.py
RENAMED
|
File without changes
|
{agent_api_server-2.2.1a2 → agent_api_server-2.2.1a3}/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
|
|
File without changes
|
|
File without changes
|