@moltzap/router 2026.902.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +19 -0
  3. package/README.md +31 -0
  4. package/bin/moltzap-router +9 -0
  5. package/dist/index.d.ts +16 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +16 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/router/contract.d.ts +209 -0
  10. package/dist/router/contract.d.ts.map +1 -0
  11. package/dist/router/contract.js +347 -0
  12. package/dist/router/contract.js.map +1 -0
  13. package/dist/router/feed.d.ts +89 -0
  14. package/dist/router/feed.d.ts.map +1 -0
  15. package/dist/router/feed.js +157 -0
  16. package/dist/router/feed.js.map +1 -0
  17. package/dist/router/http.d.ts +30 -0
  18. package/dist/router/http.d.ts.map +1 -0
  19. package/dist/router/http.js +219 -0
  20. package/dist/router/http.js.map +1 -0
  21. package/dist/router/poll-cursor.d.ts +50 -0
  22. package/dist/router/poll-cursor.d.ts.map +1 -0
  23. package/dist/router/poll-cursor.js +142 -0
  24. package/dist/router/poll-cursor.js.map +1 -0
  25. package/dist/router/poll-waiters.d.ts +24 -0
  26. package/dist/router/poll-waiters.d.ts.map +1 -0
  27. package/dist/router/poll-waiters.js +66 -0
  28. package/dist/router/poll-waiters.js.map +1 -0
  29. package/dist/router/poll.d.ts +38 -0
  30. package/dist/router/poll.d.ts.map +1 -0
  31. package/dist/router/poll.js +118 -0
  32. package/dist/router/poll.js.map +1 -0
  33. package/dist/router/rpc.d.ts +37 -0
  34. package/dist/router/rpc.d.ts.map +1 -0
  35. package/dist/router/rpc.js +75 -0
  36. package/dist/router/rpc.js.map +1 -0
  37. package/dist/router/send.d.ts +27 -0
  38. package/dist/router/send.d.ts.map +1 -0
  39. package/dist/router/send.js +91 -0
  40. package/dist/router/send.js.map +1 -0
  41. package/dist/router.d.ts +60 -0
  42. package/dist/router.d.ts.map +1 -0
  43. package/dist/router.js +177 -0
  44. package/dist/router.js.map +1 -0
  45. package/dist/server.d.ts +29 -0
  46. package/dist/server.d.ts.map +1 -0
  47. package/dist/server.js +112 -0
  48. package/dist/server.js.map +1 -0
  49. package/package.json +128 -0
@@ -0,0 +1,118 @@
1
+ /** @file Verified polling over the volatile feed, cursor codec, and bounded waiters. */
2
+ import { InternalServerError, OverloadedError, } from "@moltzap/identity";
3
+ import canonicalize from "canonicalize";
4
+ import { Duration, Effect, Option, Schema } from "effect";
5
+ import { RouterPollResult, } from "./contract.js";
6
+ import { entriesAfter } from "./feed.js";
7
+ /**
8
+ * Builds endpoint-wide bounded polling over one volatile global feed.
9
+ *
10
+ * @param input Current process state and finite poll bounds.
11
+ * @param input.routerInstanceId Current volatile process identity.
12
+ * @param input.feed Global volatile feed.
13
+ * @param input.pollWaiters Addressed poll-waiter notifications.
14
+ * @param input.cursorCodec Caller-bound cursor codec.
15
+ * @param input.pollMessageLimit Maximum messages in one result.
16
+ * @param input.pollResponseByteLimit Maximum complete result bytes.
17
+ * @returns The authenticated poll domain operation.
18
+ */
19
+ export const makeRouterPoll = (input) => Object.freeze({
20
+ handle: (request, verifiedRequest) => handlePoll(input, request, verifiedRequest),
21
+ });
22
+ const HOLD_DURATION = Duration.seconds(25);
23
+ const utf8Encoder = new TextEncoder();
24
+ const encodedResultLength = (result) => Schema.encode(RouterPollResult)(result).pipe(Effect.catchTag("ParseError", () => Effect.fail(new InternalServerError())), Effect.flatMap((encoded) => {
25
+ const jcs = canonicalize(encoded);
26
+ return jcs === undefined
27
+ ? Effect.fail(new InternalServerError())
28
+ : Effect.succeed(utf8Encoder.encode(jcs).byteLength);
29
+ }));
30
+ const addressedDataIsReady = (feed, callerAgentId, order) => feed.snapshot.pipe(Effect.map((snapshot) => order < snapshot.greatestEvictedOrder ||
31
+ entriesAfter(snapshot, order).some((entry) => entry.recipients.has(callerAgentId))));
32
+ const makeBatch = (input, callerAgentId, signedMessages, lastScannedOrder) => input.cursorCodec.encrypt({ agentId: callerAgentId, lastScannedOrder }).pipe(Effect.catchTag("PollCursorEncryptionError", () => Effect.fail(new InternalServerError())), Effect.map((pollCursor) => ({
33
+ kind: "batch",
34
+ routerInstanceId: input.routerInstanceId,
35
+ signedMessages,
36
+ pollCursor,
37
+ })));
38
+ const scanEntry = (input, callerAgentId, state, entry) => {
39
+ if (!entry.recipients.has(callerAgentId)) {
40
+ return Effect.succeed(Option.some({
41
+ ...state,
42
+ lastScannedOrder: entry.order,
43
+ }));
44
+ }
45
+ if (state.selected.length >= input.pollMessageLimit) {
46
+ return Effect.succeed(Option.none());
47
+ }
48
+ const selected = [...state.selected, entry.signedMessage];
49
+ return makeBatch(input, callerAgentId, selected, entry.order).pipe(Effect.flatMap(encodedResultLength), Effect.map((byteLength) => byteLength <= input.pollResponseByteLimit
50
+ ? Option.some({
51
+ selected,
52
+ lastScannedOrder: entry.order,
53
+ })
54
+ : Option.none()));
55
+ };
56
+ const scan = (input, snapshot, callerAgentId, startOrder) => Effect.gen(function* () {
57
+ let state = {
58
+ selected: [],
59
+ lastScannedOrder: startOrder,
60
+ };
61
+ let reachedTail = true;
62
+ for (const entry of entriesAfter(snapshot, startOrder)) {
63
+ const next = yield* scanEntry(input, callerAgentId, state, entry);
64
+ if (Option.isNone(next)) {
65
+ reachedTail = false;
66
+ break;
67
+ }
68
+ state = next.value;
69
+ }
70
+ return {
71
+ result: yield* makeBatch(input, callerAgentId, state.selected, state.lastScannedOrder),
72
+ reachedTail,
73
+ lastScannedOrder: state.lastScannedOrder,
74
+ };
75
+ });
76
+ const feedGap = (routerInstanceId) => ({
77
+ kind: "feed_gap",
78
+ routerInstanceId,
79
+ });
80
+ const holdAtTail = (input, callerAgentId, startOrder) => input.pollWaiters
81
+ .awaitSignal(callerAgentId, addressedDataIsReady(input.feed, callerAgentId, startOrder))
82
+ .pipe(Effect.raceFirst(Effect.sleep(HOLD_DURATION)), Effect.catchTag("HeldPollCapacityError", () => Effect.fail(new OverloadedError())));
83
+ const continueFromOrder = (input, callerAgentId, startOrder) => Effect.gen(function* () {
84
+ const snapshot = yield* input.feed.snapshot;
85
+ if (startOrder > snapshot.tailOrder) {
86
+ return { kind: "cursor_invalid" };
87
+ }
88
+ if (startOrder < snapshot.greatestEvictedOrder) {
89
+ return feedGap(input.routerInstanceId);
90
+ }
91
+ const first = yield* scan(input, snapshot, callerAgentId, startOrder);
92
+ const hasImmediateResult = first.result.kind !== "batch" ||
93
+ first.result.signedMessages.length > 0 ||
94
+ !first.reachedTail;
95
+ if (hasImmediateResult) {
96
+ return first.result;
97
+ }
98
+ yield* holdAtTail(input, callerAgentId, first.lastScannedOrder);
99
+ const finalSnapshot = yield* input.feed.snapshot;
100
+ if (first.lastScannedOrder < finalSnapshot.greatestEvictedOrder) {
101
+ return feedGap(input.routerInstanceId);
102
+ }
103
+ return (yield* scan(input, finalSnapshot, callerAgentId, first.lastScannedOrder)).result;
104
+ });
105
+ const continuePoll = (input, callerAgentId, pollCursor) => input.cursorCodec.decrypt(pollCursor, callerAgentId).pipe(Effect.option, Effect.flatMap(Option.match({
106
+ onNone: () => Effect.succeed({
107
+ kind: "cursor_invalid",
108
+ }),
109
+ onSome: (order) => continueFromOrder(input, callerAgentId, order),
110
+ })));
111
+ function handlePoll(input, request, verifiedRequest) {
112
+ const callerAgentId = verifiedRequest.callerAgentId;
113
+ if (request.pollCursor !== undefined) {
114
+ return continuePoll(input, callerAgentId, request.pollCursor);
115
+ }
116
+ return input.feed.snapshot.pipe(Effect.flatMap((snapshot) => makeBatch(input, callerAgentId, [], snapshot.tailOrder)));
117
+ }
118
+ //# sourceMappingURL=poll.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"poll.js","sourceRoot":"","sources":["../../src/router/poll.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { AuthenticationFailedError, InternalServerError, OverloadedError, type VerifiedAgentRequest } from "@moltzap/identity";
2
+ import { Effect, type Scope } from "effect";
3
+ import type { RouterPoll } from "./poll.js";
4
+ import type { RouterSend } from "./send.js";
5
+ import { type RawRouterSendRequest as RawRouterSendRequestValue, type RouterPollRequest as RouterPollRequestValue, type RouterPollResult as RouterPollResultValue, type RouterSendResult as RouterSendResultValue } from "./contract.js";
6
+ type RouterHandlerError = AuthenticationFailedError | OverloadedError | InternalServerError;
7
+ /** Typed package-private client used by the HTTP adapter. */
8
+ export interface RouterRpcClient {
9
+ readonly send: (input: {
10
+ readonly request: RawRouterSendRequestValue;
11
+ }) => Effect.Effect<RouterSendResultValue, RouterHandlerError>;
12
+ readonly poll: (input: {
13
+ readonly request: RouterPollRequestValue;
14
+ }) => Effect.Effect<RouterPollResultValue, RouterHandlerError>;
15
+ }
16
+ /**
17
+ * Connects private typed operations directly to their handlers.
18
+ *
19
+ * @param input Domain handlers for both correlated operations.
20
+ * @param input.send Send domain handler.
21
+ * @param input.poll Poll domain handler.
22
+ * @returns A scoped in-process client with typed failures.
23
+ */
24
+ export declare const makeRouterRpcClient: (input: {
25
+ readonly send: RouterSend;
26
+ readonly poll: RouterPoll;
27
+ }) => Effect.Effect<RouterRpcClient, never, Scope.Scope>;
28
+ /**
29
+ * Limits one verified request proof to the dynamic extent of one RPC call.
30
+ *
31
+ * @param verifiedRequest Authentication proof for the current HTTP request.
32
+ * @param effect Correlated private RPC call.
33
+ * @returns The call with the proof installed only for its dynamic extent.
34
+ */
35
+ export declare const withVerifiedRouterRequest: <A, E, R>(verifiedRequest: VerifiedAgentRequest, effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
36
+ export {};
37
+ //# sourceMappingURL=rpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc.d.ts","sourceRoot":"","sources":["../../src/router/rpc.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,KAAK,oBAAoB,EAC1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAGL,MAAM,EAKN,KAAK,KAAK,EACX,MAAM,QAAQ,CAAC;AAChB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAEL,KAAK,oBAAoB,IAAI,yBAAyB,EAEtD,KAAK,iBAAiB,IAAI,sBAAsB,EAEhD,KAAK,gBAAgB,IAAI,qBAAqB,EAE9C,KAAK,gBAAgB,IAAI,qBAAqB,EAC/C,MAAM,eAAe,CAAC;AAEvB,KAAK,kBAAkB,GACnB,yBAAyB,GACzB,eAAe,GACf,mBAAmB,CAAC;AAExB,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE;QACrB,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC;KAC7C,KAAK,MAAM,CAAC,MAAM,CAAC,qBAAqB,EAAE,kBAAkB,CAAC,CAAC;IAC/D,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE;QACrB,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;KAC1C,KAAK,MAAM,CAAC,MAAM,CAAC,qBAAqB,EAAE,kBAAkB,CAAC,CAAC;CAChE;AA6CD;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,UAAW;IACzC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;CAC3B,KAAG,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CA6BpD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,mBAC9B,oBAAoB,UAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CACsD,CAAC"}
@@ -0,0 +1,75 @@
1
+ /** @file Private correlated RPC between authenticated HTTP and Router operations. */
2
+ import { Rpc, RpcClient, RpcGroup, RpcMiddleware, RpcServer, } from "@effect/rpc";
3
+ import { AuthenticationFailedError, InternalServerError, OverloadedError, } from "@moltzap/identity";
4
+ import { Context, Deferred, Effect, FiberRef, Layer, Option, Schema, } from "effect";
5
+ import { RawRouterSendRequest, RouterPollRequest, RouterPollResult, RouterSendResult, } from "./contract.js";
6
+ const currentVerifiedRequest = FiberRef.unsafeMake(Option.none());
7
+ /** Private RPC service containing the current verified HTTP request. */
8
+ class VerifiedRouterRequest extends Context.Tag("@moltzap/router/VerifiedRouterRequest")() {
9
+ }
10
+ /** Required private RPC middleware for registered-agent operations. */
11
+ class RegisteredAgentRequest extends RpcMiddleware.Tag()("@moltzap/router/RegisteredAgentRequest", {
12
+ failure: AuthenticationFailedError,
13
+ provides: VerifiedRouterRequest,
14
+ }) {
15
+ }
16
+ const registeredAgentRequestLayer = Layer.succeed(RegisteredAgentRequest, () => FiberRef.get(currentVerifiedRequest).pipe(Effect.flatMap(Option.match({
17
+ onNone: () => Effect.fail(new AuthenticationFailedError()),
18
+ onSome: Effect.succeed,
19
+ }))));
20
+ const handlerErrors = Schema.Union(OverloadedError, InternalServerError);
21
+ const sendRpc = Rpc.make("send", {
22
+ payload: { request: RawRouterSendRequest },
23
+ success: RouterSendResult,
24
+ error: handlerErrors,
25
+ }).middleware(RegisteredAgentRequest);
26
+ const pollRpc = Rpc.make("poll", {
27
+ payload: { request: RouterPollRequest },
28
+ success: RouterPollResult,
29
+ error: handlerErrors,
30
+ }).middleware(RegisteredAgentRequest);
31
+ const routerRpcGroup = RpcGroup.make(sendRpc, pollRpc);
32
+ /**
33
+ * Connects private typed operations directly to their handlers.
34
+ *
35
+ * @param input Domain handlers for both correlated operations.
36
+ * @param input.send Send domain handler.
37
+ * @param input.poll Poll domain handler.
38
+ * @returns A scoped in-process client with typed failures.
39
+ */
40
+ export const makeRouterRpcClient = (input) => {
41
+ const handlerLayer = makeRouterRpcHandlersLayer(input);
42
+ return Effect.gen(function* () {
43
+ const clientReady = yield* Deferred.make();
44
+ const server = yield* RpcServer.makeNoSerialization(routerRpcGroup, {
45
+ onFromServer: (message) => Deferred.await(clientReady).pipe(Effect.flatMap((client) => client.write(message))),
46
+ });
47
+ const client = yield* RpcClient.makeNoSerialization(routerRpcGroup, {
48
+ supportsAck: true,
49
+ onFromClient: ({ message }) => server.write(0, message),
50
+ });
51
+ yield* Deferred.succeed(clientReady, client);
52
+ return client.client;
53
+ }).pipe(Effect.provide(handlerLayer), Effect.provide(registeredAgentRequestLayer), Effect.withSpan("makeRouterRpcClient"));
54
+ };
55
+ /**
56
+ * Limits one verified request proof to the dynamic extent of one RPC call.
57
+ *
58
+ * @param verifiedRequest Authentication proof for the current HTTP request.
59
+ * @param effect Correlated private RPC call.
60
+ * @returns The call with the proof installed only for its dynamic extent.
61
+ */
62
+ export const withVerifiedRouterRequest = (verifiedRequest, effect) => Effect.locally(currentVerifiedRequest, Option.some(verifiedRequest))(effect);
63
+ function makeRouterRpcHandlersLayer(input) {
64
+ return routerRpcGroup.toLayer({
65
+ send: ({ request }) => Effect.gen(function* () {
66
+ const verifiedRequest = yield* VerifiedRouterRequest;
67
+ return yield* input.send.handle(request, verifiedRequest);
68
+ }),
69
+ poll: ({ request }) => Effect.gen(function* () {
70
+ const verifiedRequest = yield* VerifiedRouterRequest;
71
+ return yield* input.poll.handle(request, verifiedRequest);
72
+ }),
73
+ });
74
+ }
75
+ //# sourceMappingURL=rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../src/router/rpc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /** @file Verified opaque-message acceptance into the volatile feed. */
2
+ import { InternalServerError, OverloadedError, type VerifiedAgentRequest } from "@moltzap/identity";
3
+ import { Effect } from "effect";
4
+ import type { RouterFeed } from "./feed.js";
5
+ import type { PollWaiters } from "./poll-waiters.js";
6
+ import { type RawRouterSendRequest, type RouterInstanceId, type RouterSendResult } from "./contract.js";
7
+ /** Send domain operation after HTTP authentication. */
8
+ export interface RouterSend {
9
+ readonly handle: (request: RawRouterSendRequest, verifiedRequest: VerifiedAgentRequest) => Effect.Effect<RouterSendResult, OverloadedError | InternalServerError>;
10
+ }
11
+ interface SendDependencies {
12
+ readonly routerInstanceId: RouterInstanceId;
13
+ readonly feed: RouterFeed;
14
+ readonly pollWaiters: PollWaiters;
15
+ }
16
+ /**
17
+ * Builds send precedence over one current Router instance and feed.
18
+ *
19
+ * @param input Current process identity and state capabilities.
20
+ * @param input.routerInstanceId Current volatile process identity.
21
+ * @param input.feed Global volatile feed.
22
+ * @param input.pollWaiters Addressed poll-waiter notifications.
23
+ * @returns The authenticated send domain operation.
24
+ */
25
+ export declare const makeRouterSend: (input: SendDependencies) => RouterSend;
26
+ export {};
27
+ //# sourceMappingURL=send.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/router/send.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,OAAO,EACL,mBAAmB,EACnB,eAAe,EAGf,KAAK,oBAAoB,EAE1B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,EAAoB,MAAM,QAAQ,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAEtB,MAAM,eAAe,CAAC;AAEvB,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,CACf,OAAO,EAAE,oBAAoB,EAC7B,eAAe,EAAE,oBAAoB,KAClC,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,eAAe,GAAG,mBAAmB,CAAC,CAAC;CAC7E;AAED,UAAU,gBAAgB;IACxB,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,UAAW,gBAAgB,KAAG,UAMrD,CAAC"}
@@ -0,0 +1,91 @@
1
+ /** @file Verified opaque-message acceptance into the volatile feed. */
2
+ import { InternalServerError, OverloadedError, SignedMessage, } from "@moltzap/identity";
3
+ import canonicalize from "canonicalize";
4
+ import { Effect, Encoding, Schema } from "effect";
5
+ import { SignedMessageDigest, } from "./contract.js";
6
+ /**
7
+ * Builds send precedence over one current Router instance and feed.
8
+ *
9
+ * @param input Current process identity and state capabilities.
10
+ * @param input.routerInstanceId Current volatile process identity.
11
+ * @param input.feed Global volatile feed.
12
+ * @param input.pollWaiters Addressed poll-waiter notifications.
13
+ * @returns The authenticated send domain operation.
14
+ */
15
+ export const makeRouterSend = (input) => Object.freeze({
16
+ handle: (request, verifiedRequest) => handleSend(input, request, verifiedRequest),
17
+ });
18
+ const messageInvalid = { kind: "message_invalid" };
19
+ const utf8Encoder = new TextEncoder();
20
+ const encodedLengthIsValid = (message, encodedMessageJcs) => {
21
+ const encodedByteLength = SignedMessage.encodedByteLength(message);
22
+ return (encodedByteLength === utf8Encoder.encode(encodedMessageJcs).byteLength &&
23
+ encodedByteLength <= SignedMessage.maximumEncodedByteLength);
24
+ };
25
+ const retainMessage = (input, mode, message) => Effect.gen(function* () {
26
+ const encodedMessageJcs = yield* encodeMessage(message);
27
+ if (!encodedLengthIsValid(message, encodedMessageJcs)) {
28
+ return messageInvalid;
29
+ }
30
+ const signedMessageDigest = yield* digestMessage(encodedMessageJcs);
31
+ const recipients = new Set(message.recipientAgentIds);
32
+ const accepted = yield* input.feed.accept({
33
+ mode,
34
+ signedMessage: message,
35
+ encodedMessageJcs,
36
+ encodedByteLength: SignedMessage.encodedByteLength(message),
37
+ recipients,
38
+ senderAgentId: message.senderAgentId,
39
+ messageId: message.messageId,
40
+ signedMessageDigest,
41
+ });
42
+ if (accepted.kind === "overloaded") {
43
+ return yield* Effect.fail(new OverloadedError());
44
+ }
45
+ if (accepted.acceptedRecipients !== undefined) {
46
+ yield* input.pollWaiters.notify(accepted.acceptedRecipients);
47
+ }
48
+ return accepted.result;
49
+ });
50
+ const handleDecodedMessage = (input, request, verifiedRequest, signedMessage) => {
51
+ if (signedMessage.senderAgentId !== verifiedRequest.callerAgentId) {
52
+ return Effect.succeed(messageInvalid);
53
+ }
54
+ return SignedMessage.verify({
55
+ signedMessage,
56
+ agentCard: verifiedRequest.agentCard,
57
+ }).pipe(Effect.matchEffect({
58
+ onFailure: () => Effect.succeed(messageInvalid),
59
+ onSuccess: (message) => retainMessage(input, request.mode, message),
60
+ }));
61
+ };
62
+ const handleCurrentInstance = (input, request, verifiedRequest) => Schema.decodeUnknown(SignedMessage)(request.signedMessage, {
63
+ exact: true,
64
+ onExcessProperty: "error",
65
+ }).pipe(Effect.matchEffect({
66
+ onFailure: () => Effect.succeed(messageInvalid),
67
+ onSuccess: (signedMessage) => handleDecodedMessage(input, request, verifiedRequest, signedMessage),
68
+ }));
69
+ function handleSend(input, request, verifiedRequest) {
70
+ return request.expectedRouterInstanceId !== input.routerInstanceId
71
+ ? Effect.succeed({
72
+ kind: "router_restarted",
73
+ routerInstanceId: input.routerInstanceId,
74
+ })
75
+ : handleCurrentInstance(input, request, verifiedRequest);
76
+ }
77
+ function encodeMessage(signedMessage) {
78
+ return Schema.encode(SignedMessage)(signedMessage).pipe(Effect.catchTag("ParseError", () => Effect.fail(new InternalServerError())), Effect.flatMap((encoded) => {
79
+ const jcs = canonicalize(encoded);
80
+ return jcs === undefined
81
+ ? Effect.fail(new InternalServerError())
82
+ : Effect.succeed(jcs);
83
+ }));
84
+ }
85
+ function digestMessage(encodedMessageJcs) {
86
+ return Effect.tryPromise({
87
+ try: () => globalThis.crypto.subtle.digest("SHA-256", utf8Encoder.encode(encodedMessageJcs)),
88
+ catch: () => new InternalServerError(),
89
+ }).pipe(Effect.map((digest) => `smd_${Encoding.encodeBase64Url(new Uint8Array(digest))}`), Effect.flatMap(Schema.decodeUnknown(SignedMessageDigest)), Effect.catchTag("ParseError", () => Effect.fail(new InternalServerError())));
90
+ }
91
+ //# sourceMappingURL=send.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/router/send.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @file Public Router capability, its authenticated HTTP implementation, and
3
+ * the private process configuration consumed by the Router server.
4
+ */
5
+ import { HttpClient } from "@effect/platform";
6
+ import { type AgentId, type AgentSigningAuthority, type Ed25519PublicKey as Ed25519PublicKeyValue } from "@moltzap/identity";
7
+ import { Context, Duration, Effect, Layer } from "effect";
8
+ import { type RouterClientError, RouterPollRequest, RouterPollResult, RouterSendRequest, RouterSendResult } from "./router/contract.js";
9
+ interface RouterClientService {
10
+ readonly send: (input: {
11
+ readonly request: RouterSendRequest;
12
+ readonly callerAgentId: AgentId;
13
+ readonly signingAuthority: AgentSigningAuthority;
14
+ }) => Effect.Effect<RouterSendResult, RouterClientError>;
15
+ readonly poll: (input: {
16
+ readonly request: RouterPollRequest;
17
+ readonly callerAgentId: AgentId;
18
+ readonly signingAuthority: AgentSigningAuthority;
19
+ }) => Effect.Effect<RouterPollResult, RouterClientError>;
20
+ }
21
+ declare const Router_base: Context.TagClass<Router, "@moltzap/router/Router", RouterClientService>;
22
+ /** Opaque message acceptance and endpoint-wide bounded polling. */
23
+ export declare class Router extends Router_base {
24
+ static readonly send: (input: {
25
+ readonly request: RouterSendRequest;
26
+ readonly callerAgentId: AgentId;
27
+ readonly signingAuthority: AgentSigningAuthority;
28
+ }) => Effect.Effect<RouterSendResult, RouterClientError, Router>;
29
+ static readonly poll: (input: {
30
+ readonly request: RouterPollRequest;
31
+ readonly callerAgentId: AgentId;
32
+ readonly signingAuthority: AgentSigningAuthority;
33
+ }) => Effect.Effect<RouterPollResult, RouterClientError, Router>;
34
+ static readonly layer: (input: {
35
+ readonly origin: URL;
36
+ readonly sendTimeout: Duration.Duration;
37
+ readonly pollTimeout: Duration.Duration;
38
+ }) => Layer.Layer<Router, never, HttpClient.HttpClient>;
39
+ }
40
+ /** Complete validated private process configuration. */
41
+ export interface RouterConfiguration {
42
+ readonly host: string;
43
+ readonly port: number;
44
+ readonly registryOrigin: URL;
45
+ readonly registrySignerPublicKey: Ed25519PublicKeyValue;
46
+ readonly retainedMessageCapacity: number;
47
+ readonly retainedMessageByteCapacity: number;
48
+ readonly pollMessageLimit: number;
49
+ readonly pollResponseByteLimit: number;
50
+ readonly requestConcurrencyLimit: number;
51
+ readonly heldPollCapacity: number;
52
+ readonly liveNonceCapacity: number;
53
+ readonly agentCardCacheCapacity: number;
54
+ readonly registryLookupConcurrencyLimit: number;
55
+ readonly registryLookupTimeoutMs: number;
56
+ }
57
+ /** Loads and cross-validates the complete private Router process configuration. */
58
+ export declare const loadRouterConfiguration: Effect.Effect<RouterConfiguration, import("effect/ConfigError").ConfigError, never>;
59
+ export {};
60
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
package/dist/router.js ADDED
@@ -0,0 +1,177 @@
1
+ /**
2
+ * @file Public Router capability, its authenticated HTTP implementation, and
3
+ * the private process configuration consumed by the Router server.
4
+ */
5
+ import { HttpClient, HttpClientRequest, } from "@effect/platform";
6
+ import { AgentSigningError, AuthenticatedHttp, Ed25519PublicKey, SignedMessage, } from "@moltzap/identity";
7
+ import canonicalize from "canonicalize";
8
+ import { Config, Context, Duration, Effect, Layer, Option, Schema, } from "effect";
9
+ import { RouterConnectionError, routerHttpErrorFromResponse, RouterInvalidResponseError, routerJsonContentType, routerPollPath, RouterPollRequest, RouterPollResult, routerRepresentationLimits, RouterRequestTimeoutError, routerSendPath, RouterSendRequest, RouterSendResult, } from "./router/contract.js";
10
+ /** Opaque message acceptance and endpoint-wide bounded polling. */
11
+ export class Router extends Context.Tag("@moltzap/router/Router")() {
12
+ static send = Effect.serviceFunctionEffect(Router, (service) => service.send);
13
+ static poll = Effect.serviceFunctionEffect(Router, (service) => service.poll);
14
+ static layer = (input) => Layer.effect(Router, makeRouterClient(input));
15
+ }
16
+ function makeRouterClient(input) {
17
+ const settings = Object.freeze({
18
+ origin: new URL(input.origin.href),
19
+ sendTimeout: snapshotDuration(input.sendTimeout),
20
+ pollTimeout: snapshotDuration(input.pollTimeout),
21
+ });
22
+ return HttpClient.HttpClient.pipe(Effect.map((client) => makeClientService(client, settings)), Effect.withSpan("makeRouterClient"));
23
+ }
24
+ const invalidResponse = () => new RouterInvalidResponseError();
25
+ const utf8Decoder = new TextDecoder("utf-8", {
26
+ fatal: true,
27
+ ignoreBOM: true,
28
+ });
29
+ const utf8Encoder = new TextEncoder();
30
+ const sameBytes = (left, right) => {
31
+ if (left.byteLength !== right.byteLength) {
32
+ return false;
33
+ }
34
+ for (let index = 0; index < left.byteLength; index += 1) {
35
+ if (left[index] !== right[index]) {
36
+ return false;
37
+ }
38
+ }
39
+ return true;
40
+ };
41
+ const decodeUtf8 = (bytes) => Effect.try({
42
+ try: () => utf8Decoder.decode(bytes),
43
+ catch: invalidResponse,
44
+ });
45
+ const decodeCanonicalResult = (schema, bytes) => Effect.gen(function* () {
46
+ const text = yield* decodeUtf8(bytes);
47
+ const result = yield* Schema.decodeUnknown(Schema.parseJson(schema))(text, {
48
+ exact: true,
49
+ onExcessProperty: "error",
50
+ }).pipe(Effect.mapError(invalidResponse));
51
+ const encoded = yield* Schema.encode(schema)(result).pipe(Effect.mapError(invalidResponse));
52
+ const canonical = canonicalize(encoded);
53
+ if (canonical === undefined ||
54
+ !sameBytes(bytes, utf8Encoder.encode(canonical))) {
55
+ return yield* Effect.fail(invalidResponse());
56
+ }
57
+ return result;
58
+ });
59
+ const decodeResponse = (schema, response) => Effect.gen(function* () {
60
+ const bytes = yield* response.arrayBuffer.pipe(Effect.catchTag("ResponseError", () => Effect.fail(new RouterConnectionError())), Effect.map((buffer) => new Uint8Array(buffer)));
61
+ if (response.headers["content-type"] !== routerJsonContentType) {
62
+ return yield* Effect.fail(invalidResponse());
63
+ }
64
+ if (response.status === 200) {
65
+ return yield* decodeCanonicalResult(schema, bytes);
66
+ }
67
+ const text = yield* decodeUtf8(bytes);
68
+ const recognized = routerHttpErrorFromResponse(response.status, text);
69
+ if (Option.isNone(recognized) ||
70
+ !sameBytes(bytes, utf8Encoder.encode(text))) {
71
+ return yield* Effect.fail(invalidResponse());
72
+ }
73
+ return yield* Effect.fail(recognized.value);
74
+ });
75
+ const execute = (input) => Effect.gen(function* () {
76
+ const request = HttpClientRequest.post(new URL(input.path, input.origin));
77
+ const encodedRequest = yield* Schema.encode(input.requestSchema)(input.request).pipe(Effect.catchTag("ParseError", () => Effect.fail(new AgentSigningError())));
78
+ const signedRequest = yield* AuthenticatedHttp.signAgentRequest({
79
+ httpRequest: request,
80
+ callerAgentId: input.callerAgentId,
81
+ encodedRequest,
82
+ signingAuthority: input.signingAuthority,
83
+ });
84
+ const response = yield* input.client.execute(signedRequest).pipe(Effect.catchTags({
85
+ RequestError: () => Effect.fail(new RouterConnectionError()),
86
+ ResponseError: () => Effect.fail(new RouterConnectionError()),
87
+ }));
88
+ return yield* decodeResponse(input.schema, response);
89
+ }).pipe(Effect.timeoutFail({
90
+ duration: input.timeout,
91
+ onTimeout: () => new RouterRequestTimeoutError(),
92
+ }));
93
+ function snapshotDuration(duration) {
94
+ return Duration.match(duration, {
95
+ onMillis: Duration.millis,
96
+ onNanos: Duration.nanos,
97
+ });
98
+ }
99
+ function makeClientService(client, settings) {
100
+ return {
101
+ send: (call) => execute({
102
+ client,
103
+ origin: settings.origin,
104
+ path: routerSendPath,
105
+ request: call.request,
106
+ requestSchema: RouterSendRequest,
107
+ schema: RouterSendResult,
108
+ callerAgentId: call.callerAgentId,
109
+ signingAuthority: call.signingAuthority,
110
+ timeout: settings.sendTimeout,
111
+ }),
112
+ poll: (call) => execute({
113
+ client,
114
+ origin: settings.origin,
115
+ path: routerPollPath,
116
+ request: call.request,
117
+ requestSchema: RouterPollRequest,
118
+ schema: RouterPollResult,
119
+ callerAgentId: call.callerAgentId,
120
+ signingAuthority: call.signingAuthority,
121
+ timeout: settings.pollTimeout,
122
+ }),
123
+ };
124
+ }
125
+ const MAXIMUM_PROCESS_INTEGER = 2_147_483_647;
126
+ const canonicalUnsignedDecimal = Schema.String.pipe(Schema.pattern(/^(?:0|[1-9]\d*)$/));
127
+ const processInteger = canonicalUnsignedDecimal.pipe(Schema.compose(Schema.NumberFromString), Schema.int(), Schema.between(1, MAXIMUM_PROCESS_INTEGER));
128
+ const port = canonicalUnsignedDecimal.pipe(Schema.compose(Schema.NumberFromString), Schema.int(), Schema.between(1, 65_535));
129
+ const bindHost = Schema.String.pipe(Schema.minLength(1));
130
+ const isSerializedRegistryOrigin = (value) => {
131
+ if (!URL.canParse(value)) {
132
+ return false;
133
+ }
134
+ const parsed = new URL(value);
135
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
136
+ return false;
137
+ }
138
+ return value === parsed.origin;
139
+ };
140
+ const registryOriginText = Schema.String.pipe(Schema.filter(isSerializedRegistryOrigin));
141
+ const registryOrigin = registryOriginText.pipe(Schema.compose(Schema.URL));
142
+ const compactPublicKeyJson = Schema.String.pipe(Schema.pattern(/^\{"crv":"Ed25519","kty":"OKP","x":"[A-Za-z0-9_-]{43}"\}$/), Schema.compose(Schema.parseJson(Ed25519PublicKey)));
143
+ const configuredValues = Config.all({
144
+ host: Schema.Config("MOLTZAP_ROUTER_HOST", bindHost).pipe(Config.withDefault("127.0.0.1")),
145
+ port: Schema.Config("MOLTZAP_ROUTER_PORT", port),
146
+ registryOrigin: Schema.Config("MOLTZAP_ROUTER_REGISTRY_ORIGIN", registryOrigin),
147
+ registrySignerPublicKey: Schema.Config("MOLTZAP_ROUTER_REGISTRY_SIGNER_PUBLIC_KEY", compactPublicKeyJson),
148
+ retainedMessageCapacity: Schema.Config("MOLTZAP_ROUTER_RETAINED_MESSAGE_CAPACITY", processInteger).pipe(Config.withDefault(4_096)),
149
+ retainedMessageByteCapacity: Schema.Config("MOLTZAP_ROUTER_RETAINED_MESSAGE_BYTE_CAPACITY", processInteger).pipe(Config.withDefault(67_108_864)),
150
+ pollMessageLimit: Schema.Config("MOLTZAP_ROUTER_POLL_MESSAGE_LIMIT", processInteger).pipe(Config.withDefault(128)),
151
+ pollResponseByteLimit: Schema.Config("MOLTZAP_ROUTER_POLL_RESPONSE_BYTE_LIMIT", processInteger).pipe(Config.withDefault(1_048_576)),
152
+ requestConcurrencyLimit: Schema.Config("MOLTZAP_ROUTER_REQUEST_CONCURRENCY_LIMIT", processInteger).pipe(Config.withDefault(512)),
153
+ heldPollCapacity: Schema.Config("MOLTZAP_ROUTER_HELD_POLL_CAPACITY", processInteger).pipe(Config.withDefault(256)),
154
+ liveNonceCapacity: Schema.Config("MOLTZAP_ROUTER_LIVE_NONCE_CAPACITY", processInteger).pipe(Config.withDefault(100_000)),
155
+ agentCardCacheCapacity: Schema.Config("MOLTZAP_ROUTER_AGENT_CARD_CACHE_CAPACITY", processInteger).pipe(Config.withDefault(10_000)),
156
+ registryLookupConcurrencyLimit: Schema.Config("MOLTZAP_ROUTER_REGISTRY_LOOKUP_CONCURRENCY_LIMIT", processInteger).pipe(Config.withDefault(32)),
157
+ registryLookupTimeoutMs: Schema.Config("MOLTZAP_ROUTER_REGISTRY_LOOKUP_TIMEOUT_MS", processInteger).pipe(Config.withDefault(5_000)),
158
+ });
159
+ const retentionFits = (candidate) => candidate.retainedMessageCapacity >= 1 &&
160
+ candidate.retainedMessageByteCapacity >=
161
+ SignedMessage.maximumEncodedByteLength;
162
+ const pollBatchFits = (candidate) => candidate.pollMessageLimit >= 1 &&
163
+ candidate.pollResponseByteLimit >=
164
+ routerRepresentationLimits.oneMessageBatchBytes;
165
+ const heldPollsFit = (candidate) => candidate.heldPollCapacity < candidate.requestConcurrencyLimit;
166
+ const validatedConfiguration = configuredValues.pipe(Config.validate({
167
+ message: "Router resource bounds do not satisfy the representation fit laws",
168
+ validation: (candidate) => retentionFits(candidate) &&
169
+ pollBatchFits(candidate) &&
170
+ heldPollsFit(candidate),
171
+ }));
172
+ /** Loads and cross-validates the complete private Router process configuration. */
173
+ export const loadRouterConfiguration = Effect.gen(function* () {
174
+ const configuration = yield* validatedConfiguration;
175
+ return configuration;
176
+ }).pipe(Effect.withSpan("loadRouterConfiguration"));
177
+ //# sourceMappingURL=router.js.map