agentscope-runtime 1.0.4a1__py3-none-any.whl → 1.0.5__py3-none-any.whl
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.
- agentscope_runtime/adapters/agentscope/stream.py +2 -8
- agentscope_runtime/adapters/langgraph/stream.py +120 -70
- agentscope_runtime/adapters/ms_agent_framework/__init__.py +0 -0
- agentscope_runtime/adapters/ms_agent_framework/message.py +205 -0
- agentscope_runtime/adapters/ms_agent_framework/stream.py +418 -0
- agentscope_runtime/adapters/utils.py +6 -0
- agentscope_runtime/cli/commands/deploy.py +836 -1
- agentscope_runtime/cli/commands/stop.py +16 -0
- agentscope_runtime/common/container_clients/__init__.py +52 -0
- agentscope_runtime/common/container_clients/agentrun_client.py +6 -4
- agentscope_runtime/common/container_clients/boxlite_client.py +442 -0
- agentscope_runtime/common/container_clients/docker_client.py +0 -20
- agentscope_runtime/common/container_clients/fc_client.py +6 -4
- agentscope_runtime/common/container_clients/gvisor_client.py +38 -0
- agentscope_runtime/common/container_clients/knative_client.py +467 -0
- agentscope_runtime/common/utils/deprecation.py +164 -0
- agentscope_runtime/engine/__init__.py +4 -0
- agentscope_runtime/engine/app/agent_app.py +16 -4
- agentscope_runtime/engine/constant.py +1 -0
- agentscope_runtime/engine/deployers/__init__.py +34 -11
- agentscope_runtime/engine/deployers/adapter/__init__.py +8 -0
- agentscope_runtime/engine/deployers/adapter/a2a/__init__.py +26 -51
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_protocol_adapter.py +23 -13
- agentscope_runtime/engine/deployers/adapter/a2a/a2a_registry.py +4 -201
- agentscope_runtime/engine/deployers/adapter/a2a/nacos_a2a_registry.py +152 -25
- agentscope_runtime/engine/deployers/adapter/agui/__init__.py +8 -0
- agentscope_runtime/engine/deployers/adapter/agui/agui_adapter_utils.py +652 -0
- agentscope_runtime/engine/deployers/adapter/agui/agui_protocol_adapter.py +225 -0
- agentscope_runtime/engine/deployers/agentrun_deployer.py +2 -2
- agentscope_runtime/engine/deployers/fc_deployer.py +1506 -0
- agentscope_runtime/engine/deployers/knative_deployer.py +290 -0
- agentscope_runtime/engine/deployers/pai_deployer.py +2335 -0
- agentscope_runtime/engine/deployers/utils/net_utils.py +37 -0
- agentscope_runtime/engine/deployers/utils/oss_utils.py +38 -0
- agentscope_runtime/engine/deployers/utils/package.py +46 -42
- agentscope_runtime/engine/helpers/agent_api_client.py +372 -0
- agentscope_runtime/engine/runner.py +13 -0
- agentscope_runtime/engine/schemas/agent_schemas.py +9 -3
- agentscope_runtime/engine/services/agent_state/__init__.py +7 -0
- agentscope_runtime/engine/services/memory/__init__.py +7 -0
- agentscope_runtime/engine/services/memory/redis_memory_service.py +15 -16
- agentscope_runtime/engine/services/session_history/__init__.py +7 -0
- agentscope_runtime/engine/tracing/local_logging_handler.py +2 -3
- agentscope_runtime/engine/tracing/wrapper.py +18 -4
- agentscope_runtime/sandbox/__init__.py +14 -6
- agentscope_runtime/sandbox/box/base/__init__.py +2 -2
- agentscope_runtime/sandbox/box/base/base_sandbox.py +51 -1
- agentscope_runtime/sandbox/box/browser/__init__.py +2 -2
- agentscope_runtime/sandbox/box/browser/browser_sandbox.py +198 -2
- agentscope_runtime/sandbox/box/filesystem/__init__.py +2 -2
- agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +99 -2
- agentscope_runtime/sandbox/box/gui/__init__.py +2 -2
- agentscope_runtime/sandbox/box/gui/gui_sandbox.py +117 -1
- agentscope_runtime/sandbox/box/mobile/__init__.py +2 -2
- agentscope_runtime/sandbox/box/mobile/mobile_sandbox.py +247 -100
- agentscope_runtime/sandbox/box/sandbox.py +102 -65
- agentscope_runtime/sandbox/box/shared/routers/generic.py +36 -29
- agentscope_runtime/sandbox/client/__init__.py +6 -1
- agentscope_runtime/sandbox/client/async_http_client.py +339 -0
- agentscope_runtime/sandbox/client/base.py +74 -0
- agentscope_runtime/sandbox/client/http_client.py +108 -329
- agentscope_runtime/sandbox/enums.py +7 -0
- agentscope_runtime/sandbox/manager/sandbox_manager.py +275 -29
- agentscope_runtime/sandbox/manager/server/app.py +7 -1
- agentscope_runtime/sandbox/manager/server/config.py +3 -1
- agentscope_runtime/sandbox/model/manager_config.py +11 -9
- agentscope_runtime/tools/modelstudio_memory/__init__.py +106 -0
- agentscope_runtime/tools/modelstudio_memory/base.py +220 -0
- agentscope_runtime/tools/modelstudio_memory/config.py +86 -0
- agentscope_runtime/tools/modelstudio_memory/core.py +594 -0
- agentscope_runtime/tools/modelstudio_memory/exceptions.py +60 -0
- agentscope_runtime/tools/modelstudio_memory/schemas.py +253 -0
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.dist-info}/METADATA +186 -73
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.dist-info}/RECORD +79 -55
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.dist-info}/WHEEL +0 -0
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.dist-info}/entry_points.txt +0 -0
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-1.0.4a1.dist-info → agentscope_runtime-1.0.5.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
+
# flake8: noqa: E501
|
|
2
3
|
import logging
|
|
3
4
|
import os
|
|
4
5
|
import types
|
|
@@ -20,6 +21,7 @@ from ..deployers.adapter.a2a import (
|
|
|
20
21
|
from ..deployers.adapter.responses.response_api_protocol_adapter import (
|
|
21
22
|
ResponseAPIDefaultAdapter,
|
|
22
23
|
)
|
|
24
|
+
from ..deployers.adapter.agui import AGUIDefaultAdapter, AGUIAdaptorConfig
|
|
23
25
|
from ..deployers.utils.deployment_modes import DeploymentMode
|
|
24
26
|
from ..deployers.utils.service_utils.fastapi_factory import FastAPIAppFactory
|
|
25
27
|
from ..runner import Runner
|
|
@@ -52,6 +54,7 @@ class AgentApp(BaseApp):
|
|
|
52
54
|
runner: Optional[Runner] = None,
|
|
53
55
|
enable_embedded_worker: bool = False,
|
|
54
56
|
a2a_config: Optional["AgentCardWithRuntimeConfig"] = None,
|
|
57
|
+
agui_config: Optional[AGUIAdaptorConfig] = None,
|
|
55
58
|
**kwargs,
|
|
56
59
|
):
|
|
57
60
|
"""
|
|
@@ -74,11 +77,14 @@ class AgentApp(BaseApp):
|
|
|
74
77
|
Must be an ``AgentCardWithRuntimeConfig`` instance, which
|
|
75
78
|
contains ``agent_card`` (AgentCard object or dict) and runtime
|
|
76
79
|
settings (host, port, registry, task_timeout, etc.).
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
|
|
81
|
+
Example::
|
|
82
|
+
|
|
83
|
+
from a2a.types import AgentCapabilities
|
|
84
|
+
from agentscope_runtime.engine.deployers.adapter.a2a import (
|
|
80
85
|
AgentCardWithRuntimeConfig,
|
|
81
86
|
)
|
|
87
|
+
|
|
82
88
|
config = AgentCardWithRuntimeConfig(
|
|
83
89
|
agent_card={
|
|
84
90
|
"name": "MyAgent",
|
|
@@ -93,6 +99,7 @@ class AgentApp(BaseApp):
|
|
|
93
99
|
registry=[nacos_registry],
|
|
94
100
|
task_timeout=120,
|
|
95
101
|
)
|
|
102
|
+
agui_config: Config for AGUI adaptor.
|
|
96
103
|
**kwargs: Additional keyword arguments passed to FastAPI app
|
|
97
104
|
"""
|
|
98
105
|
|
|
@@ -125,7 +132,12 @@ class AgentApp(BaseApp):
|
|
|
125
132
|
)
|
|
126
133
|
|
|
127
134
|
response_protocol = ResponseAPIDefaultAdapter()
|
|
128
|
-
|
|
135
|
+
agui_protocol = AGUIDefaultAdapter(config=agui_config)
|
|
136
|
+
self.protocol_adapters = [
|
|
137
|
+
a2a_protocol,
|
|
138
|
+
response_protocol,
|
|
139
|
+
agui_protocol,
|
|
140
|
+
]
|
|
129
141
|
|
|
130
142
|
self._app_kwargs = {
|
|
131
143
|
"title": "Agent Service",
|
|
@@ -1,25 +1,48 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
from
|
|
3
|
-
from .
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
from .
|
|
9
|
-
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
from ...common.utils.lazy_loader import install_lazy_loader
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from .base import DeployManager
|
|
7
|
+
from .local_deployer import LocalDeployManager
|
|
8
|
+
from .kubernetes_deployer import (
|
|
9
|
+
KubernetesDeployManager,
|
|
10
|
+
K8sConfig,
|
|
11
|
+
)
|
|
12
|
+
from .modelstudio_deployer import ModelstudioDeployManager
|
|
13
|
+
from .knative_deployer import KnativeDeployManager
|
|
14
|
+
from .agentrun_deployer import AgentRunDeployManager
|
|
15
|
+
from .fc_deployer import FCDeployManager
|
|
16
|
+
|
|
17
|
+
install_lazy_loader(
|
|
18
|
+
globals(),
|
|
19
|
+
{
|
|
20
|
+
"DeployManager": ".base",
|
|
21
|
+
"LocalDeployManager": ".local_deployer",
|
|
22
|
+
"KubernetesDeployManager": ".kubernetes_deployer",
|
|
23
|
+
"K8sConfig": ".kubernetes_deployer",
|
|
24
|
+
"ModelstudioDeployManager": ".modelstudio_deployer",
|
|
25
|
+
"KnativeDeployManager": ".knative_deployer",
|
|
26
|
+
"AgentRunDeployManager": ".agentrun_deployer",
|
|
27
|
+
"FCDeployManager": ".fc_deployer",
|
|
28
|
+
},
|
|
10
29
|
)
|
|
11
30
|
|
|
12
31
|
try:
|
|
13
|
-
from .
|
|
14
|
-
|
|
32
|
+
from .pai_deployer import (
|
|
33
|
+
PAIDeployManager,
|
|
15
34
|
)
|
|
16
35
|
except ImportError:
|
|
17
|
-
|
|
36
|
+
PAIDeployManager = None # type: ignore
|
|
18
37
|
|
|
19
38
|
__all__ = [
|
|
39
|
+
"K8sConfig",
|
|
20
40
|
"DeployManager",
|
|
21
41
|
"LocalDeployManager",
|
|
22
42
|
"KubernetesDeployManager",
|
|
23
43
|
"ModelstudioDeployManager",
|
|
24
44
|
"AgentRunDeployManager",
|
|
45
|
+
"KnativeDeployManager",
|
|
46
|
+
"FCDeployManager",
|
|
47
|
+
"PAIDeployManager",
|
|
25
48
|
]
|
|
@@ -1,2 +1,10 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
from .a2a import A2AFastAPIDefaultAdapter
|
|
3
|
+
from .agui import AGUIDefaultAdapter
|
|
4
|
+
from .responses import ResponseAPIDefaultAdapter
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"A2AFastAPIDefaultAdapter",
|
|
8
|
+
"AGUIDefaultAdapter",
|
|
9
|
+
"ResponseAPIDefaultAdapter",
|
|
10
|
+
]
|
|
@@ -1,57 +1,32 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
from
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
from .....common.utils.lazy_loader import install_lazy_loader
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from .a2a_protocol_adapter import (
|
|
7
|
+
A2AFastAPIDefaultAdapter,
|
|
8
|
+
AgentCardWithRuntimeConfig,
|
|
9
|
+
extract_a2a_config,
|
|
10
|
+
)
|
|
11
|
+
from .a2a_registry import A2ARegistry
|
|
12
|
+
from .nacos_a2a_registry import NacosRegistry
|
|
13
13
|
|
|
14
14
|
# NOTE: NacosRegistry is NOT imported at module import time to avoid forcing
|
|
15
15
|
# an optional dependency on environments that don't have nacos SDK installed.
|
|
16
|
-
# Instead, NacosRegistry is imported lazily via
|
|
16
|
+
# Instead, NacosRegistry is imported lazily via install_lazy_loader when
|
|
17
17
|
# actually needed (e.g., when user does: from ... import NacosRegistry).
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
Lazy import for NacosRegistry to avoid forcing optional nacos dependency.
|
|
34
|
-
|
|
35
|
-
This function is called by Python when an attribute is accessed
|
|
36
|
-
that doesn't exist at module level. This allows NacosRegistry
|
|
37
|
-
to be imported only when actually needed, rather than at module
|
|
38
|
-
import time.
|
|
39
|
-
|
|
40
|
-
If the nacos SDK is not installed, provides a helpful error message
|
|
41
|
-
instead of a confusing ImportError.
|
|
42
|
-
"""
|
|
43
|
-
if name == "NacosRegistry":
|
|
44
|
-
try:
|
|
45
|
-
from .nacos_a2a_registry import NacosRegistry
|
|
46
|
-
|
|
47
|
-
return NacosRegistry
|
|
48
|
-
except ImportError as e:
|
|
49
|
-
# Check if it's the v2.nacos dependency that's missing
|
|
50
|
-
if "v2.nacos" in str(e) or "nacos" in str(e).lower():
|
|
51
|
-
raise ImportError(
|
|
52
|
-
"NacosRegistry requires the 'v2-nacos' package. "
|
|
53
|
-
"Install it with: pip install v2-nacos",
|
|
54
|
-
) from e
|
|
55
|
-
# Re-raise other import errors as-is
|
|
56
|
-
raise
|
|
57
|
-
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
19
|
+
install_lazy_loader(
|
|
20
|
+
globals(),
|
|
21
|
+
{
|
|
22
|
+
"A2AFastAPIDefaultAdapter": ".a2a_protocol_adapter",
|
|
23
|
+
"AgentCardWithRuntimeConfig": ".a2a_protocol_adapter",
|
|
24
|
+
"extract_a2a_config": ".a2a_protocol_adapter",
|
|
25
|
+
"A2ARegistry": ".a2a_registry",
|
|
26
|
+
"NacosRegistry": {
|
|
27
|
+
"module": ".nacos_a2a_registry",
|
|
28
|
+
"hint": "NacosRegistry requires the 'nacos-sdk-python' package. "
|
|
29
|
+
"Install it with: pip install nacos-sdk-python",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
)
|
|
@@ -19,19 +19,18 @@ from a2a.types import (
|
|
|
19
19
|
AgentCard,
|
|
20
20
|
AgentSkill,
|
|
21
21
|
)
|
|
22
|
+
from a2a.utils import AGENT_CARD_WELL_KNOWN_PATH
|
|
22
23
|
from fastapi import FastAPI
|
|
23
24
|
from pydantic import ConfigDict, BaseModel, field_validator
|
|
24
25
|
|
|
25
26
|
from agentscope_runtime.engine.deployers.utils.net_utils import (
|
|
26
27
|
get_first_non_loopback_ip,
|
|
27
28
|
)
|
|
28
|
-
from agentscope_runtime.version import __version__ as runtime_version
|
|
29
29
|
|
|
30
30
|
from .a2a_agent_adapter import A2AExecutor
|
|
31
31
|
from .a2a_registry import (
|
|
32
32
|
A2ARegistry,
|
|
33
33
|
A2ATransportsProperties,
|
|
34
|
-
create_registry_from_env,
|
|
35
34
|
)
|
|
36
35
|
|
|
37
36
|
# NOTE: Do NOT import NacosRegistry at module import time to avoid
|
|
@@ -44,7 +43,7 @@ from ..protocol_adapter import ProtocolAdapter
|
|
|
44
43
|
logger = logging.getLogger(__name__)
|
|
45
44
|
|
|
46
45
|
A2A_JSON_RPC_URL = "/a2a"
|
|
47
|
-
DEFAULT_WELLKNOWN_PATH =
|
|
46
|
+
DEFAULT_WELLKNOWN_PATH = AGENT_CARD_WELL_KNOWN_PATH
|
|
48
47
|
DEFAULT_TASK_TIMEOUT = 60
|
|
49
48
|
DEFAULT_TASK_EVENT_TIMEOUT = 10
|
|
50
49
|
DEFAULT_TRANSPORT = "JSONRPC"
|
|
@@ -56,26 +55,37 @@ AGENT_VERSION = "1.0.0"
|
|
|
56
55
|
def extract_a2a_config(
|
|
57
56
|
a2a_config: Optional["AgentCardWithRuntimeConfig"] = None,
|
|
58
57
|
) -> "AgentCardWithRuntimeConfig":
|
|
59
|
-
"""Normalize a2a_config to AgentCardWithRuntimeConfig object.
|
|
58
|
+
"""Normalize ``a2a_config`` to an ``AgentCardWithRuntimeConfig`` object.
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
Registry resolution priority:
|
|
61
|
+
|
|
62
|
+
1. Use ``registry`` from ``a2a_config`` if provided.
|
|
63
|
+
2. Fallback to environment variables if ``a2a_config.registry`` is
|
|
64
|
+
``None``.
|
|
65
|
+
3. If neither is available, registry remains ``None``
|
|
66
|
+
(user doesn't want it).
|
|
63
67
|
|
|
64
68
|
Args:
|
|
65
|
-
a2a_config: Optional AgentCardWithRuntimeConfig instance.
|
|
69
|
+
a2a_config: Optional ``AgentCardWithRuntimeConfig`` instance.
|
|
66
70
|
|
|
67
71
|
Returns:
|
|
68
|
-
Normalized AgentCardWithRuntimeConfig object.
|
|
72
|
+
Normalized ``AgentCardWithRuntimeConfig`` object.
|
|
69
73
|
"""
|
|
70
74
|
if a2a_config is None:
|
|
71
75
|
a2a_config = AgentCardWithRuntimeConfig()
|
|
72
76
|
|
|
73
|
-
#
|
|
77
|
+
# Try environment variables only if registry is not explicitly provided
|
|
74
78
|
if a2a_config.registry is None:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
try:
|
|
80
|
+
from .nacos_a2a_registry import create_nacos_registry_from_env
|
|
81
|
+
|
|
82
|
+
env_registry = create_nacos_registry_from_env()
|
|
83
|
+
if env_registry is not None:
|
|
84
|
+
a2a_config.registry = env_registry
|
|
85
|
+
logger.debug("[A2A] Using registry from environment variables")
|
|
86
|
+
except ImportError:
|
|
87
|
+
# Nacos SDK not available, registry remains None
|
|
88
|
+
logger.debug("[A2A] Nacos registry not available")
|
|
79
89
|
|
|
80
90
|
return a2a_config
|
|
81
91
|
|
|
@@ -2,35 +2,20 @@
|
|
|
2
2
|
"""
|
|
3
3
|
A2A Registry Extension Point
|
|
4
4
|
|
|
5
|
-
Defines the abstract interface
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
This module focuses on clarity and small helper functions used by the
|
|
10
|
-
runtime to instantiate registry implementations from environment
|
|
11
|
-
configuration or .env files.
|
|
5
|
+
Defines the abstract interface for A2A registry implementations.
|
|
6
|
+
Registry implementations are responsible for registering agent services
|
|
7
|
+
to service discovery systems (for example: Nacos).
|
|
12
8
|
"""
|
|
13
9
|
import logging
|
|
14
|
-
import os
|
|
15
10
|
from abc import ABC, abstractmethod
|
|
16
11
|
from dataclasses import dataclass, field
|
|
17
|
-
from typing import
|
|
18
|
-
|
|
19
|
-
from dotenv import find_dotenv, load_dotenv
|
|
20
|
-
from pydantic import ConfigDict
|
|
21
|
-
from pydantic_settings import BaseSettings
|
|
12
|
+
from typing import Any, Dict, List, Optional
|
|
22
13
|
|
|
23
14
|
from a2a.types import AgentCard
|
|
24
15
|
|
|
25
|
-
if TYPE_CHECKING:
|
|
26
|
-
from v2.nacos import ClientConfig
|
|
27
|
-
|
|
28
16
|
__all__ = [
|
|
29
17
|
"A2ARegistry",
|
|
30
18
|
"A2ATransportsProperties",
|
|
31
|
-
"A2ARegistrySettings",
|
|
32
|
-
"get_registry_settings",
|
|
33
|
-
"create_registry_from_env",
|
|
34
19
|
]
|
|
35
20
|
|
|
36
21
|
logger = logging.getLogger(__name__)
|
|
@@ -89,185 +74,3 @@ class A2ARegistry(ABC):
|
|
|
89
74
|
depending on their semantics.
|
|
90
75
|
"""
|
|
91
76
|
raise NotImplementedError("Subclasses must implement register()")
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
class A2ARegistrySettings(BaseSettings):
|
|
95
|
-
"""Settings that control A2A registry behavior.
|
|
96
|
-
|
|
97
|
-
Values are loaded from environment variables or a .env file when
|
|
98
|
-
`get_registry_settings()` is called.
|
|
99
|
-
"""
|
|
100
|
-
|
|
101
|
-
# Feature toggle
|
|
102
|
-
A2A_REGISTRY_ENABLED: bool = True
|
|
103
|
-
|
|
104
|
-
# Registry type(s). Can be a single value like "nacos" or a comma-separated
|
|
105
|
-
# list of registry types (e.g. "nacos").
|
|
106
|
-
A2A_REGISTRY_TYPE: Optional[str] = None
|
|
107
|
-
|
|
108
|
-
# Nacos specific configuration
|
|
109
|
-
NACOS_SERVER_ADDR: str = "localhost:8848"
|
|
110
|
-
NACOS_USERNAME: Optional[str] = None
|
|
111
|
-
NACOS_PASSWORD: Optional[str] = None
|
|
112
|
-
NACOS_NAMESPACE_ID: Optional[str] = None
|
|
113
|
-
NACOS_ACCESS_KEY: Optional[str] = None
|
|
114
|
-
NACOS_SECRET_KEY: Optional[str] = None
|
|
115
|
-
|
|
116
|
-
model_config = ConfigDict(
|
|
117
|
-
extra="allow",
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
_registry_settings: Optional[A2ARegistrySettings] = None
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
def get_registry_settings() -> A2ARegistrySettings:
|
|
125
|
-
"""Return a singleton settings instance, loading .env files if needed."""
|
|
126
|
-
global _registry_settings
|
|
127
|
-
|
|
128
|
-
if _registry_settings is None:
|
|
129
|
-
# Inline _load_env_files() logic
|
|
130
|
-
# prefer a .env file if present, otherwise fall back to .env.example
|
|
131
|
-
dotenv_path = find_dotenv(raise_error_if_not_found=False)
|
|
132
|
-
if dotenv_path:
|
|
133
|
-
load_dotenv(dotenv_path, override=False)
|
|
134
|
-
else:
|
|
135
|
-
# If find_dotenv didn't find a file, try the explicit fallback name
|
|
136
|
-
if os.path.exists(".env.example"):
|
|
137
|
-
load_dotenv(".env.example", override=False)
|
|
138
|
-
_registry_settings = A2ARegistrySettings()
|
|
139
|
-
|
|
140
|
-
return _registry_settings
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
def _create_nacos_registry_from_settings(
|
|
144
|
-
settings: A2ARegistrySettings,
|
|
145
|
-
) -> Optional[A2ARegistry]:
|
|
146
|
-
"""Create a NacosRegistry instance from provided settings, or return
|
|
147
|
-
None if the required nacos SDK is not available or construction fails."""
|
|
148
|
-
try:
|
|
149
|
-
# lazy import so package is optional
|
|
150
|
-
from .nacos_a2a_registry import NacosRegistry
|
|
151
|
-
except ImportError:
|
|
152
|
-
logger.warning(
|
|
153
|
-
"[A2A] Nacos registry requested but nacos SDK not available. "
|
|
154
|
-
"Install with: pip install v2-nacos",
|
|
155
|
-
exc_info=False,
|
|
156
|
-
)
|
|
157
|
-
return None
|
|
158
|
-
except Exception as e:
|
|
159
|
-
logger.warning(
|
|
160
|
-
"[A2A] Unexpected error during Nacos registry import: %s",
|
|
161
|
-
str(e),
|
|
162
|
-
exc_info=True,
|
|
163
|
-
)
|
|
164
|
-
return None
|
|
165
|
-
|
|
166
|
-
try:
|
|
167
|
-
nacos_client_config = _build_nacos_client_config(settings)
|
|
168
|
-
registry = NacosRegistry(nacos_client_config=nacos_client_config)
|
|
169
|
-
|
|
170
|
-
# Determine authentication status
|
|
171
|
-
auth_methods = []
|
|
172
|
-
if settings.NACOS_USERNAME and settings.NACOS_PASSWORD:
|
|
173
|
-
auth_methods.append("username/password")
|
|
174
|
-
if settings.NACOS_ACCESS_KEY and settings.NACOS_SECRET_KEY:
|
|
175
|
-
auth_methods.append("access_key")
|
|
176
|
-
auth_status = ", ".join(auth_methods) if auth_methods else "disabled"
|
|
177
|
-
|
|
178
|
-
namespace_info = (
|
|
179
|
-
f", namespace={settings.NACOS_NAMESPACE_ID}"
|
|
180
|
-
if settings.NACOS_NAMESPACE_ID
|
|
181
|
-
else ""
|
|
182
|
-
)
|
|
183
|
-
logger.info(
|
|
184
|
-
f"[A2A] Created Nacos registry from environment: "
|
|
185
|
-
f"server={settings.NACOS_SERVER_ADDR}, "
|
|
186
|
-
f"authentication={auth_status}{namespace_info}",
|
|
187
|
-
)
|
|
188
|
-
return registry
|
|
189
|
-
except Exception:
|
|
190
|
-
logger.warning(
|
|
191
|
-
"[A2A] Failed to construct Nacos registry from settings",
|
|
192
|
-
exc_info=True,
|
|
193
|
-
)
|
|
194
|
-
return None
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
def _build_nacos_client_config(
|
|
198
|
-
settings: A2ARegistrySettings,
|
|
199
|
-
) -> Any:
|
|
200
|
-
"""Build Nacos client configuration from settings.
|
|
201
|
-
|
|
202
|
-
Supports both username/password and access key authentication.
|
|
203
|
-
"""
|
|
204
|
-
from v2.nacos import ClientConfigBuilder
|
|
205
|
-
|
|
206
|
-
builder = ClientConfigBuilder().server_address(settings.NACOS_SERVER_ADDR)
|
|
207
|
-
|
|
208
|
-
if settings.NACOS_NAMESPACE_ID:
|
|
209
|
-
builder.namespace_id(settings.NACOS_NAMESPACE_ID)
|
|
210
|
-
logger.debug(
|
|
211
|
-
"[A2A] Using Nacos namespace: %s",
|
|
212
|
-
settings.NACOS_NAMESPACE_ID,
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
if settings.NACOS_USERNAME and settings.NACOS_PASSWORD:
|
|
216
|
-
builder.username(settings.NACOS_USERNAME).password(
|
|
217
|
-
settings.NACOS_PASSWORD,
|
|
218
|
-
)
|
|
219
|
-
logger.debug("[A2A] Using Nacos username/password authentication")
|
|
220
|
-
|
|
221
|
-
if settings.NACOS_ACCESS_KEY and settings.NACOS_SECRET_KEY:
|
|
222
|
-
builder.access_key(settings.NACOS_ACCESS_KEY).secret_key(
|
|
223
|
-
settings.NACOS_SECRET_KEY,
|
|
224
|
-
)
|
|
225
|
-
logger.debug("[A2A] Using Nacos access key authentication")
|
|
226
|
-
|
|
227
|
-
return builder.build()
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
def create_registry_from_env() -> (
|
|
231
|
-
Optional[Union[A2ARegistry, List[A2ARegistry]]]
|
|
232
|
-
):
|
|
233
|
-
"""Create registry instance(s) from environment settings.
|
|
234
|
-
|
|
235
|
-
Supports single or multiple registry types (comma-separated).
|
|
236
|
-
Returns None if disabled or no valid registry created.
|
|
237
|
-
"""
|
|
238
|
-
settings = get_registry_settings()
|
|
239
|
-
|
|
240
|
-
if not settings.A2A_REGISTRY_ENABLED:
|
|
241
|
-
logger.debug("[A2A] Registry disabled via A2A_REGISTRY_ENABLED")
|
|
242
|
-
return None
|
|
243
|
-
|
|
244
|
-
# Inline _split_registry_types() logic
|
|
245
|
-
raw = settings.A2A_REGISTRY_TYPE
|
|
246
|
-
types = (
|
|
247
|
-
[r.strip().lower() for r in raw.split(",") if r.strip()] if raw else []
|
|
248
|
-
)
|
|
249
|
-
if not types:
|
|
250
|
-
logger.debug("[A2A] No registry type specified in A2A_REGISTRY_TYPE")
|
|
251
|
-
return None
|
|
252
|
-
|
|
253
|
-
registry_list: List[A2ARegistry] = []
|
|
254
|
-
|
|
255
|
-
for registry_type in types:
|
|
256
|
-
if registry_type == "nacos":
|
|
257
|
-
registry = _create_nacos_registry_from_settings(settings)
|
|
258
|
-
if registry:
|
|
259
|
-
registry_list.append(registry)
|
|
260
|
-
else:
|
|
261
|
-
logger.debug(
|
|
262
|
-
"[A2A] Skipping nacos registry due to earlier errors",
|
|
263
|
-
)
|
|
264
|
-
else:
|
|
265
|
-
logger.warning(
|
|
266
|
-
f"[A2A] Unknown registry type requested: "
|
|
267
|
-
f"{registry_type}. Supported: nacos",
|
|
268
|
-
)
|
|
269
|
-
|
|
270
|
-
if not registry_list:
|
|
271
|
-
return None
|
|
272
|
-
|
|
273
|
-
return registry_list[0] if len(registry_list) == 1 else registry_list
|