@moltzap/client 2026.511.0 → 2026.518.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/auth.d.ts +12 -6
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +67 -29
- package/dist/auth.js.map +1 -1
- package/dist/auth.test.js +113 -76
- package/dist/auth.test.js.map +1 -1
- package/dist/channel-core-context.test.d.ts +2 -0
- package/dist/channel-core-context.test.d.ts.map +1 -0
- package/dist/channel-core-context.test.js +334 -0
- package/dist/channel-core-context.test.js.map +1 -0
- package/dist/channel-core-dispatch.test.d.ts +2 -0
- package/dist/channel-core-dispatch.test.d.ts.map +1 -0
- package/dist/channel-core-dispatch.test.js +550 -0
- package/dist/channel-core-dispatch.test.js.map +1 -0
- package/dist/channel-core-enrichment.d.ts +8 -0
- package/dist/channel-core-enrichment.d.ts.map +1 -0
- package/dist/channel-core-enrichment.js +134 -0
- package/dist/channel-core-enrichment.js.map +1 -0
- package/dist/channel-core-errors.d.ts +20 -0
- package/dist/channel-core-errors.d.ts.map +1 -0
- package/dist/channel-core-errors.js +12 -0
- package/dist/channel-core-errors.js.map +1 -0
- package/dist/channel-core-test-support.d.ts +48 -0
- package/dist/channel-core-test-support.d.ts.map +1 -0
- package/dist/channel-core-test-support.js +111 -0
- package/dist/channel-core-test-support.js.map +1 -0
- package/dist/channel-core.d.ts +30 -7
- package/dist/channel-core.d.ts.map +1 -1
- package/dist/channel-core.js +214 -237
- package/dist/channel-core.js.map +1 -1
- package/dist/channel-core.test.js +216 -1082
- package/dist/channel-core.test.js.map +1 -1
- package/dist/cli/__tests__/cli-multi-agent.int.test.js +129 -23
- package/dist/cli/__tests__/cli-multi-agent.int.test.js.map +1 -1
- package/dist/cli/commands/conversations-v2.test.js +64 -54
- package/dist/cli/commands/conversations-v2.test.js.map +1 -1
- package/dist/cli/commands/conversations.d.ts +5 -5
- package/dist/cli/commands/conversations.d.ts.map +1 -1
- package/dist/cli/commands/conversations.js +43 -36
- package/dist/cli/commands/conversations.js.map +1 -1
- package/dist/cli/commands/messages.d.ts +4 -4
- package/dist/cli/commands/messages.d.ts.map +1 -1
- package/dist/cli/commands/messages.js +4 -4
- package/dist/cli/commands/messages.js.map +1 -1
- package/dist/cli/commands/messages.test.js +61 -49
- package/dist/cli/commands/messages.test.js.map +1 -1
- package/dist/cli/commands/ping.d.ts +0 -9
- package/dist/cli/commands/ping.d.ts.map +1 -1
- package/dist/cli/commands/ping.js +1 -1
- package/dist/cli/commands/ping.js.map +1 -1
- package/dist/cli/commands/presence.d.ts +1 -1
- package/dist/cli/commands/presence.js +1 -1
- package/dist/cli/commands/register.d.ts +2 -2
- package/dist/cli/commands/register.d.ts.map +1 -1
- package/dist/cli/commands/register.js +98 -77
- package/dist/cli/commands/register.js.map +1 -1
- package/dist/cli/commands/register.test.js +63 -39
- package/dist/cli/commands/register.test.js.map +1 -1
- package/dist/cli/commands/send.d.ts +6 -6
- package/dist/cli/commands/send.js +6 -6
- package/dist/cli/commands/send.test.js +32 -28
- package/dist/cli/commands/send.test.js.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +3 -4
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/config.d.ts +0 -2
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +86 -76
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/config.test.js +80 -42
- package/dist/cli/config.test.js.map +1 -1
- package/dist/cli/index.d.ts +1 -16
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +50 -113
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/process-argv.d.ts +2 -0
- package/dist/cli/process-argv.d.ts.map +1 -0
- package/dist/cli/process-argv.js +2 -0
- package/dist/cli/process-argv.js.map +1 -0
- package/dist/cli/profile.d.ts +3 -10
- package/dist/cli/profile.d.ts.map +1 -1
- package/dist/cli/profile.js +105 -104
- package/dist/cli/profile.js.map +1 -1
- package/dist/cli/profile.test.js +338 -232
- package/dist/cli/profile.test.js.map +1 -1
- package/dist/cli/runtime.d.ts +5 -17
- package/dist/cli/runtime.d.ts.map +1 -1
- package/dist/cli/runtime.js +6 -59
- package/dist/cli/runtime.js.map +1 -1
- package/dist/cli/socket-client.d.ts +10 -15
- package/dist/cli/socket-client.d.ts.map +1 -1
- package/dist/cli/socket-client.js +74 -89
- package/dist/cli/socket-client.js.map +1 -1
- package/dist/cli/transport.d.ts +9 -5
- package/dist/cli/transport.d.ts.map +1 -1
- package/dist/cli/transport.js +45 -42
- package/dist/cli/transport.js.map +1 -1
- package/dist/cli/transport.test.js +227 -133
- package/dist/cli/transport.test.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/local-daemon-rpc.d.ts +13 -0
- package/dist/local-daemon-rpc.d.ts.map +1 -0
- package/dist/local-daemon-rpc.js +17 -0
- package/dist/local-daemon-rpc.js.map +1 -0
- package/dist/local-paths.d.ts +7 -0
- package/dist/local-paths.d.ts.map +1 -0
- package/dist/local-paths.js +20 -0
- package/dist/local-paths.js.map +1 -0
- package/dist/runtime/close-info.d.ts +3 -12
- package/dist/runtime/close-info.d.ts.map +1 -1
- package/dist/runtime/close-info.js +28 -39
- package/dist/runtime/close-info.js.map +1 -1
- package/dist/runtime/close-info.test.js +77 -70
- package/dist/runtime/close-info.test.js.map +1 -1
- package/dist/runtime/errors.test.js +42 -28
- package/dist/runtime/errors.test.js.map +1 -1
- package/dist/runtime/frame.d.ts +4 -31
- package/dist/runtime/frame.d.ts.map +1 -1
- package/dist/runtime/frame.js +7 -116
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/frame.test.js +41 -54
- package/dist/runtime/frame.test.js.map +1 -1
- package/dist/runtime/index.d.ts +7 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +7 -11
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/local-history.d.ts +67 -0
- package/dist/runtime/local-history.d.ts.map +1 -0
- package/dist/runtime/local-history.js +77 -0
- package/dist/runtime/local-history.js.map +1 -0
- package/dist/runtime/local-service-commands.d.ts +19 -0
- package/dist/runtime/local-service-commands.d.ts.map +1 -1
- package/dist/runtime/local-service-commands.js +23 -0
- package/dist/runtime/local-service-commands.js.map +1 -1
- package/dist/runtime/local-socket-server.d.ts +20 -0
- package/dist/runtime/local-socket-server.d.ts.map +1 -0
- package/dist/runtime/local-socket-server.js +94 -0
- package/dist/runtime/local-socket-server.js.map +1 -0
- package/dist/runtime/refs.d.ts +1 -1
- package/dist/runtime/refs.js +1 -1
- package/dist/runtime/runtime.test.js +29 -21
- package/dist/runtime/runtime.test.js.map +1 -1
- package/dist/runtime/service-helpers.d.ts +32 -0
- package/dist/runtime/service-helpers.d.ts.map +1 -0
- package/dist/runtime/service-helpers.js +85 -0
- package/dist/runtime/service-helpers.js.map +1 -0
- package/dist/runtime/subscribers.d.ts +13 -17
- package/dist/runtime/subscribers.d.ts.map +1 -1
- package/dist/runtime/subscribers.js +37 -32
- package/dist/runtime/subscribers.js.map +1 -1
- package/dist/runtime/subscribers.test.js +139 -131
- package/dist/runtime/subscribers.test.js.map +1 -1
- package/dist/service-socket-path.test.d.ts +2 -0
- package/dist/service-socket-path.test.d.ts.map +1 -0
- package/dist/service-socket-path.test.js +87 -0
- package/dist/service-socket-path.test.js.map +1 -0
- package/dist/service.d.ts +46 -20
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +243 -340
- package/dist/service.js.map +1 -1
- package/dist/service.test.js +650 -571
- package/dist/service.test.js.map +1 -1
- package/dist/test/index.d.ts +30 -14
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +25 -21
- package/dist/test/index.js.map +1 -1
- package/dist/test-utils/channel-service-fixture.d.ts +1 -0
- package/dist/test-utils/channel-service-fixture.d.ts.map +1 -1
- package/dist/test-utils/channel-service-fixture.js +139 -98
- package/dist/test-utils/channel-service-fixture.js.map +1 -1
- package/dist/test-utils/conformance-adapter.d.ts.map +1 -1
- package/dist/test-utils/conformance-adapter.js +145 -124
- package/dist/test-utils/conformance-adapter.js.map +1 -1
- package/dist/test-utils/fake-service.d.ts.map +1 -1
- package/dist/test-utils/fake-service.js +3 -3
- package/dist/test-utils/fake-service.js.map +1 -1
- package/dist/test-utils/index.d.ts +25 -0
- package/dist/test-utils/index.d.ts.map +1 -1
- package/dist/test-utils/index.js +25 -8
- package/dist/test-utils/index.js.map +1 -1
- package/dist/ws-client-test-support.d.ts +180 -0
- package/dist/ws-client-test-support.d.ts.map +1 -0
- package/dist/ws-client-test-support.js +399 -0
- package/dist/ws-client-test-support.js.map +1 -0
- package/dist/ws-client.d.ts +59 -32
- package/dist/ws-client.d.ts.map +1 -1
- package/dist/ws-client.js +272 -321
- package/dist/ws-client.js.map +1 -1
- package/dist/ws-client.test.js +388 -800
- package/dist/ws-client.test.js.map +1 -1
- package/package.json +14 -10
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
* filter-narrows tests but leaves order tests passing — the tests
|
|
15
15
|
* discriminate.
|
|
16
16
|
*/
|
|
17
|
-
import
|
|
17
|
+
import * as fc from "fast-check";
|
|
18
|
+
import { expect, it } from "vitest";
|
|
18
19
|
import { Effect, Ref } from "effect";
|
|
19
20
|
import { ConversationArchivedNotificationDefinition, } from "@moltzap/protocol";
|
|
20
21
|
import { agentId, conversationId, taskId, TaskFailedNotificationDefinition, } from "@moltzap/protocol/testing";
|
|
@@ -23,6 +24,31 @@ const TASK_ID = taskId("11111111-1111-4111-8111-111111111111");
|
|
|
23
24
|
const CONV_1 = conversationId("22222222-2222-4222-8222-222222222222");
|
|
24
25
|
const CONV_2 = conversationId("33333333-3333-4333-8333-333333333333");
|
|
25
26
|
const AGENT_ID = agentId("44444444-4444-4444-8444-444444444444");
|
|
27
|
+
const PROPERTY_RUNS = 25;
|
|
28
|
+
const SUBSCRIBER_DEFECT_MESSAGE = "subscriber blew up";
|
|
29
|
+
const CONSTRUCTION_THROW_MESSAGE = "construction-time throw";
|
|
30
|
+
function pushValue(values, value) {
|
|
31
|
+
return Effect.sync(() => {
|
|
32
|
+
values.push(value);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function recordAndMaybeUnsubscribe(calls, frameIdx, unsubscribe) {
|
|
36
|
+
return Effect.gen(function* () {
|
|
37
|
+
calls.push(frameIdx);
|
|
38
|
+
if (frameIdx === 0 && unsubscribe !== null) {
|
|
39
|
+
yield* unsubscribe;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function subscriberDefect() {
|
|
44
|
+
return Effect.die(new Error(SUBSCRIBER_DEFECT_MESSAGE));
|
|
45
|
+
}
|
|
46
|
+
function constructionThrow() {
|
|
47
|
+
throw new Error(CONSTRUCTION_THROW_MESSAGE);
|
|
48
|
+
}
|
|
49
|
+
function increment(value) {
|
|
50
|
+
return value + 1;
|
|
51
|
+
}
|
|
26
52
|
const filterableNotification = (method, params) => ({
|
|
27
53
|
method,
|
|
28
54
|
params,
|
|
@@ -49,137 +75,119 @@ const conversationArchivedNotification = (conv) => decodedNotification(Conversat
|
|
|
49
75
|
archivedAt: "2026-05-03T00:00:00Z",
|
|
50
76
|
by: AGENT_ID,
|
|
51
77
|
});
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
expect(matchesFilter({}, filterableNotification(
|
|
56
|
-
});
|
|
57
|
-
it("emissionTag matches on `__emissionTag` key", () => {
|
|
58
|
-
const frame = filterableNotification("e", { __emissionTag: "tag-1" });
|
|
59
|
-
expect(matchesFilter({ emissionTag: "tag-1" }, frame)).toBe(true);
|
|
60
|
-
expect(matchesFilter({ emissionTag: "tag-other" }, frame)).toBe(false);
|
|
61
|
-
});
|
|
62
|
-
it("conversationId matches on `conversationId` key", () => {
|
|
63
|
-
const frame = filterableNotification("e", { conversationId: "c-1" });
|
|
64
|
-
expect(matchesFilter({ conversationId: "c-1" }, frame)).toBe(true);
|
|
65
|
-
expect(matchesFilter({ conversationId: "c-2" }, frame)).toBe(false);
|
|
66
|
-
});
|
|
67
|
-
it("notificationNamePrefix uses startsWith", () => {
|
|
68
|
-
const frame = filterableNotification("messages/received", {});
|
|
69
|
-
expect(matchesFilter({ notificationNamePrefix: "messages/" }, frame)).toBe(true);
|
|
70
|
-
expect(matchesFilter({ notificationNamePrefix: "presence/" }, frame)).toBe(false);
|
|
71
|
-
});
|
|
72
|
-
it("AND semantics: all set fields must match", () => {
|
|
73
|
-
const frame = filterableNotification("messages/received", {
|
|
74
|
-
__emissionTag: "tag-1",
|
|
75
|
-
conversationId: "c-1",
|
|
76
|
-
});
|
|
77
|
-
expect(matchesFilter({
|
|
78
|
-
emissionTag: "tag-1",
|
|
79
|
-
conversationId: "c-1",
|
|
80
|
-
notificationNamePrefix: "m",
|
|
81
|
-
}, frame)).toBe(true);
|
|
82
|
-
// conversationId mismatch → reject even when other fields match.
|
|
83
|
-
expect(matchesFilter({ emissionTag: "tag-1", conversationId: "c-other" }, frame)).toBe(false);
|
|
84
|
-
});
|
|
85
|
-
it("non-record `params` cannot satisfy payload-key filters", () => {
|
|
86
|
-
const stringData = filterableNotification("e", "string-payload");
|
|
87
|
-
expect(matchesFilter({ emissionTag: "x" }, stringData)).toBe(false);
|
|
88
|
-
expect(matchesFilter({ conversationId: "x" }, stringData)).toBe(false);
|
|
89
|
-
// …but a notification-name-prefix filter still applies.
|
|
90
|
-
expect(matchesFilter({ notificationNamePrefix: "e" }, stringData)).toBe(true);
|
|
91
|
-
});
|
|
78
|
+
it("property: notificationNamePrefix follows string startsWith", () => {
|
|
79
|
+
expect.hasAssertions();
|
|
80
|
+
fc.assert(fc.property(fc.string(), fc.string(), (method, prefix) => {
|
|
81
|
+
expect(matchesFilter({ notificationNamePrefix: prefix }, filterableNotification(method, {}))).toBe(method.startsWith(prefix));
|
|
82
|
+
}), { numRuns: PROPERTY_RUNS });
|
|
92
83
|
});
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
})));
|
|
117
|
-
unsubA = handleA.unsubscribe;
|
|
118
|
-
await Effect.runPromise(registry.register({}, () => Effect.sync(() => void bCalls.push(frameIdx))));
|
|
119
|
-
frameIdx = 0;
|
|
120
|
-
await Effect.runPromise(registry.dispatch(taskFailedNotification()));
|
|
121
|
-
frameIdx = 1;
|
|
122
|
-
await Effect.runPromise(registry.dispatch(taskFailedNotification()));
|
|
123
|
-
expect(aCalls).toEqual([0]); // a saw frame 0, not frame 1.
|
|
124
|
-
expect(bCalls).toEqual([0, 1]); // b saw both — snapshot at start of frame 0 still included a; b is unaffected by a's unsub.
|
|
125
|
-
});
|
|
126
|
-
it("filters narrow delivery", async () => {
|
|
127
|
-
const registry = await Effect.runPromise(makeSubscriberRegistry(noopLogger));
|
|
128
|
-
const seenByConv1 = [];
|
|
129
|
-
const seenByConv2 = [];
|
|
130
|
-
await Effect.runPromise(registry.register({ conversationId: CONV_1 }, (frame) => Effect.sync(() => void seenByConv1.push(frame))));
|
|
131
|
-
await Effect.runPromise(registry.register({ conversationId: CONV_2 }, (frame) => Effect.sync(() => void seenByConv2.push(frame))));
|
|
132
|
-
await Effect.runPromise(registry.dispatch(conversationArchivedNotification(CONV_1)));
|
|
133
|
-
await Effect.runPromise(registry.dispatch(conversationArchivedNotification(CONV_2)));
|
|
134
|
-
expect(seenByConv1).toHaveLength(1);
|
|
135
|
-
expect(seenByConv2).toHaveLength(1);
|
|
136
|
-
expect(seenByConv1[0].params.conversationId).toBe(CONV_1);
|
|
137
|
-
expect(seenByConv2[0].params.conversationId).toBe(CONV_2);
|
|
138
|
-
});
|
|
139
|
-
it("handler exceptions are caught + logged via the injected logger", async () => {
|
|
140
|
-
const warn = vi.fn();
|
|
141
|
-
const registry = await Effect.runPromise(makeSubscriberRegistry({ warn }));
|
|
142
|
-
const otherCalls = [];
|
|
143
|
-
await Effect.runPromise(registry.register({}, () => Effect.sync(() => {
|
|
144
|
-
throw new Error("subscriber blew up");
|
|
145
|
-
})));
|
|
146
|
-
await Effect.runPromise(registry.register({}, () => Effect.sync(() => void otherCalls.push(1))));
|
|
147
|
-
await Effect.runPromise(registry.dispatch(taskFailedNotification()));
|
|
148
|
-
expect(warn).toHaveBeenCalledTimes(1);
|
|
149
|
-
expect(otherCalls).toEqual([1]); // other subscribers still fire.
|
|
150
|
-
});
|
|
151
|
-
it("construction-time throw from handler is caught + logged (not escaped)", async () => {
|
|
152
|
-
const warn = vi.fn();
|
|
153
|
-
const registry = await Effect.runPromise(makeSubscriberRegistry({ warn }));
|
|
154
|
-
const otherCalls = [];
|
|
155
|
-
await Effect.runPromise(registry.register({}, (_frame) => {
|
|
156
|
-
throw new Error("construction-time throw");
|
|
157
|
-
}));
|
|
158
|
-
await Effect.runPromise(registry.register({}, () => Effect.sync(() => void otherCalls.push(1))));
|
|
159
|
-
await Effect.runPromise(registry.dispatch(taskFailedNotification()));
|
|
160
|
-
expect(warn).toHaveBeenCalledTimes(1);
|
|
161
|
-
expect(otherCalls).toEqual([1]); // subsequent subscribers still fire.
|
|
162
|
-
});
|
|
163
|
-
it("closeAll drops every subscription", async () => {
|
|
164
|
-
const registry = await Effect.runPromise(makeSubscriberRegistry(noopLogger));
|
|
165
|
-
const calls = [];
|
|
166
|
-
await Effect.runPromise(registry.register({}, () => Effect.sync(() => void calls.push(1))));
|
|
167
|
-
await Effect.runPromise(registry.closeAll);
|
|
168
|
-
await Effect.runPromise(registry.dispatch(taskFailedNotification()));
|
|
169
|
-
expect(calls).toEqual([]);
|
|
170
|
-
});
|
|
171
|
-
it("Ref-make composition works: register inside an Effect.gen", async () => {
|
|
172
|
-
// Smoke test that the Effect surface composes; the registry never
|
|
173
|
-
// resolves with `never` failure tag, so this can't catch
|
|
174
|
-
// typechecker drift, but it does pin behaviour.
|
|
175
|
-
const result = await Effect.runPromise(Effect.gen(function* () {
|
|
176
|
-
const registry = yield* makeSubscriberRegistry(noopLogger);
|
|
177
|
-
const counter = yield* Ref.make(0);
|
|
178
|
-
yield* registry.register({}, () => Ref.update(counter, (n) => n + 1));
|
|
179
|
-
yield* registry.dispatch(taskFailedNotification());
|
|
180
|
-
return yield* Ref.get(counter);
|
|
181
|
-
}));
|
|
182
|
-
expect(result).toBe(1);
|
|
84
|
+
it("empty filter matches every frame", () => {
|
|
85
|
+
expect(matchesFilter({}, filterableNotification("any", { x: 1 }))).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
it("emissionTag matches on `__emissionTag` key", () => {
|
|
88
|
+
const frame = filterableNotification("e", { __emissionTag: "tag-1" });
|
|
89
|
+
expect(matchesFilter({ emissionTag: "tag-1" }, frame)).toBe(true);
|
|
90
|
+
expect(matchesFilter({ emissionTag: "tag-other" }, frame)).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
it("conversationId matches on `conversationId` key", () => {
|
|
93
|
+
const frame = filterableNotification("e", { conversationId: "c-1" });
|
|
94
|
+
expect(matchesFilter({ conversationId: "c-1" }, frame)).toBe(true);
|
|
95
|
+
expect(matchesFilter({ conversationId: "c-2" }, frame)).toBe(false);
|
|
96
|
+
});
|
|
97
|
+
it("notificationNamePrefix uses startsWith", () => {
|
|
98
|
+
const frame = filterableNotification("messages/received", {});
|
|
99
|
+
expect(matchesFilter({ notificationNamePrefix: "messages/" }, frame)).toBe(true);
|
|
100
|
+
expect(matchesFilter({ notificationNamePrefix: "presence/" }, frame)).toBe(false);
|
|
101
|
+
});
|
|
102
|
+
it("AND semantics: all set fields must match", () => {
|
|
103
|
+
const frame = filterableNotification("messages/received", {
|
|
104
|
+
__emissionTag: "tag-1",
|
|
105
|
+
conversationId: "c-1",
|
|
183
106
|
});
|
|
107
|
+
expect(matchesFilter({
|
|
108
|
+
emissionTag: "tag-1",
|
|
109
|
+
conversationId: "c-1",
|
|
110
|
+
notificationNamePrefix: "m",
|
|
111
|
+
}, frame)).toBe(true);
|
|
112
|
+
expect(matchesFilter({ emissionTag: "tag-1", conversationId: "c-other" }, frame)).toBe(false);
|
|
113
|
+
});
|
|
114
|
+
it("non-record `params` cannot satisfy payload-key filters", () => {
|
|
115
|
+
const stringData = filterableNotification("e", "string-payload");
|
|
116
|
+
expect(matchesFilter({ emissionTag: "x" }, stringData)).toBe(false);
|
|
117
|
+
expect(matchesFilter({ conversationId: "x" }, stringData)).toBe(false);
|
|
118
|
+
expect(matchesFilter({ notificationNamePrefix: "e" }, stringData)).toBe(true);
|
|
184
119
|
});
|
|
120
|
+
it("dispatches in registration order", () => Effect.runPromise(Effect.gen(function* () {
|
|
121
|
+
const registry = yield* makeSubscriberRegistry();
|
|
122
|
+
const order = [];
|
|
123
|
+
yield* registry.register({}, () => pushValue(order, "a"));
|
|
124
|
+
yield* registry.register({}, () => pushValue(order, "b"));
|
|
125
|
+
yield* registry.dispatch(taskFailedNotification());
|
|
126
|
+
expect(order).toEqual(["a", "b"]);
|
|
127
|
+
})));
|
|
128
|
+
it("unsubscribe stops delivery for the next frame", () => Effect.runPromise(Effect.gen(function* () {
|
|
129
|
+
const registry = yield* makeSubscriberRegistry();
|
|
130
|
+
const aCalls = [];
|
|
131
|
+
const bCalls = [];
|
|
132
|
+
let frameIdx = 0;
|
|
133
|
+
let unsubA = null;
|
|
134
|
+
const handleA = yield* registry.register({}, () => recordAndMaybeUnsubscribe(aCalls, frameIdx, unsubA));
|
|
135
|
+
unsubA = handleA.unsubscribe;
|
|
136
|
+
yield* registry.register({}, () => pushValue(bCalls, frameIdx));
|
|
137
|
+
frameIdx = 0;
|
|
138
|
+
yield* registry.dispatch(taskFailedNotification());
|
|
139
|
+
frameIdx = 1;
|
|
140
|
+
yield* registry.dispatch(taskFailedNotification());
|
|
141
|
+
expect(aCalls).toEqual([0]); // a saw frame 0, not frame 1.
|
|
142
|
+
expect(bCalls).toEqual([0, 1]); // b saw both — snapshot at start of frame 0 still included a; b is unaffected by a's unsub.
|
|
143
|
+
})));
|
|
144
|
+
it("filters narrow delivery", () => Effect.runPromise(Effect.gen(function* () {
|
|
145
|
+
const registry = yield* makeSubscriberRegistry();
|
|
146
|
+
const seenByConv1 = [];
|
|
147
|
+
const seenByConv2 = [];
|
|
148
|
+
yield* registry.register({ conversationId: CONV_1 }, (frame) => pushValue(seenByConv1, frame));
|
|
149
|
+
yield* registry.register({ conversationId: CONV_2 }, (frame) => pushValue(seenByConv2, frame));
|
|
150
|
+
yield* registry.dispatch(conversationArchivedNotification(CONV_1));
|
|
151
|
+
yield* registry.dispatch(conversationArchivedNotification(CONV_2));
|
|
152
|
+
expect(seenByConv1).toHaveLength(1);
|
|
153
|
+
expect(seenByConv2).toHaveLength(1);
|
|
154
|
+
expect(seenByConv1[0].params.conversationId).toBe(CONV_1);
|
|
155
|
+
expect(seenByConv2[0].params.conversationId).toBe(CONV_2);
|
|
156
|
+
})));
|
|
157
|
+
it("handler exceptions are caught and subsequent subscribers still run", () => Effect.runPromise(Effect.gen(function* () {
|
|
158
|
+
const registry = yield* makeSubscriberRegistry();
|
|
159
|
+
const otherCalls = [];
|
|
160
|
+
yield* registry.register({}, subscriberDefect);
|
|
161
|
+
yield* registry.register({}, () => pushValue(otherCalls, 1));
|
|
162
|
+
yield* registry.dispatch(taskFailedNotification());
|
|
163
|
+
expect(otherCalls).toEqual([1]); // other subscribers still fire.
|
|
164
|
+
})));
|
|
165
|
+
it("construction-time handler throw is caught", () => Effect.runPromise(Effect.gen(function* () {
|
|
166
|
+
const registry = yield* makeSubscriberRegistry();
|
|
167
|
+
const otherCalls = [];
|
|
168
|
+
yield* registry.register({}, constructionThrow);
|
|
169
|
+
yield* registry.register({}, () => pushValue(otherCalls, 1));
|
|
170
|
+
yield* registry.dispatch(taskFailedNotification());
|
|
171
|
+
expect(otherCalls).toEqual([1]); // subsequent subscribers still fire.
|
|
172
|
+
})));
|
|
173
|
+
it("closeAll drops every subscription", () => Effect.runPromise(Effect.gen(function* () {
|
|
174
|
+
const registry = yield* makeSubscriberRegistry();
|
|
175
|
+
const calls = [];
|
|
176
|
+
yield* registry.register({}, () => pushValue(calls, 1));
|
|
177
|
+
yield* registry.closeAll;
|
|
178
|
+
yield* registry.dispatch(taskFailedNotification());
|
|
179
|
+
expect(calls).toEqual([]);
|
|
180
|
+
})));
|
|
181
|
+
it("Ref-make composition works inside an Effect.gen", () => Effect.runPromise(
|
|
182
|
+
// Smoke test that the Effect surface composes; the registry never
|
|
183
|
+
// resolves with `never` failure tag, so this can't catch
|
|
184
|
+
// typechecker drift, but it does pin behaviour.
|
|
185
|
+
Effect.gen(function* () {
|
|
186
|
+
const registry = yield* makeSubscriberRegistry();
|
|
187
|
+
const counter = yield* Ref.make(0);
|
|
188
|
+
yield* registry.register({}, () => Ref.update(counter, increment));
|
|
189
|
+
yield* registry.dispatch(taskFailedNotification());
|
|
190
|
+
const result = yield* Ref.get(counter);
|
|
191
|
+
expect(result).toBe(1);
|
|
192
|
+
})));
|
|
185
193
|
//# sourceMappingURL=subscribers.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscribers.test.js","sourceRoot":"","sources":["../../src/runtime/subscribers.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"subscribers.test.js","sourceRoot":"","sources":["../../src/runtime/subscribers.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-socket-path.test.d.ts","sourceRoot":"","sources":["../src/service-socket-path.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { getMoltZapAgentServiceSocketPath } from "./local-paths.js";
|
|
3
|
+
import { FakeMoltZapService } from "./test-utils/fake-service.js";
|
|
4
|
+
const SAFE_AGENT_ID = "agent-abc_123";
|
|
5
|
+
const DEFAULT_SOCKET_SEGMENT = "default";
|
|
6
|
+
const SAFE_SOCKET_NAME = "service-agent-abc_123.sock";
|
|
7
|
+
const DEFAULT_SOCKET_NAME = "service-default.sock";
|
|
8
|
+
const ETC_PASSWD_SEGMENT = "etc/passwd";
|
|
9
|
+
const EXPECTED_DEFAULT_SOCKET_PATH = getMoltZapAgentServiceSocketPath(DEFAULT_SOCKET_SEGMENT);
|
|
10
|
+
const EXPECTED_SAFE_SOCKET_PATH = getMoltZapAgentServiceSocketPath(SAFE_AGENT_ID);
|
|
11
|
+
const MOLTZAP_SOCKET_DIR = EXPECTED_DEFAULT_SOCKET_PATH.slice(0, -DEFAULT_SOCKET_NAME.length);
|
|
12
|
+
function setOwnAgentId(service, id) {
|
|
13
|
+
Reflect.set(service, "_ownAgentId", id);
|
|
14
|
+
}
|
|
15
|
+
function socketPathAcceptsSafeAgentIds() {
|
|
16
|
+
const service = new FakeMoltZapService();
|
|
17
|
+
setOwnAgentId(service, SAFE_AGENT_ID);
|
|
18
|
+
expect(service.socketPath).toBe(EXPECTED_SAFE_SOCKET_PATH);
|
|
19
|
+
expect(service.socketPath.endsWith(SAFE_SOCKET_NAME)).toBe(true);
|
|
20
|
+
}
|
|
21
|
+
function socketPathRejectsTraversal() {
|
|
22
|
+
const service = new FakeMoltZapService();
|
|
23
|
+
setOwnAgentId(service, "../etc/passwd");
|
|
24
|
+
expect(service.socketPath).toBe(EXPECTED_DEFAULT_SOCKET_PATH);
|
|
25
|
+
expect(service.socketPath).not.toContain("..");
|
|
26
|
+
expect(service.socketPath).not.toContain(ETC_PASSWD_SEGMENT);
|
|
27
|
+
}
|
|
28
|
+
function socketPathRejectsForwardSlash() {
|
|
29
|
+
const service = new FakeMoltZapService();
|
|
30
|
+
setOwnAgentId(service, "foo/bar");
|
|
31
|
+
expect(service.socketPath).toBe(EXPECTED_DEFAULT_SOCKET_PATH);
|
|
32
|
+
}
|
|
33
|
+
function socketPathRejectsParentSegment() {
|
|
34
|
+
const service = new FakeMoltZapService();
|
|
35
|
+
setOwnAgentId(service, "..");
|
|
36
|
+
expect(service.socketPath).toBe(EXPECTED_DEFAULT_SOCKET_PATH);
|
|
37
|
+
}
|
|
38
|
+
function socketPathRejectsEmptyAndWhitespace() {
|
|
39
|
+
const service = new FakeMoltZapService();
|
|
40
|
+
setOwnAgentId(service, "");
|
|
41
|
+
expect(service.socketPath).toBe(EXPECTED_DEFAULT_SOCKET_PATH);
|
|
42
|
+
setOwnAgentId(service, " ");
|
|
43
|
+
expect(service.socketPath).toBe(EXPECTED_DEFAULT_SOCKET_PATH);
|
|
44
|
+
}
|
|
45
|
+
function socketPathRejectsPunctuation() {
|
|
46
|
+
const service = new FakeMoltZapService();
|
|
47
|
+
for (const bad of [
|
|
48
|
+
"a;b",
|
|
49
|
+
"a|b",
|
|
50
|
+
"a$b",
|
|
51
|
+
"a\\b",
|
|
52
|
+
"a\nb",
|
|
53
|
+
".hidden",
|
|
54
|
+
"foo.sock",
|
|
55
|
+
]) {
|
|
56
|
+
setOwnAgentId(service, bad);
|
|
57
|
+
expect(service.socketPath).toBe(EXPECTED_DEFAULT_SOCKET_PATH);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function socketPathDefaultsBeforeAgentAssignment() {
|
|
61
|
+
const service = new FakeMoltZapService();
|
|
62
|
+
expect(service.socketPath).toBe(EXPECTED_DEFAULT_SOCKET_PATH);
|
|
63
|
+
}
|
|
64
|
+
function rejectedSocketPathsStayInMoltzapDir() {
|
|
65
|
+
const service = new FakeMoltZapService();
|
|
66
|
+
for (const bad of ["../foo", "a/b", "a\x00b", "a\\b"]) {
|
|
67
|
+
setOwnAgentId(service, bad);
|
|
68
|
+
expect(service.socketPath.startsWith(MOLTZAP_SOCKET_DIR)).toBe(true);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
describe("MoltZapService.socketPath safe ids", () => {
|
|
72
|
+
it("accepts safe alphanumeric agent ids verbatim", socketPathAcceptsSafeAgentIds);
|
|
73
|
+
});
|
|
74
|
+
describe("MoltZapService.socketPath rejected ids", () => {
|
|
75
|
+
it("rejects `..` traversal and falls back to `service-default.sock`", socketPathRejectsTraversal);
|
|
76
|
+
it("rejects forward-slash separators", socketPathRejectsForwardSlash);
|
|
77
|
+
it("rejects a plain `..` agent id", socketPathRejectsParentSegment);
|
|
78
|
+
});
|
|
79
|
+
describe("MoltZapService.socketPath fallback ids", () => {
|
|
80
|
+
it("rejects empty-string and whitespace agent ids", socketPathRejectsEmptyAndWhitespace);
|
|
81
|
+
it("rejects shell metacharacters and path-like punctuation", socketPathRejectsPunctuation);
|
|
82
|
+
it("falls back to `default` when no agent id has been assigned yet", socketPathDefaultsBeforeAgentAssignment);
|
|
83
|
+
});
|
|
84
|
+
describe("MoltZapService.socketPath containment", () => {
|
|
85
|
+
it("keeps the socket inside ~/.moltzap/ for every rejected id", rejectedSocketPathsStayInMoltzapDir);
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=service-socket-path.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-socket-path.test.js","sourceRoot":"","sources":["../src/service-socket-path.test.ts"],"names":[],"mappings":"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"}
|
package/dist/service.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { type HelloOk, type AnyNotificationDefinition, type DecodedNotification, DispatchRequest, DispatchRelease, DispatchesConsumed, DispatchesExpired, DispatchesGet, type DispatchId, type Message, type ConversationArchivedNotification, type ConversationUnarchivedNotification,
|
|
1
|
+
import { type HelloOk, type AnyNotificationDefinition, type DecodedNotification, DispatchRequest, DispatchRelease, DispatchesConsumed, DispatchesExpired, DispatchesGet, type DispatchId, type Message, type ConversationArchivedNotification, type ConversationUnarchivedNotification, type RpcCallError, RpcTimeoutError, type NotificationParamsOf, type ParamsOf, type ResultOf, type RpcDefinition } from "@moltzap/protocol";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
|
-
import { type RpcCallOptions
|
|
3
|
+
import { type RpcCallOptions } from "./ws-client.js";
|
|
4
4
|
import { AgentNotFoundError } from "./runtime/errors.js";
|
|
5
5
|
/**
|
|
6
6
|
* Errors that can surface from the Effect-based service API. Matches the
|
|
7
7
|
* failure channel of `MoltZapWsClient.sendRpc` / `connect`.
|
|
8
8
|
*/
|
|
9
|
-
export type ServiceRpcError =
|
|
9
|
+
export type ServiceRpcError = RpcCallError | RpcTimeoutError;
|
|
10
10
|
export interface ConversationMeta {
|
|
11
11
|
id: string;
|
|
12
12
|
type: string;
|
|
@@ -28,10 +28,10 @@ export interface CrossConversationEntry {
|
|
|
28
28
|
/** Messages in this summary (capped by maxMessagesPerConv). */
|
|
29
29
|
count: number;
|
|
30
30
|
}
|
|
31
|
-
/** Escape
|
|
31
|
+
/** Escape `<`, `>`, `&` so sender content can't escape a `<system-reminder>` block. */
|
|
32
32
|
export declare function sanitizeForSystemReminder(s: string): string;
|
|
33
33
|
/**
|
|
34
|
-
* Format CrossConversationEntry[] as a
|
|
34
|
+
* Format CrossConversationEntry[] as a `<system-reminder>` block. Adapters
|
|
35
35
|
* that inline context into prompt text (nanoclaw) and `MoltZapService.getContext`
|
|
36
36
|
* share this formatter so sanitization and line shape stay in one place.
|
|
37
37
|
*/
|
|
@@ -41,14 +41,13 @@ export declare function formatCrossConversationBlock(entries: CrossConversationE
|
|
|
41
41
|
export interface ServiceOptions {
|
|
42
42
|
serverUrl: string;
|
|
43
43
|
agentKey: string;
|
|
44
|
-
logger?: WsClientLogger;
|
|
45
44
|
}
|
|
46
45
|
type NotificationHandler<T> = (data: T) => void;
|
|
47
46
|
interface ServiceHandlerPayloads {
|
|
48
47
|
readonly message: Message;
|
|
49
48
|
/**
|
|
50
49
|
* The "raw notification" surface receives the wire decoder's
|
|
51
|
-
* `DecodedNotification
|
|
50
|
+
* `DecodedNotification<AnyNotificationDefinition>` union — known methods carry the
|
|
52
51
|
* descriptor and a raw `params: unknown` payload (validation hasn't
|
|
53
52
|
* happened yet); unknown methods carry no descriptor at all.
|
|
54
53
|
* Subscribers that want validated payloads register specific typed
|
|
@@ -96,7 +95,18 @@ export declare class MoltZapService {
|
|
|
96
95
|
private readonly lastNotifiedRef;
|
|
97
96
|
private readonly lastReadRef;
|
|
98
97
|
private readonly archivedConversationIds;
|
|
98
|
+
/**
|
|
99
|
+
* Insertion-ordered set of recently seen messageIds per conversation.
|
|
100
|
+
* Bounded at DEDUP_WINDOW_PER_CONV entries per conversation; oldest entry
|
|
101
|
+
* is evicted when the window is full. Set#keys() preserves insertion
|
|
102
|
+
* order in V8 / the spec, so eviction via `.next()` is O(1).
|
|
103
|
+
*
|
|
104
|
+
* Keyed and valued by their branded ids so the compiler rejects a
|
|
105
|
+
* `MessageId` accidentally used as a conversation key (or vice versa).
|
|
106
|
+
*/
|
|
107
|
+
private readonly seenMessageIds;
|
|
99
108
|
private readonly handlers;
|
|
109
|
+
private readonly notificationDispatchers;
|
|
100
110
|
private _ownAgentId;
|
|
101
111
|
constructor(opts: ServiceOptions);
|
|
102
112
|
get connected(): boolean;
|
|
@@ -105,12 +115,12 @@ export declare class MoltZapService {
|
|
|
105
115
|
connect(): Effect.Effect<HelloOk, ServiceRpcError>;
|
|
106
116
|
/**
|
|
107
117
|
* Tear down the service. `close()` is sync because it fans out to the
|
|
108
|
-
* socket server, Refs, and the ws-client
|
|
109
|
-
*
|
|
110
|
-
* shutdown
|
|
118
|
+
* socket server, Refs, and the ws-client. Effectful network/filesystem
|
|
119
|
+
* cleanup is forked at the edge so existing callers still get immediate
|
|
120
|
+
* shutdown.
|
|
111
121
|
*/
|
|
112
122
|
close(): void;
|
|
113
|
-
private
|
|
123
|
+
private socketServerScope;
|
|
114
124
|
private activeSocketPath;
|
|
115
125
|
/** Default socket path for CLI discovery. Per-instance path uses agentId. */
|
|
116
126
|
static readonly SOCKET_PATH: string;
|
|
@@ -123,17 +133,15 @@ export declare class MoltZapService {
|
|
|
123
133
|
private static safeAgentIdSegment;
|
|
124
134
|
/** Per-instance socket path based on connected agentId. */
|
|
125
135
|
get socketPath(): string;
|
|
126
|
-
startSocketServer(): void
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
* Handle one JSON line from the unix socket as an Effect. Parses the
|
|
130
|
-
* request, dispatches through `handleSocketRequestEffect`, and writes
|
|
131
|
-
* either a `{result}` or `{error}` frame back onto the connection.
|
|
132
|
-
* Never fails — all branches resolve into a `conn.write` side effect.
|
|
133
|
-
*/
|
|
134
|
-
private handleSocketLineEffect;
|
|
136
|
+
startSocketServer(): Effect.Effect<void, unknown, never>;
|
|
137
|
+
private resetSocketServerState;
|
|
138
|
+
private stopSocketServer;
|
|
135
139
|
private handleSocketRequestEffect;
|
|
136
140
|
private handleHistoryRequest;
|
|
141
|
+
private loadHistorySupportData;
|
|
142
|
+
private refreshHistoryAgentNames;
|
|
143
|
+
private fetchHistoryConversationMeta;
|
|
144
|
+
private advanceHistoryLastRead;
|
|
137
145
|
getConversation(convId: string): ConversationMeta | undefined;
|
|
138
146
|
isConversationArchived(convId: string): boolean;
|
|
139
147
|
getConversations(): ConversationMeta[];
|
|
@@ -196,6 +204,7 @@ export declare class MoltZapService {
|
|
|
196
204
|
commit: () => void;
|
|
197
205
|
};
|
|
198
206
|
private readCrossConvState;
|
|
207
|
+
private collectContextCandidates;
|
|
199
208
|
private iterNewMessagesByConv;
|
|
200
209
|
private advanceLastNotified;
|
|
201
210
|
on<K extends ServiceHandlerName>(notification: K, handler: NotificationHandler<ServiceHandlerPayloads[K]>): void;
|
|
@@ -208,9 +217,26 @@ export declare class MoltZapService {
|
|
|
208
217
|
*/
|
|
209
218
|
private refreshConversationParticipants;
|
|
210
219
|
protected handleNotification(notification: DecodedNotification<AnyNotificationDefinition>): void;
|
|
220
|
+
private recordNotificationTrace;
|
|
221
|
+
private dispatchTypedNotification;
|
|
222
|
+
/**
|
|
223
|
+
* Record `messageId` in the per-conversation dedup window. Returns
|
|
224
|
+
* `true` when the id is new (caller proceeds), `false` when the id is
|
|
225
|
+
* a duplicate within the window (caller drops). On a new id, evicts
|
|
226
|
+
* the oldest entry if the window is full.
|
|
227
|
+
*
|
|
228
|
+
* Bound to the live `messages/received` notification path: a single
|
|
229
|
+
* server-side broadcast that surfaces the same id twice (network
|
|
230
|
+
* replay, dual subscription) is suppressed to one
|
|
231
|
+
* `on("message", ...)` event. `messages/list` returns raw history
|
|
232
|
+
* unfiltered; consumers that combine both feeds dedup themselves.
|
|
233
|
+
*/
|
|
234
|
+
private recordMessageIdIfNew;
|
|
211
235
|
private handleMessageReceivedNotification;
|
|
212
236
|
private handleConversationCreatedNotification;
|
|
213
237
|
private handleConversationUpdatedNotification;
|
|
238
|
+
private handleConversationArchivedNotification;
|
|
239
|
+
private handleConversationUnarchivedNotification;
|
|
214
240
|
private upsertConversationNotification;
|
|
215
241
|
private markConversationArchived;
|
|
216
242
|
private storeMessage;
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,OAAO,EAKZ,KAAK,yBAAyB,EAE9B,KAAK,mBAAmB,EACxB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,KAAK,UAAU,EACf,KAAK,OAAO,EAEZ,KAAK,gCAAgC,EACrC,KAAK,kCAAkC,EAWvC,KAAK,YAAY,EAEjB,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAGL,MAAM,EAKP,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AA6EzD;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,eAAe,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,uEAAuE;AACvE,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,iGAAiG;AACjG,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,sBAAsB,EAAE,EACjC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GACvB,MAAM,GAAG,IAAI,CAef;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;AAKhD,UAAU,sBAAsB;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,EAAE,mBAAmB,CAAC,yBAAyB,CAAC,CAAC;IACzE,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,oBAAoB,EAAE,gCAAgC,CAAC;IAChE,QAAQ,CAAC,sBAAsB,EAAE,kCAAkC,CAAC;IACpE,QAAQ,CAAC,eAAe,EAAE,oBAAoB,CAAC,OAAO,eAAe,CAAC,CAAC;IACvE,QAAQ,CAAC,kBAAkB,EAAE,oBAAoB,CAAC,OAAO,kBAAkB,CAAC,CAAC;IAC7E,QAAQ,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,OAAO,iBAAiB,CAAC,CAAC;CAC5E;AAED,KAAK,kBAAkB,GAAG,MAAM,sBAAsB,CAAC;AAEvD,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAkCD;;;;;;;;;;GAUG;AACH,qBAAa,cAAc;IA2Hb,OAAO,CAAC,IAAI;IA1HxB,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAEuC;IACxE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAEkD;IAC9E,OAAO,CAAC,QAAQ,CAAC,aAAa,CAC8B;IAC5D,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAEoB;IAC9D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAI9B;IACF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAM1B;IACF,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAqB;IAE7D;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6C;IAC5E,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAcvB;IACF,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAiErC;IAEH,OAAO,CAAC,WAAW,CAAqB;gBAEpB,IAAI,EAAE,cAAc;IAExC,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAEnC;IAED,yFAAyF;IACzF,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC;IAiClD;;;;;OAKG;IACH,KAAK,IAAI,IAAI;IA2Bb,OAAO,CAAC,iBAAiB,CAAqC;IAC9D,OAAO,CAAC,gBAAgB,CAAuB;IAE/C,6EAA6E;IAC7E,MAAM,CAAC,QAAQ,CAAC,WAAW,SAAiC;IAE5D;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAIjC,2DAA2D;IAC3D,IAAI,UAAU,IAAI,MAAM,CAGvB;IAED,iBAAiB,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC;IAmBxD,OAAO,CAAC,sBAAsB;IAW9B,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,yBAAyB;IAkDjC,OAAO,CAAC,oBAAoB;IAqC5B,OAAO,CAAC,sBAAsB;IAkB9B,OAAO,CAAC,wBAAwB;IAyBhC,OAAO,CAAC,4BAA4B;IASpC,OAAO,CAAC,sBAAsB;IAgC9B,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAM7D,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAI/C,gBAAgB,IAAI,gBAAgB,EAAE;IAMtC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE;IAWrD,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAMjD;;;;;OAKG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IA+B/D,IAAI,CACF,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,GACpD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC;IAqBvC;;;;OAIG;IACH,eAAe,CACb,MAAM,EAAE,QAAQ,CAAC,OAAO,eAAe,CAAC,GACvC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,eAAe,CAAC,EAAE,eAAe,CAAC;IAInE;;;;OAIG;IACH,aAAa,CAAC,MAAM,EAAE;QACpB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;KACjC,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,aAAa,CAAC,EAAE,eAAe,CAAC;IAIlE,WAAW,CACT,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,GAAG,kBAAkB,CAAC;IA4B5D;;;;OAIG;IACH,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAavE;;;;;OAKG;IACH,kBAAkB,CAChB,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;KAAE,GAChE;QAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE;IAmB5D;;;;OAIG;IACH,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG;QACvC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAC7B,MAAM,EAAE,MAAM,IAAI,CAAC;KACpB;IAsCD,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,wBAAwB;IAgBhC,OAAO,CAAE,qBAAqB;IAgB9B,OAAO,CAAC,mBAAmB;IAoB3B,EAAE,CAAC,CAAC,SAAS,kBAAkB,EAC7B,YAAY,EAAE,CAAC,EACf,OAAO,EAAE,mBAAmB,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,GACtD,IAAI;IAMP,OAAO,CAAC,CAAC,SAAS,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,EAC/C,UAAU,EAAE,CAAC,EACb,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EACnB,IAAI,CAAC,EAAE,cAAc,GACpB,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC;IAW9C;;;;;OAKG;IACH,OAAO,CAAC,+BAA+B;IA8BvC,SAAS,CAAC,kBAAkB,CAC1B,YAAY,EAAE,mBAAmB,CAAC,yBAAyB,CAAC,GAC3D,IAAI;IAMP,OAAO,CAAC,uBAAuB;IAU/B,OAAO,CAAC,yBAAyB;IAUjC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,oBAAoB;IAoB5B,OAAO,CAAC,iCAAiC;IAmBzC,OAAO,CAAC,qCAAqC;IAS7C,OAAO,CAAC,qCAAqC;IAM7C,OAAO,CAAC,sCAAsC;IAO9C,OAAO,CAAC,wCAAwC;IAOhD,OAAO,CAAC,8BAA8B;IAsBtC,OAAO,CAAC,wBAAwB;IAiDhC,OAAO,CAAC,YAAY;CAiBrB"}
|