atlas-agent-adapters 1.0.1__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.
- atlas_agent_adapters-1.0.1/.gitignore +35 -0
- atlas_agent_adapters-1.0.1/LICENSE +21 -0
- atlas_agent_adapters-1.0.1/PKG-INFO +34 -0
- atlas_agent_adapters-1.0.1/README.md +7 -0
- atlas_agent_adapters-1.0.1/proto/atlas_agents/adapters/grpc/v1/agent_execution.proto +144 -0
- atlas_agent_adapters-1.0.1/pyproject.toml +47 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/__init__.py +107 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/_version.py +3 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/errors.py +71 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/events/__init__.py +29 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/events/consumer.py +168 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/events/models.py +122 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/events/publisher.py +13 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/grpc/__init__.py +30 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/grpc/mapping.py +264 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/grpc/server.py +200 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/grpc/v1/__init__.py +1 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/grpc/v1/agent_execution_pb2.py +70 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/grpc/v1/agent_execution_pb2.pyi +241 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/grpc/v1/agent_execution_pb2_grpc.py +226 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/idempotency.py +103 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/models.py +223 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/optional.py +5 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/policies.py +180 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/py.typed +1 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/registry.py +39 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/rest/__init__.py +29 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/rest/app.py +266 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/rest/v1/__init__.py +10 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/rest/v1/models.py +125 -0
- atlas_agent_adapters-1.0.1/src/atlas_agents/adapters/service.py +494 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
.coverage
|
|
5
|
+
coverage.xml
|
|
6
|
+
reports/release/*coverage.xml
|
|
7
|
+
reports/release/junit.xml
|
|
8
|
+
reports/release/bandit.json
|
|
9
|
+
reports/release/dependency-audit.json
|
|
10
|
+
reports/release/requirements-audit.txt
|
|
11
|
+
.mypy_cache/
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.tmp-pytest-*/
|
|
14
|
+
.tmp-pytest/
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
.uv-cache/
|
|
17
|
+
.venv/
|
|
18
|
+
build/
|
|
19
|
+
dist/
|
|
20
|
+
/release/
|
|
21
|
+
bin/
|
|
22
|
+
obj/
|
|
23
|
+
htmlcov/
|
|
24
|
+
.env
|
|
25
|
+
.env.*
|
|
26
|
+
!.env.example
|
|
27
|
+
*.key
|
|
28
|
+
*.log
|
|
29
|
+
*.pem
|
|
30
|
+
*.tmp
|
|
31
|
+
*.swp
|
|
32
|
+
.DS_Store
|
|
33
|
+
Thumbs.db
|
|
34
|
+
.idea/
|
|
35
|
+
.vscode/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jorge Medina
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: atlas-agent-adapters
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Adapters externos REST, gRPC e orientados a eventos para o Atlas
|
|
5
|
+
Project-URL: Repository, https://github.com/Medicode/ai-agent-framework
|
|
6
|
+
Project-URL: Documentation, https://github.com/Medicode/ai-agent-framework/tree/main/docs/adapters
|
|
7
|
+
Project-URL: Issues, https://github.com/Medicode/ai-agent-framework/issues
|
|
8
|
+
Author: Jorge Medina
|
|
9
|
+
Maintainer: Jorge Medina
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Python: >=3.12
|
|
19
|
+
Requires-Dist: atlas-agent-core~=1.0.1
|
|
20
|
+
Requires-Dist: pydantic<3,>=2.13
|
|
21
|
+
Provides-Extra: grpc
|
|
22
|
+
Requires-Dist: grpcio<2,>=1.81.1; extra == 'grpc'
|
|
23
|
+
Requires-Dist: protobuf<7,>=6.33.5; extra == 'grpc'
|
|
24
|
+
Provides-Extra: rest
|
|
25
|
+
Requires-Dist: fastapi<1,>=0.141; extra == 'rest'
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# atlas-agent-adapters
|
|
29
|
+
|
|
30
|
+
Adapters externos opcionais para REST, gRPC e mensageria.
|
|
31
|
+
|
|
32
|
+
Este pacote integra o ecossistema modular Atlas Agent Framework. Consulte a
|
|
33
|
+
[documentação oficial](https://github.com/Medicode/ai-agent-framework/tree/main/docs)
|
|
34
|
+
para instalação, compatibilidade e APIs públicas.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# atlas-agent-adapters
|
|
2
|
+
|
|
3
|
+
Adapters externos opcionais para REST, gRPC e mensageria.
|
|
4
|
+
|
|
5
|
+
Este pacote integra o ecossistema modular Atlas Agent Framework. Consulte a
|
|
6
|
+
[documentação oficial](https://github.com/Medicode/ai-agent-framework/tree/main/docs)
|
|
7
|
+
para instalação, compatibilidade e APIs públicas.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
syntax = "proto3";
|
|
2
|
+
|
|
3
|
+
package atlas.agent.v1;
|
|
4
|
+
|
|
5
|
+
import "google/protobuf/struct.proto";
|
|
6
|
+
import "google/protobuf/timestamp.proto";
|
|
7
|
+
|
|
8
|
+
enum ApprovalDecision {
|
|
9
|
+
APPROVAL_DECISION_UNSPECIFIED = 0;
|
|
10
|
+
APPROVAL_DECISION_APPROVE = 1;
|
|
11
|
+
APPROVAL_DECISION_REJECT = 2;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
message Attachment {
|
|
15
|
+
string attachment_id = 1;
|
|
16
|
+
string name = 2;
|
|
17
|
+
string media_type = 3;
|
|
18
|
+
string uri = 4;
|
|
19
|
+
google.protobuf.Struct metadata = 5;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
message AgentInput {
|
|
23
|
+
string message = 1;
|
|
24
|
+
repeated Attachment attachments = 2;
|
|
25
|
+
google.protobuf.Struct metadata = 3;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
message ExecutionContext {
|
|
29
|
+
optional string session_id = 1;
|
|
30
|
+
google.protobuf.Struct metadata = 2;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
message RequestedLimits {
|
|
34
|
+
optional int32 max_turns = 1;
|
|
35
|
+
optional int32 max_tool_calls = 2;
|
|
36
|
+
optional int64 max_input_tokens = 3;
|
|
37
|
+
optional int64 max_output_tokens = 4;
|
|
38
|
+
optional int64 max_total_tokens = 5;
|
|
39
|
+
optional double timeout_seconds = 6;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
message RequestedBudget {
|
|
43
|
+
optional string max_estimated_cost = 1;
|
|
44
|
+
optional string currency = 2;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
message ExecuteRequest {
|
|
48
|
+
string request_id = 1;
|
|
49
|
+
string agent_id = 2;
|
|
50
|
+
AgentInput input = 3;
|
|
51
|
+
ExecutionContext context = 4;
|
|
52
|
+
RequestedLimits requested_limits = 5;
|
|
53
|
+
RequestedBudget requested_budget = 6;
|
|
54
|
+
google.protobuf.Struct metadata = 7;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
message ResumeRequest {
|
|
58
|
+
string request_id = 1;
|
|
59
|
+
string agent_id = 2;
|
|
60
|
+
string resume_token = 3;
|
|
61
|
+
string approval_request_id = 4;
|
|
62
|
+
ApprovalDecision decision = 5;
|
|
63
|
+
optional string reason = 6;
|
|
64
|
+
google.protobuf.Timestamp decided_at = 7;
|
|
65
|
+
google.protobuf.Struct metadata = 8;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
message Error {
|
|
69
|
+
string code = 1;
|
|
70
|
+
string message = 2;
|
|
71
|
+
bool retryable = 3;
|
|
72
|
+
google.protobuf.Struct details = 4;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
message Usage {
|
|
76
|
+
int64 input_tokens = 1;
|
|
77
|
+
int64 output_tokens = 2;
|
|
78
|
+
int64 cached_input_tokens = 3;
|
|
79
|
+
int64 reasoning_tokens = 4;
|
|
80
|
+
optional string estimated_cost = 5;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
message Citation {
|
|
84
|
+
string citation_key = 1;
|
|
85
|
+
string source_id = 2;
|
|
86
|
+
string document_id = 3;
|
|
87
|
+
string passage_id = 4;
|
|
88
|
+
optional string title = 5;
|
|
89
|
+
optional string uri = 6;
|
|
90
|
+
optional int32 page = 7;
|
|
91
|
+
optional string section = 8;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
message ApprovalSubject {
|
|
95
|
+
string tool_call_id = 1;
|
|
96
|
+
string tool_name = 2;
|
|
97
|
+
repeated string argument_keys = 3;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
message ApprovalRequest {
|
|
101
|
+
string approval_request_id = 1;
|
|
102
|
+
string execution_id = 2;
|
|
103
|
+
string agent_id = 3;
|
|
104
|
+
string kind = 4;
|
|
105
|
+
string summary = 5;
|
|
106
|
+
string reason = 6;
|
|
107
|
+
google.protobuf.Timestamp requested_at = 7;
|
|
108
|
+
optional google.protobuf.Timestamp expires_at = 8;
|
|
109
|
+
ApprovalSubject subject = 9;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
message Suspension {
|
|
113
|
+
string execution_id = 1;
|
|
114
|
+
ApprovalRequest approval_request = 2;
|
|
115
|
+
string resume_token = 3;
|
|
116
|
+
int32 checkpoint_version = 4;
|
|
117
|
+
google.protobuf.Timestamp created_at = 5;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
message ExecuteResponse {
|
|
121
|
+
string request_id = 1;
|
|
122
|
+
string execution_id = 2;
|
|
123
|
+
string status = 3;
|
|
124
|
+
google.protobuf.Value output = 4;
|
|
125
|
+
optional Error error = 5;
|
|
126
|
+
optional Usage usage = 6;
|
|
127
|
+
repeated Citation citations = 7;
|
|
128
|
+
optional Suspension suspension = 8;
|
|
129
|
+
google.protobuf.Struct metadata = 9;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
message StreamItem {
|
|
133
|
+
string type = 1;
|
|
134
|
+
int64 sequence = 2;
|
|
135
|
+
string execution_id = 3;
|
|
136
|
+
google.protobuf.Struct data = 4;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
service AgentExecutionService {
|
|
140
|
+
rpc Execute(ExecuteRequest) returns (ExecuteResponse);
|
|
141
|
+
rpc Stream(ExecuteRequest) returns (stream StreamItem);
|
|
142
|
+
rpc Resume(ResumeRequest) returns (ExecuteResponse);
|
|
143
|
+
rpc ResumeStream(ResumeRequest) returns (stream StreamItem);
|
|
144
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "atlas-agent-adapters"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Adapters externos REST, gRPC e orientados a eventos para o Atlas"
|
|
9
|
+
requires-python = ">=3.12"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
authors = [{ name = "Jorge Medina" }]
|
|
14
|
+
maintainers = [{ name = "Jorge Medina" }]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
"Typing :: Typed",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"atlas-agent-core~=1.0.1",
|
|
25
|
+
"pydantic>=2.13,<3",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.optional-dependencies]
|
|
29
|
+
rest = ["fastapi>=0.141,<1"]
|
|
30
|
+
grpc = ["grpcio>=1.81.1,<2", "protobuf>=6.33.5,<7"]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Repository = "https://github.com/Medicode/ai-agent-framework"
|
|
34
|
+
Documentation = "https://github.com/Medicode/ai-agent-framework/tree/main/docs/adapters"
|
|
35
|
+
Issues = "https://github.com/Medicode/ai-agent-framework/issues"
|
|
36
|
+
|
|
37
|
+
[tool.hatch.version]
|
|
38
|
+
path = "src/atlas_agents/adapters/_version.py"
|
|
39
|
+
|
|
40
|
+
[tool.hatch.build.targets.wheel]
|
|
41
|
+
packages = ["src/atlas_agents"]
|
|
42
|
+
|
|
43
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
44
|
+
"proto/atlas_agents/adapters/grpc/v1/agent_execution.proto" = "atlas_agents/adapters/grpc/v1/agent_execution.proto"
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.sdist]
|
|
47
|
+
include = ["src/atlas_agents/adapters", "proto", "LICENSE", "README.md", "pyproject.toml"]
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""External transport adapters over one application execution facade."""
|
|
2
|
+
|
|
3
|
+
from atlas_agents.adapters._version import __version__
|
|
4
|
+
from atlas_agents.adapters.errors import (
|
|
5
|
+
AdapterConfigurationError,
|
|
6
|
+
AdapterError,
|
|
7
|
+
AdapterSerializationError,
|
|
8
|
+
AdapterStreamingError,
|
|
9
|
+
AdapterUnavailableError,
|
|
10
|
+
AgentAccessDeniedError,
|
|
11
|
+
AgentNotRegisteredError,
|
|
12
|
+
DuplicateAgentError,
|
|
13
|
+
IdempotencyConflictError,
|
|
14
|
+
IdentityMappingError,
|
|
15
|
+
InvalidExternalRequestError,
|
|
16
|
+
)
|
|
17
|
+
from atlas_agents.adapters.idempotency import (
|
|
18
|
+
IdempotencyRecord,
|
|
19
|
+
IdempotencyState,
|
|
20
|
+
IdempotencyStore,
|
|
21
|
+
InMemoryIdempotencyStore,
|
|
22
|
+
)
|
|
23
|
+
from atlas_agents.adapters.models import (
|
|
24
|
+
AdapterErrorResponse,
|
|
25
|
+
AdapterExecutionStatus,
|
|
26
|
+
ApprovalRequestDTO,
|
|
27
|
+
CitationDTO,
|
|
28
|
+
ExecuteAgentRequest,
|
|
29
|
+
ExecuteAgentResponse,
|
|
30
|
+
ExecutionStreamItem,
|
|
31
|
+
ExecutionSuspensionDTO,
|
|
32
|
+
ExternalAgentInput,
|
|
33
|
+
ExternalAttachment,
|
|
34
|
+
ExternalExecutionContext,
|
|
35
|
+
ReadinessResponse,
|
|
36
|
+
RequestedExecutionBudget,
|
|
37
|
+
RequestedExecutionLimits,
|
|
38
|
+
ResumeExecutionRequest,
|
|
39
|
+
TransportPrincipal,
|
|
40
|
+
UsageDTO,
|
|
41
|
+
)
|
|
42
|
+
from atlas_agents.adapters.optional import MissingAdapterDependencyError
|
|
43
|
+
from atlas_agents.adapters.policies import (
|
|
44
|
+
AgentAccessPolicy,
|
|
45
|
+
AgentOperation,
|
|
46
|
+
AllowAllAgentAccessPolicy,
|
|
47
|
+
BoundedExecutionPolicyResolver,
|
|
48
|
+
EffectiveExecutionPolicy,
|
|
49
|
+
ExecutionIdentityMapper,
|
|
50
|
+
ExecutionPolicyResolver,
|
|
51
|
+
SubjectExecutionIdentityMapper,
|
|
52
|
+
)
|
|
53
|
+
from atlas_agents.adapters.registry import AgentRegistry
|
|
54
|
+
from atlas_agents.adapters.service import (
|
|
55
|
+
AgentExecutionService,
|
|
56
|
+
AgentRegistryPort,
|
|
57
|
+
AgentRuntimePort,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
__all__ = [
|
|
61
|
+
"AdapterConfigurationError",
|
|
62
|
+
"AdapterError",
|
|
63
|
+
"AdapterErrorResponse",
|
|
64
|
+
"AdapterExecutionStatus",
|
|
65
|
+
"AdapterSerializationError",
|
|
66
|
+
"AdapterStreamingError",
|
|
67
|
+
"AdapterUnavailableError",
|
|
68
|
+
"AgentAccessDeniedError",
|
|
69
|
+
"AgentAccessPolicy",
|
|
70
|
+
"AgentExecutionService",
|
|
71
|
+
"AgentNotRegisteredError",
|
|
72
|
+
"AgentOperation",
|
|
73
|
+
"AgentRegistry",
|
|
74
|
+
"AgentRegistryPort",
|
|
75
|
+
"AgentRuntimePort",
|
|
76
|
+
"AllowAllAgentAccessPolicy",
|
|
77
|
+
"ApprovalRequestDTO",
|
|
78
|
+
"BoundedExecutionPolicyResolver",
|
|
79
|
+
"CitationDTO",
|
|
80
|
+
"DuplicateAgentError",
|
|
81
|
+
"EffectiveExecutionPolicy",
|
|
82
|
+
"ExecuteAgentRequest",
|
|
83
|
+
"ExecuteAgentResponse",
|
|
84
|
+
"ExecutionIdentityMapper",
|
|
85
|
+
"ExecutionPolicyResolver",
|
|
86
|
+
"ExecutionStreamItem",
|
|
87
|
+
"ExecutionSuspensionDTO",
|
|
88
|
+
"ExternalAgentInput",
|
|
89
|
+
"ExternalAttachment",
|
|
90
|
+
"ExternalExecutionContext",
|
|
91
|
+
"IdempotencyConflictError",
|
|
92
|
+
"IdempotencyRecord",
|
|
93
|
+
"IdempotencyState",
|
|
94
|
+
"IdempotencyStore",
|
|
95
|
+
"IdentityMappingError",
|
|
96
|
+
"InMemoryIdempotencyStore",
|
|
97
|
+
"InvalidExternalRequestError",
|
|
98
|
+
"MissingAdapterDependencyError",
|
|
99
|
+
"ReadinessResponse",
|
|
100
|
+
"RequestedExecutionBudget",
|
|
101
|
+
"RequestedExecutionLimits",
|
|
102
|
+
"ResumeExecutionRequest",
|
|
103
|
+
"SubjectExecutionIdentityMapper",
|
|
104
|
+
"TransportPrincipal",
|
|
105
|
+
"UsageDTO",
|
|
106
|
+
"__version__",
|
|
107
|
+
]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Safe application and transport adapter errors."""
|
|
2
|
+
|
|
3
|
+
from atlas_agents.exceptions import AtlasAgentError
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AdapterError(AtlasAgentError):
|
|
7
|
+
"""Base error with a stable wire code and retry indication."""
|
|
8
|
+
|
|
9
|
+
code = "adapter_error"
|
|
10
|
+
retryable = False
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AdapterConfigurationError(AdapterError):
|
|
14
|
+
"""Report invalid explicit adapter configuration."""
|
|
15
|
+
|
|
16
|
+
code = "adapter_configuration_error"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AgentNotRegisteredError(AdapterError):
|
|
20
|
+
"""Report an unknown agent without exposing registry contents."""
|
|
21
|
+
|
|
22
|
+
code = "agent_not_registered"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DuplicateAgentError(AdapterError):
|
|
26
|
+
"""Reject silent replacement of an existing agent."""
|
|
27
|
+
|
|
28
|
+
code = "duplicate_agent"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AgentAccessDeniedError(AdapterError):
|
|
32
|
+
"""Report transport-level agent authorization denial."""
|
|
33
|
+
|
|
34
|
+
code = "agent_access_denied"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class InvalidExternalRequestError(AdapterError):
|
|
38
|
+
"""Report semantically invalid external input."""
|
|
39
|
+
|
|
40
|
+
code = "invalid_external_request"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class IdentityMappingError(AdapterError):
|
|
44
|
+
"""Report failure to map a trusted transport principal."""
|
|
45
|
+
|
|
46
|
+
code = "identity_mapping_error"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class IdempotencyConflictError(AdapterError):
|
|
50
|
+
"""Report reuse of a key with a different canonical request."""
|
|
51
|
+
|
|
52
|
+
code = "idempotency_conflict"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class AdapterSerializationError(AdapterError):
|
|
56
|
+
"""Report data that cannot cross a wire boundary."""
|
|
57
|
+
|
|
58
|
+
code = "adapter_serialization_error"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class AdapterStreamingError(AdapterError):
|
|
62
|
+
"""Report an adapter streaming failure."""
|
|
63
|
+
|
|
64
|
+
code = "adapter_streaming_error"
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class AdapterUnavailableError(AdapterError):
|
|
68
|
+
"""Report a transient application or transport dependency failure."""
|
|
69
|
+
|
|
70
|
+
code = "adapter_unavailable"
|
|
71
|
+
retryable = True
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Provider-neutral event-driven adapter contracts and consumer."""
|
|
2
|
+
|
|
3
|
+
from atlas_agents.adapters.events.consumer import ExecutionCommandConsumer
|
|
4
|
+
from atlas_agents.adapters.events.models import (
|
|
5
|
+
EventAdapterConfig,
|
|
6
|
+
EventPublicationMode,
|
|
7
|
+
ExecuteAgentCommand,
|
|
8
|
+
MessageEnvelope,
|
|
9
|
+
MessagePrincipalResolver,
|
|
10
|
+
MessageProcessingResult,
|
|
11
|
+
ResumeExecutionCommand,
|
|
12
|
+
TrustedContextPrincipalResolver,
|
|
13
|
+
TrustedMessageContext,
|
|
14
|
+
)
|
|
15
|
+
from atlas_agents.adapters.events.publisher import ExecutionEventPublisher
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"EventAdapterConfig",
|
|
19
|
+
"EventPublicationMode",
|
|
20
|
+
"ExecuteAgentCommand",
|
|
21
|
+
"ExecutionCommandConsumer",
|
|
22
|
+
"ExecutionEventPublisher",
|
|
23
|
+
"MessageEnvelope",
|
|
24
|
+
"MessagePrincipalResolver",
|
|
25
|
+
"MessageProcessingResult",
|
|
26
|
+
"ResumeExecutionCommand",
|
|
27
|
+
"TrustedContextPrincipalResolver",
|
|
28
|
+
"TrustedMessageContext",
|
|
29
|
+
]
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"""Broker-neutral command handler over the shared execution service."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
from datetime import UTC, datetime
|
|
7
|
+
from typing import cast
|
|
8
|
+
from uuid import uuid4
|
|
9
|
+
|
|
10
|
+
from pydantic import JsonValue, ValidationError
|
|
11
|
+
|
|
12
|
+
from atlas_agents.adapters.errors import AdapterError, AdapterUnavailableError
|
|
13
|
+
from atlas_agents.adapters.events.models import (
|
|
14
|
+
EventAdapterConfig,
|
|
15
|
+
EventPublicationMode,
|
|
16
|
+
ExecuteAgentCommand,
|
|
17
|
+
MessageEnvelope,
|
|
18
|
+
MessagePrincipalResolver,
|
|
19
|
+
MessageProcessingResult,
|
|
20
|
+
ResumeExecutionCommand,
|
|
21
|
+
TrustedMessageContext,
|
|
22
|
+
)
|
|
23
|
+
from atlas_agents.adapters.events.publisher import ExecutionEventPublisher
|
|
24
|
+
from atlas_agents.adapters.models import (
|
|
25
|
+
ExecuteAgentRequest,
|
|
26
|
+
ExecuteAgentResponse,
|
|
27
|
+
ResumeExecutionRequest,
|
|
28
|
+
TransportPrincipal,
|
|
29
|
+
)
|
|
30
|
+
from atlas_agents.adapters.service import AgentExecutionService
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ExecutionCommandConsumer:
|
|
34
|
+
"""Handle execute and resume commands without owning broker lifecycle."""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
*,
|
|
39
|
+
service: AgentExecutionService,
|
|
40
|
+
publisher: ExecutionEventPublisher,
|
|
41
|
+
principal_resolver: MessagePrincipalResolver,
|
|
42
|
+
config: EventAdapterConfig | None = None,
|
|
43
|
+
message_id_factory: Callable[[], str] | None = None,
|
|
44
|
+
) -> None:
|
|
45
|
+
"""Store explicit dependencies and safe event configuration."""
|
|
46
|
+
self._service = service
|
|
47
|
+
self._publisher = publisher
|
|
48
|
+
self._principal_resolver = principal_resolver
|
|
49
|
+
self._config = config or EventAdapterConfig()
|
|
50
|
+
self._message_id_factory = message_id_factory or (lambda: str(uuid4()))
|
|
51
|
+
|
|
52
|
+
async def handle(
|
|
53
|
+
self, envelope: MessageEnvelope, context: TrustedMessageContext
|
|
54
|
+
) -> MessageProcessingResult:
|
|
55
|
+
"""Process one delivery and report ack/retry semantics explicitly."""
|
|
56
|
+
if envelope.schema_version != self._config.schema_version:
|
|
57
|
+
return MessageProcessingResult(
|
|
58
|
+
acknowledge=False,
|
|
59
|
+
retryable=False,
|
|
60
|
+
error_code="unsupported_schema_version",
|
|
61
|
+
)
|
|
62
|
+
try:
|
|
63
|
+
principal = self._principal_resolver.resolve(envelope, context)
|
|
64
|
+
if envelope.message_type == "execution.execute":
|
|
65
|
+
execute_command = ExecuteAgentCommand.model_validate(envelope.payload)
|
|
66
|
+
await self._execute(envelope, execute_command, principal)
|
|
67
|
+
elif envelope.message_type == "execution.resume":
|
|
68
|
+
resume_command = ResumeExecutionCommand.model_validate(envelope.payload)
|
|
69
|
+
await self._resume(envelope, resume_command, principal)
|
|
70
|
+
else:
|
|
71
|
+
return MessageProcessingResult(
|
|
72
|
+
acknowledge=False,
|
|
73
|
+
retryable=False,
|
|
74
|
+
error_code="unsupported_message_type",
|
|
75
|
+
)
|
|
76
|
+
except ValidationError:
|
|
77
|
+
return MessageProcessingResult(
|
|
78
|
+
acknowledge=False,
|
|
79
|
+
retryable=False,
|
|
80
|
+
error_code="invalid_external_request",
|
|
81
|
+
)
|
|
82
|
+
except AdapterError as error:
|
|
83
|
+
return MessageProcessingResult(
|
|
84
|
+
acknowledge=False,
|
|
85
|
+
retryable=error.retryable,
|
|
86
|
+
error_code=error.code,
|
|
87
|
+
)
|
|
88
|
+
except Exception:
|
|
89
|
+
return MessageProcessingResult(
|
|
90
|
+
acknowledge=False,
|
|
91
|
+
retryable=True,
|
|
92
|
+
error_code="adapter_unavailable",
|
|
93
|
+
)
|
|
94
|
+
return MessageProcessingResult(acknowledge=True)
|
|
95
|
+
|
|
96
|
+
async def _execute(
|
|
97
|
+
self,
|
|
98
|
+
envelope: MessageEnvelope,
|
|
99
|
+
command: ExecuteAgentCommand,
|
|
100
|
+
principal: TransportPrincipal,
|
|
101
|
+
) -> None:
|
|
102
|
+
request = ExecuteAgentRequest(
|
|
103
|
+
**command.model_dump(),
|
|
104
|
+
principal=principal,
|
|
105
|
+
idempotency_key=envelope.message_id,
|
|
106
|
+
)
|
|
107
|
+
if self._config.publication_mode is EventPublicationMode.TERMINAL_ONLY:
|
|
108
|
+
await self._publish_terminal(envelope, await self._service.execute(request))
|
|
109
|
+
return
|
|
110
|
+
async for item in self._service.stream(request):
|
|
111
|
+
await self._publish(
|
|
112
|
+
source=envelope,
|
|
113
|
+
message_type="execution.stream",
|
|
114
|
+
payload=cast("dict[str, JsonValue]", item.model_dump(mode="json")),
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
async def _resume(
|
|
118
|
+
self,
|
|
119
|
+
envelope: MessageEnvelope,
|
|
120
|
+
command: ResumeExecutionCommand,
|
|
121
|
+
principal: TransportPrincipal,
|
|
122
|
+
) -> None:
|
|
123
|
+
request = ResumeExecutionRequest(
|
|
124
|
+
**command.model_dump(),
|
|
125
|
+
principal=principal,
|
|
126
|
+
idempotency_key=envelope.message_id,
|
|
127
|
+
)
|
|
128
|
+
if self._config.publication_mode is EventPublicationMode.TERMINAL_ONLY:
|
|
129
|
+
await self._publish_terminal(envelope, await self._service.resume(request))
|
|
130
|
+
return
|
|
131
|
+
async for item in self._service.resume_stream(request):
|
|
132
|
+
await self._publish(
|
|
133
|
+
source=envelope,
|
|
134
|
+
message_type="execution.stream",
|
|
135
|
+
payload=cast("dict[str, JsonValue]", item.model_dump(mode="json")),
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
async def _publish_terminal(
|
|
139
|
+
self, source: MessageEnvelope, response: ExecuteAgentResponse
|
|
140
|
+
) -> None:
|
|
141
|
+
await self._publish(
|
|
142
|
+
source=source,
|
|
143
|
+
message_type=f"execution.{response.status.value}",
|
|
144
|
+
payload=cast("dict[str, JsonValue]", response.model_dump(mode="json")),
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
async def _publish(
|
|
148
|
+
self,
|
|
149
|
+
*,
|
|
150
|
+
source: MessageEnvelope,
|
|
151
|
+
message_type: str,
|
|
152
|
+
payload: dict[str, JsonValue],
|
|
153
|
+
) -> None:
|
|
154
|
+
event = MessageEnvelope(
|
|
155
|
+
message_id=self._message_id_factory(),
|
|
156
|
+
message_type=message_type,
|
|
157
|
+
schema_version=self._config.schema_version,
|
|
158
|
+
correlation_id=source.correlation_id,
|
|
159
|
+
causation_id=source.message_id,
|
|
160
|
+
timestamp=datetime.now(UTC),
|
|
161
|
+
payload=payload,
|
|
162
|
+
)
|
|
163
|
+
try:
|
|
164
|
+
await self._publisher.publish(event)
|
|
165
|
+
except Exception:
|
|
166
|
+
raise AdapterUnavailableError(
|
|
167
|
+
"Não foi possível publicar o evento de execução."
|
|
168
|
+
) from None
|