macp-sdk-typescript 0.2.0 → 0.3.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 (47) hide show
  1. package/CHANGELOG.md +124 -1
  2. package/README.md +99 -3
  3. package/dist/agent/cancel-callback.d.ts +23 -0
  4. package/dist/agent/cancel-callback.js +108 -0
  5. package/dist/agent/index.d.ts +1 -0
  6. package/dist/agent/index.js +1 -0
  7. package/dist/agent/participant.d.ts +58 -0
  8. package/dist/agent/participant.js +143 -45
  9. package/dist/agent/runner.d.ts +34 -1
  10. package/dist/agent/runner.js +53 -0
  11. package/dist/agent/strategies.d.ts +2 -0
  12. package/dist/agent/strategies.js +8 -0
  13. package/dist/agent/transports.js +5 -0
  14. package/dist/base-session.d.ts +64 -0
  15. package/dist/base-session.js +112 -0
  16. package/dist/client.d.ts +25 -0
  17. package/dist/client.js +100 -10
  18. package/dist/constants.d.ts +21 -16
  19. package/dist/constants.js +24 -17
  20. package/dist/decision.d.ts +2 -1
  21. package/dist/decision.js +2 -1
  22. package/dist/envelope.d.ts +25 -3
  23. package/dist/envelope.js +42 -11
  24. package/dist/errors.d.ts +17 -4
  25. package/dist/errors.js +19 -10
  26. package/dist/handoff.d.ts +2 -9
  27. package/dist/handoff.js +2 -17
  28. package/dist/index.d.ts +3 -1
  29. package/dist/index.js +10 -2
  30. package/dist/logging.d.ts +21 -0
  31. package/dist/logging.js +64 -0
  32. package/dist/policy.d.ts +47 -42
  33. package/dist/policy.js +6 -6
  34. package/dist/projections/base.d.ts +20 -0
  35. package/dist/projections/base.js +37 -0
  36. package/dist/projections.d.ts +1 -0
  37. package/dist/projections.js +1 -0
  38. package/dist/proposal.d.ts +2 -1
  39. package/dist/proposal.js +2 -1
  40. package/dist/quorum.d.ts +2 -1
  41. package/dist/quorum.js +2 -1
  42. package/dist/task.d.ts +6 -5
  43. package/dist/task.js +6 -5
  44. package/dist/types.d.ts +11 -2
  45. package/dist/watchers.d.ts +23 -1
  46. package/dist/watchers.js +59 -1
  47. package/package.json +2 -2
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ /**
3
+ * Structured logger for the MACP SDK.
4
+ *
5
+ * Parity with python-sdk's `macp_sdk._logging.logger` + `configure_logging()`:
6
+ * production Node apps need controllable log levels (silent by default-ish,
7
+ * opt-in verbose) and the ability to re-route to Pino / Winston / etc.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.logger = void 0;
11
+ exports.configureLogging = configureLogging;
12
+ exports._resetLoggingForTests = _resetLoggingForTests;
13
+ const LEVEL_ORDER = {
14
+ silent: 0,
15
+ error: 1,
16
+ warn: 2,
17
+ info: 3,
18
+ debug: 4,
19
+ };
20
+ const defaultSink = (level, args) => {
21
+ const method = level === 'debug' || level === 'info' ? 'log' : level;
22
+ // eslint-disable-next-line no-console
23
+ (console[method] ?? console.log)('[macp-sdk]', ...args);
24
+ };
25
+ function envLevel() {
26
+ const raw = typeof process !== 'undefined' ? process.env?.MACP_LOG_LEVEL?.toLowerCase() : undefined;
27
+ if (raw && raw in LEVEL_ORDER)
28
+ return raw;
29
+ return 'warn';
30
+ }
31
+ const state = {
32
+ level: envLevel(),
33
+ sink: defaultSink,
34
+ };
35
+ function shouldLog(level) {
36
+ return LEVEL_ORDER[state.level] >= LEVEL_ORDER[level];
37
+ }
38
+ function emit(level, args) {
39
+ if (!shouldLog(level))
40
+ return;
41
+ state.sink(level, args);
42
+ }
43
+ exports.logger = {
44
+ error: (...args) => emit('error', args),
45
+ warn: (...args) => emit('warn', args),
46
+ info: (...args) => emit('info', args),
47
+ debug: (...args) => emit('debug', args),
48
+ };
49
+ function configureLogging(options) {
50
+ if (options.level !== undefined) {
51
+ if (!(options.level in LEVEL_ORDER)) {
52
+ throw new Error(`configureLogging: unknown level "${options.level}"`);
53
+ }
54
+ state.level = options.level;
55
+ }
56
+ if (options.sink !== undefined) {
57
+ state.sink = options.sink;
58
+ }
59
+ }
60
+ /** Test-only: reset to env-derived level + default sink. */
61
+ function _resetLoggingForTests() {
62
+ state.level = envLevel();
63
+ state.sink = defaultSink;
64
+ }
package/dist/policy.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import type { PolicyDescriptor } from './types';
2
- export interface CommitmentRulesInput {
2
+ export interface CommitmentRules {
3
3
  authority?: 'initiator_only' | 'any_participant' | 'designated_role';
4
4
  designatedRoles?: string[];
5
+ /** Decision-specific: require quorum before commit. Ignored for other modes. */
6
+ requireVoteQuorum?: boolean;
5
7
  }
6
- export interface DecisionVotingRules {
8
+ export interface VotingRules {
7
9
  algorithm?: 'none' | 'majority' | 'supermajority' | 'unanimous' | 'weighted' | 'plurality';
8
10
  threshold?: number;
9
11
  quorum?: {
@@ -12,62 +14,65 @@ export interface DecisionVotingRules {
12
14
  };
13
15
  weights?: Record<string, number>;
14
16
  }
15
- export interface DecisionObjectionHandling {
17
+ export interface ObjectionHandlingRules {
16
18
  criticalSeverityVetoes?: boolean;
17
19
  vetoThreshold?: number;
18
20
  }
19
- export interface DecisionEvaluationRules {
21
+ export interface EvaluationRules {
20
22
  minimumConfidence?: number;
21
23
  requiredBeforeVoting?: boolean;
22
24
  }
23
- export interface DecisionCommitmentRules {
24
- authority?: 'initiator_only' | 'any_participant' | 'designated_role';
25
- designatedRoles?: string[];
26
- requireVoteQuorum?: boolean;
25
+ export interface QuorumThreshold {
26
+ type: 'n_of_m' | 'percentage' | 'weighted';
27
+ value: number;
28
+ }
29
+ export interface AbstentionRules {
30
+ countsTowardQuorum?: boolean;
31
+ interpretation?: 'neutral' | 'implicit_reject' | 'ignored';
32
+ }
33
+ export interface ProposalAcceptanceRules {
34
+ criterion?: 'all_parties' | 'counterparty' | 'initiator';
35
+ }
36
+ export interface CounterProposalRules {
37
+ maxRounds?: number;
38
+ }
39
+ export interface RejectionRules {
40
+ terminalOnAnyReject?: boolean;
41
+ }
42
+ export interface TaskAssignmentRules {
43
+ allowReassignmentOnReject?: boolean;
44
+ }
45
+ export interface TaskCompletionRules {
46
+ requireOutput?: boolean;
47
+ }
48
+ export interface HandoffAcceptanceRules {
49
+ implicitAcceptTimeoutMs?: number;
27
50
  }
28
51
  export interface DecisionPolicyRulesInput {
29
- voting?: DecisionVotingRules;
30
- objectionHandling?: DecisionObjectionHandling;
31
- evaluation?: DecisionEvaluationRules;
32
- commitment?: DecisionCommitmentRules;
52
+ voting?: VotingRules;
53
+ objectionHandling?: ObjectionHandlingRules;
54
+ evaluation?: EvaluationRules;
55
+ commitment?: CommitmentRules;
33
56
  }
34
57
  export interface QuorumPolicyRulesInput {
35
- threshold?: {
36
- type: 'n_of_m' | 'percentage' | 'weighted';
37
- value: number;
38
- };
39
- abstention?: {
40
- countsTowardQuorum?: boolean;
41
- interpretation?: 'neutral' | 'implicit_reject' | 'ignored';
42
- };
43
- commitment?: CommitmentRulesInput;
58
+ threshold?: QuorumThreshold;
59
+ abstention?: AbstentionRules;
60
+ commitment?: CommitmentRules;
44
61
  }
45
62
  export interface ProposalPolicyRulesInput {
46
- acceptance?: {
47
- criterion?: 'all_parties' | 'counterparty' | 'initiator';
48
- };
49
- counterProposal?: {
50
- maxRounds?: number;
51
- };
52
- rejection?: {
53
- terminalOnAnyReject?: boolean;
54
- };
55
- commitment?: CommitmentRulesInput;
63
+ acceptance?: ProposalAcceptanceRules;
64
+ counterProposal?: CounterProposalRules;
65
+ rejection?: RejectionRules;
66
+ commitment?: CommitmentRules;
56
67
  }
57
68
  export interface TaskPolicyRulesInput {
58
- assignment?: {
59
- allowReassignmentOnReject?: boolean;
60
- };
61
- completion?: {
62
- requireOutput?: boolean;
63
- };
64
- commitment?: CommitmentRulesInput;
69
+ assignment?: TaskAssignmentRules;
70
+ completion?: TaskCompletionRules;
71
+ commitment?: CommitmentRules;
65
72
  }
66
73
  export interface HandoffPolicyRulesInput {
67
- acceptance?: {
68
- implicitAcceptTimeoutMs?: number;
69
- };
70
- commitment?: CommitmentRulesInput;
74
+ acceptance?: HandoffAcceptanceRules;
75
+ commitment?: CommitmentRules;
71
76
  }
72
77
  export declare function buildDecisionPolicy(policyId: string, description: string, rules: DecisionPolicyRulesInput): PolicyDescriptor;
73
78
  export declare function buildQuorumPolicy(policyId: string, description: string, rules: QuorumPolicyRulesInput): PolicyDescriptor;
package/dist/policy.js CHANGED
@@ -5,13 +5,13 @@ exports.buildQuorumPolicy = buildQuorumPolicy;
5
5
  exports.buildProposalPolicy = buildProposalPolicy;
6
6
  exports.buildTaskPolicy = buildTaskPolicy;
7
7
  exports.buildHandoffPolicy = buildHandoffPolicy;
8
+ // ── Builder helpers ─────────────────────────────────────────────────
8
9
  function serializeCommitment(commitment) {
9
10
  return {
10
11
  authority: commitment?.authority ?? 'initiator_only',
11
12
  designated_roles: commitment?.designatedRoles ?? [],
12
13
  };
13
14
  }
14
- // ── Builder helpers ─────────────────────────────────────────────────
15
15
  function buildDecisionPolicy(policyId, description, rules) {
16
16
  const rulesJson = {
17
17
  voting: {
@@ -38,7 +38,7 @@ function buildDecisionPolicy(policyId, description, rules) {
38
38
  policyId,
39
39
  mode: 'macp.mode.decision.v1',
40
40
  description,
41
- rules: Buffer.from(JSON.stringify(rulesJson)),
41
+ rules: JSON.stringify(rulesJson),
42
42
  schemaVersion: 1,
43
43
  };
44
44
  }
@@ -58,7 +58,7 @@ function buildQuorumPolicy(policyId, description, rules) {
58
58
  policyId,
59
59
  mode: 'macp.mode.quorum.v1',
60
60
  description,
61
- rules: Buffer.from(JSON.stringify(rulesJson)),
61
+ rules: JSON.stringify(rulesJson),
62
62
  schemaVersion: 1,
63
63
  };
64
64
  }
@@ -79,7 +79,7 @@ function buildProposalPolicy(policyId, description, rules) {
79
79
  policyId,
80
80
  mode: 'macp.mode.proposal.v1',
81
81
  description,
82
- rules: Buffer.from(JSON.stringify(rulesJson)),
82
+ rules: JSON.stringify(rulesJson),
83
83
  schemaVersion: 1,
84
84
  };
85
85
  }
@@ -97,7 +97,7 @@ function buildTaskPolicy(policyId, description, rules) {
97
97
  policyId,
98
98
  mode: 'macp.mode.task.v1',
99
99
  description,
100
- rules: Buffer.from(JSON.stringify(rulesJson)),
100
+ rules: JSON.stringify(rulesJson),
101
101
  schemaVersion: 1,
102
102
  };
103
103
  }
@@ -112,7 +112,7 @@ function buildHandoffPolicy(policyId, description, rules) {
112
112
  policyId,
113
113
  mode: 'macp.mode.handoff.v1',
114
114
  description,
115
- rules: Buffer.from(JSON.stringify(rulesJson)),
115
+ rules: JSON.stringify(rulesJson),
116
116
  schemaVersion: 1,
117
117
  };
118
118
  }
@@ -0,0 +1,20 @@
1
+ import type { ProtoRegistry } from '../proto-registry';
2
+ import type { Envelope } from '../types';
3
+ /**
4
+ * Abstract base for in-process mode-state tracking — parity with python-sdk's
5
+ * `macp_sdk.base_projection.BaseProjection`. Maintains a shared transcript,
6
+ * phase string, and commitment payload; subclasses override `applyMode`
7
+ * to handle mode-specific envelopes. `SessionStart` and `Commitment` are
8
+ * handled here so custom modes get the common lifecycle for free.
9
+ */
10
+ export declare abstract class BaseProjection {
11
+ readonly transcript: Envelope[];
12
+ phase: string;
13
+ commitment?: Record<string, unknown>;
14
+ protected abstract readonly mode: string;
15
+ get isCommitted(): boolean;
16
+ get isPositiveOutcome(): boolean | undefined;
17
+ applyEnvelope(envelope: Envelope, protoRegistry: ProtoRegistry): void;
18
+ /** Handle a mode-specific (non-Commitment) envelope. */
19
+ protected abstract applyMode(envelope: Envelope, protoRegistry: ProtoRegistry): void;
20
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseProjection = void 0;
4
+ /**
5
+ * Abstract base for in-process mode-state tracking — parity with python-sdk's
6
+ * `macp_sdk.base_projection.BaseProjection`. Maintains a shared transcript,
7
+ * phase string, and commitment payload; subclasses override `applyMode`
8
+ * to handle mode-specific envelopes. `SessionStart` and `Commitment` are
9
+ * handled here so custom modes get the common lifecycle for free.
10
+ */
11
+ class BaseProjection {
12
+ transcript = [];
13
+ phase = '';
14
+ commitment;
15
+ get isCommitted() {
16
+ return this.commitment !== undefined;
17
+ }
18
+ get isPositiveOutcome() {
19
+ if (!this.commitment)
20
+ return undefined;
21
+ const val = this.commitment.outcomePositive ??
22
+ this.commitment.outcome_positive;
23
+ return val !== undefined ? Boolean(val) : true;
24
+ }
25
+ applyEnvelope(envelope, protoRegistry) {
26
+ if (envelope.mode !== this.mode)
27
+ return;
28
+ this.transcript.push(envelope);
29
+ if (envelope.messageType === 'Commitment') {
30
+ this.commitment = protoRegistry.decodeKnownPayload(envelope.mode, envelope.messageType, envelope.payload);
31
+ this.phase = 'Committed';
32
+ return;
33
+ }
34
+ this.applyMode(envelope, protoRegistry);
35
+ }
36
+ }
37
+ exports.BaseProjection = BaseProjection;
@@ -1,3 +1,4 @@
1
+ export * from './projections/base';
1
2
  export * from './projections/decision';
2
3
  export * from './projections/proposal';
3
4
  export * from './projections/task';
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./projections/base"), exports);
17
18
  __exportStar(require("./projections/decision"), exports);
18
19
  __exportStar(require("./projections/proposal"), exports);
19
20
  __exportStar(require("./projections/task"), exports);
@@ -24,7 +24,8 @@ export declare class ProposalSession {
24
24
  intent: string;
25
25
  participants: string[];
26
26
  ttlMs: number;
27
- context?: Buffer | string | Record<string, unknown>;
27
+ contextId?: string;
28
+ extensions?: Record<string, Buffer>;
28
29
  roots?: {
29
30
  uri: string;
30
31
  name?: string;
package/dist/proposal.js CHANGED
@@ -47,7 +47,8 @@ class ProposalSession {
47
47
  intent: input.intent,
48
48
  participants: input.participants,
49
49
  ttlMs: input.ttlMs,
50
- context: input.context,
50
+ contextId: input.contextId,
51
+ extensions: input.extensions,
51
52
  roots: input.roots,
52
53
  modeVersion: this.modeVersion,
53
54
  configurationVersion: this.configurationVersion,
package/dist/quorum.d.ts CHANGED
@@ -24,7 +24,8 @@ export declare class QuorumSession {
24
24
  intent: string;
25
25
  participants: string[];
26
26
  ttlMs: number;
27
- context?: Buffer | string | Record<string, unknown>;
27
+ contextId?: string;
28
+ extensions?: Record<string, Buffer>;
28
29
  roots?: {
29
30
  uri: string;
30
31
  name?: string;
package/dist/quorum.js CHANGED
@@ -47,7 +47,8 @@ class QuorumSession {
47
47
  intent: input.intent,
48
48
  participants: input.participants,
49
49
  ttlMs: input.ttlMs,
50
- context: input.context,
50
+ contextId: input.contextId,
51
+ extensions: input.extensions,
51
52
  roots: input.roots,
52
53
  modeVersion: this.modeVersion,
53
54
  configurationVersion: this.configurationVersion,
package/dist/task.d.ts CHANGED
@@ -24,14 +24,15 @@ export declare class TaskSession {
24
24
  intent: string;
25
25
  participants: string[];
26
26
  ttlMs: number;
27
- context?: Buffer | string | Record<string, unknown>;
27
+ contextId?: string;
28
+ extensions?: Record<string, Buffer>;
28
29
  roots?: {
29
30
  uri: string;
30
31
  name?: string;
31
32
  }[];
32
33
  sender?: string;
33
34
  }): Promise<Ack>;
34
- request(input: TaskRequestPayload & {
35
+ requestTask(input: TaskRequestPayload & {
35
36
  sender?: string;
36
37
  auth?: AuthConfig;
37
38
  }): Promise<Ack>;
@@ -43,15 +44,15 @@ export declare class TaskSession {
43
44
  sender?: string;
44
45
  auth?: AuthConfig;
45
46
  }): Promise<Ack>;
46
- update(input: TaskUpdatePayload & {
47
+ updateTask(input: TaskUpdatePayload & {
47
48
  sender?: string;
48
49
  auth?: AuthConfig;
49
50
  }): Promise<Ack>;
50
- complete(input: TaskCompletePayload & {
51
+ completeTask(input: TaskCompletePayload & {
51
52
  sender?: string;
52
53
  auth?: AuthConfig;
53
54
  }): Promise<Ack>;
54
- fail(input: TaskFailPayload & {
55
+ failTask(input: TaskFailPayload & {
55
56
  sender?: string;
56
57
  auth?: AuthConfig;
57
58
  }): Promise<Ack>;
package/dist/task.js CHANGED
@@ -47,7 +47,8 @@ class TaskSession {
47
47
  intent: input.intent,
48
48
  participants: input.participants,
49
49
  ttlMs: input.ttlMs,
50
- context: input.context,
50
+ contextId: input.contextId,
51
+ extensions: input.extensions,
51
52
  roots: input.roots,
52
53
  modeVersion: this.modeVersion,
53
54
  configurationVersion: this.configurationVersion,
@@ -62,7 +63,7 @@ class TaskSession {
62
63
  });
63
64
  return this.sendAndTrack(envelope, this.auth);
64
65
  }
65
- async request(input) {
66
+ async requestTask(input) {
66
67
  (0, validation_1.validateRequiredField)('taskId', input.taskId);
67
68
  (0, validation_1.validateRequiredField)('title', input.title);
68
69
  (0, validation_1.validateRequiredField)('instructions', input.instructions);
@@ -97,7 +98,7 @@ class TaskSession {
97
98
  });
98
99
  return this.sendAndTrack(envelope, input.auth);
99
100
  }
100
- async update(input) {
101
+ async updateTask(input) {
101
102
  (0, validation_1.validateRequiredField)('taskId', input.taskId);
102
103
  const envelope = (0, envelope_1.buildEnvelope)({
103
104
  mode: constants_1.MODE_TASK,
@@ -108,7 +109,7 @@ class TaskSession {
108
109
  });
109
110
  return this.sendAndTrack(envelope, input.auth);
110
111
  }
111
- async complete(input) {
112
+ async completeTask(input) {
112
113
  (0, validation_1.validateRequiredField)('taskId', input.taskId);
113
114
  const envelope = (0, envelope_1.buildEnvelope)({
114
115
  mode: constants_1.MODE_TASK,
@@ -119,7 +120,7 @@ class TaskSession {
119
120
  });
120
121
  return this.sendAndTrack(envelope, input.auth);
121
122
  }
122
- async fail(input) {
123
+ async failTask(input) {
123
124
  (0, validation_1.validateRequiredField)('taskId', input.taskId);
124
125
  const envelope = (0, envelope_1.buildEnvelope)({
125
126
  mode: constants_1.MODE_TASK,
package/dist/types.d.ts CHANGED
@@ -45,6 +45,8 @@ export interface SessionMetadata {
45
45
  participants?: string[];
46
46
  participantActivity?: ParticipantActivity[];
47
47
  initiator?: string;
48
+ contextId?: string;
49
+ extensionKeys?: string[];
48
50
  }
49
51
  export interface ModeDescriptor {
50
52
  mode: string;
@@ -93,7 +95,8 @@ export interface SessionStartPayload {
93
95
  configurationVersion: string;
94
96
  policyVersion?: string;
95
97
  ttlMs: number;
96
- context?: Buffer;
98
+ contextId?: string;
99
+ extensions?: Record<string, Buffer>;
97
100
  roots?: Root[];
98
101
  }
99
102
  export interface CommitmentPayload {
@@ -250,7 +253,7 @@ export interface PolicyDescriptor {
250
253
  policyId: string;
251
254
  mode: string;
252
255
  description: string;
253
- rules: Buffer | Uint8Array;
256
+ rules: string;
254
257
  schemaVersion: number;
255
258
  registeredAtUnixMs?: number;
256
259
  }
@@ -261,3 +264,9 @@ export interface RegistryChanged {
261
264
  export interface RootsChanged {
262
265
  observedAtUnixMs: string;
263
266
  }
267
+ export type SessionLifecycleEventType = 'EVENT_TYPE_UNSPECIFIED' | 'EVENT_TYPE_CREATED' | 'EVENT_TYPE_RESOLVED' | 'EVENT_TYPE_EXPIRED';
268
+ export interface SessionLifecycleEvent {
269
+ eventType: SessionLifecycleEventType;
270
+ session: SessionMetadata;
271
+ observedAtUnixMs: string;
272
+ }
@@ -1,6 +1,6 @@
1
1
  import type { AuthConfig } from './auth';
2
2
  import type { MacpClient } from './client';
3
- import type { Envelope, PolicyDescriptor, RegistryChanged, RootsChanged } from './types';
3
+ import type { Envelope, PolicyDescriptor, RegistryChanged, RootsChanged, SessionLifecycleEvent } from './types';
4
4
  export declare class ModeRegistryWatcher {
5
5
  private readonly client;
6
6
  private readonly auth?;
@@ -45,3 +45,25 @@ export declare class PolicyWatcher {
45
45
  watch(handler: (change: PolicyChange) => void | Promise<void>): Promise<void>;
46
46
  nextChange(): Promise<PolicyChange>;
47
47
  }
48
+ export declare class SessionLifecycleWatcher {
49
+ private readonly client;
50
+ private readonly auth?;
51
+ private deprecatedEventsWarned;
52
+ private deprecatedNextEventWarned;
53
+ constructor(client: MacpClient, options?: {
54
+ auth?: AuthConfig;
55
+ });
56
+ changes(signal?: AbortSignal): AsyncGenerator<SessionLifecycleEvent, void, void>;
57
+ watch(handler: (event: SessionLifecycleEvent) => void | Promise<void>): Promise<void>;
58
+ nextChange(): Promise<SessionLifecycleEvent>;
59
+ /**
60
+ * @deprecated Use {@link changes} — renamed for parity with python-sdk's
61
+ * `SessionLifecycleWatcher.changes()` and the uniform `changes()` name
62
+ * used by all other watchers in both SDKs. Will be removed in 0.5.0.
63
+ */
64
+ events(signal?: AbortSignal): AsyncGenerator<SessionLifecycleEvent, void, void>;
65
+ /**
66
+ * @deprecated Use {@link nextChange}. Will be removed in 0.5.0.
67
+ */
68
+ nextEvent(): Promise<SessionLifecycleEvent>;
69
+ }
package/dist/watchers.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PolicyWatcher = exports.SignalWatcher = exports.RootsWatcher = exports.ModeRegistryWatcher = void 0;
3
+ exports.SessionLifecycleWatcher = exports.PolicyWatcher = exports.SignalWatcher = exports.RootsWatcher = exports.ModeRegistryWatcher = void 0;
4
+ const logging_1 = require("./logging");
4
5
  function serverStreamToAsyncGenerator(stream) {
5
6
  const queue = [];
6
7
  let resolve = null;
@@ -174,3 +175,60 @@ class PolicyWatcher {
174
175
  }
175
176
  }
176
177
  exports.PolicyWatcher = PolicyWatcher;
178
+ class SessionLifecycleWatcher {
179
+ client;
180
+ auth;
181
+ deprecatedEventsWarned = false;
182
+ deprecatedNextEventWarned = false;
183
+ constructor(client, options) {
184
+ this.client = client;
185
+ this.auth = options?.auth;
186
+ }
187
+ async *changes(signal) {
188
+ const stream = this.client.watchSessions(this.auth);
189
+ if (signal) {
190
+ signal.addEventListener('abort', () => stream.cancel(), { once: true });
191
+ }
192
+ const gen = serverStreamToAsyncGenerator(stream);
193
+ for await (const response of gen) {
194
+ if (response.event)
195
+ yield response.event;
196
+ }
197
+ }
198
+ async watch(handler) {
199
+ for await (const event of this.changes()) {
200
+ await handler(event);
201
+ }
202
+ }
203
+ async nextChange() {
204
+ const gen = this.changes();
205
+ const result = await gen.next();
206
+ await gen.return(undefined);
207
+ if (result.done)
208
+ throw new Error('stream ended before receiving a session lifecycle event');
209
+ return result.value;
210
+ }
211
+ /**
212
+ * @deprecated Use {@link changes} — renamed for parity with python-sdk's
213
+ * `SessionLifecycleWatcher.changes()` and the uniform `changes()` name
214
+ * used by all other watchers in both SDKs. Will be removed in 0.5.0.
215
+ */
216
+ async *events(signal) {
217
+ if (!this.deprecatedEventsWarned) {
218
+ this.deprecatedEventsWarned = true;
219
+ logging_1.logger.warn('[deprecated] SessionLifecycleWatcher.events() — use changes() instead');
220
+ }
221
+ yield* this.changes(signal);
222
+ }
223
+ /**
224
+ * @deprecated Use {@link nextChange}. Will be removed in 0.5.0.
225
+ */
226
+ async nextEvent() {
227
+ if (!this.deprecatedNextEventWarned) {
228
+ this.deprecatedNextEventWarned = true;
229
+ logging_1.logger.warn('[deprecated] SessionLifecycleWatcher.nextEvent() — use nextChange() instead');
230
+ }
231
+ return this.nextChange();
232
+ }
233
+ }
234
+ exports.SessionLifecycleWatcher = SessionLifecycleWatcher;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "macp-sdk-typescript",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "TypeScript SDK for the MACP Rust runtime",
5
5
  "license": "Apache-2.0",
6
6
  "type": "commonjs",
@@ -55,7 +55,7 @@
55
55
  "dependencies": {
56
56
  "@grpc/grpc-js": "^1.14.3",
57
57
  "@grpc/proto-loader": "^0.8.0",
58
- "@multiagentcoordinationprotocol/proto": "^0.1.0",
58
+ "@multiagentcoordinationprotocol/proto": "^0.1.2",
59
59
  "protobufjs": "^8.0.0"
60
60
  },
61
61
  "devDependencies": {