macp-sdk-typescript 0.4.1 → 0.6.0

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 (45) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/README.md +17 -6
  3. package/dist/agent/participant.d.ts +2 -0
  4. package/dist/agent/participant.js +1 -0
  5. package/dist/agent/runner.d.ts +1 -0
  6. package/dist/agent/runner.js +1 -0
  7. package/dist/agent/transports.d.ts +10 -0
  8. package/dist/agent/transports.js +13 -0
  9. package/dist/auth.d.ts +10 -5
  10. package/dist/auth.js +15 -15
  11. package/dist/base-session.d.ts +1 -0
  12. package/dist/base-session.js +3 -0
  13. package/dist/client.d.ts +60 -14
  14. package/dist/client.js +88 -30
  15. package/dist/decision.d.ts +1 -0
  16. package/dist/decision.js +2 -0
  17. package/dist/envelope.d.ts +20 -0
  18. package/dist/envelope.js +15 -0
  19. package/dist/errors.d.ts +10 -1
  20. package/dist/errors.js +11 -1
  21. package/dist/handoff.d.ts +1 -0
  22. package/dist/handoff.js +9 -1
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +3 -1
  25. package/dist/policy.d.ts +20 -0
  26. package/dist/policy.js +9 -0
  27. package/dist/projections/handoff.d.ts +12 -0
  28. package/dist/projections/handoff.js +13 -0
  29. package/dist/proposal.d.ts +1 -0
  30. package/dist/proposal.js +2 -0
  31. package/dist/proto-registry.d.ts +10 -0
  32. package/dist/proto-registry.js +34 -1
  33. package/dist/quorum.d.ts +1 -0
  34. package/dist/quorum.js +2 -0
  35. package/dist/retry.d.ts +7 -0
  36. package/dist/task.d.ts +1 -0
  37. package/dist/task.js +2 -0
  38. package/dist/types.d.ts +18 -0
  39. package/dist/validation.d.ts +2 -0
  40. package/dist/validation.js +10 -0
  41. package/dist/version.d.ts +7 -0
  42. package/dist/version.js +10 -0
  43. package/dist/watchers.d.ts +17 -13
  44. package/dist/watchers.js +26 -26
  45. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -4,6 +4,124 @@ All notable changes to `macp-sdk-typescript` are documented here. The format
4
4
  follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
5
5
  project uses [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## [0.6.0](https://github.com/multiagentcoordinationprotocol/macp-sdk-typescript/compare/v0.5.0...v0.6.0) (2026-07-10)
8
+
9
+
10
+ ### Features
11
+
12
+ * export package VERSION constant ([#37](https://github.com/multiagentcoordinationprotocol/macp-sdk-typescript/issues/37)) ([4ae5cda](https://github.com/multiagentcoordinationprotocol/macp-sdk-typescript/commit/4ae5cda23255b82339490f740a30ca0b7fee0d5a))
13
+
14
+ ## [Unreleased]
15
+
16
+ ### Changed
17
+
18
+ - **BREAKING: requires Node.js >= 20** (`engines.node`). Node 18 reached
19
+ end-of-life in April 2025 and was never exercised in CI; the CI matrix now
20
+ tests Node 20, 22, and 24.
21
+ - CI installs with `npm ci` against the committed lockfile (regenerated so all
22
+ platform-specific optional binaries are recorded), with npm caching and a
23
+ concurrency group that cancels superseded PR runs. The advisory-only
24
+ `npm audit` job is replaced by Dependabot (weekly grouped npm and
25
+ github-actions updates). All workflow actions are pinned by commit SHA.
26
+ - Publishing now runs the full `prepublishOnly` gate (check + lint +
27
+ format:check + test + build) against the exact tree being published —
28
+ the `--ignore-scripts` workaround is gone.
29
+ - Pull requests get a coverage summary comment from CI.
30
+
31
+ ### Added
32
+
33
+ - Extensive unit coverage for previously integration-only surface: the
34
+ `MacpStream` data path (envelope unwrapping, inline errors, timeouts,
35
+ end-of-stream semantics), the entire `MacpClient` unary RPC surface and its
36
+ metadata/deadline dispatch, the `watch*` stream factories, session
37
+ `cancel`/`suspend`/`resume` delegation for all five modes, `BaseSession`/
38
+ `BaseProjection` extension-point behavior, and the `Participant` run loop
39
+ (terminal dispatch, cancel-callback wiring, initiator kickoff defaults).
40
+ Coverage thresholds raised to lines 94 / branches 88 / functions 90 /
41
+ statements 94.
42
+ - Conformance: `ext.multi_round.v1` fixtures now replay with real assertions
43
+ (previously silently skipped); fixtures for unmapped modes fail loudly; and
44
+ reject-path fixtures are contract-checked (canonical `expected_error_code`,
45
+ resolvable `payload_type`) with explicit skip markers pointing at the
46
+ runtime conformance oracle for the NACK behavior itself.
47
+
48
+ ## [0.5.0] - 2026-07-06
49
+
50
+ Absorbs `macp-runtime` 0.5.0 and `@multiagentcoordinationprotocol/proto` 0.1.6
51
+ (resolves to ≥ 0.1.6; content identical through 0.1.8). Plan:
52
+ `plans/absorb-runtime-v0.5.0.md`.
53
+
54
+ **Requires `macp-runtime` ≥ 0.5.0** for: protobuf `Contribute` encoding, the
55
+ empty-`policy_version` commitment echo, the external task orchestrator, and the
56
+ bearer-only dev-auth flow (the runtime no longer reads `x-macp-agent-id`, and
57
+ refuses to start with no auth unless `MACP_ALLOW_INSECURE=1`). Pin `0.4.x` to
58
+ talk to an older runtime.
59
+
60
+ ### Added
61
+
62
+ - **`SessionStartPayload.maxSuspendMs`** (proto ≥ 0.1.5) — per-session cap on
63
+ cumulative suspended time before a `SUSPENDED` session `EXPIRE`s (RFC-MACP-0001
64
+ §7.5). Threaded through `buildSessionStartPayload`, every mode session's
65
+ `start()`, the `Participant` initiator config, and the bootstrap runner
66
+ (`session_start.max_suspend_ms`). `0`/absent = runtime default (7 days);
67
+ negatives are rejected client-side.
68
+ - **`HandoffAcceptPayload.implicit` decode support** (proto ≥ 0.1.6) — surfaced
69
+ read-only on `HandoffRecord.implicit` and `HandoffProjection.isImplicitlyAccepted()`
70
+ for the runtime-emitted synthetic accept (RFC-MACP-0010 §5.1). Client-submitted
71
+ `implicit` is stripped before encoding so it can never reach the wire.
72
+ - **`ListSessions` pagination** (proto ≥ 0.1.6) — new
73
+ `MacpClient.listSessionsPage({ pageSize, pageToken })` returning
74
+ `{ sessions, nextPageToken }`; `listSessions()` now transparently auto-paginates
75
+ so it still returns the complete listing.
76
+ - **`ext.multi_round.v1` `Contribute` uses canonical protobuf** — encodes as
77
+ `ContributePayload`; decode tries legacy JSON (`{"value":"..."}`) first for
78
+ byte-identical replay of pre-proto histories.
79
+ - **`MacpTransportError.code`** — carries the gRPC status name
80
+ (`RESOURCE_EXHAUSTED`, `FAILED_PRECONDITION`, `UNAUTHENTICATED`, …) surfaced on
81
+ unary calls, `MacpStream`, and watch streams, so consumers can distinguish
82
+ watch-stream lag (reconnect) from auth failure (don't) and passive-subscribe
83
+ resume below a compacted base.
84
+ - **`GrpcTransportAdapter.lastSequence`** — the 1-based accepted-envelope ordinal
85
+ of the last delivered envelope, a resume cursor for `sendSubscribe`.
86
+
87
+ ### Changed
88
+
89
+ - **Dev auth is bearer-only.** `Auth.devAgent(agentId)` now sends
90
+ `Authorization: Bearer <agentId>` (was the `x-macp-agent-id` header). The
91
+ runtime's dev fallback authenticates any bearer value as its sender, so
92
+ behavior is transparent for existing callers — but the wire header changed.
93
+ Integration/runbook: drop `MACP_ALLOW_DEV_SENDER_HEADER=1`, keep the now-mandatory
94
+ `MACP_ALLOW_INSECURE=1`.
95
+ - **`MacpClient.watchSignals` requires auth** (runtime 0.5.0) — routed through
96
+ `requireAuth`, so a missing credential fails fast client-side instead of as a
97
+ stream `UNAUTHENTICATED`. Breaking for anyone watching signals without auth.
98
+ - **`buildQuorumPolicy` validates percentage thresholds.** A `percentage`
99
+ `threshold.value` must be an integer 0–100 (the approval bar =
100
+ `ceil(value/100 × participants)`); a fractional value like `0.75` (previously a
101
+ silent ~1% bar) now throws `MacpSessionError`. Bug-surfacing by design.
102
+ - **`registerExtMode` pre-validates descriptors** — throws if
103
+ `terminalMessageTypes` lacks `'Commitment'` (mirrors the runtime, which rejects
104
+ such descriptors).
105
+ - **Canonical conformance fixtures + harness.** Vendored fixtures byte-synced to
106
+ the spec canonical pack (fully-qualified `payload_type`, `expected_error_code`,
107
+ `schema.json`); the harness parses FQ names only, with a format guard rejecting
108
+ legacy shorthand.
109
+ - **`SessionStartPayload` bodies now emit `maxSuspendMs`** (`0` when unset).
110
+
111
+ ### Removed
112
+
113
+ - **`AuthConfig.agentId`** and the `x-macp-agent-id` metadata path — no supported
114
+ runtime reads the header. Use `Auth.devAgent` / `Auth.bearer`.
115
+ - **`SessionLifecycleWatcher.events()` / `nextEvent()`** — deprecated aliases;
116
+ use `changes()` / `nextChange()`.
117
+ - **`MacpClient._watchModeRegistry` / `_watchRoots` / `_watchSignals` /
118
+ `_watchPolicies`** — deprecated underscored aliases; use the un-prefixed
119
+ `watch*` methods.
120
+
121
+ ### Fixed
122
+
123
+ - `MacpClient.clientVersion` default was a stale `'0.3.0'`; now `'0.5.0'`.
124
+
7
125
  ## [0.4.0] - 2026-06-22
8
126
 
9
127
  Adopts `@multiagentcoordinationprotocol/proto` 0.1.3 — session
package/README.md CHANGED
@@ -2,8 +2,14 @@
2
2
 
3
3
  TypeScript SDK for the [Multi-Agent Coordination Protocol (MACP)](https://github.com/multiagentcoordinationprotocol/multiagentcoordinationprotocol) runtime. Connects TypeScript/Node.js applications to the Rust MACP runtime over gRPC.
4
4
 
5
+ SDK documentation lives in [`docs/`](docs/index.md) and covers the TypeScript API.
6
+ Protocol semantics are normative in the [spec repo's docs and RFCs](https://github.com/multiagentcoordinationprotocol/multiagentcoordinationprotocol/tree/main/rfcs);
7
+ runtime behavior is documented in the [runtime repo's docs](https://github.com/multiagentcoordinationprotocol/macp-runtime/blob/main/docs/getting-started.md).
8
+
5
9
  ## Install
6
10
 
11
+ Requires Node.js >= 20.
12
+
7
13
  ```bash
8
14
  npm install macp-sdk-typescript
9
15
  ```
@@ -287,7 +293,7 @@ reference: [`docs/api/strategies.md`](docs/api/strategies.md).
287
293
  ### Cancel Callback
288
294
 
289
295
  Long-running agents can expose an HTTP endpoint that an orchestrator POSTs to
290
- in order to request a clean shutdown (RFC-MACP-0001 §7.2 Option A). Bootstrap
296
+ in order to request a clean shutdown ([RFC-MACP-0001 (Core)](https://github.com/multiagentcoordinationprotocol/multiagentcoordinationprotocol/blob/main/rfcs/RFC-MACP-0001-core.md) §7.2 Option A). Bootstrap
291
297
  JSON with a `cancel_callback: { host, port, path }` block auto-wires the
292
298
  server via `fromBootstrap()`; for the manual path use
293
299
  `startCancelCallbackServer(...)` + `Participant.attachCancelCallbackServer(...)`.
@@ -297,7 +303,8 @@ See [`docs/api/cancel-callback.md`](docs/api/cancel-callback.md) and
297
303
  ## Authentication
298
304
 
299
305
  ```typescript
300
- // Development (uses x-macp-agent-id header)
306
+ // Development (bearer-only; sends Authorization: Bearer my-agent).
307
+ // Requires the runtime to run with MACP_ALLOW_INSECURE=1.
301
308
  const auth = Auth.devAgent('my-agent');
302
309
 
303
310
  // Production (Bearer token with authenticated identity — RFC-MACP-0004 §4).
@@ -322,7 +329,7 @@ await session.vote({
322
329
 
323
330
  ## TLS
324
331
 
325
- TLS is on by default (RFC-MACP-0006 §3). To connect to an insecure runtime
332
+ TLS is on by default ([RFC-MACP-0006 (Transport Bindings)](https://github.com/multiagentcoordinationprotocol/multiagentcoordinationprotocol/blob/main/rfcs/RFC-MACP-0006-transport-bindings.md) §3). To connect to an insecure runtime
326
333
  during local development, you must opt out explicitly:
327
334
 
328
335
  ```typescript
@@ -404,10 +411,14 @@ npm run lint # ESLint
404
411
  npm run format # Prettier
405
412
  npm test # Run unit + conformance tests
406
413
  npm run test:watch # Watch mode
407
- npm run test:coverage # With coverage
408
- npm run test:integration # Integration tests (requires Docker runtime)
414
+ npm run test:coverage # With coverage (CI enforces thresholds from vitest.config.ts)
415
+ npm run test:integration # Integration tests (requires Docker runtime; not run in CI)
409
416
  ```
410
417
 
418
+ CI (GitHub Actions) runs type-check, lint, format check, the coverage-gated
419
+ test suite, and the build on Node 20, 22, and 24 for every push and pull
420
+ request, and posts a coverage summary comment on PRs.
421
+
411
422
  ### Integration Tests
412
423
 
413
424
  Run the full SDK against a live MACP runtime:
@@ -417,7 +428,7 @@ Run the full SDK against a live MACP runtime:
417
428
  docker build -t macp-runtime ../macp-runtime/
418
429
  docker run -d --name macp-runtime-test -p 50051:50051 \
419
430
  -e MACP_BIND_ADDR=0.0.0.0:50051 -e MACP_ALLOW_INSECURE=1 \
420
- -e MACP_ALLOW_DEV_SENDER_HEADER=1 -e MACP_MEMORY_ONLY=1 macp-runtime
431
+ -e MACP_MEMORY_ONLY=1 macp-runtime
421
432
 
422
433
  # Run tests
423
434
  npm run test:integration
@@ -9,6 +9,8 @@ export interface InitiatorConfig {
9
9
  intent: string;
10
10
  participants: string[];
11
11
  ttlMs: number;
12
+ /** Per-session max-suspend cap (ms, proto ≥ 0.1.5). 0/absent = runtime default. */
13
+ maxSuspendMs?: number;
12
14
  contextId?: string;
13
15
  extensions?: Record<string, Buffer>;
14
16
  context?: Record<string, unknown>;
@@ -298,6 +298,7 @@ class Participant {
298
298
  intent: ss.intent,
299
299
  participants: ss.participants,
300
300
  ttlMs: ss.ttlMs,
301
+ maxSuspendMs: ss.maxSuspendMs,
301
302
  contextId: ss.contextId,
302
303
  extensions: ss.extensions,
303
304
  roots: ss.roots,
@@ -18,6 +18,7 @@ export interface BootstrapPayload {
18
18
  intent: string;
19
19
  participants: string[];
20
20
  ttl_ms: number;
21
+ max_suspend_ms?: number;
21
22
  mode_version?: string;
22
23
  configuration_version?: string;
23
24
  policy_version?: string;
@@ -77,6 +77,7 @@ function fromBootstrap(bootstrapPath) {
77
77
  intent: ss.intent,
78
78
  participants: ss.participants,
79
79
  ttlMs: ss.ttl_ms,
80
+ maxSuspendMs: ss.max_suspend_ms,
80
81
  contextId: ss.context_id,
81
82
  extensions: encodeExtensions(ss.extensions),
82
83
  roots: ss.roots,
@@ -11,7 +11,17 @@ export declare class GrpcTransportAdapter implements TransportAdapter {
11
11
  private readonly auth?;
12
12
  private stream;
13
13
  private seq;
14
+ private delivered;
14
15
  constructor(client: MacpClient, sessionId: string, auth?: AuthConfig | undefined);
16
+ /**
17
+ * The server passive-subscribe ordinal of the last delivered envelope (the
18
+ * 1-based count of accepted envelopes delivered on this stream, RFC-MACP-0006
19
+ * §3.2). `0` before anything is delivered. Pass this as `afterSequence` to
20
+ * `MacpStream.sendSubscribe` on a reconnect to resume exactly-once — ordinals
21
+ * are stable across compaction/restart. Distinct from `IncomingMessage.seq`,
22
+ * which is a client-local 0-based delivery index.
23
+ */
24
+ get lastSequence(): number;
15
25
  start(): AsyncIterable<IncomingMessage>;
16
26
  stop(): Promise<void>;
17
27
  }
@@ -18,11 +18,23 @@ class GrpcTransportAdapter {
18
18
  auth;
19
19
  stream = null;
20
20
  seq = 0;
21
+ delivered = 0;
21
22
  constructor(client, sessionId, auth) {
22
23
  this.client = client;
23
24
  this.sessionId = sessionId;
24
25
  this.auth = auth;
25
26
  }
27
+ /**
28
+ * The server passive-subscribe ordinal of the last delivered envelope (the
29
+ * 1-based count of accepted envelopes delivered on this stream, RFC-MACP-0006
30
+ * §3.2). `0` before anything is delivered. Pass this as `afterSequence` to
31
+ * `MacpStream.sendSubscribe` on a reconnect to resume exactly-once — ordinals
32
+ * are stable across compaction/restart. Distinct from `IncomingMessage.seq`,
33
+ * which is a client-local 0-based delivery index.
34
+ */
35
+ get lastSequence() {
36
+ return this.delivered;
37
+ }
26
38
  async *start() {
27
39
  this.stream = this.client.openStream({ auth: this.auth });
28
40
  // RFC-MACP-0006-A1: Subscribe to the session with history replay.
@@ -33,6 +45,7 @@ class GrpcTransportAdapter {
33
45
  for await (const envelope of this.stream.responses()) {
34
46
  if (envelope.sessionId !== this.sessionId)
35
47
  continue;
48
+ this.delivered++;
36
49
  yield normalizeEnvelope(envelope, (mode, mt, p) => this.client.protoRegistry.decodeKnownPayload(mode, mt, p), this.seq++);
37
50
  }
38
51
  }
package/dist/auth.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import * as grpc from '@grpc/grpc-js';
2
2
  export interface AuthConfig {
3
3
  bearerToken?: string;
4
- agentId?: string;
5
4
  senderHint?: string;
6
5
  /**
7
6
  * The authenticated sender this credential represents. When present, the SDK
@@ -22,10 +21,16 @@ export type BearerAuthOptions = string | {
22
21
  };
23
22
  export declare const Auth: {
24
23
  /**
25
- * Dev-mode agent identity. Uses the `x-macp-agent-id` header — only accepted
26
- * by runtimes started with `MACP_ALLOW_DEV_SENDER_HEADER=1`. Not for
27
- * production. Does not set {@link AuthConfig.expectedSender}; dev flows stay
28
- * permissive so tests can reuse a single credential across senders.
24
+ * Dev-mode agent identity (bearer-only, runtime ≥ 0.5.0). Sends
25
+ * `Authorization: Bearer <agentId>`; the runtime's dev fallback authenticates
26
+ * any bearer value as the sender of that value, so `Auth.devAgent('alice')`
27
+ * authenticates as sender `alice`. Requires the runtime to be started with
28
+ * `MACP_ALLOW_INSECURE=1` (it refuses to start with no auth configured
29
+ * otherwise). Not for production — use {@link Auth.bearer}.
30
+ *
31
+ * The legacy `x-macp-agent-id` header was removed in 0.5.0: no supported
32
+ * runtime reads it. Does not set {@link AuthConfig.expectedSender}; dev flows
33
+ * stay permissive so tests can reuse a single credential across senders.
29
34
  */
30
35
  devAgent(agentId: string): AuthConfig;
31
36
  /**
package/dist/auth.js CHANGED
@@ -42,13 +42,19 @@ const grpc = __importStar(require("@grpc/grpc-js"));
42
42
  const errors_1 = require("./errors");
43
43
  exports.Auth = {
44
44
  /**
45
- * Dev-mode agent identity. Uses the `x-macp-agent-id` header — only accepted
46
- * by runtimes started with `MACP_ALLOW_DEV_SENDER_HEADER=1`. Not for
47
- * production. Does not set {@link AuthConfig.expectedSender}; dev flows stay
48
- * permissive so tests can reuse a single credential across senders.
45
+ * Dev-mode agent identity (bearer-only, runtime ≥ 0.5.0). Sends
46
+ * `Authorization: Bearer <agentId>`; the runtime's dev fallback authenticates
47
+ * any bearer value as the sender of that value, so `Auth.devAgent('alice')`
48
+ * authenticates as sender `alice`. Requires the runtime to be started with
49
+ * `MACP_ALLOW_INSECURE=1` (it refuses to start with no auth configured
50
+ * otherwise). Not for production — use {@link Auth.bearer}.
51
+ *
52
+ * The legacy `x-macp-agent-id` header was removed in 0.5.0: no supported
53
+ * runtime reads it. Does not set {@link AuthConfig.expectedSender}; dev flows
54
+ * stay permissive so tests can reuse a single credential across senders.
49
55
  */
50
56
  devAgent(agentId) {
51
- return { agentId, senderHint: agentId };
57
+ return { bearerToken: agentId, senderHint: agentId };
52
58
  },
53
59
  /**
54
60
  * Production bearer-token credential. Pass `{ expectedSender }` to have the
@@ -75,17 +81,14 @@ exports.Auth = {
75
81
  },
76
82
  };
77
83
  function validateAuth(auth) {
78
- if (!auth.bearerToken && !auth.agentId) {
79
- throw new Error('either bearerToken or agentId is required');
80
- }
81
- if (auth.bearerToken && auth.agentId) {
82
- throw new Error('choose either bearerToken or agentId, not both');
84
+ if (!auth.bearerToken) {
85
+ throw new Error('bearerToken is required');
83
86
  }
84
87
  }
85
88
  function authSender(auth) {
86
89
  if (!auth)
87
90
  return undefined;
88
- return auth.expectedSender ?? auth.senderHint ?? auth.agentId;
91
+ return auth.expectedSender ?? auth.senderHint;
89
92
  }
90
93
  /**
91
94
  * Throw {@link MacpIdentityMismatchError} when a caller-supplied `sender`
@@ -104,9 +107,6 @@ function assertSenderMatchesIdentity(auth, sender) {
104
107
  function metadataFromAuth(auth) {
105
108
  validateAuth(auth);
106
109
  const metadata = new grpc.Metadata();
107
- if (auth.bearerToken)
108
- metadata.set('authorization', `Bearer ${auth.bearerToken}`);
109
- if (auth.agentId)
110
- metadata.set('x-macp-agent-id', auth.agentId);
110
+ metadata.set('authorization', `Bearer ${auth.bearerToken}`);
111
111
  return metadata;
112
112
  }
@@ -40,6 +40,7 @@ export declare abstract class BaseSession<P extends BaseProjection> {
40
40
  intent: string;
41
41
  participants: string[];
42
42
  ttlMs: number;
43
+ maxSuspendMs?: number;
43
44
  contextId?: string;
44
45
  extensions?: Record<string, Buffer>;
45
46
  roots?: Root[];
@@ -58,10 +58,13 @@ class BaseSession {
58
58
  /** Send SessionStart and begin tracking via the projection. */
59
59
  async start(input) {
60
60
  (0, validation_1.validateParticipantCount)(input.participants.length);
61
+ if (input.maxSuspendMs !== undefined)
62
+ (0, validation_1.validateMaxSuspendMs)(input.maxSuspendMs);
61
63
  const payload = (0, envelope_1.buildSessionStartPayload)({
62
64
  intent: input.intent,
63
65
  participants: input.participants,
64
66
  ttlMs: input.ttlMs,
67
+ maxSuspendMs: input.maxSuspendMs,
65
68
  contextId: input.contextId,
66
69
  extensions: input.extensions,
67
70
  roots: input.roots,
package/dist/client.d.ts CHANGED
@@ -23,6 +23,12 @@ interface MacpClientOptions {
23
23
  clientVersion?: string;
24
24
  protoDir?: string;
25
25
  }
26
+ /**
27
+ * Map a gRPC `ServiceError.code` (numeric `grpc.status`) to its status name
28
+ * (e.g. `8` → `'RESOURCE_EXHAUSTED'`). Returns `undefined` for non-numeric or
29
+ * unknown codes. Used to populate {@link MacpTransportError.code}.
30
+ */
31
+ export declare function grpcStatusName(code: unknown): string | undefined;
26
32
  export type InlineErrorCallback = (error: {
27
33
  code?: string;
28
34
  message?: string;
@@ -36,9 +42,19 @@ export declare class MacpStream {
36
42
  onInlineError(callback: InlineErrorCallback): void;
37
43
  send(envelope: Envelope): Promise<void>;
38
44
  /**
39
- * RFC-MACP-0006-A1: Send a subscribe-only frame to receive session history
40
- * + live broadcast. The runtime replays accepted envelopes from
41
- * `afterSequence` onwards, then continues with live broadcast.
45
+ * RFC-MACP-0006 §3.2: Send a subscribe-only frame to receive session history
46
+ * + live broadcast. The runtime replays accepted envelopes strictly after
47
+ * `afterSequence`, then continues with live broadcast.
48
+ *
49
+ * `afterSequence` is the **1-based accepted-envelope ordinal**, exclusive:
50
+ * `0` (default) replays from the very start; `k` replays envelopes with
51
+ * ordinal `> k`. Clients derive the ordinal by counting delivered envelopes
52
+ * (the Nth accepted envelope has ordinal N) — see
53
+ * `IncomingMessage.seq`, which is exactly this ordinal under the new contract.
54
+ * Ordinals are stable across log compaction and runtime restart. Resuming
55
+ * below a compacted base returns `FAILED_PRECONDITION` (inspectable via
56
+ * `MacpTransportError.code`) rather than silently skipping history (runtime
57
+ * ≥ 0.5.0; older runtimes compared inclusively against a raw log index).
42
58
  */
43
59
  sendSubscribe(sessionId: string, afterSequence?: number): Promise<void>;
44
60
  responses(): AsyncGenerator<Envelope, void, void>;
@@ -135,6 +151,20 @@ export declare class MacpClient {
135
151
  listRoots(deadlineMs?: number): Promise<{
136
152
  roots: Root[];
137
153
  }>;
154
+ /**
155
+ * Register an extension-mode descriptor (runtime 0.5.0 guardrails,
156
+ * change-review A5):
157
+ * - the descriptor MUST declare `Commitment` among `terminalMessageTypes` —
158
+ * an ext mode without a terminal `Commitment` can never resolve, so the
159
+ * runtime rejects it. This method fails fast client-side to match.
160
+ * - a later {@link promoteMode} into the reserved `macp.mode.*` namespace is
161
+ * rejected by the runtime.
162
+ * - a SessionStart with an empty `mode_version` binds the registered
163
+ * descriptor's `modeVersion`; a subsequent Commitment must echo that bound
164
+ * version (echoing `""` no longer matches vacuously). `BaseSession`
165
+ * defaults `modeVersion` to `'1.0.0'`, so set the descriptor's version to
166
+ * match, or override the session's `modeVersion`.
167
+ */
138
168
  registerExtMode(descriptor: ModeDescriptor, options?: {
139
169
  auth?: AuthConfig;
140
170
  deadlineMs?: number;
@@ -179,30 +209,46 @@ export declare class MacpClient {
179
209
  auth?: AuthConfig;
180
210
  deadlineMs?: number;
181
211
  }): Promise<PolicyDescriptor[]>;
212
+ /**
213
+ * Fetch a single page of sessions (proto ≥ 0.1.6). `pageSize: 0` (or absent)
214
+ * lets the server choose the page size; the server MAY cap it. Callers MUST
215
+ * NOT assume the listing is complete unless `nextPageToken` is empty. Pass a
216
+ * returned non-empty `nextPageToken` back as `pageToken` to fetch the next
217
+ * page; a stale token yields `INVALID_ARGUMENT`.
218
+ */
219
+ listSessionsPage(options?: {
220
+ pageSize?: number;
221
+ pageToken?: string;
222
+ auth?: AuthConfig;
223
+ deadlineMs?: number;
224
+ }): Promise<{
225
+ sessions: SessionMetadata[];
226
+ nextPageToken: string;
227
+ }>;
228
+ /**
229
+ * Enumerate ALL sessions, transparently walking pages until the runtime
230
+ * returns an empty `nextPageToken`. Preserves the "complete list" semantics
231
+ * this method has always documented, even against runtimes that cap page
232
+ * sizes (proto ≥ 0.1.6). For manual page control, use {@link listSessionsPage}.
233
+ */
182
234
  listSessions(options?: {
183
235
  auth?: AuthConfig;
184
236
  deadlineMs?: number;
237
+ pageSize?: number;
185
238
  }): Promise<SessionMetadata[]>;
186
239
  watchSessions(auth?: AuthConfig): grpc.ClientReadableStream<any>;
187
240
  watchPolicies(auth?: AuthConfig): grpc.ClientReadableStream<any>;
188
- /** @deprecated Use {@link watchPolicies}. Scheduled for removal in 0.4.0. */
189
- _watchPolicies(auth?: AuthConfig): grpc.ClientReadableStream<any>;
190
241
  openStream(options?: {
191
242
  auth?: AuthConfig;
192
243
  }): MacpStream;
193
244
  watchModeRegistry(auth?: AuthConfig): grpc.ClientReadableStream<any>;
194
245
  watchRoots(auth?: AuthConfig): grpc.ClientReadableStream<any>;
195
- watchSignals(auth?: AuthConfig): grpc.ClientReadableStream<any>;
196
246
  /**
197
- * @deprecated Use {@link watchModeRegistry}, {@link watchRoots},
198
- * {@link watchSignals}. Scheduled for removal in 0.4.0 — the underscored
199
- * aliases were kept while `src/watchers.ts` migrated.
247
+ * Subscribe to the ambient signal plane. Requires auth as of runtime 0.5.0 —
248
+ * routed through {@link requireAuth} so a missing credential fails fast with a
249
+ * clear client-side error instead of a stream `UNAUTHENTICATED`.
200
250
  */
201
- _watchModeRegistry(auth?: AuthConfig): grpc.ClientReadableStream<any>;
202
- /** @deprecated Use {@link watchRoots}. Scheduled for removal in 0.4.0. */
203
- _watchRoots(auth?: AuthConfig): grpc.ClientReadableStream<any>;
204
- /** @deprecated Use {@link watchSignals}. Scheduled for removal in 0.4.0. */
205
- _watchSignals(auth?: AuthConfig): grpc.ClientReadableStream<any>;
251
+ watchSignals(auth?: AuthConfig): grpc.ClientReadableStream<any>;
206
252
  sendSignal(options: {
207
253
  signalType: string;
208
254
  data?: Buffer;