macp-sdk-typescript 0.10.0 → 0.11.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 +94 -0
- package/README.md +1 -1
- package/dist/policy.d.ts +54 -7
- package/dist/policy.js +143 -19
- package/dist/projections/base.js +24 -5
- package/dist/projections/decision.d.ts +5 -49
- package/dist/projections/decision.js +7 -82
- package/dist/projections/handoff.d.ts +5 -48
- package/dist/projections/handoff.js +5 -77
- package/dist/projections/proposal.d.ts +5 -48
- package/dist/projections/proposal.js +5 -77
- package/dist/projections/quorum.d.ts +5 -49
- package/dist/projections/quorum.js +7 -82
- package/dist/projections/task.d.ts +5 -48
- package/dist/projections/task.js +5 -77
- package/dist/proto-registry.d.ts +19 -5
- package/dist/proto-registry.js +24 -16
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -4
package/dist/projections/task.js
CHANGED
|
@@ -2,35 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TaskProjection = void 0;
|
|
4
4
|
const constants_1 = require("../constants");
|
|
5
|
-
const
|
|
6
|
-
class TaskProjection {
|
|
5
|
+
const base_1 = require("./base");
|
|
6
|
+
class TaskProjection extends base_1.BaseProjection {
|
|
7
|
+
mode = constants_1.MODE_TASK;
|
|
7
8
|
tasks = new Map();
|
|
8
9
|
updates = [];
|
|
9
10
|
completions = [];
|
|
10
11
|
failures = [];
|
|
11
|
-
/**
|
|
12
|
-
* The session's accepted history, one envelope per unique `message_id`. See
|
|
13
|
-
* `BaseProjection.transcript` (`src/projections/base.ts`) for the full
|
|
14
|
-
* redelivery-idempotence contract (RFC-MACP-0006 §3.2); duplicated here
|
|
15
|
-
* only as a one-line pointer.
|
|
16
|
-
*/
|
|
17
|
-
transcript = [];
|
|
18
|
-
/**
|
|
19
|
-
* Cardinality anomalies recorded while replaying this projection's accepted
|
|
20
|
-
* transcript. See `BaseProjection.anomalies` (`src/projections/base.ts`)
|
|
21
|
-
* for the canonical description; duplicated here only as a one-line
|
|
22
|
-
* pointer. No built-in detection populates this for Task mode.
|
|
23
|
-
*/
|
|
24
|
-
anomalies = [];
|
|
25
12
|
phase = 'Pending';
|
|
26
|
-
commitment;
|
|
27
|
-
/**
|
|
28
|
-
* `message_id`s already applied to this projection. See
|
|
29
|
-
* `BaseProjection.seenMessageIds` (`src/projections/base.ts`) for the full
|
|
30
|
-
* redelivery-idempotence rationale (RFC-MACP-0006 §3.2); duplicated here
|
|
31
|
-
* only as a one-line pointer.
|
|
32
|
-
*/
|
|
33
|
-
seenMessageIds = new Set();
|
|
34
13
|
/**
|
|
35
14
|
* The **session-level** active assignment: who currently holds the session's
|
|
36
15
|
* single assignee slot, and which `task_id` they took it on.
|
|
@@ -51,36 +30,8 @@ class TaskProjection {
|
|
|
51
30
|
* the right `TaskRecord.assignee` even on a multi-task transcript.
|
|
52
31
|
*/
|
|
53
32
|
activeAssignment;
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
*
|
|
57
|
-
* Input contract: **accepted-only**, caller-maintained (`Envelope` carries
|
|
58
|
-
* no acceptance marker). Canonical source: `schemas/conformance/README.md`
|
|
59
|
-
* "Notes:", RFC-MACP-0007 §5.3, RFC-MACP-0011 §5. Full rationale and failure
|
|
60
|
-
* mode are documented once, on `BaseProjection.applyEnvelope`
|
|
61
|
-
* (`src/projections/base.ts`), and duplicated here only as a one-line
|
|
62
|
-
* pointer so six independent copies of the same prose cannot drift.
|
|
63
|
-
*
|
|
64
|
-
* Redelivery idempotence: a redelivered envelope (same `message_id`) is a
|
|
65
|
-
* non-event — not appended to `transcript`, not passed to the `switch`.
|
|
66
|
-
* See `BaseProjection.applyEnvelope` for the full RFC-MACP-0006 §3.2
|
|
67
|
-
* citation; duplicated here only as a one-line pointer.
|
|
68
|
-
*/
|
|
69
|
-
applyEnvelope(envelope, protoRegistry) {
|
|
70
|
-
if (envelope.mode !== constants_1.MODE_TASK)
|
|
71
|
-
return;
|
|
72
|
-
if (envelope.messageId) {
|
|
73
|
-
if (this.seenMessageIds.has(envelope.messageId)) {
|
|
74
|
-
logging_1.logger.debug('projection redelivery ignored', {
|
|
75
|
-
messageId: envelope.messageId,
|
|
76
|
-
mode: envelope.mode,
|
|
77
|
-
messageType: envelope.messageType,
|
|
78
|
-
});
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
this.seenMessageIds.add(envelope.messageId);
|
|
82
|
-
}
|
|
83
|
-
this.transcript.push(envelope);
|
|
33
|
+
/** Handle a Task-mode envelope. See `BaseProjection.applyEnvelope` for the accepted-only input contract and redelivery/rollback semantics shared by all built-in modes. */
|
|
34
|
+
applyMode(envelope, protoRegistry) {
|
|
84
35
|
const payload = protoRegistry.decodeKnownPayload(envelope.mode, envelope.messageType, envelope.payload);
|
|
85
36
|
switch (envelope.messageType) {
|
|
86
37
|
case 'TaskRequest': {
|
|
@@ -199,33 +150,10 @@ class TaskProjection {
|
|
|
199
150
|
this.phase = 'Failed';
|
|
200
151
|
break;
|
|
201
152
|
}
|
|
202
|
-
case 'Commitment': {
|
|
203
|
-
this.commitment = payload;
|
|
204
|
-
this.phase = 'Committed';
|
|
205
|
-
break;
|
|
206
|
-
}
|
|
207
153
|
default:
|
|
208
154
|
break;
|
|
209
155
|
}
|
|
210
156
|
}
|
|
211
|
-
/**
|
|
212
|
-
* True once at least one `ProjectionAnomaly` has been recorded. See
|
|
213
|
-
* `BaseProjection.hasAnomalies` (`src/projections/base.ts`) for the
|
|
214
|
-
* canonical description; duplicated here only as a one-line pointer.
|
|
215
|
-
*/
|
|
216
|
-
get hasAnomalies() {
|
|
217
|
-
return this.anomalies.length > 0;
|
|
218
|
-
}
|
|
219
|
-
get isCommitted() {
|
|
220
|
-
return this.commitment !== undefined;
|
|
221
|
-
}
|
|
222
|
-
get isPositiveOutcome() {
|
|
223
|
-
if (!this.commitment)
|
|
224
|
-
return undefined;
|
|
225
|
-
const val = this.commitment.outcomePositive ??
|
|
226
|
-
this.commitment.outcome_positive;
|
|
227
|
-
return val !== undefined ? Boolean(val) : true;
|
|
228
|
-
}
|
|
229
157
|
getTask(taskId) {
|
|
230
158
|
return this.tasks.get(taskId);
|
|
231
159
|
}
|
package/dist/proto-registry.d.ts
CHANGED
|
@@ -10,11 +10,25 @@ export declare class ProtoRegistry {
|
|
|
10
10
|
/**
|
|
11
11
|
* Decode an `ext.multi_round.v1` `Contribute` payload, accepting both wire
|
|
12
12
|
* formats: legacy JSON (`{"value":"..."}`, still replayed verbatim from
|
|
13
|
-
* pre-proto histories) and canonical protobuf (`ContributePayload`).
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* pre-proto histories) and canonical protobuf (`ContributePayload`). Both
|
|
14
|
+
* normalize to `{ value: string }`.
|
|
15
|
+
*
|
|
16
|
+
* Parse-then-fallback (issue #93), not a first-byte shortcut: JSON is always
|
|
17
|
+
* attempted first, and only a `JSON.parse` failure falls through to
|
|
18
|
+
* protobuf. A first-byte check (`{` = 0x7b vs proto field-1 tag 0x0A) does
|
|
19
|
+
* not generalize — e.g. legacy JSON with leading whitespace has neither byte
|
|
20
|
+
* first, and used to reach `decodeMessage` and throw. Parity with
|
|
21
|
+
* `macp-sdk-python`'s `_decode_json_first_then_proto`, which has always
|
|
22
|
+
* worked this way. Safe because a canonical proto payload's bytes are
|
|
23
|
+
* essentially never also syntactically valid JSON.
|
|
24
|
+
*
|
|
25
|
+
* An empty payload falls through the same path: `JSON.parse('')` throws, so
|
|
26
|
+
* it reaches `decodeMessage` on zero bytes, which yields `{}` (proto3
|
|
27
|
+
* defaults) rather than a decode error. This SDK's decode layer is
|
|
28
|
+
* observational, not an acceptance gate — whether an empty `Contribute`
|
|
29
|
+
* should be rejected is a runtime-acceptance question (tracked cross-repo,
|
|
30
|
+
* `contribute_acceptance.empty_payload` in `schemas/parity/contract.json`,
|
|
31
|
+
* currently `macp-runtime`-only), not something this method decides.
|
|
18
32
|
*/
|
|
19
33
|
private decodeMultiRoundContribute;
|
|
20
34
|
private lookupType;
|
package/dist/proto-registry.js
CHANGED
|
@@ -169,26 +169,34 @@ class ProtoRegistry {
|
|
|
169
169
|
/**
|
|
170
170
|
* Decode an `ext.multi_round.v1` `Contribute` payload, accepting both wire
|
|
171
171
|
* formats: legacy JSON (`{"value":"..."}`, still replayed verbatim from
|
|
172
|
-
* pre-proto histories) and canonical protobuf (`ContributePayload`).
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
172
|
+
* pre-proto histories) and canonical protobuf (`ContributePayload`). Both
|
|
173
|
+
* normalize to `{ value: string }`.
|
|
174
|
+
*
|
|
175
|
+
* Parse-then-fallback (issue #93), not a first-byte shortcut: JSON is always
|
|
176
|
+
* attempted first, and only a `JSON.parse` failure falls through to
|
|
177
|
+
* protobuf. A first-byte check (`{` = 0x7b vs proto field-1 tag 0x0A) does
|
|
178
|
+
* not generalize — e.g. legacy JSON with leading whitespace has neither byte
|
|
179
|
+
* first, and used to reach `decodeMessage` and throw. Parity with
|
|
180
|
+
* `macp-sdk-python`'s `_decode_json_first_then_proto`, which has always
|
|
181
|
+
* worked this way. Safe because a canonical proto payload's bytes are
|
|
182
|
+
* essentially never also syntactically valid JSON.
|
|
183
|
+
*
|
|
184
|
+
* An empty payload falls through the same path: `JSON.parse('')` throws, so
|
|
185
|
+
* it reaches `decodeMessage` on zero bytes, which yields `{}` (proto3
|
|
186
|
+
* defaults) rather than a decode error. This SDK's decode layer is
|
|
187
|
+
* observational, not an acceptance gate — whether an empty `Contribute`
|
|
188
|
+
* should be rejected is a runtime-acceptance question (tracked cross-repo,
|
|
189
|
+
* `contribute_acceptance.empty_payload` in `schemas/parity/contract.json`,
|
|
190
|
+
* currently `macp-runtime`-only), not something this method decides.
|
|
177
191
|
*/
|
|
178
192
|
decodeMultiRoundContribute(payload) {
|
|
179
|
-
|
|
193
|
+
try {
|
|
194
|
+
const parsed = JSON.parse(payload.toString('utf8'));
|
|
195
|
+
return { value: typeof parsed.value === 'string' ? parsed.value : String(parsed.value ?? '') };
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
180
198
|
return this.decodeMessage(MULTI_ROUND_CONTRIBUTE, payload);
|
|
181
|
-
if (payload[0] === 0x7b) {
|
|
182
|
-
// Leading `{` — legacy JSON. Parse and normalize to { value }.
|
|
183
|
-
try {
|
|
184
|
-
const parsed = JSON.parse(payload.toString('utf8'));
|
|
185
|
-
return { value: typeof parsed.value === 'string' ? parsed.value : String(parsed.value ?? '') };
|
|
186
|
-
}
|
|
187
|
-
catch {
|
|
188
|
-
// Not valid JSON despite the leading brace — fall through to protobuf.
|
|
189
|
-
}
|
|
190
199
|
}
|
|
191
|
-
return this.decodeMessage(MULTI_ROUND_CONTRIBUTE, payload);
|
|
192
200
|
}
|
|
193
201
|
lookupType(typeName) {
|
|
194
202
|
const lookedUp = this.root.lookupType(typeName);
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "macp-sdk-typescript",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "TypeScript SDK for the MACP Rust runtime",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -55,18 +55,18 @@
|
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@grpc/grpc-js": "^1.14.3",
|
|
57
57
|
"@grpc/proto-loader": "^0.8.0",
|
|
58
|
-
"@multiagentcoordinationprotocol/proto": "^0.1.
|
|
58
|
+
"@multiagentcoordinationprotocol/proto": "^0.1.10",
|
|
59
59
|
"protobufjs": "^8.6.5"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/node": "^26.4.0",
|
|
63
63
|
"@typescript-eslint/eslint-plugin": "^8.68.0",
|
|
64
64
|
"@typescript-eslint/parser": "^8.68.0",
|
|
65
|
-
"@vitest/coverage-v8": "^
|
|
65
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
66
66
|
"eslint": "^10.9.1",
|
|
67
67
|
"prettier": "^3.0.0",
|
|
68
68
|
"tsx": "^4.21.0",
|
|
69
69
|
"typescript": "^6.0.3",
|
|
70
|
-
"vitest": "^
|
|
70
|
+
"vitest": "^5.0.0"
|
|
71
71
|
}
|
|
72
72
|
}
|