@moltzap/client 2026.802.0 → 2026.803.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/bounded-map.d.ts +3 -3
- package/dist/bounded-map.js +3 -3
- package/dist/channel-base/index.d.ts +3 -7
- package/dist/channel-base/index.d.ts.map +1 -1
- package/dist/channel-base/index.js +2 -6
- package/dist/channel-base/index.js.map +1 -1
- package/dist/channel-base/reply-guard.d.ts +52 -0
- package/dist/channel-base/reply-guard.d.ts.map +1 -0
- package/dist/channel-base/reply-guard.js +78 -0
- package/dist/channel-base/reply-guard.js.map +1 -0
- package/dist/channel-core-test-support.d.ts +5 -27
- package/dist/channel-core-test-support.d.ts.map +1 -1
- package/dist/channel-core-test-support.js +2 -90
- package/dist/channel-core-test-support.js.map +1 -1
- package/dist/channel-core.d.ts +130 -248
- package/dist/channel-core.d.ts.map +1 -1
- package/dist/channel-core.js +169 -526
- package/dist/channel-core.js.map +1 -1
- package/dist/cli/commands/start.d.ts +1 -5
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +0 -3
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/dist/local-daemon-rpc.d.ts +12 -195
- package/dist/local-daemon-rpc.d.ts.map +1 -1
- package/dist/local-daemon-rpc.js +1 -5
- package/dist/local-daemon-rpc.js.map +1 -1
- package/dist/notification/__tests__/subscribe-signatures.types-check.d.ts +14 -14
- package/dist/notification/__tests__/subscribe-signatures.types-check.d.ts.map +1 -1
- package/dist/notification/__tests__/subscribe-signatures.types-check.js +5 -5
- package/dist/notification/__tests__/subscribe-signatures.types-check.js.map +1 -1
- package/dist/service-local-daemon.d.ts +1 -1
- package/dist/service-local-daemon.d.ts.map +1 -1
- package/dist/service-local-daemon.js +2 -4
- package/dist/service-local-daemon.js.map +1 -1
- package/dist/service.d.ts +4 -25
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +7 -44
- package/dist/service.js.map +1 -1
- package/dist/test-utils/channel-service-fixture.d.ts +1 -3
- package/dist/test-utils/channel-service-fixture.d.ts.map +1 -1
- package/dist/test-utils/channel-service-fixture.js +2 -22
- package/dist/test-utils/channel-service-fixture.js.map +1 -1
- package/dist/test-utils/ids.d.ts +0 -13
- package/dist/test-utils/ids.d.ts.map +1 -1
- package/dist/test-utils/ids.js +1 -16
- package/dist/test-utils/ids.js.map +1 -1
- package/dist/test-utils/index.d.ts +1 -1
- package/dist/test-utils/index.d.ts.map +1 -1
- package/dist/test-utils/index.js +1 -1
- package/dist/test-utils/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/dist/app-client.d.ts +0 -5
- package/dist/app-client.d.ts.map +0 -1
- package/dist/app-client.js +0 -3
- package/dist/app-client.js.map +0 -1
- package/dist/channel-base/lease-guard.d.ts +0 -31
- package/dist/channel-base/lease-guard.d.ts.map +0 -1
- package/dist/channel-base/lease-guard.js +0 -44
- package/dist/channel-base/lease-guard.js.map +0 -1
- package/dist/channel-base/lease-store.d.ts +0 -48
- package/dist/channel-base/lease-store.d.ts.map +0 -1
- package/dist/channel-base/lease-store.js +0 -77
- package/dist/channel-base/lease-store.js.map +0 -1
- package/dist/channel-base/lease.d.ts +0 -96
- package/dist/channel-base/lease.d.ts.map +0 -1
- package/dist/channel-base/lease.js +0 -106
- package/dist/channel-base/lease.js.map +0 -1
package/dist/channel-core.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Channel core: serialized inbound turn delivery over a MoltZapService.
|
|
3
|
+
* Owns the inbound queue, same-conversation coalescing, the interceptor
|
|
4
|
+
* gate, the per-turn timeout, and channel teardown; enrichment lives in
|
|
5
|
+
* channel-core-enrichment.ts.
|
|
3
6
|
*/
|
|
4
7
|
import { Effect } from "effect";
|
|
5
8
|
import type { ConversationId } from "@moltzap/protocol/conversation";
|
|
6
|
-
import { type LeaseId } from "@moltzap/protocol/message/dispatch";
|
|
7
9
|
import type { Message } from "@moltzap/protocol/message";
|
|
8
10
|
import type { CrossConversationEntry, CrossConvMessage, ServiceRpcError } from "./service.js";
|
|
9
11
|
/** Describes enriched sender. */
|
|
@@ -37,7 +39,7 @@ export interface EnrichedInboundMessage {
|
|
|
37
39
|
contextBlocks: ContextBlocks;
|
|
38
40
|
/**
|
|
39
41
|
* Present when multiple queued messages from the same conversation were
|
|
40
|
-
* coalesced into this single
|
|
42
|
+
* coalesced into this single turn. Includes the primary message first.
|
|
41
43
|
*/
|
|
42
44
|
coalescedMessages?: ReadonlyArray<{
|
|
43
45
|
id: string;
|
|
@@ -45,63 +47,6 @@ export interface EnrichedInboundMessage {
|
|
|
45
47
|
text: string;
|
|
46
48
|
createdAt: string;
|
|
47
49
|
}>;
|
|
48
|
-
/** Lease that authorizes a runtime reply for this dispatch, when present. */
|
|
49
|
-
dispatchLeaseId?: LeaseId;
|
|
50
|
-
}
|
|
51
|
-
/** Describes pending dispatch message. */
|
|
52
|
-
export interface PendingDispatchMessage {
|
|
53
|
-
messageId: string;
|
|
54
|
-
conversationId: string;
|
|
55
|
-
senderAgentId: string;
|
|
56
|
-
createdAt: string;
|
|
57
|
-
receivedAt: string;
|
|
58
|
-
parts?: Message["parts"];
|
|
59
|
-
}
|
|
60
|
-
/** Describes dispatch admission request. */
|
|
61
|
-
export interface DispatchAdmissionRequest {
|
|
62
|
-
message: Message;
|
|
63
|
-
conversationId: string;
|
|
64
|
-
senderAgentId: string;
|
|
65
|
-
attempt: number;
|
|
66
|
-
receivedAt: string;
|
|
67
|
-
pending: readonly PendingDispatchMessage[];
|
|
68
|
-
}
|
|
69
|
-
/** Represents dispatch admission decision values. */
|
|
70
|
-
export type DispatchAdmissionDecision = {
|
|
71
|
-
_tag: "grant";
|
|
72
|
-
leaseId?: LeaseId;
|
|
73
|
-
leaseTimeoutMs?: number;
|
|
74
|
-
dispatchMessageId?: string;
|
|
75
|
-
} | {
|
|
76
|
-
_tag: "deny";
|
|
77
|
-
reason?: string;
|
|
78
|
-
} | {
|
|
79
|
-
_tag: "hold";
|
|
80
|
-
reason?: string;
|
|
81
|
-
};
|
|
82
|
-
/**
|
|
83
|
-
* Server → recipient `agent/dispatch/released` notification payload (the
|
|
84
|
-
* verdict). Mirrors `NotificationParamsOf<typeof DispatchRelease>` from
|
|
85
|
-
* the protocol, kept structurally typed here so this module does not
|
|
86
|
-
* need a direct protocol descriptor import (the channel core stays
|
|
87
|
-
* descriptor-free; the wire shape is asserted by the service module).
|
|
88
|
-
*/
|
|
89
|
-
export interface DispatchReleaseFrame {
|
|
90
|
-
readonly dispatchId: string;
|
|
91
|
-
readonly leaseId: LeaseId;
|
|
92
|
-
readonly verdict: {
|
|
93
|
-
readonly decision: "grant";
|
|
94
|
-
readonly leaseId?: LeaseId;
|
|
95
|
-
readonly leaseTimeoutMs?: number;
|
|
96
|
-
readonly dispatchMessageId?: string;
|
|
97
|
-
} | {
|
|
98
|
-
readonly decision: "deny";
|
|
99
|
-
readonly reason?: string;
|
|
100
|
-
} | {
|
|
101
|
-
readonly decision: "hold";
|
|
102
|
-
readonly reason?: string;
|
|
103
|
-
};
|
|
104
|
-
readonly leaseTimeoutMs?: number;
|
|
105
50
|
}
|
|
106
51
|
/** The subset of MoltZapService that MoltZapChannelCore needs. */
|
|
107
52
|
export interface ChannelService {
|
|
@@ -110,14 +55,15 @@ export interface ChannelService {
|
|
|
110
55
|
message: Message;
|
|
111
56
|
}) => void): void;
|
|
112
57
|
on(event: "disconnect", handler: () => void): void;
|
|
113
|
-
on(event: "dispatchRelease", handler: (frame: DispatchReleaseFrame) => void): void;
|
|
114
58
|
connect(): Effect.Effect<unknown, ServiceRpcError>;
|
|
115
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* Effectful teardown for scoped process owners, which need the service's
|
|
61
|
+
* transports closed before the scope's release completes. Services that
|
|
62
|
+
* only offer the fire-and-forget {@link ChannelService.close} omit it.
|
|
63
|
+
*/
|
|
116
64
|
shutdown?(): Effect.Effect<void>;
|
|
117
65
|
close(): void;
|
|
118
|
-
send(conversationId: ConversationId, text: string,
|
|
119
|
-
dispatchLeaseId?: LeaseId;
|
|
120
|
-
}): Effect.Effect<void, ServiceRpcError>;
|
|
66
|
+
send(conversationId: ConversationId, text: string): Effect.Effect<void, ServiceRpcError>;
|
|
121
67
|
getConversation(convId: string): {
|
|
122
68
|
type: string;
|
|
123
69
|
name?: string;
|
|
@@ -136,38 +82,30 @@ export interface ChannelService {
|
|
|
136
82
|
messages: CrossConvMessage[];
|
|
137
83
|
commit: () => void;
|
|
138
84
|
};
|
|
139
|
-
/**
|
|
140
|
-
* Issue `agent/dispatch/request` and receive either the immediate
|
|
141
|
-
* `{leaseId, dispatchId}` ack or `conversation_busy`. The verdict for a
|
|
142
|
-
* minted lease arrives asynchronously via the `dispatchRelease` event.
|
|
143
|
-
*
|
|
144
|
-
* The argument shape mirrors `ParamsOf<DispatchRequest>` from the
|
|
145
|
-
* protocol (the channel core does not depend on the protocol
|
|
146
|
-
* descriptor, hence the structural shape duplicated here).
|
|
147
|
-
*
|
|
148
|
-
* Optional: when undefined (e.g. Unauthenticated test fakes), the
|
|
149
|
-
* channel core falls back to default-grant — every inbound message
|
|
150
|
-
* dispatches without admission.
|
|
151
|
-
*/
|
|
152
|
-
requestDispatch?(params: {
|
|
153
|
-
readonly conversationId: string;
|
|
154
|
-
readonly messageId: string;
|
|
155
|
-
readonly senderAgentId: string;
|
|
156
|
-
readonly parts?: readonly unknown[];
|
|
157
|
-
readonly receivedAt?: string;
|
|
158
|
-
readonly pending?: readonly unknown[];
|
|
159
|
-
readonly attempt?: number;
|
|
160
|
-
}): Effect.Effect<{
|
|
161
|
-
readonly leaseId: LeaseId;
|
|
162
|
-
readonly dispatchId: string;
|
|
163
|
-
} | {
|
|
164
|
-
readonly outcome: "conversation_busy";
|
|
165
|
-
}, ServiceRpcError>;
|
|
166
85
|
}
|
|
167
86
|
/** Configures channel core. */
|
|
168
87
|
export interface ChannelCoreOptions {
|
|
169
88
|
service: ChannelService;
|
|
170
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Wall-clock bound on one handler invocation. On expiry the turn is
|
|
91
|
+
* abandoned and the consumer keeps draining.
|
|
92
|
+
*
|
|
93
|
+
* Unset means unbounded, which is the safe default for runtimes whose
|
|
94
|
+
* turns legitimately run for minutes: nothing else can interrupt the
|
|
95
|
+
* handler, so a bound that is too tight silently drops real work. The
|
|
96
|
+
* cost of leaving it unset is that a hung handler stalls the serial
|
|
97
|
+
* drain forever — set it for runtimes that can wedge.
|
|
98
|
+
*
|
|
99
|
+
* The bound covers the handler only. Enrichment and
|
|
100
|
+
* {@link ChannelCoreOptions.inboundInterceptor} run outside it.
|
|
101
|
+
*/
|
|
102
|
+
turnTimeoutMs?: number;
|
|
103
|
+
/**
|
|
104
|
+
* Endpoint-side gate consulted once per coalesced turn, after enrichment
|
|
105
|
+
* and before the handler. Unset is passthrough: every turn is delivered
|
|
106
|
+
* and the inbound path does no extra work.
|
|
107
|
+
*/
|
|
108
|
+
inboundInterceptor?: InboundInterceptor;
|
|
171
109
|
}
|
|
172
110
|
/**
|
|
173
111
|
* Handler invoked for every enriched inbound message. Returns an Effect so the
|
|
@@ -177,10 +115,47 @@ export interface ChannelCoreOptions {
|
|
|
177
115
|
*/
|
|
178
116
|
export type InboundHandler<E = unknown> = (msg: EnrichedInboundMessage) => Effect.Effect<void, E>;
|
|
179
117
|
/**
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
118
|
+
* Verdict an {@link InboundInterceptor} returns for one coalesced turn.
|
|
119
|
+
*
|
|
120
|
+
* The union is closed at deliver and drop on purpose: there is no hold or
|
|
121
|
+
* delay verdict. An interceptor is an Effect, so pacing is expressed by
|
|
122
|
+
* suspending inside it — an ambient Clock sleep, a semaphore, a gate the
|
|
123
|
+
* embedder opens later — and the verdict says only whether the turn runs. A
|
|
124
|
+
* hold verdict would ask the core to park this turn and start the next one,
|
|
125
|
+
* which is the multi-turn concurrency the single consumer fiber exists to
|
|
126
|
+
* prevent.
|
|
127
|
+
*/
|
|
128
|
+
export type InboundInterceptDecision = {
|
|
129
|
+
readonly _tag: "deliver";
|
|
130
|
+
} | {
|
|
131
|
+
readonly _tag: "drop";
|
|
132
|
+
readonly reason?: string;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Gate the embedder installs between enrichment and the handler. It receives
|
|
136
|
+
* the newest message of the coalesced batch — a gate deciding whether a turn
|
|
137
|
+
* is still worth running cares about the latest thing said — and its verdict
|
|
138
|
+
* governs the whole batch.
|
|
139
|
+
*
|
|
140
|
+
* It runs on the single consumer fiber, so suspending inside it delays this
|
|
141
|
+
* turn and every message queued behind it, and `turnTimeoutMs` does not bound
|
|
142
|
+
* that suspension. An interceptor that never resumes stalls the drain
|
|
143
|
+
* permanently.
|
|
144
|
+
*
|
|
145
|
+
* A defect, a failure, or a synchronous throw delivers. An embedder bug in a
|
|
146
|
+
* gate must not silently black-hole a production channel: a channel that
|
|
147
|
+
* over-delivers announces itself, one that has gone quiet looks like a network
|
|
148
|
+
* problem for hours.
|
|
149
|
+
*/
|
|
150
|
+
export type InboundInterceptor = (message: Message) => Effect.Effect<InboundInterceptDecision>;
|
|
151
|
+
/**
|
|
152
|
+
* Wraps a `MoltZapService` with message enrichment, one-turn-at-a-time
|
|
153
|
+
* inbound delivery, and a send helper. One core per service —
|
|
154
|
+
* `getContextEntries()` is side-effectful (advances per-conversation
|
|
155
|
+
* markers), so a second core would consume entries the first expected.
|
|
156
|
+
*
|
|
157
|
+
* Turn-taking is entirely endpoint-local: the server delivers every message
|
|
158
|
+
* it accepts, and this core decides when the runtime sees them.
|
|
184
159
|
*
|
|
185
160
|
* Inbound path from wire bytes to user handler:.
|
|
186
161
|
*
|
|
@@ -195,61 +170,30 @@ export type InboundHandler<E = unknown> = (msg: EnrichedInboundMessage) => Effec
|
|
|
195
170
|
* server->>ws: agent/message/received notification
|
|
196
171
|
* ws->>svc: subscribers.dispatch — fanout(message)
|
|
197
172
|
* svc->>core: message listener
|
|
198
|
-
* Note over core: dedup via recordMessageIdIfNew
|
|
199
|
-
* Note over core:
|
|
200
|
-
* core
|
|
201
|
-
*
|
|
202
|
-
* Note over
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
* Note over core: log + drop
|
|
207
|
-
* else verdict hold
|
|
208
|
-
* Note over core: parkDispatchWork — front of parked[convId]
|
|
209
|
-
* else verdict grant
|
|
210
|
-
* Note over core: takeCoalescedConversationMessages; drains same-conv from queue + parked
|
|
211
|
-
* Note over core: dispatchWithLease; lease scoped to ConversationId; enrichMessage — sender name, conversation, context entries
|
|
212
|
-
* core->>handler: inboundHandler(enriched)
|
|
213
|
-
* handler-->>core: Effect.void
|
|
214
|
-
* Note over core: handler exceeds leaseTimeoutMs (90s) → DispatchLeaseExpired
|
|
215
|
-
* end
|
|
173
|
+
* Note over core: dedup via recordMessageIdIfNew, drop when stopped or no handler is installed, then Queue.unsafeOffer(inboundQueue, message)
|
|
174
|
+
* Note over core: consumer fiber — Queue.take
|
|
175
|
+
* Note over core: takeCoalescedConversationMessages drains same-conv backlog into one turn
|
|
176
|
+
* Note over core: enrichMessage — sender name, conversation, context entries
|
|
177
|
+
* Note over core: inboundInterceptor — deliver or drop this turn
|
|
178
|
+
* core->>handler: inboundHandler(enriched)
|
|
179
|
+
* handler-->>core: Effect.void
|
|
180
|
+
* Note over core: handler exceeds turnTimeoutMs — turn abandoned, drain continues
|
|
216
181
|
* ```
|
|
217
182
|
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
* so backpressure within one conversation does not starve others.
|
|
183
|
+
* The single consumer fiber awaits the handler inline, so at most one turn
|
|
184
|
+
* runs at a time and messages that arrive mid-turn wait in the queue.
|
|
221
185
|
*/
|
|
222
186
|
export declare class MoltZapChannelCore {
|
|
223
187
|
private readonly service;
|
|
224
|
-
private readonly
|
|
188
|
+
private readonly turnTimeoutMs?;
|
|
189
|
+
private readonly inboundInterceptor?;
|
|
225
190
|
private connected;
|
|
226
|
-
private
|
|
227
|
-
|
|
228
|
-
* Dispatch authority is keyed by conversation so work performed through
|
|
229
|
-
* the core for another conversation cannot inherit the active handler's
|
|
230
|
-
* lease. The single consumer prevents overlapping writes for the same
|
|
231
|
-
* conversation while set/restore cleanup is active.
|
|
232
|
-
*/
|
|
233
|
-
private readonly leaseIdsInFlightByConversation;
|
|
234
|
-
/**
|
|
235
|
-
* Per-lease parking Deferreds for dispatches awaiting their
|
|
236
|
-
* `dispatchRelease` verdict. Settled by the `dispatchRelease` event
|
|
237
|
-
* handler when a matching frame arrives.
|
|
238
|
-
*/
|
|
239
|
-
private readonly pendingDispatchesByLease;
|
|
240
|
-
/**
|
|
241
|
-
* Ring buffer of `dispatchRelease` frames that arrived before the
|
|
242
|
-
* recipient registered its parking Deferred (release-then-ack
|
|
243
|
-
* race). `BoundedMap` refreshes insertion order when a lease is set
|
|
244
|
-
* again and evicts the oldest entry at capacity. Soft-TTL eviction at
|
|
245
|
-
* `DISPATCH_RELEASE_RING_SOFT_TTL_MS` keeps a release without a matching
|
|
246
|
-
* ack from retaining memory.
|
|
247
|
-
*/
|
|
248
|
-
private readonly pendingReleasesByLease;
|
|
249
|
-
private readonly parkedByConversation;
|
|
191
|
+
private stopped;
|
|
192
|
+
private inboundHandler;
|
|
250
193
|
/**
|
|
251
194
|
* Inbound messages with an installed handler enqueue synchronously; a single
|
|
252
|
-
* forked consumer fiber serialises delivery
|
|
195
|
+
* forked consumer fiber serialises delivery so handlers execute
|
|
196
|
+
* one-at-a-time in arrival order.
|
|
253
197
|
*/
|
|
254
198
|
private readonly inboundQueue;
|
|
255
199
|
private readonly consumerFiber;
|
|
@@ -259,138 +203,76 @@ export declare class MoltZapChannelCore {
|
|
|
259
203
|
private startConsumerFiber;
|
|
260
204
|
private logInboundFailure;
|
|
261
205
|
private registerConnectionListeners;
|
|
262
|
-
private registerDispatchReleaseListener;
|
|
263
|
-
/**
|
|
264
|
-
* Record an incoming `dispatchRelease` frame. If a matching
|
|
265
|
-
* parking Deferred is registered, settle it inline; otherwise
|
|
266
|
-
* insert into the ring buffer for the future ack-side `consume`.
|
|
267
|
-
* Soft-TTL evicts buffered entries whose age exceeds
|
|
268
|
-
* `DISPATCH_RELEASE_RING_SOFT_TTL_MS`; insertion at the hard cap
|
|
269
|
-
* evicts the oldest entry. Both eviction paths warn-log so operators
|
|
270
|
-
* can spot release-without-ack adversarial patterns.
|
|
271
|
-
* @param frame Value supplied to the operation.
|
|
272
|
-
*/
|
|
273
|
-
private recordDispatchRelease;
|
|
274
|
-
private evictDispatchReleaseRing;
|
|
275
|
-
private consumeDispatchRelease;
|
|
276
206
|
/**
|
|
277
207
|
* Replaces any previous handler.
|
|
278
208
|
* @param handler Handler invoked for matching requests.
|
|
279
|
-
* @returns An idempotent disposer for this registration generation.
|
|
280
209
|
*/
|
|
281
|
-
onInbound<E>(handler: InboundHandler<E>):
|
|
210
|
+
onInbound<E>(handler: InboundHandler<E>): void;
|
|
282
211
|
onDisconnect(handler: () => void): void;
|
|
283
212
|
private fanout;
|
|
284
213
|
connect(): Effect.Effect<void, ServiceRpcError>;
|
|
214
|
+
/**
|
|
215
|
+
* Tear the channel down, resolving only once the service's own transports
|
|
216
|
+
* are closed. A scoped owner releases this before its process exits, so
|
|
217
|
+
* fire-and-forget teardown would leave sockets open past the scope.
|
|
218
|
+
*
|
|
219
|
+
* Service shutdown runs concurrently with interrupting the consumer fiber
|
|
220
|
+
* because an in-flight turn's finalizer can take arbitrarily long. Awaiting
|
|
221
|
+
* the interrupt first would hold the transports open for exactly as long as
|
|
222
|
+
* that finalizer runs.
|
|
223
|
+
* @returns Completion of the channel-owned teardown.
|
|
224
|
+
*/
|
|
285
225
|
disconnect(): Effect.Effect<void>;
|
|
286
226
|
isConnected(): boolean;
|
|
287
227
|
/**
|
|
288
|
-
* Reply into a conversation
|
|
289
|
-
* otherwise with only the active lease for `conversationId`.
|
|
228
|
+
* Reply into a conversation.
|
|
290
229
|
* @param conversationId Value supplied to the operation.
|
|
291
230
|
* @param text Text to process.
|
|
292
|
-
* @param opts Value supplied to the operation.
|
|
293
|
-
* @param opts.dispatchLeaseId Value supplied to the operation.
|
|
294
231
|
* @returns The send result.
|
|
295
232
|
*/
|
|
296
|
-
sendReply(conversationId: ConversationId, text: string,
|
|
297
|
-
|
|
298
|
-
}): Effect.Effect<void, ServiceRpcError>;
|
|
299
|
-
private takeDispatchCandidate;
|
|
300
|
-
private parkDispatchWork;
|
|
233
|
+
sendReply(conversationId: ConversationId, text: string): Effect.Effect<void, ServiceRpcError>;
|
|
234
|
+
private runInboundTurn;
|
|
301
235
|
/**
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
* AWAITING_RELEASE --> GRANTED : verdict grant
|
|
323
|
-
* AWAITING_RELEASE --> DENIED : verdict deny
|
|
324
|
-
* AWAITING_RELEASE --> HELD : verdict hold
|
|
325
|
-
* HELD : parkDispatchWork — re-queued at parked[convId] front
|
|
326
|
-
* GRANTED : proceed to enrichment
|
|
327
|
-
* DENIED : drop message — consumer fiber continues
|
|
328
|
-
* GRANTED --> IN_FLIGHT : dispatchWithLease
|
|
329
|
-
* IN_FLIGHT : lease keyed by ConversationId; handler executing; lease authorizes one agent/message/send
|
|
330
|
-
* IN_FLIGHT --> CONSUMED : handler returns within leaseTimeoutMs; server marks via dispatchLeaseId
|
|
331
|
-
* IN_FLIGHT --> EXPIRED : handler exceeds leaseTimeoutMs; DispatchLeaseExpired logged
|
|
332
|
-
* CONSUMED --> [*]
|
|
333
|
-
* DENIED --> [*]
|
|
334
|
-
* EXPIRED --> [*]
|
|
335
|
-
* ```
|
|
336
|
-
*
|
|
337
|
-
* `HELD` stays at the parked-front. Later inbound work for that same
|
|
338
|
-
* conversation wakes its next dispatch attempt without preventing inbound
|
|
339
|
-
* work for other conversations from progressing.
|
|
340
|
-
*
|
|
341
|
-
* When the service has no `requestDispatch` (test fakes that don't
|
|
342
|
-
* exercise admission), default-grant.
|
|
343
|
-
*
|
|
344
|
-
* On request error or release wait timeout, fail-closed with a
|
|
345
|
-
* synthetic deny verdict. The lease (if minted server-side) ages
|
|
346
|
-
* out via the post-grant TTL or LeaseRegistry's
|
|
347
|
-
* abandon-on-disconnect path; nothing here re-issues.
|
|
348
|
-
* @param work Value supplied to the operation.
|
|
349
|
-
* @returns The dispatch admission result.
|
|
236
|
+
* Consult the interceptor for this turn, if one is installed.
|
|
237
|
+
* @param messages The coalesced batch, primary first.
|
|
238
|
+
* @returns Whether the handler runs for this batch.
|
|
239
|
+
*/
|
|
240
|
+
private interceptTurn;
|
|
241
|
+
/**
|
|
242
|
+
* Apply a verdict, logging the drops at debug so a quiet channel can be
|
|
243
|
+
* traced back to its gate.
|
|
244
|
+
* @param newest Message the interceptor judged.
|
|
245
|
+
* @param decision Verdict for the whole coalesced batch.
|
|
246
|
+
* @returns Whether the handler runs.
|
|
247
|
+
*/
|
|
248
|
+
private applyInterceptDecision;
|
|
249
|
+
private logInterceptorFailure;
|
|
250
|
+
/**
|
|
251
|
+
* Await the user handler, bounded by `turnTimeoutMs` when it is set.
|
|
252
|
+
* @param handler Installed inbound handler.
|
|
253
|
+
* @param enriched Enriched form of the coalesced batch.
|
|
254
|
+
* @param primary Message that opened this turn.
|
|
255
|
+
* @returns Whether the handler ran to completion.
|
|
350
256
|
*/
|
|
351
|
-
private
|
|
257
|
+
private awaitHandlerTurn;
|
|
352
258
|
/**
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
* @param work Value supplied to the operation.
|
|
359
|
-
* @param leaseId Value supplied to the operation.
|
|
360
|
-
* @returns The buffered result.
|
|
259
|
+
* Drain every queued message for the primary's conversation into one turn,
|
|
260
|
+
* leaving other conversations queued in arrival order. Coalescing keeps a
|
|
261
|
+
* burst in one conversation from costing one turn per message.
|
|
262
|
+
* @param primary Message that opened this turn.
|
|
263
|
+
* @returns The messages belonging to this turn, primary first.
|
|
361
264
|
*/
|
|
362
|
-
private awaitDispatchRelease;
|
|
363
|
-
private projectVerdict;
|
|
364
|
-
private projectGrantVerdict;
|
|
365
|
-
private static denyDecision;
|
|
366
|
-
private static holdDecision;
|
|
367
|
-
private dispatchInboundWork;
|
|
368
|
-
private handleDispatchDecision;
|
|
369
|
-
private dispatchGrantedWork;
|
|
370
|
-
private messagesForGrantedDispatch;
|
|
371
|
-
private runGrantedDispatch;
|
|
372
|
-
private dispatchWithLease;
|
|
373
|
-
private static leaseTimeoutMs;
|
|
374
|
-
private handleDispatchFailure;
|
|
375
|
-
private holdDispatchWork;
|
|
376
|
-
private logDispatchTargetUnavailable;
|
|
377
|
-
private logDispatchStart;
|
|
378
|
-
private logDispatchLeaseExpired;
|
|
379
|
-
private logDispatchCompleted;
|
|
380
|
-
private logDeniedDispatch;
|
|
381
|
-
private pendingDispatchSnapshot;
|
|
382
265
|
private takeCoalescedConversationMessages;
|
|
383
266
|
/**
|
|
384
267
|
* Stateless enrichment helper. Falls back to `sender.id` if
|
|
385
268
|
* `resolveAgentName` throws (e.g. Service not yet connected).
|
|
386
269
|
* @param service Value supplied to the operation.
|
|
387
270
|
* @param messageOrMessages Value supplied to the operation.
|
|
388
|
-
* @returns The
|
|
271
|
+
* @returns The enriched message and its context-commit callback.
|
|
389
272
|
*/
|
|
390
273
|
static enrichMessage(service: ChannelService, messageOrMessages: Message | readonly Message[]): Effect.Effect<{
|
|
391
274
|
enriched: EnrichedInboundMessage;
|
|
392
275
|
commitContext?: () => void;
|
|
393
276
|
}>;
|
|
394
|
-
private dispatchInboundEffect;
|
|
395
277
|
}
|
|
396
278
|
//# sourceMappingURL=channel-core.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-core.d.ts","sourceRoot":"","sources":["../src/channel-core.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"channel-core.d.ts","sourceRoot":"","sources":["../src/channel-core.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA0B,MAAM,EAAwB,MAAM,QAAQ,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EAChB,MAAM,cAAc,CAAC;AAGtB,iCAAiC;AACjC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,4CAA4C;AAC5C,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,gCAAgC;AAChC,MAAM,WAAW,aAAa;IAC5B,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC,iBAAiB,CAAC,EAAE,sBAAsB,EAAE,CAAC;IAC7C,yBAAyB,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAChD;AAED,0CAA0C;AAC1C,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,wBAAwB,CAAC;IAC5C,aAAa,EAAE,aAAa,CAAC;IAE7B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,aAAa,CAAC;QAChC,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,cAAc,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;CACJ;AAED,kEAAkE;AAClE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IAC7E,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IACnD,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACnD;;;;OAIG;IACH,QAAQ,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjC,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,CACF,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IACxC,eAAe,CACb,MAAM,EAAE,MAAM,GACb;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,SAAS,CAAC;IACvE,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAClD,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACzD,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,CAAC;IAC7D,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG;QACvC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAC7B,MAAM,EAAE,MAAM,IAAI,CAAC;KACpB,CAAC;CACH;AAED,+BAA+B;AAC/B,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,cAAc,CAAC;IAExB;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAED;;;;;GAKG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,GAAG,OAAO,IAAI,CACxC,GAAG,EAAE,sBAAsB,KACxB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAE5B;;;;;;;;;;GAUG;AACH,MAAM,MAAM,wBAAwB,GAChC;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAC/B,OAAO,EAAE,OAAO,KACb,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC;AAwC7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAqB;IACzD,OAAO,CAAC,SAAS,CAAS;IAO1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAA+B;IAErD;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAE3B;IACF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA2B;IACzD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAyB;IAE5D,YAAY,IAAI,EAAE,kBAAkB,EAYnC;IAED,OAAO,CAAC,uBAAuB;IAc/B,OAAO,CAAC,kBAAkB;IAe1B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,2BAA2B;IAOnC;;;OAGG;IACH,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,CAE7C;IAED,YAAY,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAEtC;IAED,OAAO,CAAC,MAAM;IAed,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAkB9C;IAED;;;;;;;;;;OAUG;IACH,UAAU,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAoBhC;IAED,WAAW,IAAI,OAAO,CAErB;IAED;;;;;OAKG;IACH,SAAS,CACP,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAEtC;IAED,OAAO,CAAC,cAAc;IA2BtB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IA4BrB;;;;;;OAMG;IACH,OAAO,CAAC,sBAAsB;IAiB9B,OAAO,CAAC,qBAAqB;IAe7B;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IA+BxB;;;;;;OAMG;IACH,OAAO,CAAC,iCAAiC;IAuBzC;;;;;;OAMG;IACH,MAAM,CAAC,aAAa,CAClB,OAAO,EAAE,cAAc,EACvB,iBAAiB,EAAE,OAAO,GAAG,SAAS,OAAO,EAAE,GAC9C,MAAM,CAAC,MAAM,CAAC;QACf,QAAQ,EAAE,sBAAsB,CAAC;QACjC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;KAC5B,CAAC,CAED;CACF"}
|