macp-sdk-python 0.3.0__tar.gz → 0.4.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.
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/PKG-INFO +11 -5
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/README.md +2 -1
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/pyproject.toml +19 -8
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/__init__.py +2 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/base_session.py +17 -1
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/client.py +73 -5
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/envelope.py +23 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/policy.py +36 -3
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/watchers.py +33 -10
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk_python.egg-info/PKG-INFO +11 -5
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk_python.egg-info/requires.txt +2 -2
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/LICENSE +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/setup.cfg +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/_logging.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/agent/__init__.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/agent/cancel_callback.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/agent/dispatcher.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/agent/participant.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/agent/runner.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/agent/strategies.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/agent/transports.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/agent/types.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/auth.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/base_projection.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/constants.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/decision.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/errors.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/handoff.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/projections.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/proposal.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/proto_registry.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/py.typed +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/quorum.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/retry.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/task.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk/validation.py +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk_python.egg-info/SOURCES.txt +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk_python.egg-info/dependency_links.txt +0 -0
- {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk_python.egg-info/top_level.txt +0 -0
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: macp-sdk-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Python SDK for the MACP Rust runtime
|
|
5
|
-
Author-email:
|
|
5
|
+
Author-email: Multi-Agent Coordination Protocol <macp@multiagentcoordinationprotocol.org>
|
|
6
6
|
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/multiagentcoordinationprotocol/macp-sdk-python
|
|
8
|
+
Project-URL: Repository, https://github.com/multiagentcoordinationprotocol/macp-sdk-python
|
|
9
|
+
Project-URL: Documentation, https://github.com/multiagentcoordinationprotocol/macp-sdk-python/tree/main/docs
|
|
10
|
+
Project-URL: Changelog, https://github.com/multiagentcoordinationprotocol/macp-sdk-python/blob/main/CHANGELOG.md
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/multiagentcoordinationprotocol/macp-sdk-python/issues
|
|
7
12
|
Classifier: Development Status :: 3 - Alpha
|
|
8
13
|
Classifier: Intended Audience :: Developers
|
|
9
14
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -15,9 +20,9 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
15
20
|
Requires-Python: >=3.11
|
|
16
21
|
Description-Content-Type: text/markdown
|
|
17
22
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: grpcio>=1.
|
|
23
|
+
Requires-Dist: grpcio>=1.81.1
|
|
19
24
|
Requires-Dist: protobuf>=5.27.0
|
|
20
|
-
Requires-Dist: macp-proto<0.2.0,>=0.1.
|
|
25
|
+
Requires-Dist: macp-proto<0.2.0,>=0.1.3
|
|
21
26
|
Provides-Extra: dev
|
|
22
27
|
Requires-Dist: grpcio-tools>=1.74.0; extra == "dev"
|
|
23
28
|
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
@@ -165,6 +170,7 @@ Business logic — voting rules, AI decision heuristics, policy enforcement —
|
|
|
165
170
|
|
|
166
171
|
- `GetSession` returns metadata only (not mode state/transcript) — hence the local projection pattern; use `StreamSession` + `send_subscribe` for the full transcript
|
|
167
172
|
- `StreamSession` is scoped to one session per stream; use `MacpStream.send_subscribe(session_id)` (RFC-MACP-0006-A1, since SDK 0.2.3 / `macp-proto 0.1.2`) to replay accepted history before live broadcast
|
|
168
|
-
- For cross-session observability, use `MacpClient.list_sessions()` and `SessionLifecycleWatcher` (SDK 0.3.0) to enumerate active sessions and stream `CREATED` / `RESOLVED` / `EXPIRED` lifecycle events
|
|
173
|
+
- For cross-session observability, use `MacpClient.list_sessions()` and `SessionLifecycleWatcher` (SDK 0.3.0) to enumerate active sessions and stream `CREATED` / `RESOLVED` / `EXPIRED` / `CANCELLED` / `SUSPENDED` / `RESUMED` lifecycle events
|
|
174
|
+
- Pause and cancel sessions with `MacpClient.suspend_session()` / `resume_session()` / `cancel_session()` (SDK 0.4.0 / `macp-proto 0.1.3`). A suspended session is non-terminal and rejects messages until resumed; an accepted `cancel_session()` now terminates as `CANCELLED` (previously surfaced as `EXPIRED`)
|
|
169
175
|
- `ListRoots` currently returns an empty list and `WatchRoots` idles — the runtime does not yet populate roots
|
|
170
176
|
- Business policy (majority, quorum, veto) belongs in your orchestrator/policy layer
|
|
@@ -131,6 +131,7 @@ Business logic — voting rules, AI decision heuristics, policy enforcement —
|
|
|
131
131
|
|
|
132
132
|
- `GetSession` returns metadata only (not mode state/transcript) — hence the local projection pattern; use `StreamSession` + `send_subscribe` for the full transcript
|
|
133
133
|
- `StreamSession` is scoped to one session per stream; use `MacpStream.send_subscribe(session_id)` (RFC-MACP-0006-A1, since SDK 0.2.3 / `macp-proto 0.1.2`) to replay accepted history before live broadcast
|
|
134
|
-
- For cross-session observability, use `MacpClient.list_sessions()` and `SessionLifecycleWatcher` (SDK 0.3.0) to enumerate active sessions and stream `CREATED` / `RESOLVED` / `EXPIRED` lifecycle events
|
|
134
|
+
- For cross-session observability, use `MacpClient.list_sessions()` and `SessionLifecycleWatcher` (SDK 0.3.0) to enumerate active sessions and stream `CREATED` / `RESOLVED` / `EXPIRED` / `CANCELLED` / `SUSPENDED` / `RESUMED` lifecycle events
|
|
135
|
+
- Pause and cancel sessions with `MacpClient.suspend_session()` / `resume_session()` / `cancel_session()` (SDK 0.4.0 / `macp-proto 0.1.3`). A suspended session is non-terminal and rejects messages until resumed; an accepted `cancel_session()` now terminates as `CANCELLED` (previously surfaced as `EXPIRED`)
|
|
135
136
|
- `ListRoots` currently returns an empty list and `WatchRoots` idles — the runtime does not yet populate roots
|
|
136
137
|
- Business policy (majority, quorum, veto) belongs in your orchestrator/policy layer
|
|
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "macp-sdk-python"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.1"
|
|
8
8
|
description = "Python SDK for the MACP Rust runtime"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
11
11
|
license = {text = "Apache-2.0"}
|
|
12
12
|
authors = [
|
|
13
|
-
{name = "
|
|
13
|
+
{name = "Multi-Agent Coordination Protocol", email = "macp@multiagentcoordinationprotocol.org"}
|
|
14
14
|
]
|
|
15
15
|
classifiers = [
|
|
16
16
|
"Development Status :: 3 - Alpha",
|
|
@@ -23,16 +23,27 @@ classifiers = [
|
|
|
23
23
|
"Topic :: Software Development :: Libraries",
|
|
24
24
|
]
|
|
25
25
|
dependencies = [
|
|
26
|
-
|
|
26
|
+
# macp-proto 0.1.3's generated gRPC stubs require grpcio>=1.81.1.
|
|
27
|
+
"grpcio>=1.81.1",
|
|
27
28
|
"protobuf>=5.27.0",
|
|
28
|
-
# Requires 0.1.
|
|
29
|
+
# Requires 0.1.3+ for the suspend/cancel/supersede surface: SuspendSession
|
|
30
|
+
# /ResumeSession RPCs, SESSION_STATE_SUSPENDED/CANCELLED, the SUSPENDED/
|
|
31
|
+
# RESUMED/CANCELLED lifecycle events, and CommitmentPayload.supersedes
|
|
32
|
+
# (CommitmentRef). 0.1.2 added the RFC-MACP-0006-A1 subscribe_session_id /
|
|
29
33
|
# after_sequence fields on StreamSessionRequest (used by MacpStream
|
|
30
|
-
# .send_subscribe and the gRPC agent transport adapter)
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
"macp-proto>=0.1.
|
|
34
|
+
# .send_subscribe and the gRPC agent transport adapter); 0.1.1 is the
|
|
35
|
+
# earlier baseline for context_id / extensions on SessionStartPayload.
|
|
36
|
+
# See docs/contributing.md "Bumping macp-proto".
|
|
37
|
+
"macp-proto>=0.1.3,<0.2.0",
|
|
34
38
|
]
|
|
35
39
|
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://github.com/multiagentcoordinationprotocol/macp-sdk-python"
|
|
42
|
+
Repository = "https://github.com/multiagentcoordinationprotocol/macp-sdk-python"
|
|
43
|
+
Documentation = "https://github.com/multiagentcoordinationprotocol/macp-sdk-python/tree/main/docs"
|
|
44
|
+
Changelog = "https://github.com/multiagentcoordinationprotocol/macp-sdk-python/blob/main/CHANGELOG.md"
|
|
45
|
+
"Bug Tracker" = "https://github.com/multiagentcoordinationprotocol/macp-sdk-python/issues"
|
|
46
|
+
|
|
36
47
|
[project.optional-dependencies]
|
|
37
48
|
dev = [
|
|
38
49
|
"grpcio-tools>=1.74.0", # only needed for proto-python package publishing
|
|
@@ -19,6 +19,7 @@ from .constants import (
|
|
|
19
19
|
from .decision import DecisionSession
|
|
20
20
|
from .envelope import (
|
|
21
21
|
build_commitment_payload,
|
|
22
|
+
build_commitment_ref,
|
|
22
23
|
build_envelope,
|
|
23
24
|
build_progress_payload,
|
|
24
25
|
build_root,
|
|
@@ -181,6 +182,7 @@ __all__ = [
|
|
|
181
182
|
"TaskSession",
|
|
182
183
|
"VotingRules",
|
|
183
184
|
"build_commitment_payload",
|
|
185
|
+
"build_commitment_ref",
|
|
184
186
|
"build_decision_policy",
|
|
185
187
|
"build_envelope",
|
|
186
188
|
"build_handoff_policy",
|
|
@@ -163,9 +163,25 @@ class BaseSession(ABC):
|
|
|
163
163
|
return self.client.get_session(self.session_id, auth=auth or self.auth)
|
|
164
164
|
|
|
165
165
|
def cancel(self, *, reason: str = "", auth: AuthConfig | None = None) -> envelope_pb2.Ack:
|
|
166
|
-
"""Cancel the session."""
|
|
166
|
+
"""Cancel the session (terminates as ``CANCELLED`` since proto 0.1.3)."""
|
|
167
167
|
return self.client.cancel_session(self.session_id, reason=reason, auth=auth or self.auth)
|
|
168
168
|
|
|
169
|
+
def suspend(self, *, reason: str = "", auth: AuthConfig | None = None) -> envelope_pb2.Ack:
|
|
170
|
+
"""Suspend this session (proto 0.1.3+).
|
|
171
|
+
|
|
172
|
+
Moves it to the non-terminal ``SUSPENDED`` state; the runtime rejects
|
|
173
|
+
messages until :meth:`resume`. Delegates to
|
|
174
|
+
:meth:`MacpClient.suspend_session`.
|
|
175
|
+
"""
|
|
176
|
+
return self.client.suspend_session(self.session_id, reason=reason, auth=auth or self.auth)
|
|
177
|
+
|
|
178
|
+
def resume(self, *, reason: str = "", auth: AuthConfig | None = None) -> envelope_pb2.Ack:
|
|
179
|
+
"""Resume this suspended session (proto 0.1.3+), restoring ``OPEN``.
|
|
180
|
+
|
|
181
|
+
Delegates to :meth:`MacpClient.resume_session`.
|
|
182
|
+
"""
|
|
183
|
+
return self.client.resume_session(self.session_id, reason=reason, auth=auth or self.auth)
|
|
184
|
+
|
|
169
185
|
def open_stream(self, *, auth: AuthConfig | None = None) -> MacpStream:
|
|
170
186
|
"""Open a bidirectional stream for this session."""
|
|
171
187
|
return self.client.open_stream(auth=auth or self.auth)
|
|
@@ -213,7 +213,7 @@ class MacpClient:
|
|
|
213
213
|
root_certificates: bytes | None = None,
|
|
214
214
|
default_timeout: float | None = None,
|
|
215
215
|
client_name: str = "macp-sdk-python",
|
|
216
|
-
client_version: str = "0.
|
|
216
|
+
client_version: str = "0.4.0",
|
|
217
217
|
) -> None:
|
|
218
218
|
if secure is None:
|
|
219
219
|
secure = not allow_insecure
|
|
@@ -370,6 +370,13 @@ class MacpClient:
|
|
|
370
370
|
timeout: float | None = None,
|
|
371
371
|
raise_on_nack: bool = True,
|
|
372
372
|
) -> envelope_pb2.Ack:
|
|
373
|
+
"""Terminate a session.
|
|
374
|
+
|
|
375
|
+
Since runtime 0.4.0 / macp-proto 0.1.3 an accepted cancellation
|
|
376
|
+
moves the session to ``SESSION_STATE_CANCELLED`` (previously
|
|
377
|
+
``EXPIRED``) and surfaces an ``EVENT_TYPE_CANCELLED`` lifecycle
|
|
378
|
+
event. The returned ``Ack.session_state`` reflects ``CANCELLED``.
|
|
379
|
+
"""
|
|
373
380
|
auth_cfg = self._require_auth(auth)
|
|
374
381
|
request_kwargs: dict[str, object] = {
|
|
375
382
|
"session_id": session_id,
|
|
@@ -395,6 +402,66 @@ class MacpClient:
|
|
|
395
402
|
raise MacpAckError(self._failure_from_ack(ack))
|
|
396
403
|
return ack
|
|
397
404
|
|
|
405
|
+
def suspend_session(
|
|
406
|
+
self,
|
|
407
|
+
session_id: str,
|
|
408
|
+
*,
|
|
409
|
+
reason: str = "",
|
|
410
|
+
auth: AuthConfig | None = None,
|
|
411
|
+
timeout: float | None = None,
|
|
412
|
+
raise_on_nack: bool = True,
|
|
413
|
+
) -> envelope_pb2.Ack:
|
|
414
|
+
"""Suspend an open session (macp-proto 0.1.3 / runtime 0.4.0).
|
|
415
|
+
|
|
416
|
+
Moves the session to the non-terminal ``SESSION_STATE_SUSPENDED``
|
|
417
|
+
state and emits an ``EVENT_TYPE_SUSPENDED`` lifecycle event. While
|
|
418
|
+
suspended the runtime rejects messages sent to the session with a
|
|
419
|
+
non-OPEN error; call :meth:`resume_session` to return it to OPEN.
|
|
420
|
+
The returned ``Ack.session_state`` reflects ``SUSPENDED``.
|
|
421
|
+
"""
|
|
422
|
+
auth_cfg = self._require_auth(auth)
|
|
423
|
+
try:
|
|
424
|
+
response = self.stub.SuspendSession(
|
|
425
|
+
core_pb2.SuspendSessionRequest(session_id=session_id, reason=reason),
|
|
426
|
+
metadata=self._metadata(auth_cfg),
|
|
427
|
+
timeout=timeout or self.default_timeout,
|
|
428
|
+
)
|
|
429
|
+
except grpc.RpcError as rpc_err:
|
|
430
|
+
raise MacpTransportError(rpc_err.details() or str(rpc_err)) from rpc_err
|
|
431
|
+
ack = response.ack
|
|
432
|
+
if raise_on_nack and not ack.ok:
|
|
433
|
+
raise MacpAckError(self._failure_from_ack(ack))
|
|
434
|
+
return ack
|
|
435
|
+
|
|
436
|
+
def resume_session(
|
|
437
|
+
self,
|
|
438
|
+
session_id: str,
|
|
439
|
+
*,
|
|
440
|
+
reason: str = "",
|
|
441
|
+
auth: AuthConfig | None = None,
|
|
442
|
+
timeout: float | None = None,
|
|
443
|
+
raise_on_nack: bool = True,
|
|
444
|
+
) -> envelope_pb2.Ack:
|
|
445
|
+
"""Resume a suspended session (macp-proto 0.1.3 / runtime 0.4.0).
|
|
446
|
+
|
|
447
|
+
Returns a ``SESSION_STATE_SUSPENDED`` session to
|
|
448
|
+
``SESSION_STATE_OPEN`` and emits an ``EVENT_TYPE_RESUMED`` lifecycle
|
|
449
|
+
event. The returned ``Ack.session_state`` reflects ``OPEN``.
|
|
450
|
+
"""
|
|
451
|
+
auth_cfg = self._require_auth(auth)
|
|
452
|
+
try:
|
|
453
|
+
response = self.stub.ResumeSession(
|
|
454
|
+
core_pb2.ResumeSessionRequest(session_id=session_id, reason=reason),
|
|
455
|
+
metadata=self._metadata(auth_cfg),
|
|
456
|
+
timeout=timeout or self.default_timeout,
|
|
457
|
+
)
|
|
458
|
+
except grpc.RpcError as rpc_err:
|
|
459
|
+
raise MacpTransportError(rpc_err.details() or str(rpc_err)) from rpc_err
|
|
460
|
+
ack = response.ack
|
|
461
|
+
if raise_on_nack and not ack.ok:
|
|
462
|
+
raise MacpAckError(self._failure_from_ack(ack))
|
|
463
|
+
return ack
|
|
464
|
+
|
|
398
465
|
def get_manifest(
|
|
399
466
|
self, agent_id: str = "", *, timeout: float | None = None
|
|
400
467
|
) -> core_pb2.GetManifestResponse:
|
|
@@ -452,10 +519,11 @@ class MacpClient:
|
|
|
452
519
|
|
|
453
520
|
The runtime emits an initial ``EVENT_TYPE_CREATED`` frame for every
|
|
454
521
|
currently-open session, then live events as sessions transition
|
|
455
|
-
through ``CREATED``, ``RESOLVED``,
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
522
|
+
through ``CREATED``, ``RESOLVED``, ``EXPIRED``, ``CANCELLED``, and
|
|
523
|
+
the non-terminal ``SUSPENDED`` / ``RESUMED`` pair (the latter three
|
|
524
|
+
since macp-proto 0.1.3). Each event carries a full
|
|
525
|
+
``SessionMetadata`` (including ``context_id`` and ``extension_keys``),
|
|
526
|
+
so callers can project run state without a follow-up ``get_session``.
|
|
459
527
|
"""
|
|
460
528
|
logger.debug("watch_sessions starting")
|
|
461
529
|
auth_cfg = self._require_auth(auth)
|
|
@@ -80,6 +80,17 @@ def _has_outcome_positive_field() -> bool:
|
|
|
80
80
|
return any(f.name == "outcome_positive" for f in core_pb2.CommitmentPayload.DESCRIPTOR.fields)
|
|
81
81
|
|
|
82
82
|
|
|
83
|
+
def _has_supersedes_field() -> bool:
|
|
84
|
+
"""Check if the proto schema supports CommitmentPayload.supersedes (>=0.1.3)."""
|
|
85
|
+
return any(f.name == "supersedes" for f in core_pb2.CommitmentPayload.DESCRIPTOR.fields)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def build_commitment_ref(*, session_id: str, commitment_hash: str) -> core_pb2.CommitmentRef:
|
|
89
|
+
"""Build a ``CommitmentRef`` (macp-proto 0.1.3) pointing at a prior
|
|
90
|
+
commitment, for use as ``build_commitment_payload(supersedes=...)``."""
|
|
91
|
+
return core_pb2.CommitmentRef(session_id=session_id, commitment_hash=commitment_hash)
|
|
92
|
+
|
|
93
|
+
|
|
83
94
|
def build_commitment_payload(
|
|
84
95
|
*,
|
|
85
96
|
action: str,
|
|
@@ -90,7 +101,15 @@ def build_commitment_payload(
|
|
|
90
101
|
configuration_version: str = DEFAULT_CONFIGURATION_VERSION,
|
|
91
102
|
policy_version: str = DEFAULT_POLICY_VERSION,
|
|
92
103
|
outcome_positive: bool | None = None,
|
|
104
|
+
supersedes: core_pb2.CommitmentRef | None = None,
|
|
93
105
|
) -> core_pb2.CommitmentPayload:
|
|
106
|
+
"""Build a ``CommitmentPayload``.
|
|
107
|
+
|
|
108
|
+
``supersedes`` (macp-proto 0.1.3) optionally references a prior
|
|
109
|
+
commitment this one revises, as a ``CommitmentRef`` of
|
|
110
|
+
``(session_id, commitment_hash)``. It is absent by default and unrelated
|
|
111
|
+
to proposal-mode ``supersedes_proposal_id``.
|
|
112
|
+
"""
|
|
94
113
|
if outcome_positive is None:
|
|
95
114
|
outcome_positive = infer_outcome_positive(action)
|
|
96
115
|
kwargs: dict[str, object] = dict(
|
|
@@ -104,6 +123,10 @@ def build_commitment_payload(
|
|
|
104
123
|
)
|
|
105
124
|
if _has_outcome_positive_field():
|
|
106
125
|
kwargs["outcome_positive"] = outcome_positive
|
|
126
|
+
if supersedes is not None:
|
|
127
|
+
if not _has_supersedes_field():
|
|
128
|
+
raise MacpSessionError("CommitmentPayload.supersedes requires macp-proto >= 0.1.3")
|
|
129
|
+
kwargs["supersedes"] = supersedes
|
|
107
130
|
return core_pb2.CommitmentPayload(**kwargs)
|
|
108
131
|
|
|
109
132
|
|
|
@@ -22,9 +22,20 @@ class CommitmentRules:
|
|
|
22
22
|
authority: str = "initiator_only"
|
|
23
23
|
designated_roles: list[str] = field(default_factory=list)
|
|
24
24
|
require_vote_quorum: bool = False
|
|
25
|
+
# RFC-MACP-0012 schema_version 2, Decision mode only: when True, a
|
|
26
|
+
# reject-majority resolves the session with a committed *negative* outcome
|
|
27
|
+
# (``outcome_positive = false``) instead of denying commitment. Emitted only
|
|
28
|
+
# by ``build_decision_policy`` (see ``_commitment_dict`` note) so version-1
|
|
29
|
+
# quorum/proposal/task/handoff schemas are unaffected. Default False keeps
|
|
30
|
+
# version-1 behaviour for existing callers.
|
|
31
|
+
allow_decline_over_approval: bool = False
|
|
25
32
|
|
|
26
33
|
|
|
27
34
|
def _commitment_dict(c: CommitmentRules) -> dict[str, object]:
|
|
35
|
+
# Shared by all five mode builders — intentionally excludes the Decision-only
|
|
36
|
+
# ``allow_decline_over_approval`` field so it does not leak into the still
|
|
37
|
+
# version-1 quorum/proposal/task/handoff commitment schemas. Decision emits
|
|
38
|
+
# that field itself in ``build_decision_policy``.
|
|
28
39
|
return {
|
|
29
40
|
"authority": c.authority,
|
|
30
41
|
"designated_roles": c.designated_roles,
|
|
@@ -52,6 +63,12 @@ class ObjectionHandlingRules:
|
|
|
52
63
|
|
|
53
64
|
critical_severity_vetoes: bool = False
|
|
54
65
|
veto_threshold: int = 1
|
|
66
|
+
# RFC-MACP-0012 schema_version 2: action taken when a critical objection
|
|
67
|
+
# would block commitment. One of ``"deny"`` (reject the commitment; legacy
|
|
68
|
+
# default), ``"finalize_decline"`` (resolve the session as a negative
|
|
69
|
+
# outcome), or ``"hold"`` (leave the session open). Default ``"deny"``
|
|
70
|
+
# preserves version-1 behaviour.
|
|
71
|
+
critical_objection_action: str = "deny"
|
|
55
72
|
|
|
56
73
|
|
|
57
74
|
@dataclass(frozen=True, slots=True)
|
|
@@ -80,22 +97,38 @@ def build_decision_policy(
|
|
|
80
97
|
voting_section: dict[str, object] = {
|
|
81
98
|
"algorithm": v.algorithm,
|
|
82
99
|
"threshold": v.threshold,
|
|
83
|
-
"quorum": {"type": v.quorum_type or "count", "value": v.quorum_value or 0},
|
|
84
100
|
}
|
|
101
|
+
# Emit ``quorum`` only when the caller sets it, mirroring the conditional
|
|
102
|
+
# ``weights`` emission below. This keeps the Decision ``rules`` JSON
|
|
103
|
+
# byte-identical to the typescript-sdk builder (which omits an unset quorum)
|
|
104
|
+
# and to the canonical example descriptors, which drop optional voting fields
|
|
105
|
+
# they do not set. ``quorum`` is optional with defaults ``type="count"``,
|
|
106
|
+
# ``value=0`` in decision-rules.schema.json, so omission is schema-equivalent.
|
|
107
|
+
if v.quorum_type is not None or v.quorum_value is not None:
|
|
108
|
+
voting_section["quorum"] = {
|
|
109
|
+
"type": v.quorum_type or "count",
|
|
110
|
+
"value": v.quorum_value or 0,
|
|
111
|
+
}
|
|
85
112
|
if v.weights is not None:
|
|
86
113
|
voting_section["weights"] = v.weights
|
|
87
114
|
|
|
115
|
+
# Decision-only: extend the shared commitment rules with the schema_version 2
|
|
116
|
+
# decline-over-approval switch without polluting the other four builders.
|
|
117
|
+
commitment_section = _commitment_dict(c)
|
|
118
|
+
commitment_section["allow_decline_over_approval"] = c.allow_decline_over_approval
|
|
119
|
+
|
|
88
120
|
rules: dict[str, object] = {
|
|
89
121
|
"voting": voting_section,
|
|
90
122
|
"objection_handling": {
|
|
91
123
|
"critical_severity_vetoes": o.critical_severity_vetoes,
|
|
92
124
|
"veto_threshold": o.veto_threshold,
|
|
125
|
+
"critical_objection_action": o.critical_objection_action,
|
|
93
126
|
},
|
|
94
127
|
"evaluation": {
|
|
95
128
|
"minimum_confidence": e.minimum_confidence,
|
|
96
129
|
"required_before_voting": e.required_before_voting,
|
|
97
130
|
},
|
|
98
|
-
"commitment":
|
|
131
|
+
"commitment": commitment_section,
|
|
99
132
|
}
|
|
100
133
|
|
|
101
134
|
return policy_pb2.PolicyDescriptor(
|
|
@@ -103,7 +136,7 @@ def build_decision_policy(
|
|
|
103
136
|
mode="macp.mode.decision.v1",
|
|
104
137
|
description=description,
|
|
105
138
|
rules=json.dumps(rules).encode(),
|
|
106
|
-
schema_version=
|
|
139
|
+
schema_version=2,
|
|
107
140
|
)
|
|
108
141
|
|
|
109
142
|
|
|
@@ -29,10 +29,13 @@ class PolicyChange:
|
|
|
29
29
|
class SessionLifecycle:
|
|
30
30
|
"""A single session lifecycle event from ``WatchSessions``.
|
|
31
31
|
|
|
32
|
-
Runtime event types (per ``SessionLifecycleEvent.EventType
|
|
33
|
-
on SessionStart acceptance (also emitted
|
|
34
|
-
subscribe time), ``RESOLVED`` on
|
|
35
|
-
``EXPIRED`` on TTL expiry
|
|
32
|
+
Runtime event types (per ``SessionLifecycleEvent.EventType``, since
|
|
33
|
+
macp-proto 0.1.3): ``CREATED`` on SessionStart acceptance (also emitted
|
|
34
|
+
for pre-existing sessions at subscribe time), ``RESOLVED`` on
|
|
35
|
+
mode-determined terminal outcome, ``EXPIRED`` on TTL/policy expiry,
|
|
36
|
+
``CANCELLED`` on an accepted ``CancelSession`` (previously surfaced as
|
|
37
|
+
``EXPIRED``), and the non-terminal pair ``SUSPENDED`` / ``RESUMED`` from
|
|
38
|
+
``SuspendSession`` / ``ResumeSession``.
|
|
36
39
|
"""
|
|
37
40
|
|
|
38
41
|
event_type: str = "UNSPECIFIED"
|
|
@@ -49,12 +52,31 @@ class SessionLifecycle:
|
|
|
49
52
|
|
|
50
53
|
@property
|
|
51
54
|
def is_expired(self) -> bool:
|
|
55
|
+
"""``True`` only for TTL/policy expiry; explicit cancellation now
|
|
56
|
+
surfaces as ``CANCELLED`` — see ``is_cancelled``."""
|
|
52
57
|
return self.event_type == "EXPIRED"
|
|
53
58
|
|
|
59
|
+
@property
|
|
60
|
+
def is_cancelled(self) -> bool:
|
|
61
|
+
"""``True`` for an accepted ``CancelSession`` (terminal)."""
|
|
62
|
+
return self.event_type == "CANCELLED"
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def is_suspended(self) -> bool:
|
|
66
|
+
"""``True`` after ``SuspendSession`` — non-terminal; the session can
|
|
67
|
+
still ``RESUMED``."""
|
|
68
|
+
return self.event_type == "SUSPENDED"
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def is_resumed(self) -> bool:
|
|
72
|
+
"""``True`` after ``ResumeSession`` returns a suspended session to OPEN."""
|
|
73
|
+
return self.event_type == "RESUMED"
|
|
74
|
+
|
|
54
75
|
@property
|
|
55
76
|
def is_terminal(self) -> bool:
|
|
56
|
-
"""``True`` for RESOLVED or
|
|
57
|
-
|
|
77
|
+
"""``True`` for RESOLVED, EXPIRED, or CANCELLED — the session won't
|
|
78
|
+
emit more events. ``SUSPENDED`` / ``RESUMED`` are non-terminal."""
|
|
79
|
+
return self.event_type in ("RESOLVED", "EXPIRED", "CANCELLED")
|
|
58
80
|
|
|
59
81
|
|
|
60
82
|
class ModeRegistryWatcher:
|
|
@@ -151,10 +173,11 @@ class SessionLifecycleWatcher:
|
|
|
151
173
|
|
|
152
174
|
Wraps ``MacpClient.watch_sessions()`` and normalises each response into
|
|
153
175
|
a ``SessionLifecycle`` record carrying the event type as a short
|
|
154
|
-
string (``CREATED`` / ``RESOLVED`` / ``EXPIRED``
|
|
155
|
-
``
|
|
156
|
-
every already-open session at
|
|
157
|
-
thereafter — see
|
|
176
|
+
string (``CREATED`` / ``RESOLVED`` / ``EXPIRED`` / ``CANCELLED`` /
|
|
177
|
+
``SUSPENDED`` / ``RESUMED``) and the full ``SessionMetadata``. The
|
|
178
|
+
runtime emits an initial CREATED event for every already-open session at
|
|
179
|
+
subscribe time, then live events thereafter — see
|
|
180
|
+
``runtime/src/server.rs::watch_sessions``.
|
|
158
181
|
"""
|
|
159
182
|
|
|
160
183
|
def __init__(self, client: MacpClient, *, auth: AuthConfig | None = None) -> None:
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: macp-sdk-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Python SDK for the MACP Rust runtime
|
|
5
|
-
Author-email:
|
|
5
|
+
Author-email: Multi-Agent Coordination Protocol <macp@multiagentcoordinationprotocol.org>
|
|
6
6
|
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/multiagentcoordinationprotocol/macp-sdk-python
|
|
8
|
+
Project-URL: Repository, https://github.com/multiagentcoordinationprotocol/macp-sdk-python
|
|
9
|
+
Project-URL: Documentation, https://github.com/multiagentcoordinationprotocol/macp-sdk-python/tree/main/docs
|
|
10
|
+
Project-URL: Changelog, https://github.com/multiagentcoordinationprotocol/macp-sdk-python/blob/main/CHANGELOG.md
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/multiagentcoordinationprotocol/macp-sdk-python/issues
|
|
7
12
|
Classifier: Development Status :: 3 - Alpha
|
|
8
13
|
Classifier: Intended Audience :: Developers
|
|
9
14
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -15,9 +20,9 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
15
20
|
Requires-Python: >=3.11
|
|
16
21
|
Description-Content-Type: text/markdown
|
|
17
22
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: grpcio>=1.
|
|
23
|
+
Requires-Dist: grpcio>=1.81.1
|
|
19
24
|
Requires-Dist: protobuf>=5.27.0
|
|
20
|
-
Requires-Dist: macp-proto<0.2.0,>=0.1.
|
|
25
|
+
Requires-Dist: macp-proto<0.2.0,>=0.1.3
|
|
21
26
|
Provides-Extra: dev
|
|
22
27
|
Requires-Dist: grpcio-tools>=1.74.0; extra == "dev"
|
|
23
28
|
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
@@ -165,6 +170,7 @@ Business logic — voting rules, AI decision heuristics, policy enforcement —
|
|
|
165
170
|
|
|
166
171
|
- `GetSession` returns metadata only (not mode state/transcript) — hence the local projection pattern; use `StreamSession` + `send_subscribe` for the full transcript
|
|
167
172
|
- `StreamSession` is scoped to one session per stream; use `MacpStream.send_subscribe(session_id)` (RFC-MACP-0006-A1, since SDK 0.2.3 / `macp-proto 0.1.2`) to replay accepted history before live broadcast
|
|
168
|
-
- For cross-session observability, use `MacpClient.list_sessions()` and `SessionLifecycleWatcher` (SDK 0.3.0) to enumerate active sessions and stream `CREATED` / `RESOLVED` / `EXPIRED` lifecycle events
|
|
173
|
+
- For cross-session observability, use `MacpClient.list_sessions()` and `SessionLifecycleWatcher` (SDK 0.3.0) to enumerate active sessions and stream `CREATED` / `RESOLVED` / `EXPIRED` / `CANCELLED` / `SUSPENDED` / `RESUMED` lifecycle events
|
|
174
|
+
- Pause and cancel sessions with `MacpClient.suspend_session()` / `resume_session()` / `cancel_session()` (SDK 0.4.0 / `macp-proto 0.1.3`). A suspended session is non-terminal and rejects messages until resumed; an accepted `cancel_session()` now terminates as `CANCELLED` (previously surfaced as `EXPIRED`)
|
|
169
175
|
- `ListRoots` currently returns an empty list and `WatchRoots` idles — the runtime does not yet populate roots
|
|
170
176
|
- Business policy (majority, quorum, veto) belongs in your orchestrator/policy layer
|
|
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
|
{macp_sdk_python-0.3.0 → macp_sdk_python-0.4.1}/src/macp_sdk_python.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|