macp-sdk-typescript 0.2.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 (64) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/LICENSE +201 -0
  3. package/README.md +307 -0
  4. package/dist/agent/dispatcher.d.ts +16 -0
  5. package/dist/agent/dispatcher.js +61 -0
  6. package/dist/agent/index.d.ts +6 -0
  7. package/dist/agent/index.js +25 -0
  8. package/dist/agent/participant.d.ts +38 -0
  9. package/dist/agent/participant.js +221 -0
  10. package/dist/agent/runner.d.ts +18 -0
  11. package/dist/agent/runner.js +84 -0
  12. package/dist/agent/strategies.d.ts +40 -0
  13. package/dist/agent/strategies.js +106 -0
  14. package/dist/agent/transports.d.ts +35 -0
  15. package/dist/agent/transports.js +125 -0
  16. package/dist/agent/types.d.ts +72 -0
  17. package/dist/agent/types.js +2 -0
  18. package/dist/auth.d.ts +52 -0
  19. package/dist/auth.js +112 -0
  20. package/dist/client.d.ts +171 -0
  21. package/dist/client.js +384 -0
  22. package/dist/constants.d.ts +26 -0
  23. package/dist/constants.js +29 -0
  24. package/dist/decision.d.ts +65 -0
  25. package/dist/decision.js +148 -0
  26. package/dist/envelope.d.ts +50 -0
  27. package/dist/envelope.js +97 -0
  28. package/dist/errors.d.ts +44 -0
  29. package/dist/errors.js +114 -0
  30. package/dist/handoff.d.ts +73 -0
  31. package/dist/handoff.js +160 -0
  32. package/dist/index.d.ts +18 -0
  33. package/dist/index.js +57 -0
  34. package/dist/policy.d.ts +76 -0
  35. package/dist/policy.js +118 -0
  36. package/dist/projections/decision.d.ts +49 -0
  37. package/dist/projections/decision.js +132 -0
  38. package/dist/projections/handoff.d.ts +28 -0
  39. package/dist/projections/handoff.js +111 -0
  40. package/dist/projections/proposal.d.ts +40 -0
  41. package/dist/projections/proposal.js +123 -0
  42. package/dist/projections/quorum.d.ts +36 -0
  43. package/dist/projections/quorum.js +107 -0
  44. package/dist/projections/task.d.ts +54 -0
  45. package/dist/projections/task.js +127 -0
  46. package/dist/projections.d.ts +5 -0
  47. package/dist/projections.js +21 -0
  48. package/dist/proposal.d.ts +69 -0
  49. package/dist/proposal.js +155 -0
  50. package/dist/proto-registry.d.ts +12 -0
  51. package/dist/proto-registry.js +165 -0
  52. package/dist/quorum.d.ts +65 -0
  53. package/dist/quorum.js +144 -0
  54. package/dist/retry.d.ts +14 -0
  55. package/dist/retry.js +48 -0
  56. package/dist/task.d.ts +73 -0
  57. package/dist/task.js +166 -0
  58. package/dist/types.d.ts +263 -0
  59. package/dist/types.js +2 -0
  60. package/dist/validation.d.ts +17 -0
  61. package/dist/validation.js +92 -0
  62. package/dist/watchers.d.ts +47 -0
  63. package/dist/watchers.js +176 -0
  64. package/package.json +72 -0
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.HttpTransportAdapter = exports.GrpcTransportAdapter = void 0;
18
+ __exportStar(require("./types"), exports);
19
+ __exportStar(require("./dispatcher"), exports);
20
+ __exportStar(require("./participant"), exports);
21
+ __exportStar(require("./strategies"), exports);
22
+ __exportStar(require("./runner"), exports);
23
+ var transports_1 = require("./transports");
24
+ Object.defineProperty(exports, "GrpcTransportAdapter", { enumerable: true, get: function () { return transports_1.GrpcTransportAdapter; } });
25
+ Object.defineProperty(exports, "HttpTransportAdapter", { enumerable: true, get: function () { return transports_1.HttpTransportAdapter; } });
@@ -0,0 +1,38 @@
1
+ import type { AuthConfig } from '../auth';
2
+ import type { MacpClient } from '../client';
3
+ import { type TransportAdapter } from './transports';
4
+ import type { MessageHandler, PhaseChangeHandler, ProjectionLike, SessionActions, TerminalHandler } from './types';
5
+ export interface ParticipantConfig {
6
+ participantId: string;
7
+ sessionId: string;
8
+ mode: string;
9
+ client: MacpClient;
10
+ auth?: AuthConfig;
11
+ participants?: string[];
12
+ modeVersion?: string;
13
+ configurationVersion?: string;
14
+ policyVersion?: string;
15
+ transport?: TransportAdapter;
16
+ }
17
+ export declare class Participant {
18
+ readonly participantId: string;
19
+ readonly sessionId: string;
20
+ readonly mode: string;
21
+ readonly client: MacpClient;
22
+ readonly auth?: AuthConfig;
23
+ readonly projection: ProjectionLike;
24
+ readonly actions: SessionActions;
25
+ private readonly dispatcher;
26
+ private readonly session;
27
+ private readonly transport;
28
+ private running;
29
+ private lastPhase;
30
+ constructor(config: ParticipantConfig);
31
+ private createModeSession;
32
+ private buildActions;
33
+ on(messageType: string, handler: MessageHandler): Participant;
34
+ onPhaseChange(phase: string, handler: PhaseChangeHandler): Participant;
35
+ onTerminal(handler: TerminalHandler): Participant;
36
+ run(): Promise<void>;
37
+ stop(): Promise<void>;
38
+ }
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Participant = void 0;
4
+ const constants_1 = require("../constants");
5
+ const decision_1 = require("../decision");
6
+ const handoff_1 = require("../handoff");
7
+ const decision_2 = require("../projections/decision");
8
+ const proposal_1 = require("../proposal");
9
+ const quorum_1 = require("../quorum");
10
+ const task_1 = require("../task");
11
+ const dispatcher_1 = require("./dispatcher");
12
+ const transports_1 = require("./transports");
13
+ class Participant {
14
+ participantId;
15
+ sessionId;
16
+ mode;
17
+ client;
18
+ auth;
19
+ projection;
20
+ actions;
21
+ dispatcher;
22
+ session;
23
+ transport;
24
+ running = false;
25
+ lastPhase;
26
+ constructor(config) {
27
+ this.participantId = config.participantId;
28
+ this.sessionId = config.sessionId;
29
+ this.mode = config.mode;
30
+ this.client = config.client;
31
+ this.auth = config.auth;
32
+ this.dispatcher = new dispatcher_1.Dispatcher();
33
+ const sessionOpts = {
34
+ sessionId: config.sessionId,
35
+ modeVersion: config.modeVersion,
36
+ configurationVersion: config.configurationVersion,
37
+ policyVersion: config.policyVersion,
38
+ auth: config.auth,
39
+ };
40
+ const { session, projection } = this.createModeSession(config.mode, config.client, sessionOpts);
41
+ this.session = session;
42
+ this.projection = projection;
43
+ this.lastPhase = projection.phase;
44
+ this.actions = this.buildActions();
45
+ this.transport = config.transport ?? new transports_1.GrpcTransportAdapter(config.client, config.sessionId, config.auth);
46
+ }
47
+ createModeSession(mode, client, opts) {
48
+ switch (mode) {
49
+ case constants_1.MODE_DECISION: {
50
+ const s = new decision_1.DecisionSession(client, opts);
51
+ return { session: s, projection: s.projection };
52
+ }
53
+ case constants_1.MODE_PROPOSAL: {
54
+ const s = new proposal_1.ProposalSession(client, opts);
55
+ return { session: s, projection: s.projection };
56
+ }
57
+ case constants_1.MODE_TASK: {
58
+ const s = new task_1.TaskSession(client, opts);
59
+ return { session: s, projection: s.projection };
60
+ }
61
+ case constants_1.MODE_HANDOFF: {
62
+ const s = new handoff_1.HandoffSession(client, opts);
63
+ return { session: s, projection: s.projection };
64
+ }
65
+ case constants_1.MODE_QUORUM: {
66
+ const s = new quorum_1.QuorumSession(client, opts);
67
+ return { session: s, projection: s.projection };
68
+ }
69
+ default: {
70
+ const fallback = new decision_2.DecisionProjection();
71
+ return { session: null, projection: fallback };
72
+ }
73
+ }
74
+ }
75
+ buildActions() {
76
+ const participantId = this.participantId;
77
+ const actions = {};
78
+ if (this.session instanceof decision_1.DecisionSession) {
79
+ const ds = this.session;
80
+ actions.evaluate = async (input) => {
81
+ await ds.evaluate({ ...input, sender: participantId });
82
+ };
83
+ actions.vote = async (input) => {
84
+ await ds.vote({ ...input, sender: participantId });
85
+ };
86
+ actions.raiseObjection = async (input) => {
87
+ await ds.raiseObjection({ ...input, sender: participantId });
88
+ };
89
+ actions.propose = async (input) => {
90
+ await ds.propose({ ...input, sender: participantId });
91
+ };
92
+ actions.commit = async (input) => {
93
+ await ds.commit({ ...input, sender: participantId });
94
+ };
95
+ }
96
+ if (this.session instanceof proposal_1.ProposalSession) {
97
+ const ps = this.session;
98
+ actions.propose = async (input) => {
99
+ await ps.propose({
100
+ proposalId: input.proposalId,
101
+ title: input.option,
102
+ summary: input.rationale,
103
+ sender: participantId,
104
+ });
105
+ };
106
+ actions.commit = async (input) => {
107
+ await ps.commit({ ...input, sender: participantId });
108
+ };
109
+ }
110
+ if (this.session instanceof task_1.TaskSession) {
111
+ const ts = this.session;
112
+ actions.commit = async (input) => {
113
+ await ts.commit({ ...input, sender: participantId });
114
+ };
115
+ }
116
+ if (this.session instanceof handoff_1.HandoffSession) {
117
+ const hs = this.session;
118
+ actions.commit = async (input) => {
119
+ await hs.commit({ ...input, sender: participantId });
120
+ };
121
+ }
122
+ if (this.session instanceof quorum_1.QuorumSession) {
123
+ const qs = this.session;
124
+ actions.commit = async (input) => {
125
+ await qs.commit({ ...input, sender: participantId });
126
+ };
127
+ }
128
+ const mode = this.mode;
129
+ const sessionId = this.sessionId;
130
+ const client = this.client;
131
+ const auth = this.auth;
132
+ actions.send = async (messageType, payload) => {
133
+ const { buildEnvelope } = await import('../envelope.js');
134
+ const envelope = buildEnvelope({
135
+ mode,
136
+ messageType,
137
+ sessionId,
138
+ sender: participantId,
139
+ payload: client.protoRegistry.encodeKnownPayload(mode, messageType, payload),
140
+ });
141
+ await client.send(envelope, { auth });
142
+ };
143
+ return actions;
144
+ }
145
+ on(messageType, handler) {
146
+ this.dispatcher.on(messageType, handler);
147
+ return this;
148
+ }
149
+ onPhaseChange(phase, handler) {
150
+ this.dispatcher.onPhaseChange(phase, handler);
151
+ return this;
152
+ }
153
+ onTerminal(handler) {
154
+ this.dispatcher.onTerminal(handler);
155
+ return this;
156
+ }
157
+ async run() {
158
+ if (this.running)
159
+ return;
160
+ this.running = true;
161
+ const sessionInfo = {
162
+ sessionId: this.sessionId,
163
+ mode: this.mode,
164
+ participants: [],
165
+ policyVersion: undefined,
166
+ };
167
+ try {
168
+ for await (const message of this.transport.start()) {
169
+ if (!this.running)
170
+ break;
171
+ const ctx = {
172
+ participant: this,
173
+ projection: this.projection,
174
+ actions: this.actions,
175
+ session: sessionInfo,
176
+ log: (msg, details) => {
177
+ // eslint-disable-next-line no-console
178
+ console.log(`[${this.participantId}] ${msg}`, details ?? '');
179
+ },
180
+ };
181
+ // Apply envelope to projection if we have a mode session
182
+ if (this.session && message.raw) {
183
+ const applyMethod = this.session
184
+ .projection.applyEnvelope;
185
+ if (typeof applyMethod === 'function') {
186
+ applyMethod.call(this.session.projection, message.raw, this.client.protoRegistry);
187
+ }
188
+ }
189
+ // Dispatch message
190
+ await this.dispatcher.dispatch(message, ctx);
191
+ // Check for phase change
192
+ const currentPhase = this.projection.phase;
193
+ if (currentPhase !== this.lastPhase) {
194
+ this.lastPhase = currentPhase;
195
+ await this.dispatcher.dispatchPhaseChange(currentPhase, ctx);
196
+ // Check for terminal state
197
+ if (currentPhase === 'Committed' ||
198
+ currentPhase === 'Accepted' ||
199
+ currentPhase === 'Declined' ||
200
+ currentPhase === 'Cancelled' ||
201
+ currentPhase === 'TerminalRejected') {
202
+ const terminalResult = {
203
+ state: currentPhase,
204
+ commitment: this.projection.commitment,
205
+ };
206
+ await this.dispatcher.dispatchTerminal(terminalResult);
207
+ break;
208
+ }
209
+ }
210
+ }
211
+ }
212
+ finally {
213
+ this.running = false;
214
+ }
215
+ }
216
+ async stop() {
217
+ this.running = false;
218
+ await this.transport.stop();
219
+ }
220
+ }
221
+ exports.Participant = Participant;
@@ -0,0 +1,18 @@
1
+ import { Participant } from './participant';
2
+ export interface BootstrapPayload {
3
+ session_id: string;
4
+ participant_id: string;
5
+ mode: string;
6
+ mode_version?: string;
7
+ configuration_version?: string;
8
+ policy_version?: string;
9
+ runtime_address?: string;
10
+ runtime_url?: string;
11
+ auth_token?: string;
12
+ agent_id?: string;
13
+ secure?: boolean;
14
+ /** Mirror of {@link MacpClientOptions.allowInsecure}; required when `secure` is false. */
15
+ allow_insecure?: boolean;
16
+ participants?: string[];
17
+ }
18
+ export declare function fromBootstrap(bootstrapPath?: string): Participant;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.fromBootstrap = fromBootstrap;
37
+ const fs = __importStar(require("node:fs"));
38
+ const path = __importStar(require("node:path"));
39
+ const auth_1 = require("../auth");
40
+ const client_1 = require("../client");
41
+ const constants_1 = require("../constants");
42
+ const participant_1 = require("./participant");
43
+ function fromBootstrap(bootstrapPath) {
44
+ const resolvedPath = bootstrapPath ?? process.env.MACP_BOOTSTRAP_FILE;
45
+ if (!resolvedPath) {
46
+ throw new Error('No bootstrap path provided. Either pass a path argument or set the MACP_BOOTSTRAP_FILE environment variable.');
47
+ }
48
+ const absolutePath = path.isAbsolute(resolvedPath) ? resolvedPath : path.resolve(process.cwd(), resolvedPath);
49
+ if (!fs.existsSync(absolutePath)) {
50
+ throw new Error(`Bootstrap file not found: ${absolutePath}`);
51
+ }
52
+ const raw = fs.readFileSync(absolutePath, 'utf8');
53
+ const payload = JSON.parse(raw);
54
+ if (!payload.session_id)
55
+ throw new Error('Bootstrap payload missing session_id');
56
+ if (!payload.participant_id)
57
+ throw new Error('Bootstrap payload missing participant_id');
58
+ if (!payload.mode)
59
+ throw new Error('Bootstrap payload missing mode');
60
+ const runtimeAddress = payload.runtime_address ?? payload.runtime_url ?? '';
61
+ if (!runtimeAddress)
62
+ throw new Error('Bootstrap payload missing runtime_address / runtime_url');
63
+ const auth = payload.auth_token
64
+ ? auth_1.Auth.bearer(payload.auth_token, { expectedSender: payload.participant_id })
65
+ : auth_1.Auth.devAgent(payload.agent_id ?? payload.participant_id);
66
+ const client = new client_1.MacpClient({
67
+ address: runtimeAddress,
68
+ secure: payload.secure,
69
+ allowInsecure: payload.allow_insecure,
70
+ auth,
71
+ });
72
+ const config = {
73
+ participantId: payload.participant_id,
74
+ sessionId: payload.session_id,
75
+ mode: payload.mode,
76
+ client,
77
+ auth,
78
+ participants: payload.participants ?? [],
79
+ modeVersion: payload.mode_version,
80
+ configurationVersion: payload.configuration_version,
81
+ policyVersion: payload.policy_version ?? constants_1.DEFAULT_POLICY_VERSION,
82
+ };
83
+ return new participant_1.Participant(config);
84
+ }
@@ -0,0 +1,40 @@
1
+ import type { DecisionProjection } from '../projections/decision';
2
+ import type { MessageHandler, SessionInfo } from './types';
3
+ export interface EvaluationResult {
4
+ recommendation: string;
5
+ confidence: number;
6
+ reason: string;
7
+ }
8
+ export interface EvaluationStrategy {
9
+ evaluate(proposal: Record<string, unknown>, context: SessionInfo): Promise<EvaluationResult>;
10
+ }
11
+ export declare function evaluationHandler(strategy: EvaluationStrategy): MessageHandler;
12
+ export declare function functionEvaluator(fn: (proposal: Record<string, unknown>, context: SessionInfo) => Promise<EvaluationResult>): EvaluationStrategy;
13
+ export interface VoteResult {
14
+ vote: string;
15
+ reason: string;
16
+ }
17
+ export interface VotingStrategy {
18
+ shouldVote(projection: DecisionProjection): boolean;
19
+ decideVote(projection: DecisionProjection): Promise<VoteResult>;
20
+ }
21
+ export declare function votingHandler(strategy: VotingStrategy): MessageHandler;
22
+ export declare function majorityVoter(options?: {
23
+ positiveThreshold?: number;
24
+ }): VotingStrategy;
25
+ export interface CommitmentResult {
26
+ action: string;
27
+ authorityScope: string;
28
+ reason: string;
29
+ outcomePositive?: boolean;
30
+ }
31
+ export interface CommitmentStrategy {
32
+ shouldCommit(projection: DecisionProjection): boolean;
33
+ decideCommitment(projection: DecisionProjection): Promise<CommitmentResult>;
34
+ }
35
+ export declare function commitmentHandler(strategy: CommitmentStrategy): MessageHandler;
36
+ export declare function majorityCommitter(options?: {
37
+ quorumSize?: number;
38
+ action?: string;
39
+ authorityScope?: string;
40
+ }): CommitmentStrategy;
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.evaluationHandler = evaluationHandler;
4
+ exports.functionEvaluator = functionEvaluator;
5
+ exports.votingHandler = votingHandler;
6
+ exports.majorityVoter = majorityVoter;
7
+ exports.commitmentHandler = commitmentHandler;
8
+ exports.majorityCommitter = majorityCommitter;
9
+ const envelope_1 = require("../envelope");
10
+ function evaluationHandler(strategy) {
11
+ return async (event, ctx) => {
12
+ if (event.messageType !== 'Proposal')
13
+ return;
14
+ const result = await strategy.evaluate(event.payload, ctx.session);
15
+ if (ctx.actions.evaluate) {
16
+ await ctx.actions.evaluate({
17
+ proposalId: event.proposalId ?? event.payload.proposalId ?? event.payload.proposal_id,
18
+ recommendation: result.recommendation,
19
+ confidence: result.confidence,
20
+ reason: result.reason,
21
+ });
22
+ }
23
+ };
24
+ }
25
+ function functionEvaluator(fn) {
26
+ return { evaluate: fn };
27
+ }
28
+ function votingHandler(strategy) {
29
+ return async (event, ctx) => {
30
+ if (event.messageType !== 'Evaluation')
31
+ return;
32
+ const projection = ctx.projection;
33
+ if (!strategy.shouldVote(projection))
34
+ return;
35
+ const result = await strategy.decideVote(projection);
36
+ if (ctx.actions.vote) {
37
+ const proposalId = event.proposalId ?? event.payload.proposalId ?? event.payload.proposal_id;
38
+ await ctx.actions.vote({
39
+ proposalId,
40
+ vote: result.vote,
41
+ reason: result.reason,
42
+ });
43
+ }
44
+ };
45
+ }
46
+ function majorityVoter(options) {
47
+ const threshold = options?.positiveThreshold ?? 0.5;
48
+ return {
49
+ shouldVote(projection) {
50
+ return projection.evaluations.length > 0;
51
+ },
52
+ async decideVote(projection) {
53
+ const positive = projection.evaluations.filter((e) => ['approve', 'accept', 'yes'].includes(e.recommendation.toLowerCase()));
54
+ const ratio = projection.evaluations.length > 0 ? positive.length / projection.evaluations.length : 0;
55
+ if (ratio >= threshold) {
56
+ return { vote: 'APPROVE', reason: `${positive.length}/${projection.evaluations.length} evaluations positive` };
57
+ }
58
+ return {
59
+ vote: 'REJECT',
60
+ reason: `Only ${positive.length}/${projection.evaluations.length} evaluations positive`,
61
+ };
62
+ },
63
+ };
64
+ }
65
+ function commitmentHandler(strategy) {
66
+ return async (event, ctx) => {
67
+ if (event.messageType !== 'Vote')
68
+ return;
69
+ const projection = ctx.projection;
70
+ if (!strategy.shouldCommit(projection))
71
+ return;
72
+ const result = await strategy.decideCommitment(projection);
73
+ if (ctx.actions.commit) {
74
+ await ctx.actions.commit({
75
+ action: result.action,
76
+ authorityScope: result.authorityScope,
77
+ reason: result.reason,
78
+ outcomePositive: result.outcomePositive ?? (0, envelope_1.inferOutcomePositive)(result.action),
79
+ });
80
+ }
81
+ };
82
+ }
83
+ function majorityCommitter(options) {
84
+ const quorum = options?.quorumSize ?? 1;
85
+ const action = options?.action ?? 'commit';
86
+ const authorityScope = options?.authorityScope ?? 'session';
87
+ return {
88
+ shouldCommit(projection) {
89
+ const totals = projection.voteTotals();
90
+ const winner = projection.majorityWinner();
91
+ if (!winner)
92
+ return false;
93
+ return (totals[winner] ?? 0) >= quorum;
94
+ },
95
+ async decideCommitment(projection) {
96
+ const winner = projection.majorityWinner();
97
+ const proposal = winner ? projection.proposals.get(winner) : undefined;
98
+ return {
99
+ action,
100
+ authorityScope,
101
+ reason: proposal ? `Majority selected: ${proposal.option}` : 'Majority reached',
102
+ outcomePositive: (0, envelope_1.inferOutcomePositive)(action),
103
+ };
104
+ },
105
+ };
106
+ }
@@ -0,0 +1,35 @@
1
+ import type { AuthConfig } from '../auth';
2
+ import type { MacpClient } from '../client';
3
+ import type { IncomingMessage } from './types';
4
+ export interface TransportAdapter {
5
+ start(): AsyncIterable<IncomingMessage>;
6
+ stop(): Promise<void>;
7
+ }
8
+ export declare class GrpcTransportAdapter implements TransportAdapter {
9
+ private readonly client;
10
+ private readonly sessionId;
11
+ private readonly auth?;
12
+ private stream;
13
+ private seq;
14
+ constructor(client: MacpClient, sessionId: string, auth?: AuthConfig | undefined);
15
+ start(): AsyncIterable<IncomingMessage>;
16
+ stop(): Promise<void>;
17
+ }
18
+ export interface HttpPollingConfig {
19
+ baseUrl: string;
20
+ sessionId: string;
21
+ participantId: string;
22
+ pollIntervalMs: number;
23
+ authToken?: string;
24
+ }
25
+ export declare class HttpTransportAdapter implements TransportAdapter {
26
+ private readonly config;
27
+ private stopped;
28
+ private seq;
29
+ private lastSeq;
30
+ constructor(config: HttpPollingConfig);
31
+ start(): AsyncIterable<IncomingMessage>;
32
+ stop(): Promise<void>;
33
+ private tryParsePayload;
34
+ private sleep;
35
+ }