macp-sdk-typescript 0.2.2 → 0.4.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.
- package/CHANGELOG.md +176 -1
- package/README.md +49 -6
- package/dist/agent/cancel-callback.d.ts +23 -0
- package/dist/agent/cancel-callback.js +108 -0
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.js +1 -0
- package/dist/agent/participant.d.ts +39 -0
- package/dist/agent/participant.js +114 -45
- package/dist/agent/runner.d.ts +13 -0
- package/dist/agent/runner.js +34 -0
- package/dist/agent/strategies.d.ts +2 -0
- package/dist/agent/strategies.js +8 -0
- package/dist/agent/transports.js +5 -0
- package/dist/base-session.d.ts +75 -0
- package/dist/base-session.js +127 -0
- package/dist/client.d.ts +54 -0
- package/dist/client.js +130 -9
- package/dist/constants.d.ts +21 -16
- package/dist/constants.js +24 -17
- package/dist/decision.d.ts +10 -0
- package/dist/decision.js +20 -0
- package/dist/envelope.d.ts +38 -1
- package/dist/envelope.js +53 -1
- package/dist/errors.d.ts +17 -4
- package/dist/errors.js +19 -10
- package/dist/handoff.d.ts +10 -8
- package/dist/handoff.js +20 -16
- package/dist/index.d.ts +3 -1
- package/dist/index.js +10 -2
- package/dist/logging.d.ts +21 -0
- package/dist/logging.js +64 -0
- package/dist/policy.d.ts +47 -42
- package/dist/policy.js +5 -6
- package/dist/projections/base.d.ts +20 -0
- package/dist/projections/base.js +37 -0
- package/dist/projections.d.ts +1 -0
- package/dist/projections.js +1 -0
- package/dist/proposal.d.ts +10 -0
- package/dist/proposal.js +20 -0
- package/dist/quorum.d.ts +10 -0
- package/dist/quorum.js +20 -0
- package/dist/task.d.ts +14 -4
- package/dist/task.js +24 -4
- package/dist/types.d.ts +30 -3
- package/dist/watchers.d.ts +37 -2
- package/dist/watchers.js +65 -5
- package/package.json +2 -2
package/dist/client.js
CHANGED
|
@@ -60,13 +60,45 @@ class AsyncQueue {
|
|
|
60
60
|
else
|
|
61
61
|
this.items.push(item);
|
|
62
62
|
}
|
|
63
|
+
unshift(item) {
|
|
64
|
+
this.items.unshift(item);
|
|
65
|
+
}
|
|
63
66
|
shift() {
|
|
64
67
|
const item = this.items.shift();
|
|
65
68
|
if (item !== undefined)
|
|
66
69
|
return Promise.resolve(item);
|
|
67
70
|
return new Promise((resolve) => this.resolvers.push(resolve));
|
|
68
71
|
}
|
|
72
|
+
shiftWithTimeout(timeoutMs) {
|
|
73
|
+
const item = this.items.shift();
|
|
74
|
+
if (item !== undefined)
|
|
75
|
+
return Promise.resolve(item);
|
|
76
|
+
return new Promise((resolve) => {
|
|
77
|
+
let settled = false;
|
|
78
|
+
const resolver = (value) => {
|
|
79
|
+
if (settled) {
|
|
80
|
+
// Timeout already fired; put the value back so it isn't lost.
|
|
81
|
+
this.items.unshift(value);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
settled = true;
|
|
85
|
+
clearTimeout(timer);
|
|
86
|
+
resolve(value);
|
|
87
|
+
};
|
|
88
|
+
this.resolvers.push(resolver);
|
|
89
|
+
const timer = setTimeout(() => {
|
|
90
|
+
if (settled)
|
|
91
|
+
return;
|
|
92
|
+
settled = true;
|
|
93
|
+
const idx = this.resolvers.indexOf(resolver);
|
|
94
|
+
if (idx >= 0)
|
|
95
|
+
this.resolvers.splice(idx, 1);
|
|
96
|
+
resolve(TIMEOUT);
|
|
97
|
+
}, timeoutMs);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
69
100
|
}
|
|
101
|
+
const TIMEOUT = Symbol('stream-read-timeout');
|
|
70
102
|
const STREAM_END = Symbol('stream-end');
|
|
71
103
|
class MacpStream {
|
|
72
104
|
call;
|
|
@@ -109,16 +141,63 @@ class MacpStream {
|
|
|
109
141
|
});
|
|
110
142
|
});
|
|
111
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* RFC-MACP-0006-A1: Send a subscribe-only frame to receive session history
|
|
146
|
+
* + live broadcast. The runtime replays accepted envelopes from
|
|
147
|
+
* `afterSequence` onwards, then continues with live broadcast.
|
|
148
|
+
*/
|
|
149
|
+
sendSubscribe(sessionId, afterSequence = 0) {
|
|
150
|
+
if (this.closed)
|
|
151
|
+
return Promise.reject(new errors_1.MacpSdkError('stream is already closed'));
|
|
152
|
+
return new Promise((resolve, reject) => {
|
|
153
|
+
this.call.write({ subscribeSessionId: sessionId, afterSequence }, (error) => {
|
|
154
|
+
if (error)
|
|
155
|
+
reject(error);
|
|
156
|
+
else
|
|
157
|
+
resolve();
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
112
161
|
async *responses() {
|
|
113
162
|
while (true) {
|
|
114
163
|
const item = await this.queue.shift();
|
|
115
|
-
if (item === STREAM_END)
|
|
164
|
+
if (item === STREAM_END) {
|
|
165
|
+
// Re-push so a subsequent read()/responses() call also observes end-of-stream.
|
|
166
|
+
this.queue.unshift(STREAM_END);
|
|
116
167
|
return;
|
|
168
|
+
}
|
|
117
169
|
if (item instanceof Error)
|
|
118
170
|
throw item;
|
|
119
171
|
yield item;
|
|
120
172
|
}
|
|
121
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Read a single envelope from the stream. Parity with python-sdk's
|
|
176
|
+
* {@code MacpStream.read(timeout)}.
|
|
177
|
+
*
|
|
178
|
+
* @param timeoutMs Maximum time to wait for the next envelope. If omitted,
|
|
179
|
+
* blocks indefinitely until an envelope arrives, the stream
|
|
180
|
+
* ends, or an error occurs.
|
|
181
|
+
* @returns The next envelope, or {@code null} if the stream has
|
|
182
|
+
* ended.
|
|
183
|
+
* @throws MacpTimeoutError If {@code timeoutMs} elapses before an envelope
|
|
184
|
+
* arrives.
|
|
185
|
+
* @throws MacpTransportError If the underlying stream errored.
|
|
186
|
+
*/
|
|
187
|
+
async read(timeoutMs) {
|
|
188
|
+
const item = timeoutMs === undefined ? await this.queue.shift() : await this.queue.shiftWithTimeout(timeoutMs);
|
|
189
|
+
if (item === TIMEOUT) {
|
|
190
|
+
throw new errors_1.MacpTimeoutError(`stream read timed out after ${timeoutMs}ms`);
|
|
191
|
+
}
|
|
192
|
+
if (item === STREAM_END) {
|
|
193
|
+
// Re-push so future calls (including responses()) also observe the end.
|
|
194
|
+
this.queue.unshift(STREAM_END);
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
if (item instanceof Error)
|
|
198
|
+
throw item;
|
|
199
|
+
return item;
|
|
200
|
+
}
|
|
122
201
|
close() {
|
|
123
202
|
if (this.closed)
|
|
124
203
|
return;
|
|
@@ -144,7 +223,7 @@ class MacpClient {
|
|
|
144
223
|
}
|
|
145
224
|
this.defaultDeadlineMs = options.defaultDeadlineMs;
|
|
146
225
|
this.clientName = options.clientName ?? 'macp-sdk-typescript';
|
|
147
|
-
this.clientVersion = options.clientVersion ?? '0.
|
|
226
|
+
this.clientVersion = options.clientVersion ?? '0.3.0';
|
|
148
227
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
149
228
|
const { protoDir: defaultProtoDir } = require('@multiagentcoordinationprotocol/proto');
|
|
150
229
|
const protoDir = options.protoDir ?? defaultProtoDir;
|
|
@@ -240,6 +319,13 @@ class MacpClient {
|
|
|
240
319
|
const auth = this.requireAuth(options?.auth);
|
|
241
320
|
return this.unary('GetSession', { sessionId }, auth, options?.deadlineMs);
|
|
242
321
|
}
|
|
322
|
+
/**
|
|
323
|
+
* Terminate a session via the `CancelSession` control-plane RPC.
|
|
324
|
+
*
|
|
325
|
+
* As of proto 0.1.3 the resulting `Ack.sessionState` is
|
|
326
|
+
* `SESSION_STATE_CANCELLED` (previously `SESSION_STATE_EXPIRED`) — distinct
|
|
327
|
+
* from TTL/policy expiry so consumers can tell explicit cancellation apart.
|
|
328
|
+
*/
|
|
243
329
|
async cancelSession(sessionId, reason, options) {
|
|
244
330
|
const auth = this.requireAuth(options?.auth);
|
|
245
331
|
const request = { sessionId, reason };
|
|
@@ -251,6 +337,39 @@ class MacpClient {
|
|
|
251
337
|
throw new errors_1.MacpAckError(ack ?? {});
|
|
252
338
|
return ack;
|
|
253
339
|
}
|
|
340
|
+
/**
|
|
341
|
+
* Pause a session via the `SuspendSession` control-plane RPC (proto 0.1.3+).
|
|
342
|
+
*
|
|
343
|
+
* Suspension is non-terminal: the resulting `Ack.sessionState` is
|
|
344
|
+
* `SESSION_STATE_SUSPENDED`, the session's remaining TTL is banked, and
|
|
345
|
+
* messages sent to a suspended session are rejected until {@link resumeSession}
|
|
346
|
+
* restores it to `SESSION_STATE_OPEN`. Restricted to the initiator and
|
|
347
|
+
* policy-delegated roles, mirroring {@link cancelSession}.
|
|
348
|
+
*/
|
|
349
|
+
async suspendSession(sessionId, reason, options) {
|
|
350
|
+
const auth = this.requireAuth(options?.auth);
|
|
351
|
+
const response = await this.unary('SuspendSession', { sessionId, reason }, auth, options?.deadlineMs);
|
|
352
|
+
const ack = response.ack;
|
|
353
|
+
if (options?.raiseOnNack !== false && !ack?.ok)
|
|
354
|
+
throw new errors_1.MacpAckError(ack ?? {});
|
|
355
|
+
return ack;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Resume a suspended session via the `ResumeSession` control-plane RPC
|
|
359
|
+
* (proto 0.1.3+).
|
|
360
|
+
*
|
|
361
|
+
* Restores `SESSION_STATE_OPEN` and adds the banked TTL back to the session's
|
|
362
|
+
* absolute deadline. Restricted to the initiator and policy-delegated roles,
|
|
363
|
+
* mirroring {@link suspendSession}.
|
|
364
|
+
*/
|
|
365
|
+
async resumeSession(sessionId, reason, options) {
|
|
366
|
+
const auth = this.requireAuth(options?.auth);
|
|
367
|
+
const response = await this.unary('ResumeSession', { sessionId, reason }, auth, options?.deadlineMs);
|
|
368
|
+
const ack = response.ack;
|
|
369
|
+
if (options?.raiseOnNack !== false && !ack?.ok)
|
|
370
|
+
throw new errors_1.MacpAckError(ack ?? {});
|
|
371
|
+
return ack;
|
|
372
|
+
}
|
|
254
373
|
async getManifest(agentId = '', deadlineMs) {
|
|
255
374
|
return this.unary('GetManifest', { agentId }, undefined, deadlineMs);
|
|
256
375
|
}
|
|
@@ -348,12 +467,13 @@ class MacpClient {
|
|
|
348
467
|
(0, validation_1.validateSignalType)(options.signalType, options.data);
|
|
349
468
|
const auth = this.requireAuth(options.auth);
|
|
350
469
|
(0, auth_1.assertSenderMatchesIdentity)(auth, options.sender);
|
|
351
|
-
const
|
|
470
|
+
const signalPayload = (0, envelope_1.buildSignalPayload)({
|
|
352
471
|
signalType: options.signalType,
|
|
353
|
-
data: options.data
|
|
354
|
-
confidence: options.confidence
|
|
355
|
-
correlationSessionId: options.correlationSessionId
|
|
472
|
+
data: options.data,
|
|
473
|
+
confidence: options.confidence,
|
|
474
|
+
correlationSessionId: options.correlationSessionId,
|
|
356
475
|
});
|
|
476
|
+
const payload = this.protoRegistry.encodeKnownPayload('', 'Signal', signalPayload);
|
|
357
477
|
const envelope = (0, envelope_1.buildEnvelope)({
|
|
358
478
|
mode: '',
|
|
359
479
|
messageType: 'Signal',
|
|
@@ -366,13 +486,14 @@ class MacpClient {
|
|
|
366
486
|
async sendProgress(options) {
|
|
367
487
|
const auth = this.requireAuth(options.auth);
|
|
368
488
|
(0, auth_1.assertSenderMatchesIdentity)(auth, options.sender);
|
|
369
|
-
const
|
|
489
|
+
const progressPayload = (0, envelope_1.buildProgressPayload)({
|
|
370
490
|
progressToken: options.progressToken,
|
|
371
491
|
progress: options.progress,
|
|
372
492
|
total: options.total,
|
|
373
|
-
message: options.message
|
|
374
|
-
targetMessageId: options.targetMessageId
|
|
493
|
+
message: options.message,
|
|
494
|
+
targetMessageId: options.targetMessageId,
|
|
375
495
|
});
|
|
496
|
+
const payload = this.protoRegistry.encodeKnownPayload('', 'Progress', progressPayload);
|
|
376
497
|
const envelope = (0, envelope_1.buildEnvelope)({
|
|
377
498
|
mode: options.mode ?? '',
|
|
378
499
|
messageType: 'Progress',
|
package/dist/constants.d.ts
CHANGED
|
@@ -8,19 +8,24 @@ export declare const MODE_TASK = "macp.mode.task.v1";
|
|
|
8
8
|
export declare const MODE_HANDOFF = "macp.mode.handoff.v1";
|
|
9
9
|
export declare const MODE_QUORUM = "macp.mode.quorum.v1";
|
|
10
10
|
export declare const MODE_MULTI_ROUND = "ext.multi_round.v1";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export declare const
|
|
16
|
-
export declare const
|
|
17
|
-
export declare const
|
|
18
|
-
export declare const
|
|
19
|
-
export declare const
|
|
20
|
-
export declare const
|
|
21
|
-
export declare const
|
|
22
|
-
export declare const
|
|
23
|
-
export declare const
|
|
24
|
-
export declare const
|
|
25
|
-
export declare const
|
|
26
|
-
export declare const
|
|
11
|
+
/**
|
|
12
|
+
* The five first-class coordination modes. Parity with
|
|
13
|
+
* python-sdk `macp_sdk.constants.STANDARD_MODES`.
|
|
14
|
+
*/
|
|
15
|
+
export declare const STANDARD_MODES: readonly ["macp.mode.decision.v1", "macp.mode.proposal.v1", "macp.mode.task.v1", "macp.mode.handoff.v1", "macp.mode.quorum.v1"];
|
|
16
|
+
export declare const UNSUPPORTED_PROTOCOL_VERSION = "UNSUPPORTED_PROTOCOL_VERSION";
|
|
17
|
+
export declare const INVALID_ENVELOPE = "INVALID_ENVELOPE";
|
|
18
|
+
export declare const SESSION_ALREADY_EXISTS = "SESSION_ALREADY_EXISTS";
|
|
19
|
+
export declare const SESSION_NOT_FOUND = "SESSION_NOT_FOUND";
|
|
20
|
+
export declare const SESSION_NOT_OPEN = "SESSION_NOT_OPEN";
|
|
21
|
+
export declare const MODE_NOT_SUPPORTED = "MODE_NOT_SUPPORTED";
|
|
22
|
+
export declare const FORBIDDEN = "FORBIDDEN";
|
|
23
|
+
export declare const UNAUTHENTICATED = "UNAUTHENTICATED";
|
|
24
|
+
export declare const DUPLICATE_MESSAGE = "DUPLICATE_MESSAGE";
|
|
25
|
+
export declare const PAYLOAD_TOO_LARGE = "PAYLOAD_TOO_LARGE";
|
|
26
|
+
export declare const RATE_LIMITED = "RATE_LIMITED";
|
|
27
|
+
export declare const INTERNAL_ERROR = "INTERNAL_ERROR";
|
|
28
|
+
export declare const POLICY_DENIED = "POLICY_DENIED";
|
|
29
|
+
export declare const INVALID_SESSION_ID = "INVALID_SESSION_ID";
|
|
30
|
+
export declare const UNKNOWN_POLICY_VERSION = "UNKNOWN_POLICY_VERSION";
|
|
31
|
+
export declare const INVALID_POLICY_DEFINITION = "INVALID_POLICY_DEFINITION";
|
package/dist/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.INVALID_POLICY_DEFINITION = exports.UNKNOWN_POLICY_VERSION = exports.INVALID_SESSION_ID = exports.POLICY_DENIED = exports.INTERNAL_ERROR = exports.RATE_LIMITED = exports.PAYLOAD_TOO_LARGE = exports.DUPLICATE_MESSAGE = exports.UNAUTHENTICATED = exports.FORBIDDEN = exports.MODE_NOT_SUPPORTED = exports.SESSION_NOT_OPEN = exports.SESSION_NOT_FOUND = exports.SESSION_ALREADY_EXISTS = exports.INVALID_ENVELOPE = exports.UNSUPPORTED_PROTOCOL_VERSION = exports.STANDARD_MODES = exports.MODE_MULTI_ROUND = exports.MODE_QUORUM = exports.MODE_HANDOFF = exports.MODE_TASK = exports.MODE_PROPOSAL = exports.MODE_DECISION = exports.DEFAULT_POLICY_VERSION = exports.DEFAULT_CONFIGURATION_VERSION = exports.DEFAULT_MODE_VERSION = exports.MACP_VERSION = void 0;
|
|
4
4
|
exports.MACP_VERSION = '1.0';
|
|
5
5
|
exports.DEFAULT_MODE_VERSION = '1.0.0';
|
|
6
6
|
exports.DEFAULT_CONFIGURATION_VERSION = 'config.default';
|
|
@@ -11,19 +11,26 @@ exports.MODE_TASK = 'macp.mode.task.v1';
|
|
|
11
11
|
exports.MODE_HANDOFF = 'macp.mode.handoff.v1';
|
|
12
12
|
exports.MODE_QUORUM = 'macp.mode.quorum.v1';
|
|
13
13
|
exports.MODE_MULTI_ROUND = 'ext.multi_round.v1';
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
exports.
|
|
19
|
-
|
|
20
|
-
exports
|
|
21
|
-
exports.
|
|
22
|
-
exports.
|
|
23
|
-
exports.
|
|
24
|
-
exports.
|
|
25
|
-
exports.
|
|
26
|
-
exports.
|
|
27
|
-
exports.
|
|
28
|
-
exports.
|
|
29
|
-
exports.
|
|
14
|
+
/**
|
|
15
|
+
* The five first-class coordination modes. Parity with
|
|
16
|
+
* python-sdk `macp_sdk.constants.STANDARD_MODES`.
|
|
17
|
+
*/
|
|
18
|
+
exports.STANDARD_MODES = [exports.MODE_DECISION, exports.MODE_PROPOSAL, exports.MODE_TASK, exports.MODE_HANDOFF, exports.MODE_QUORUM];
|
|
19
|
+
// Well-known error codes. Names match the on-the-wire strings the runtime
|
|
20
|
+
// emits and python-sdk's exports (no ERR_ prefix).
|
|
21
|
+
exports.UNSUPPORTED_PROTOCOL_VERSION = 'UNSUPPORTED_PROTOCOL_VERSION';
|
|
22
|
+
exports.INVALID_ENVELOPE = 'INVALID_ENVELOPE';
|
|
23
|
+
exports.SESSION_ALREADY_EXISTS = 'SESSION_ALREADY_EXISTS';
|
|
24
|
+
exports.SESSION_NOT_FOUND = 'SESSION_NOT_FOUND';
|
|
25
|
+
exports.SESSION_NOT_OPEN = 'SESSION_NOT_OPEN';
|
|
26
|
+
exports.MODE_NOT_SUPPORTED = 'MODE_NOT_SUPPORTED';
|
|
27
|
+
exports.FORBIDDEN = 'FORBIDDEN';
|
|
28
|
+
exports.UNAUTHENTICATED = 'UNAUTHENTICATED';
|
|
29
|
+
exports.DUPLICATE_MESSAGE = 'DUPLICATE_MESSAGE';
|
|
30
|
+
exports.PAYLOAD_TOO_LARGE = 'PAYLOAD_TOO_LARGE';
|
|
31
|
+
exports.RATE_LIMITED = 'RATE_LIMITED';
|
|
32
|
+
exports.INTERNAL_ERROR = 'INTERNAL_ERROR';
|
|
33
|
+
exports.POLICY_DENIED = 'POLICY_DENIED';
|
|
34
|
+
exports.INVALID_SESSION_ID = 'INVALID_SESSION_ID';
|
|
35
|
+
exports.UNKNOWN_POLICY_VERSION = 'UNKNOWN_POLICY_VERSION';
|
|
36
|
+
exports.INVALID_POLICY_DEFINITION = 'INVALID_POLICY_DEFINITION';
|
package/dist/decision.d.ts
CHANGED
|
@@ -61,6 +61,16 @@ export declare class DecisionSession {
|
|
|
61
61
|
metadata: SessionMetadata;
|
|
62
62
|
}>;
|
|
63
63
|
cancel(reason?: string, auth?: AuthConfig): Promise<Ack>;
|
|
64
|
+
/**
|
|
65
|
+
* Pause this session via `SuspendSession` (proto 0.1.3+). Non-terminal: the
|
|
66
|
+
* runtime banks remaining TTL and rejects messages until {@link resume}.
|
|
67
|
+
*/
|
|
68
|
+
suspend(reason?: string, auth?: AuthConfig): Promise<Ack>;
|
|
69
|
+
/**
|
|
70
|
+
* Resume this suspended session via `ResumeSession` (proto 0.1.3+),
|
|
71
|
+
* restoring `SESSION_STATE_OPEN` and the banked TTL.
|
|
72
|
+
*/
|
|
73
|
+
resume(reason?: string, auth?: AuthConfig): Promise<Ack>;
|
|
64
74
|
openStream(auth?: AuthConfig): MacpStream;
|
|
65
75
|
}
|
|
66
76
|
export {};
|
package/dist/decision.js
CHANGED
|
@@ -142,6 +142,26 @@ class DecisionSession {
|
|
|
142
142
|
raiseOnNack: true,
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Pause this session via `SuspendSession` (proto 0.1.3+). Non-terminal: the
|
|
147
|
+
* runtime banks remaining TTL and rejects messages until {@link resume}.
|
|
148
|
+
*/
|
|
149
|
+
async suspend(reason = '', auth) {
|
|
150
|
+
return this.client.suspendSession(this.sessionId, reason, {
|
|
151
|
+
auth: auth ?? this.auth,
|
|
152
|
+
raiseOnNack: true,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Resume this suspended session via `ResumeSession` (proto 0.1.3+),
|
|
157
|
+
* restoring `SESSION_STATE_OPEN` and the banked TTL.
|
|
158
|
+
*/
|
|
159
|
+
async resume(reason = '', auth) {
|
|
160
|
+
return this.client.resumeSession(this.sessionId, reason, {
|
|
161
|
+
auth: auth ?? this.auth,
|
|
162
|
+
raiseOnNack: true,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
145
165
|
openStream(auth) {
|
|
146
166
|
return this.client.openStream({ auth: auth ?? this.auth });
|
|
147
167
|
}
|
package/dist/envelope.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CommitmentPayload, Envelope, Root, SessionStartPayload } from './types';
|
|
1
|
+
import type { CommitmentPayload, CommitmentRef, Envelope, ProgressPayload, Root, SessionStartPayload, SignalPayload } from './types';
|
|
2
2
|
export declare function newSessionId(): string;
|
|
3
3
|
export declare function newMessageId(): string;
|
|
4
4
|
export declare function newCommitmentId(): string;
|
|
@@ -15,6 +15,15 @@ export declare function buildSessionStartPayload(input: {
|
|
|
15
15
|
roots?: Root[];
|
|
16
16
|
}): SessionStartPayload;
|
|
17
17
|
export declare function inferOutcomePositive(action: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Build a {@link CommitmentRef} pointing at a prior accepted commitment, for
|
|
20
|
+
* use as `buildCommitmentPayload({ supersedes })` (cross-session supersession,
|
|
21
|
+
* RFC-MACP-0001 §7.3). Parity with python-sdk `build_commitment_ref`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildCommitmentRef(input: {
|
|
24
|
+
sessionId: string;
|
|
25
|
+
commitmentHash: string;
|
|
26
|
+
}): CommitmentRef;
|
|
18
27
|
export declare function buildCommitmentPayload(input: {
|
|
19
28
|
action: string;
|
|
20
29
|
authorityScope: string;
|
|
@@ -24,8 +33,35 @@ export declare function buildCommitmentPayload(input: {
|
|
|
24
33
|
configurationVersion?: string;
|
|
25
34
|
policyVersion?: string;
|
|
26
35
|
outcomePositive?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Cross-session supersession (RFC-MACP-0001 §7.3): reference to the prior
|
|
38
|
+
* commitment this one supersedes. Distinct from proposal-mode
|
|
39
|
+
* `supersedesProposalId`. Absent by default. Backward-compatible.
|
|
40
|
+
*/
|
|
41
|
+
supersedes?: CommitmentRef;
|
|
27
42
|
}): CommitmentPayload;
|
|
28
43
|
export declare function buildRoot(uri: string, name?: string): Root;
|
|
44
|
+
export declare function buildSignalPayload(input: {
|
|
45
|
+
signalType: string;
|
|
46
|
+
data?: Buffer | Uint8Array;
|
|
47
|
+
confidence?: number;
|
|
48
|
+
correlationSessionId?: string;
|
|
49
|
+
}): SignalPayload;
|
|
50
|
+
export declare function buildProgressPayload(input: {
|
|
51
|
+
progressToken: string;
|
|
52
|
+
progress: number;
|
|
53
|
+
total: number;
|
|
54
|
+
message?: string;
|
|
55
|
+
targetMessageId?: string;
|
|
56
|
+
}): ProgressPayload;
|
|
57
|
+
type ProtoSerializable = {
|
|
58
|
+
serializeBinary(): Uint8Array;
|
|
59
|
+
} | {
|
|
60
|
+
toBinary(): Uint8Array;
|
|
61
|
+
} | {
|
|
62
|
+
finish(): Uint8Array;
|
|
63
|
+
};
|
|
64
|
+
export declare function serializeMessage(message: ProtoSerializable | unknown): Uint8Array;
|
|
29
65
|
/**
|
|
30
66
|
* Type-erasure helper for protobuf payload encoders.
|
|
31
67
|
*
|
|
@@ -48,3 +84,4 @@ export declare function buildEnvelope(input: {
|
|
|
48
84
|
macpVersion?: string;
|
|
49
85
|
timestampUnixMs?: string | number;
|
|
50
86
|
}): Envelope;
|
|
87
|
+
export {};
|
package/dist/envelope.js
CHANGED
|
@@ -6,8 +6,12 @@ exports.newCommitmentId = newCommitmentId;
|
|
|
6
6
|
exports.nowUnixMs = nowUnixMs;
|
|
7
7
|
exports.buildSessionStartPayload = buildSessionStartPayload;
|
|
8
8
|
exports.inferOutcomePositive = inferOutcomePositive;
|
|
9
|
+
exports.buildCommitmentRef = buildCommitmentRef;
|
|
9
10
|
exports.buildCommitmentPayload = buildCommitmentPayload;
|
|
10
11
|
exports.buildRoot = buildRoot;
|
|
12
|
+
exports.buildSignalPayload = buildSignalPayload;
|
|
13
|
+
exports.buildProgressPayload = buildProgressPayload;
|
|
14
|
+
exports.serializeMessage = serializeMessage;
|
|
11
15
|
exports.toProtoPayload = toProtoPayload;
|
|
12
16
|
exports.buildEnvelope = buildEnvelope;
|
|
13
17
|
const node_crypto_1 = require("node:crypto");
|
|
@@ -44,8 +48,16 @@ function inferOutcomePositive(action) {
|
|
|
44
48
|
return false;
|
|
45
49
|
return true;
|
|
46
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Build a {@link CommitmentRef} pointing at a prior accepted commitment, for
|
|
53
|
+
* use as `buildCommitmentPayload({ supersedes })` (cross-session supersession,
|
|
54
|
+
* RFC-MACP-0001 §7.3). Parity with python-sdk `build_commitment_ref`.
|
|
55
|
+
*/
|
|
56
|
+
function buildCommitmentRef(input) {
|
|
57
|
+
return { sessionId: input.sessionId, commitmentHash: input.commitmentHash };
|
|
58
|
+
}
|
|
47
59
|
function buildCommitmentPayload(input) {
|
|
48
|
-
|
|
60
|
+
const payload = {
|
|
49
61
|
commitmentId: input.commitmentId ?? newCommitmentId(),
|
|
50
62
|
action: input.action,
|
|
51
63
|
authorityScope: input.authorityScope,
|
|
@@ -55,10 +67,50 @@ function buildCommitmentPayload(input) {
|
|
|
55
67
|
policyVersion: input.policyVersion ?? constants_1.DEFAULT_POLICY_VERSION,
|
|
56
68
|
outcomePositive: input.outcomePositive ?? inferOutcomePositive(input.action),
|
|
57
69
|
};
|
|
70
|
+
if (input.supersedes)
|
|
71
|
+
payload.supersedes = input.supersedes;
|
|
72
|
+
return payload;
|
|
58
73
|
}
|
|
59
74
|
function buildRoot(uri, name = '') {
|
|
60
75
|
return { uri, name };
|
|
61
76
|
}
|
|
77
|
+
function buildSignalPayload(input) {
|
|
78
|
+
const data = input.data instanceof Buffer ? input.data : input.data ? Buffer.from(input.data) : Buffer.alloc(0);
|
|
79
|
+
return {
|
|
80
|
+
signalType: input.signalType,
|
|
81
|
+
data,
|
|
82
|
+
confidence: input.confidence ?? 0,
|
|
83
|
+
correlationSessionId: input.correlationSessionId ?? '',
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function buildProgressPayload(input) {
|
|
87
|
+
return {
|
|
88
|
+
progressToken: input.progressToken,
|
|
89
|
+
progress: input.progress,
|
|
90
|
+
total: input.total,
|
|
91
|
+
message: input.message ?? '',
|
|
92
|
+
targetMessageId: input.targetMessageId ?? '',
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function serializeMessage(message) {
|
|
96
|
+
// Parity with python-sdk `envelope.serialize_message`: invoke the protobuf
|
|
97
|
+
// serializer exposed on the message. Supports objects with `serializeBinary`
|
|
98
|
+
// (protoc-gen-js), `toBinary` (protobuf-es / ts-proto), or `finish`
|
|
99
|
+
// (protobufjs Writer). For plain JS interface payloads, use
|
|
100
|
+
// `ProtoRegistry.encodeKnownPayload(mode, messageType, payload)` instead —
|
|
101
|
+
// the registry owns the mode/messageType → descriptor mapping.
|
|
102
|
+
const candidate = message;
|
|
103
|
+
if (typeof candidate?.serializeBinary === 'function') {
|
|
104
|
+
return candidate.serializeBinary();
|
|
105
|
+
}
|
|
106
|
+
if (typeof candidate?.toBinary === 'function') {
|
|
107
|
+
return candidate.toBinary();
|
|
108
|
+
}
|
|
109
|
+
if (typeof candidate?.finish === 'function') {
|
|
110
|
+
return candidate.finish();
|
|
111
|
+
}
|
|
112
|
+
throw new TypeError('serializeMessage: object is not a protobuf message — expected serializeBinary(), toBinary(), or finish() method. For plain JS payloads, use ProtoRegistry.encodeKnownPayload().');
|
|
113
|
+
}
|
|
62
114
|
/**
|
|
63
115
|
* Type-erasure helper for protobuf payload encoders.
|
|
64
116
|
*
|
package/dist/errors.d.ts
CHANGED
|
@@ -5,6 +5,18 @@ export declare class MacpSdkError extends Error {
|
|
|
5
5
|
export declare class MacpTransportError extends MacpSdkError {
|
|
6
6
|
constructor(message: string);
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Structured NACK record. Mirrors python-sdk's `AckFailure` dataclass so
|
|
10
|
+
* cross-SDK code can share the same shape when logging or persisting a
|
|
11
|
+
* rejected message.
|
|
12
|
+
*/
|
|
13
|
+
export interface AckFailure {
|
|
14
|
+
code: string;
|
|
15
|
+
message: string;
|
|
16
|
+
sessionId: string;
|
|
17
|
+
messageId: string;
|
|
18
|
+
reasons: string[];
|
|
19
|
+
}
|
|
8
20
|
export declare class MacpAckError extends MacpSdkError {
|
|
9
21
|
readonly ack: Ack;
|
|
10
22
|
/** Optional gRPC trailing metadata for extracting additional error details. */
|
|
@@ -12,14 +24,15 @@ export declare class MacpAckError extends MacpSdkError {
|
|
|
12
24
|
key: string;
|
|
13
25
|
value: string | Buffer;
|
|
14
26
|
}>;
|
|
27
|
+
/** Structured NACK record — parity with python-sdk `MacpAckError.failure`. */
|
|
28
|
+
readonly failure: AckFailure;
|
|
15
29
|
constructor(ack: Ack, grpcMetadata?: Array<{
|
|
16
30
|
key: string;
|
|
17
31
|
value: string | Buffer;
|
|
18
32
|
}>);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
private
|
|
22
|
-
private _parseGrpcMetadataReasons;
|
|
33
|
+
private static _extractReasons;
|
|
34
|
+
private static _parseAckReasons;
|
|
35
|
+
private static _parseGrpcMetadataReasons;
|
|
23
36
|
}
|
|
24
37
|
export declare class MacpSessionError extends MacpSdkError {
|
|
25
38
|
constructor(message: string);
|
package/dist/errors.js
CHANGED
|
@@ -19,26 +19,35 @@ class MacpAckError extends MacpSdkError {
|
|
|
19
19
|
ack;
|
|
20
20
|
/** Optional gRPC trailing metadata for extracting additional error details. */
|
|
21
21
|
grpcMetadata;
|
|
22
|
+
/** Structured NACK record — parity with python-sdk `MacpAckError.failure`. */
|
|
23
|
+
failure;
|
|
22
24
|
constructor(ack, grpcMetadata) {
|
|
23
25
|
super(`${ack.error?.code ?? 'UNKNOWN'}: ${ack.error?.message ?? 'runtime returned nack'}`);
|
|
24
26
|
this.name = 'MacpAckError';
|
|
25
27
|
this.ack = ack;
|
|
26
28
|
this.grpcMetadata = grpcMetadata;
|
|
29
|
+
const reasons = MacpAckError._extractReasons(ack, grpcMetadata);
|
|
30
|
+
this.failure = {
|
|
31
|
+
code: ack.error?.code ?? 'UNKNOWN',
|
|
32
|
+
message: ack.error?.message ?? 'runtime returned nack',
|
|
33
|
+
sessionId: ack.sessionId ?? ack.error?.sessionId ?? '',
|
|
34
|
+
messageId: ack.messageId ?? ack.error?.messageId ?? '',
|
|
35
|
+
reasons,
|
|
36
|
+
};
|
|
27
37
|
}
|
|
28
|
-
|
|
29
|
-
get reasons() {
|
|
38
|
+
static _extractReasons(ack, grpcMetadata) {
|
|
30
39
|
// First try: parse from ack.error.details (matches Python _parse_ack_reasons)
|
|
31
|
-
const fromDetails =
|
|
40
|
+
const fromDetails = MacpAckError._parseAckReasons(ack);
|
|
32
41
|
if (fromDetails.length > 0)
|
|
33
42
|
return fromDetails;
|
|
34
43
|
// Second try: parse from gRPC trailing metadata (matches Python _parse_grpc_metadata_reasons)
|
|
35
|
-
return
|
|
44
|
+
return MacpAckError._parseGrpcMetadataReasons(grpcMetadata);
|
|
36
45
|
}
|
|
37
|
-
_parseAckReasons() {
|
|
38
|
-
if (!
|
|
46
|
+
static _parseAckReasons(ack) {
|
|
47
|
+
if (!ack.error?.details)
|
|
39
48
|
return [];
|
|
40
49
|
try {
|
|
41
|
-
const details =
|
|
50
|
+
const details = ack.error.details;
|
|
42
51
|
const raw = Buffer.isBuffer(details) ? details.toString('utf-8') : String(details);
|
|
43
52
|
const parsed = JSON.parse(raw);
|
|
44
53
|
const reasons = parsed.reasons;
|
|
@@ -48,11 +57,11 @@ class MacpAckError extends MacpSdkError {
|
|
|
48
57
|
return [];
|
|
49
58
|
}
|
|
50
59
|
}
|
|
51
|
-
_parseGrpcMetadataReasons() {
|
|
52
|
-
if (!
|
|
60
|
+
static _parseGrpcMetadataReasons(grpcMetadata) {
|
|
61
|
+
if (!grpcMetadata)
|
|
53
62
|
return [];
|
|
54
63
|
try {
|
|
55
|
-
for (const item of
|
|
64
|
+
for (const item of grpcMetadata) {
|
|
56
65
|
if (item.key === 'macp-error-details-bin') {
|
|
57
66
|
const data = Buffer.isBuffer(item.value)
|
|
58
67
|
? item.value.toString('utf-8')
|
package/dist/handoff.d.ts
CHANGED
|
@@ -40,14 +40,6 @@ export declare class HandoffSession {
|
|
|
40
40
|
sender?: string;
|
|
41
41
|
auth?: AuthConfig;
|
|
42
42
|
}): Promise<Ack>;
|
|
43
|
-
/**
|
|
44
|
-
* @deprecated Use {@link addContext} instead. Scheduled for removal in 0.4.0.
|
|
45
|
-
* First call logs a one-shot warning to guide migrations without spamming long-lived processes.
|
|
46
|
-
*/
|
|
47
|
-
sendContext(input: HandoffContextPayload & {
|
|
48
|
-
sender?: string;
|
|
49
|
-
auth?: AuthConfig;
|
|
50
|
-
}): Promise<Ack>;
|
|
51
43
|
acceptHandoff(input: HandoffAcceptPayload & {
|
|
52
44
|
sender?: string;
|
|
53
45
|
auth?: AuthConfig;
|
|
@@ -69,6 +61,16 @@ export declare class HandoffSession {
|
|
|
69
61
|
metadata: SessionMetadata;
|
|
70
62
|
}>;
|
|
71
63
|
cancel(reason?: string, auth?: AuthConfig): Promise<Ack>;
|
|
64
|
+
/**
|
|
65
|
+
* Pause this session via `SuspendSession` (proto 0.1.3+). Non-terminal: the
|
|
66
|
+
* runtime banks remaining TTL and rejects messages until {@link resume}.
|
|
67
|
+
*/
|
|
68
|
+
suspend(reason?: string, auth?: AuthConfig): Promise<Ack>;
|
|
69
|
+
/**
|
|
70
|
+
* Resume this suspended session via `ResumeSession` (proto 0.1.3+),
|
|
71
|
+
* restoring `SESSION_STATE_OPEN` and the banked TTL.
|
|
72
|
+
*/
|
|
73
|
+
resume(reason?: string, auth?: AuthConfig): Promise<Ack>;
|
|
72
74
|
openStream(auth?: AuthConfig): MacpStream;
|
|
73
75
|
}
|
|
74
76
|
export {};
|