@moltzap/client 2026.505.2 → 2026.507.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/dist/cli/commands/contacts.d.ts.map +1 -1
- package/dist/cli/commands/contacts.js +3 -3
- package/dist/cli/commands/contacts.js.map +1 -1
- package/dist/cli/commands/conversations.d.ts.map +1 -1
- package/dist/cli/commands/conversations.js +11 -11
- package/dist/cli/commands/conversations.js.map +1 -1
- package/dist/cli/commands/messages.d.ts.map +1 -1
- package/dist/cli/commands/messages.js +3 -3
- package/dist/cli/commands/messages.js.map +1 -1
- package/dist/cli/commands/send.d.ts.map +1 -1
- package/dist/cli/commands/send.js +3 -3
- package/dist/cli/commands/send.js.map +1 -1
- package/dist/cli/commands/test-transport.d.ts.map +1 -1
- package/dist/cli/commands/test-transport.js +11 -8
- package/dist/cli/commands/test-transport.js.map +1 -1
- package/dist/cli/http-client.d.ts +2 -2
- package/dist/cli/http-client.d.ts.map +1 -1
- package/dist/cli/socket-client.d.ts +4 -3
- package/dist/cli/socket-client.d.ts.map +1 -1
- package/dist/cli/socket-client.js +6 -4
- package/dist/cli/socket-client.js.map +1 -1
- package/dist/cli/transport.d.ts +3 -3
- package/dist/cli/transport.d.ts.map +1 -1
- package/dist/cli/transport.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/__tests__/app-callback-partition-key.test.js +7 -20
- package/dist/internal/__tests__/app-callback-partition-key.test.js.map +1 -1
- package/dist/internal/__tests__/app-callback-partition-worker.test.js +3 -3
- package/dist/internal/__tests__/app-callback-partition-worker.test.js.map +1 -1
- package/dist/internal/__tests__/app-callback-partitioned-dispatcher.test.js +84 -394
- package/dist/internal/__tests__/app-callback-partitioned-dispatcher.test.js.map +1 -1
- package/dist/internal/__tests__/app-callback-test-requests.d.ts +12 -37
- package/dist/internal/__tests__/app-callback-test-requests.d.ts.map +1 -1
- package/dist/internal/__tests__/app-callback-test-requests.js +17 -73
- package/dist/internal/__tests__/app-callback-test-requests.js.map +1 -1
- package/dist/internal/app-callback-dispatcher-errors.d.ts +3 -3
- package/dist/internal/app-callback-dispatcher-errors.d.ts.map +1 -1
- package/dist/internal/app-callback-partition-key.d.ts +5 -15
- package/dist/internal/app-callback-partition-key.d.ts.map +1 -1
- package/dist/internal/app-callback-partition-key.js +1 -11
- package/dist/internal/app-callback-partition-key.js.map +1 -1
- package/dist/runtime/errors.d.ts +2 -12
- package/dist/runtime/errors.d.ts.map +1 -1
- package/dist/runtime/errors.js +4 -3
- package/dist/runtime/errors.js.map +1 -1
- package/dist/runtime/frame.d.ts +15 -17
- package/dist/runtime/frame.d.ts.map +1 -1
- package/dist/runtime/frame.js +25 -71
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/frame.test.js +28 -34
- package/dist/runtime/frame.test.js.map +1 -1
- package/dist/runtime/subscribers.d.ts +8 -11
- package/dist/runtime/subscribers.d.ts.map +1 -1
- package/dist/runtime/subscribers.js.map +1 -1
- package/dist/runtime/subscribers.test.js +8 -14
- package/dist/runtime/subscribers.test.js.map +1 -1
- package/dist/service.d.ts +5 -8
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +44 -65
- package/dist/service.js.map +1 -1
- package/dist/service.test.js +9 -9
- package/dist/service.test.js.map +1 -1
- package/dist/test/index.d.ts +1 -1
- package/dist/test/index.js +1 -1
- package/dist/test-utils/conformance-adapter.d.ts +5 -5
- package/dist/test-utils/conformance-adapter.d.ts.map +1 -1
- package/dist/test-utils/conformance-adapter.js +26 -29
- package/dist/test-utils/conformance-adapter.js.map +1 -1
- package/dist/test-utils/fake-service.d.ts +4 -4
- package/dist/test-utils/fake-service.d.ts.map +1 -1
- package/dist/test-utils/fake-service.js +19 -10
- package/dist/test-utils/fake-service.js.map +1 -1
- package/dist/test-utils/ids.d.ts +2 -6
- package/dist/test-utils/ids.d.ts.map +1 -1
- package/dist/test-utils/ids.js +1 -2
- package/dist/test-utils/ids.js.map +1 -1
- package/dist/ws-client.d.ts +17 -93
- package/dist/ws-client.d.ts.map +1 -1
- package/dist/ws-client.js +67 -161
- package/dist/ws-client.js.map +1 -1
- package/dist/ws-client.test.js +43 -56
- package/dist/ws-client.test.js.map +1 -1
- package/package.json +3 -4
- package/dist/internal/__tests__/app-callback-partitioned-dispatcher-real-ws.test.d.ts +0 -2
- package/dist/internal/__tests__/app-callback-partitioned-dispatcher-real-ws.test.d.ts.map +0 -1
- package/dist/internal/__tests__/app-callback-partitioned-dispatcher-real-ws.test.js +0 -230
- package/dist/internal/__tests__/app-callback-partitioned-dispatcher-real-ws.test.js.map +0 -1
- package/dist/runtime/index.d.ts +0 -3
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js +0 -3
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/notification-types.types-check.d.ts +0 -2
- package/dist/runtime/notification-types.types-check.d.ts.map +0 -1
- package/dist/runtime/notification-types.types-check.js +0 -57
- package/dist/runtime/notification-types.types-check.js.map +0 -1
- package/dist/service.typed-bridge.test.d.ts +0 -2
- package/dist/service.typed-bridge.test.d.ts.map +0 -1
- package/dist/service.typed-bridge.test.js +0 -93
- package/dist/service.typed-bridge.test.js.map +0 -1
- package/dist/ws-client.typed-bridge.test.d.ts +0 -2
- package/dist/ws-client.typed-bridge.test.d.ts.map +0 -1
- package/dist/ws-client.typed-bridge.test.js +0 -105
- package/dist/ws-client.typed-bridge.test.js.map +0 -1
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Integration: `MoltZapWsClient` end-to-end deadlock reproducer.
|
|
3
|
-
*
|
|
4
|
-
* Spec: moltzap#356 §8 (test plan, file 5 — moved from app-sdk to
|
|
5
|
-
* packages/client because the dispatcher behaviour under test is at
|
|
6
|
-
* the @moltzap/client layer, and packages/client already has the
|
|
7
|
-
* in-process WS server helper pattern needed for full-transport
|
|
8
|
-
* tests; see PR body "Deviations" for the rationale).
|
|
9
|
-
*
|
|
10
|
-
* Boots an in-process `@effect/platform-node` WebSocket server,
|
|
11
|
-
* connects a real `MoltZapWsClient`, registers two competing appCallback
|
|
12
|
-
* handlers (`before_dispatch` parks on a Deferred;
|
|
13
|
-
* `before_message_delivery` resolves it), and asserts both replies
|
|
14
|
-
* round-trip back to the server. Pre-#356 this hangs; post-#356 it
|
|
15
|
-
* completes via the partitioned dispatcher's
|
|
16
|
-
* `(taskId, conversationId, hookKind)` keying.
|
|
17
|
-
*
|
|
18
|
-
* No mocks — full transport, full schema validation, real fibers.
|
|
19
|
-
*/
|
|
20
|
-
import * as NodeSocketServer from "@effect/platform-node/NodeSocketServer";
|
|
21
|
-
import { Deferred, Effect, Scope } from "effect";
|
|
22
|
-
import { describe, expect, it } from "vitest";
|
|
23
|
-
import { MoltZapWsClient } from "../../ws-client.js";
|
|
24
|
-
import { AppsOnBeforeDispatch, AppsOnBeforeMessageDelivery, Connect, PROTOCOL_VERSION, jsonRpcStringId, requestFrame, responseFrame, validators, } from "@moltzap/protocol";
|
|
25
|
-
import { beforeDispatchParams, beforeMessageDeliveryParams, CONV_X, SESSION_A, SESSION_B, } from "./app-callback-test-requests.js";
|
|
26
|
-
const TEST_AGENT_ID = "11111111-1111-4111-8111-111111111111";
|
|
27
|
-
const TEST_POLICY = {
|
|
28
|
-
maxMessageBytes: 1_000_000,
|
|
29
|
-
maxPartsPerMessage: 10,
|
|
30
|
-
maxTextLength: 32_768,
|
|
31
|
-
maxGroupParticipants: 100,
|
|
32
|
-
heartbeatIntervalMs: 30_000,
|
|
33
|
-
rateLimits: {
|
|
34
|
-
messagesPerMinute: 60,
|
|
35
|
-
requestsPerMinute: 120,
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
const helloOk = () => ({
|
|
39
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
40
|
-
agentId: TEST_AGENT_ID,
|
|
41
|
-
conversations: [],
|
|
42
|
-
unreadCounts: {},
|
|
43
|
-
policy: TEST_POLICY,
|
|
44
|
-
});
|
|
45
|
-
/**
|
|
46
|
-
* Spin up an in-process WS server on 127.0.0.1:0. Caller owns the
|
|
47
|
-
* provided scope; when it closes the server shuts down.
|
|
48
|
-
*/
|
|
49
|
-
function startWsServer(handler) {
|
|
50
|
-
return Effect.gen(function* () {
|
|
51
|
-
const server = yield* NodeSocketServer.makeWebSocket({
|
|
52
|
-
port: 0,
|
|
53
|
-
host: "127.0.0.1",
|
|
54
|
-
});
|
|
55
|
-
const addr = server.address;
|
|
56
|
-
if (addr._tag !== "TcpAddress") {
|
|
57
|
-
return yield* Effect.die("expected TcpAddress");
|
|
58
|
-
}
|
|
59
|
-
const conns = [];
|
|
60
|
-
yield* Effect.forkScoped(server
|
|
61
|
-
.run((sock) => Effect.gen(function* () {
|
|
62
|
-
const write = yield* sock.writer;
|
|
63
|
-
const received = [];
|
|
64
|
-
const conn = {
|
|
65
|
-
send: (raw) => write(raw).pipe(Effect.ignore),
|
|
66
|
-
get received() {
|
|
67
|
-
return received;
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
conns.push(conn);
|
|
71
|
-
yield* sock.runRaw((data) => Effect.gen(function* () {
|
|
72
|
-
const raw = typeof data === "string"
|
|
73
|
-
? data
|
|
74
|
-
: new TextDecoder("utf-8").decode(data);
|
|
75
|
-
received.push(raw);
|
|
76
|
-
yield* handler(conn, raw);
|
|
77
|
-
}));
|
|
78
|
-
}))
|
|
79
|
-
.pipe(Effect.ignore));
|
|
80
|
-
return { url: `http://${addr.hostname}:${addr.port}`, conns };
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
/** Connect a client, complete auth handshake. */
|
|
84
|
-
async function connect(client) {
|
|
85
|
-
return Effect.runPromise(client.connect());
|
|
86
|
-
}
|
|
87
|
-
async function close(client) {
|
|
88
|
-
await Effect.runPromise(client.close());
|
|
89
|
-
}
|
|
90
|
-
function responseIds(rawFrames) {
|
|
91
|
-
return rawFrames.flatMap((raw) => {
|
|
92
|
-
try {
|
|
93
|
-
const parsed = JSON.parse(raw);
|
|
94
|
-
return validators.responseFrame(parsed) && typeof parsed.id === "string"
|
|
95
|
-
? [parsed.id]
|
|
96
|
-
: [];
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
return [];
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
describe("integration: AppHost + partitioned appCallback dispatcher", () => {
|
|
104
|
-
it("two competing handlers (before_dispatch + before_message_delivery) for the " +
|
|
105
|
-
"same conversation: parked before_dispatch resumes after sibling " +
|
|
106
|
-
"before_message_delivery completes — both replies ship to the server", async () => {
|
|
107
|
-
// Pre-#356 (single-fiber dispatcher) this test would hang
|
|
108
|
-
// forever — vitest's testTimeout is the only thing that
|
|
109
|
-
// catches it. Post-#356 (partitioned by hookKind) the two
|
|
110
|
-
// handlers run on independent fibers, the parking deferred
|
|
111
|
-
// fires from the sibling, and both replies ship.
|
|
112
|
-
const result = await Effect.runPromise(Effect.scoped(Effect.gen(function* () {
|
|
113
|
-
const server = yield* startWsServer((conn, raw) => Effect.gen(function* () {
|
|
114
|
-
const parsed = JSON.parse(raw);
|
|
115
|
-
if (!validators.requestFrame(parsed)) {
|
|
116
|
-
return yield* Effect.die("expected JSON-RPC request frame");
|
|
117
|
-
}
|
|
118
|
-
const frame = parsed;
|
|
119
|
-
if (frame.method === Connect.name) {
|
|
120
|
-
yield* conn.send(JSON.stringify(responseFrame(frame.id, {
|
|
121
|
-
result: helloOk(),
|
|
122
|
-
})));
|
|
123
|
-
// Fire BOTH appCallback requests for the SAME (S, C). With
|
|
124
|
-
// pre-#356 dispatching they queue on one fiber and
|
|
125
|
-
// deadlock; with #356 they run concurrently.
|
|
126
|
-
yield* conn.send(JSON.stringify(requestFrame(jsonRpcStringId("rpc-bd-1"), AppsOnBeforeDispatch, beforeDispatchParams(SESSION_A, CONV_X))));
|
|
127
|
-
yield* conn.send(JSON.stringify(requestFrame(jsonRpcStringId("rpc-bmd-1"), AppsOnBeforeMessageDelivery, beforeMessageDeliveryParams(SESSION_A, CONV_X))));
|
|
128
|
-
}
|
|
129
|
-
}));
|
|
130
|
-
const client = new MoltZapWsClient({
|
|
131
|
-
serverUrl: server.url,
|
|
132
|
-
agentKey: "k",
|
|
133
|
-
logger: {
|
|
134
|
-
info: () => { },
|
|
135
|
-
warn: () => { },
|
|
136
|
-
error: () => { },
|
|
137
|
-
},
|
|
138
|
-
});
|
|
139
|
-
// Park the dispatch handler. The delivery handler resolves
|
|
140
|
-
// the parking Deferred — pre-#356 this would never run
|
|
141
|
-
// because both queue on a single dispatch fiber.
|
|
142
|
-
const release = yield* Deferred.make();
|
|
143
|
-
yield* client.handleServerRpc(AppsOnBeforeDispatch, () => Effect.gen(function* () {
|
|
144
|
-
yield* Deferred.await(release);
|
|
145
|
-
return { admission: { decision: "grant" } };
|
|
146
|
-
}));
|
|
147
|
-
yield* client.handleServerRpc(AppsOnBeforeMessageDelivery, () => Effect.gen(function* () {
|
|
148
|
-
yield* Deferred.succeed(release, undefined);
|
|
149
|
-
return { block: false };
|
|
150
|
-
}));
|
|
151
|
-
yield* Effect.promise(() => connect(client));
|
|
152
|
-
// Wait for both replies to land at the server.
|
|
153
|
-
const deadline = Date.now() + 4000;
|
|
154
|
-
let bothReplied = false;
|
|
155
|
-
while (Date.now() < deadline) {
|
|
156
|
-
const conn = server.conns[0];
|
|
157
|
-
if (conn) {
|
|
158
|
-
const replyIds = responseIds(conn.received);
|
|
159
|
-
if (replyIds.includes("rpc-bd-1") &&
|
|
160
|
-
replyIds.includes("rpc-bmd-1")) {
|
|
161
|
-
bothReplied = true;
|
|
162
|
-
break;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
yield* Effect.sleep("20 millis");
|
|
166
|
-
}
|
|
167
|
-
yield* Effect.promise(() => close(client));
|
|
168
|
-
return bothReplied;
|
|
169
|
-
})));
|
|
170
|
-
expect(result).toBe(true);
|
|
171
|
-
}, /* per-test timeout */ 6000);
|
|
172
|
-
it("concurrent handlers across two different sessions complete independently " +
|
|
173
|
-
"(slow handler in session A does not delay session B)", async () => {
|
|
174
|
-
const result = await Effect.runPromise(Effect.scoped(Effect.gen(function* () {
|
|
175
|
-
const server = yield* startWsServer((conn, raw) => Effect.gen(function* () {
|
|
176
|
-
const parsed = JSON.parse(raw);
|
|
177
|
-
if (!validators.requestFrame(parsed)) {
|
|
178
|
-
return yield* Effect.die("expected JSON-RPC request frame");
|
|
179
|
-
}
|
|
180
|
-
const frame = parsed;
|
|
181
|
-
if (frame.method === Connect.name) {
|
|
182
|
-
yield* conn.send(JSON.stringify(responseFrame(frame.id, {
|
|
183
|
-
result: helloOk(),
|
|
184
|
-
})));
|
|
185
|
-
// Session A: park forever (until release).
|
|
186
|
-
yield* conn.send(JSON.stringify(requestFrame(jsonRpcStringId("rpc-A"), AppsOnBeforeDispatch, beforeDispatchParams(SESSION_A, CONV_X))));
|
|
187
|
-
// Session B: must complete despite A being parked.
|
|
188
|
-
yield* conn.send(JSON.stringify(requestFrame(jsonRpcStringId("rpc-B"), AppsOnBeforeDispatch, beforeDispatchParams(SESSION_B, CONV_X))));
|
|
189
|
-
}
|
|
190
|
-
}));
|
|
191
|
-
const release = yield* Deferred.make();
|
|
192
|
-
const client = new MoltZapWsClient({
|
|
193
|
-
serverUrl: server.url,
|
|
194
|
-
agentKey: "k",
|
|
195
|
-
logger: {
|
|
196
|
-
info: () => { },
|
|
197
|
-
warn: () => { },
|
|
198
|
-
error: () => { },
|
|
199
|
-
},
|
|
200
|
-
});
|
|
201
|
-
yield* client.handleServerRpc(AppsOnBeforeDispatch, (params) => Effect.gen(function* () {
|
|
202
|
-
if (params.taskId === SESSION_A) {
|
|
203
|
-
yield* Deferred.await(release);
|
|
204
|
-
}
|
|
205
|
-
return { admission: { decision: "grant" } };
|
|
206
|
-
}));
|
|
207
|
-
yield* Effect.promise(() => connect(client));
|
|
208
|
-
const deadline = Date.now() + 4000;
|
|
209
|
-
let bRan = false;
|
|
210
|
-
while (Date.now() < deadline) {
|
|
211
|
-
const conn = server.conns[0];
|
|
212
|
-
if (conn) {
|
|
213
|
-
const replyIds = responseIds(conn.received);
|
|
214
|
-
if (replyIds.includes("rpc-B")) {
|
|
215
|
-
bRan = true;
|
|
216
|
-
break;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
yield* Effect.sleep("20 millis");
|
|
220
|
-
}
|
|
221
|
-
// Release A so close() doesn't have to interrupt a parked
|
|
222
|
-
// handler.
|
|
223
|
-
yield* Deferred.succeed(release, undefined);
|
|
224
|
-
yield* Effect.promise(() => close(client));
|
|
225
|
-
return bRan;
|
|
226
|
-
})));
|
|
227
|
-
expect(result).toBe(true);
|
|
228
|
-
}, /* per-test timeout */ 6000);
|
|
229
|
-
});
|
|
230
|
-
//# sourceMappingURL=app-callback-partitioned-dispatcher-real-ws.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"app-callback-partitioned-dispatcher-real-ws.test.js","sourceRoot":"","sources":["../../../src/internal/__tests__/app-callback-partitioned-dispatcher-real-ws.test.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/runtime/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"notification-types.types-check.d.ts","sourceRoot":"","sources":["../../src/runtime/notification-types.types-check.ts"],"names":[],"mappings":""}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Negative type-test canary for Phase 7.5c (#455).
|
|
3
|
-
*
|
|
4
|
-
* Locks the compiler-enforced lift contract that splits unvalidated
|
|
5
|
-
* wire-decoder output (`RawDecodedNotification<D>`,
|
|
6
|
-
* `DecodedNotificationFrame`) from validated typed-bridge surface
|
|
7
|
-
* (`DecodedNotification<D>`).
|
|
8
|
-
*
|
|
9
|
-
* What we assert:
|
|
10
|
-
*
|
|
11
|
-
* 1. `subscribers.dispatch` accepts the raw / unknown-method union
|
|
12
|
-
* `DecodedNotificationFrame`. Validated `DecodedNotification<D>`
|
|
13
|
-
* values are still acceptable (subtype of `RawDecodedNotification<D>`),
|
|
14
|
-
* but a raw frame cannot reach the typed handler bucket without
|
|
15
|
-
* passing through `validateNotificationParams`.
|
|
16
|
-
*
|
|
17
|
-
* 2. `defineEffectNotificationHandlers(...).dispatch` (the typed
|
|
18
|
-
* handler dispatcher used by `MoltZapService`) refuses
|
|
19
|
-
* `RawDecodedNotification<D>` and the broader
|
|
20
|
-
* `DecodedNotificationFrame` union — only validated
|
|
21
|
-
* `DecodedNotification<D>` may flow in. This is the load-bearing
|
|
22
|
-
* negative: a regression that re-aliases the two types would
|
|
23
|
-
* surface here as a missing `@ts-expect-error`.
|
|
24
|
-
*
|
|
25
|
-
* Compile-only — no runtime test runner picks this file up. The
|
|
26
|
-
* `@ts-expect-error` markers fail the build if they ever start
|
|
27
|
-
* compiling cleanly.
|
|
28
|
-
*/
|
|
29
|
-
import { Effect } from "effect";
|
|
30
|
-
import { ConversationArchivedNotificationDefinition, bindNotificationHandler, defineEffectNotificationHandlers, defineNotificationGroup, } from "@moltzap/protocol";
|
|
31
|
-
import { makeSubscriberRegistry } from "./subscribers.js";
|
|
32
|
-
const noopLogger = { warn: () => { } };
|
|
33
|
-
const registry = Effect.runSync(makeSubscriberRegistry(noopLogger));
|
|
34
|
-
const canaryGroup = defineNotificationGroup("phase7.5c-canary", [
|
|
35
|
-
ConversationArchivedNotificationDefinition,
|
|
36
|
-
]);
|
|
37
|
-
const typedHandlers = defineEffectNotificationHandlers(canaryGroup, [
|
|
38
|
-
bindNotificationHandler(ConversationArchivedNotificationDefinition, () => Effect.void),
|
|
39
|
-
]);
|
|
40
|
-
// --- Subscribers (raw|unknown) accept the wire-decoder union ---
|
|
41
|
-
void registry.dispatch(rawFrame); // OK: raw subtype of the union
|
|
42
|
-
void registry.dispatch(wireUnion); // OK: union dispatch
|
|
43
|
-
// Validated values are also accepted because `DecodedNotification<D>`
|
|
44
|
-
// is a subtype of `RawDecodedNotification<D>` (params narrower).
|
|
45
|
-
void registry.dispatch(validatedFrame);
|
|
46
|
-
// --- Typed dispatcher refuses pre-validation shapes ---
|
|
47
|
-
// @ts-expect-error - typed dispatcher rejects unvalidated raw frames; lift via `validateNotificationParams` first
|
|
48
|
-
void typedHandlers.dispatch(rawFrame);
|
|
49
|
-
// @ts-expect-error - typed dispatcher rejects the wire-decoder union (includes the unknown-method branch)
|
|
50
|
-
void typedHandlers.dispatch(wireUnion);
|
|
51
|
-
// Validated frame is accepted — proves the negative is not vacuous
|
|
52
|
-
// (a regression that aliases Decoded≡Raw would still pass this line
|
|
53
|
-
// but flip the `@ts-expect-error`s above).
|
|
54
|
-
void typedHandlers.dispatch(validatedFrame);
|
|
55
|
-
// @ts-expect-error - unknown-method branch has no descriptor; typed dispatcher requires `definition`
|
|
56
|
-
void typedHandlers.dispatch(unknownMethodFrame);
|
|
57
|
-
//# sourceMappingURL=notification-types.types-check.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"notification-types.types-check.js","sourceRoot":"","sources":["../../src/runtime/notification-types.types-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EACL,0CAA0C,EAC1C,uBAAuB,EACvB,gCAAgC,EAChC,uBAAuB,GAIxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;AACtC,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAC;AACpE,MAAM,WAAW,GAAG,uBAAuB,CAAC,kBAAkB,EAAE;IAC9D,0CAA0C;CAClC,CAAC,CAAC;AACZ,MAAM,aAAa,GAAG,gCAAgC,CAAC,WAAW,EAAE;IAClE,uBAAuB,CACrB,0CAA0C,EAC1C,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAClB;CACF,CAAC,CAAC;AAUH,kEAAkE;AAElE,KAAK,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,+BAA+B;AACjE,KAAK,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,qBAAqB;AACxD,sEAAsE;AACtE,iEAAiE;AACjE,KAAK,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;AAEvC,yDAAyD;AAEzD,kHAAkH;AAClH,KAAK,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAEtC,0GAA0G;AAC1G,KAAK,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAEvC,mEAAmE;AACnE,oEAAoE;AACpE,2CAA2C;AAC3C,KAAK,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;AAS5C,qGAAqG;AACrG,KAAK,aAAa,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"service.typed-bridge.test.d.ts","sourceRoot":"","sources":["../src/service.typed-bridge.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Drives a stale-shape notification through the real subscriber →
|
|
3
|
-
* service → typed-handler dispatch path (`handleNotification` →
|
|
4
|
-
* `notificationHandlers.dispatch`). The helper test in
|
|
5
|
-
* `ws-client.typed-bridge.test.ts` exercises `validateNotificationParams`
|
|
6
|
-
* in isolation; this file proves the subscriber-fanout bridge actually
|
|
7
|
-
* invokes it and skips dispatch on drift, so the stale frame never
|
|
8
|
-
* reaches the typed handler bound inside `createNotificationHandlers`.
|
|
9
|
-
*
|
|
10
|
-
* Discriminating choice: `ConversationArchivedNotificationDefinition`
|
|
11
|
-
* is one of the five notifications in `serviceNotificationGroup`, so a
|
|
12
|
-
* payload missing the required `archivedAt` field hits the typed-handler
|
|
13
|
-
* dispatch path (which would call `markConversationArchived` +
|
|
14
|
-
* `fanout(handlers.conversationArchived, ...)`). The regression asserts:
|
|
15
|
-
* 1. The typed `conversationArchived` user handler is NOT invoked.
|
|
16
|
-
* 2. The internal `archivedConversationIds` set is NOT updated.
|
|
17
|
-
* 3. The raw-notification handler IS invoked (proves the
|
|
18
|
-
* pre-validation surface still fires; only the typed dispatch is
|
|
19
|
-
* gated).
|
|
20
|
-
* 4. A drift warning is logged with the notification name.
|
|
21
|
-
*/
|
|
22
|
-
import { describe, expect, it, vi } from "vitest";
|
|
23
|
-
import { ConversationArchivedNotificationDefinition, agentId, conversationId, notificationFrame, } from "@moltzap/protocol";
|
|
24
|
-
import { MoltZapService } from "./service.js";
|
|
25
|
-
class TestMoltZapService extends MoltZapService {
|
|
26
|
-
driveNotification(notification) {
|
|
27
|
-
this.handleNotification(notification);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
const CONV_ID = conversationId("00000000-0000-4000-8000-000000c0a4ed");
|
|
31
|
-
const BY_AGENT = agentId("00000000-0000-4000-8000-0000000a9e47");
|
|
32
|
-
// Constructing the stale-shape fixture as `RawDecodedNotification`
|
|
33
|
-
// (params: unknown) lets TypeScript accept the unvalidated payload
|
|
34
|
-
// without a type lie: the wire decoder is payload-opaque, so a frame
|
|
35
|
-
// missing the required `archivedAt` field is structurally a Raw
|
|
36
|
-
// notification — the typed-bridge lift in `validateNotificationParams`
|
|
37
|
-
// is what rejects it at dispatch time.
|
|
38
|
-
const STALE_ARCHIVED = {
|
|
39
|
-
jsonrpc: "2.0",
|
|
40
|
-
method: ConversationArchivedNotificationDefinition.name,
|
|
41
|
-
params: { conversationId: CONV_ID, by: BY_AGENT },
|
|
42
|
-
_tag: "Notification",
|
|
43
|
-
definition: ConversationArchivedNotificationDefinition,
|
|
44
|
-
};
|
|
45
|
-
const LIVE_ARCHIVED = {
|
|
46
|
-
...notificationFrame(ConversationArchivedNotificationDefinition, {
|
|
47
|
-
conversationId: CONV_ID,
|
|
48
|
-
archivedAt: "2026-05-05T00:00:00.000Z",
|
|
49
|
-
by: BY_AGENT,
|
|
50
|
-
}),
|
|
51
|
-
_tag: "Notification",
|
|
52
|
-
definition: ConversationArchivedNotificationDefinition,
|
|
53
|
-
};
|
|
54
|
-
describe("MoltZapService.handleNotification subscriber-fanout bridge", () => {
|
|
55
|
-
it("skips typed dispatch on a stale shape, fans out raw, and logs drift", () => {
|
|
56
|
-
const warn = vi.fn();
|
|
57
|
-
const service = new TestMoltZapService({
|
|
58
|
-
serverUrl: "ws://test",
|
|
59
|
-
agentKey: "test-key",
|
|
60
|
-
logger: { info: vi.fn(), warn, error: vi.fn() },
|
|
61
|
-
});
|
|
62
|
-
const onArchived = vi.fn();
|
|
63
|
-
const onRaw = vi.fn();
|
|
64
|
-
service.on("conversationArchived", onArchived);
|
|
65
|
-
service.on("rawNotification", onRaw);
|
|
66
|
-
service.driveNotification(STALE_ARCHIVED);
|
|
67
|
-
// Typed handler MUST NOT see the malformed payload.
|
|
68
|
-
expect(onArchived).not.toHaveBeenCalled();
|
|
69
|
-
expect(service.isConversationArchived(CONV_ID)).toBe(false);
|
|
70
|
-
// Raw-notification handler still fires — fanout runs before the
|
|
71
|
-
// typed-bridge gate, so subscribers using the opaque surface are
|
|
72
|
-
// unaffected.
|
|
73
|
-
expect(onRaw).toHaveBeenCalledTimes(1);
|
|
74
|
-
// Drift warning surfaced via the WsClientLogger.
|
|
75
|
-
expect(warn).toHaveBeenCalledTimes(1);
|
|
76
|
-
expect(String(warn.mock.calls[0]?.[0])).toMatch(/conversations\/archived.*drift signal/);
|
|
77
|
-
});
|
|
78
|
-
it("dispatches a live shape to the typed handler and updates internal state", () => {
|
|
79
|
-
const warn = vi.fn();
|
|
80
|
-
const service = new TestMoltZapService({
|
|
81
|
-
serverUrl: "ws://test",
|
|
82
|
-
agentKey: "test-key",
|
|
83
|
-
logger: { info: vi.fn(), warn, error: vi.fn() },
|
|
84
|
-
});
|
|
85
|
-
const onArchived = vi.fn();
|
|
86
|
-
service.on("conversationArchived", onArchived);
|
|
87
|
-
service.driveNotification(LIVE_ARCHIVED);
|
|
88
|
-
expect(onArchived).toHaveBeenCalledTimes(1);
|
|
89
|
-
expect(service.isConversationArchived(CONV_ID)).toBe(true);
|
|
90
|
-
expect(warn).not.toHaveBeenCalled();
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
//# sourceMappingURL=service.typed-bridge.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"service.typed-bridge.test.js","sourceRoot":"","sources":["../src/service.typed-bridge.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ws-client.typed-bridge.test.d.ts","sourceRoot":"","sources":["../src/ws-client.typed-bridge.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Typed-bridge regression: the wire decoder is payload-opaque (so
|
|
3
|
-
* `delivery/payload-opacity-client` conformance holds). Inbound typed
|
|
4
|
-
* consumers MUST validate `params` before exposing them to a typed
|
|
5
|
-
* handler. A stale Phase-6 `task/closed` shape (carrying `sessionId` +
|
|
6
|
-
* scalar `closedBy`) is a known-method notification whose method
|
|
7
|
-
* matches `TaskClosedNotificationDefinition`, so a definition-only
|
|
8
|
-
* match would silently bridge a malformed payload into a typed
|
|
9
|
-
* consumer. Both bridges (`acceptTypedNotification` for
|
|
10
|
-
* `waitForNotification` and the shared `validateNotificationParams`
|
|
11
|
-
* helper used by `service.handleNotification`) log and skip instead.
|
|
12
|
-
*/
|
|
13
|
-
import { describe, expect, it, vi } from "vitest";
|
|
14
|
-
import { PresenceChangedNotificationDefinition, TaskClosedNotificationDefinition, agentId, conversationId, notificationFrame, taskId, } from "@moltzap/protocol";
|
|
15
|
-
import { acceptTypedNotification, validateNotificationParams, } from "./ws-client.js";
|
|
16
|
-
// Stale wire-shape fixture as `RawDecodedNotification` (params: unknown):
|
|
17
|
-
// the wire decoder is payload-opaque, so the pre-Phase-7 `sessionId` /
|
|
18
|
-
// scalar `closedBy` shape is structurally a valid Raw notification.
|
|
19
|
-
// `validateNotificationParams` is what rejects it at the typed-bridge
|
|
20
|
-
// boundary; the type system distinguishes "decoded from the wire" from
|
|
21
|
-
// "validated against the schema."
|
|
22
|
-
const STALE_TASK_CLOSED = {
|
|
23
|
-
jsonrpc: "2.0",
|
|
24
|
-
method: TaskClosedNotificationDefinition.name,
|
|
25
|
-
params: {
|
|
26
|
-
sessionId: "11111111-1111-4111-8111-111111111111",
|
|
27
|
-
closedBy: "33333333-3333-4333-8333-333333333333",
|
|
28
|
-
},
|
|
29
|
-
_tag: "Notification",
|
|
30
|
-
definition: TaskClosedNotificationDefinition,
|
|
31
|
-
};
|
|
32
|
-
const LIVE_TASK_CLOSED = {
|
|
33
|
-
...notificationFrame(TaskClosedNotificationDefinition, {
|
|
34
|
-
taskId: taskId("11111111-1111-4111-8111-111111111111"),
|
|
35
|
-
conversations: {
|
|
36
|
-
main: conversationId("22222222-2222-4222-8222-222222222222"),
|
|
37
|
-
},
|
|
38
|
-
closedBy: {
|
|
39
|
-
agentId: agentId("33333333-3333-4333-8333-333333333333"),
|
|
40
|
-
ownerId: "owner-1",
|
|
41
|
-
},
|
|
42
|
-
}),
|
|
43
|
-
_tag: "Notification",
|
|
44
|
-
definition: TaskClosedNotificationDefinition,
|
|
45
|
-
};
|
|
46
|
-
function makeLogger() {
|
|
47
|
-
return {
|
|
48
|
-
info: vi.fn(),
|
|
49
|
-
warn: vi.fn(),
|
|
50
|
-
error: vi.fn(),
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
describe("acceptTypedNotification", () => {
|
|
54
|
-
it("rejects a stale `task/closed` payload, logs the drift signal", () => {
|
|
55
|
-
const logger = makeLogger();
|
|
56
|
-
const accepted = acceptTypedNotification(TaskClosedNotificationDefinition, STALE_TASK_CLOSED, logger);
|
|
57
|
-
expect(accepted).toBe(false);
|
|
58
|
-
expect(logger.warn).toHaveBeenCalledTimes(1);
|
|
59
|
-
expect(String(logger.warn.mock.calls[0]?.[0])).toMatch(/task\/closed.*drift signal/);
|
|
60
|
-
});
|
|
61
|
-
it("accepts a live `task/closed` payload — proves the validator is not vacuously false", () => {
|
|
62
|
-
const logger = makeLogger();
|
|
63
|
-
const accepted = acceptTypedNotification(TaskClosedNotificationDefinition, LIVE_TASK_CLOSED, logger);
|
|
64
|
-
expect(accepted).toBe(true);
|
|
65
|
-
expect(logger.warn).not.toHaveBeenCalled();
|
|
66
|
-
});
|
|
67
|
-
it("returns false for a non-matching definition without invoking validateParams", () => {
|
|
68
|
-
const logger = makeLogger();
|
|
69
|
-
const validateSpy = vi.spyOn(TaskClosedNotificationDefinition, "validateParams");
|
|
70
|
-
const wrongMethod = {
|
|
71
|
-
jsonrpc: "2.0",
|
|
72
|
-
method: PresenceChangedNotificationDefinition.name,
|
|
73
|
-
params: {},
|
|
74
|
-
_tag: "Notification",
|
|
75
|
-
definition: PresenceChangedNotificationDefinition,
|
|
76
|
-
};
|
|
77
|
-
const accepted = acceptTypedNotification(TaskClosedNotificationDefinition, wrongMethod, logger);
|
|
78
|
-
expect(accepted).toBe(false);
|
|
79
|
-
expect(validateSpy).not.toHaveBeenCalled();
|
|
80
|
-
expect(logger.warn).not.toHaveBeenCalled();
|
|
81
|
-
validateSpy.mockRestore();
|
|
82
|
-
});
|
|
83
|
-
it("works without a logger (logger is optional)", () => {
|
|
84
|
-
const accepted = acceptTypedNotification(TaskClosedNotificationDefinition, STALE_TASK_CLOSED, undefined);
|
|
85
|
-
expect(accepted).toBe(false);
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
// Tests the shared validation core used by both inbound typed bridges
|
|
89
|
-
// (`acceptTypedNotification` and `service.handleNotification`). A
|
|
90
|
-
// refactor that breaks the shared core surfaces here, not via downstream
|
|
91
|
-
// integration regressions.
|
|
92
|
-
describe("validateNotificationParams", () => {
|
|
93
|
-
it("returns false + logs when params fail the attached schema", () => {
|
|
94
|
-
const logger = makeLogger();
|
|
95
|
-
expect(validateNotificationParams(STALE_TASK_CLOSED, logger)).toBe(false);
|
|
96
|
-
expect(logger.warn).toHaveBeenCalledTimes(1);
|
|
97
|
-
expect(String(logger.warn.mock.calls[0]?.[0])).toMatch(/task\/closed.*drift signal/);
|
|
98
|
-
});
|
|
99
|
-
it("returns true + no log when params conform", () => {
|
|
100
|
-
const logger = makeLogger();
|
|
101
|
-
expect(validateNotificationParams(LIVE_TASK_CLOSED, logger)).toBe(true);
|
|
102
|
-
expect(logger.warn).not.toHaveBeenCalled();
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
//# sourceMappingURL=ws-client.typed-bridge.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ws-client.typed-bridge.test.js","sourceRoot":"","sources":["../src/ws-client.typed-bridge.test.ts"],"names":[],"mappings":"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"}
|