macp-sdk-python 0.3.0__tar.gz → 0.4.0__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.
Files changed (39) hide show
  1. {macp_sdk_python-0.3.0/src/macp_sdk_python.egg-info → macp_sdk_python-0.4.0}/PKG-INFO +5 -4
  2. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/README.md +2 -1
  3. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/pyproject.toml +11 -7
  4. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/__init__.py +2 -0
  5. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/base_session.py +17 -1
  6. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/client.py +73 -5
  7. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/envelope.py +23 -0
  8. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/watchers.py +33 -10
  9. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0/src/macp_sdk_python.egg-info}/PKG-INFO +5 -4
  10. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk_python.egg-info/requires.txt +2 -2
  11. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/LICENSE +0 -0
  12. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/setup.cfg +0 -0
  13. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/_logging.py +0 -0
  14. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/agent/__init__.py +0 -0
  15. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/agent/cancel_callback.py +0 -0
  16. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/agent/dispatcher.py +0 -0
  17. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/agent/participant.py +0 -0
  18. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/agent/runner.py +0 -0
  19. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/agent/strategies.py +0 -0
  20. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/agent/transports.py +0 -0
  21. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/agent/types.py +0 -0
  22. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/auth.py +0 -0
  23. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/base_projection.py +0 -0
  24. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/constants.py +0 -0
  25. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/decision.py +0 -0
  26. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/errors.py +0 -0
  27. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/handoff.py +0 -0
  28. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/policy.py +0 -0
  29. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/projections.py +0 -0
  30. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/proposal.py +0 -0
  31. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/proto_registry.py +0 -0
  32. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/py.typed +0 -0
  33. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/quorum.py +0 -0
  34. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/retry.py +0 -0
  35. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/task.py +0 -0
  36. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk/validation.py +0 -0
  37. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk_python.egg-info/SOURCES.txt +0 -0
  38. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk_python.egg-info/dependency_links.txt +0 -0
  39. {macp_sdk_python-0.3.0 → macp_sdk_python-0.4.0}/src/macp_sdk_python.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: macp-sdk-python
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: Python SDK for the MACP Rust runtime
5
5
  Author-email: OpenAI <support@openai.com>
6
6
  License: Apache-2.0
@@ -15,9 +15,9 @@ Classifier: Topic :: Software Development :: Libraries
15
15
  Requires-Python: >=3.11
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
- Requires-Dist: grpcio>=1.74.0
18
+ Requires-Dist: grpcio>=1.81.1
19
19
  Requires-Dist: protobuf>=5.27.0
20
- Requires-Dist: macp-proto<0.2.0,>=0.1.2
20
+ Requires-Dist: macp-proto<0.2.0,>=0.1.3
21
21
  Provides-Extra: dev
22
22
  Requires-Dist: grpcio-tools>=1.74.0; extra == "dev"
23
23
  Requires-Dist: pytest>=8.0; extra == "dev"
@@ -165,6 +165,7 @@ Business logic — voting rules, AI decision heuristics, policy enforcement —
165
165
 
166
166
  - `GetSession` returns metadata only (not mode state/transcript) — hence the local projection pattern; use `StreamSession` + `send_subscribe` for the full transcript
167
167
  - `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
168
+ - 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
169
+ - 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
170
  - `ListRoots` currently returns an empty list and `WatchRoots` idles — the runtime does not yet populate roots
170
171
  - 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,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "macp-sdk-python"
7
- version = "0.3.0"
7
+ version = "0.4.0"
8
8
  description = "Python SDK for the MACP Rust runtime"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -23,14 +23,18 @@ classifiers = [
23
23
  "Topic :: Software Development :: Libraries",
24
24
  ]
25
25
  dependencies = [
26
- "grpcio>=1.74.0",
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.2+ for the RFC-MACP-0006-A1 subscribe_session_id /
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). 0.1.1 is
31
- # the earlier baseline for the context_id / extensions fields on
32
- # SessionStartPayload. See docs/contributing.md "Bumping macp-proto".
33
- "macp-proto>=0.1.2,<0.2.0",
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
 
36
40
  [project.optional-dependencies]
@@ -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.3.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``, and ``EXPIRED``. Each event
456
- carries a full ``SessionMetadata`` (including ``context_id`` and
457
- ``extension_keys``), so callers can project run state without a
458
- follow-up ``get_session``.
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
 
@@ -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``): ``CREATED``
33
- on SessionStart acceptance (also emitted for pre-existing sessions at
34
- subscribe time), ``RESOLVED`` on mode-determined terminal outcome,
35
- ``EXPIRED`` on TTL expiry or explicit ``CancelSession``.
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 EXPIRED — the session won't emit more events."""
57
- return self.event_type in ("RESOLVED", "EXPIRED")
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``) and the full
155
- ``SessionMetadata``. The runtime emits an initial CREATED event for
156
- every already-open session at subscribe time, then live events
157
- thereafter — see ``runtime/src/server.rs::watch_sessions``.
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: macp-sdk-python
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: Python SDK for the MACP Rust runtime
5
5
  Author-email: OpenAI <support@openai.com>
6
6
  License: Apache-2.0
@@ -15,9 +15,9 @@ Classifier: Topic :: Software Development :: Libraries
15
15
  Requires-Python: >=3.11
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
- Requires-Dist: grpcio>=1.74.0
18
+ Requires-Dist: grpcio>=1.81.1
19
19
  Requires-Dist: protobuf>=5.27.0
20
- Requires-Dist: macp-proto<0.2.0,>=0.1.2
20
+ Requires-Dist: macp-proto<0.2.0,>=0.1.3
21
21
  Provides-Extra: dev
22
22
  Requires-Dist: grpcio-tools>=1.74.0; extra == "dev"
23
23
  Requires-Dist: pytest>=8.0; extra == "dev"
@@ -165,6 +165,7 @@ Business logic — voting rules, AI decision heuristics, policy enforcement —
165
165
 
166
166
  - `GetSession` returns metadata only (not mode state/transcript) — hence the local projection pattern; use `StreamSession` + `send_subscribe` for the full transcript
167
167
  - `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
168
+ - 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
169
+ - 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
170
  - `ListRoots` currently returns an empty list and `WatchRoots` idles — the runtime does not yet populate roots
170
171
  - Business policy (majority, quorum, veto) belongs in your orchestrator/policy layer
@@ -1,6 +1,6 @@
1
- grpcio>=1.74.0
1
+ grpcio>=1.81.1
2
2
  protobuf>=5.27.0
3
- macp-proto<0.2.0,>=0.1.2
3
+ macp-proto<0.2.0,>=0.1.3
4
4
 
5
5
  [dev]
6
6
  grpcio-tools>=1.74.0
File without changes