@m4trix/core 0.8.0 → 0.9.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.
@@ -2,31 +2,30 @@ import { Schema, Effect, Brand, Queue, Scope } from 'effect';
2
2
  export { Schema as S } from 'effect';
3
3
  import { ParseError } from 'effect/ParseResult';
4
4
 
5
- type LogicFn$1<TParams, TTriggerEvent, TEmitEvent> = (ctx: {
6
- params: TParams;
7
- triggerEvent: TTriggerEvent;
8
- emit: (event: TEmitEvent) => void;
9
- }) => Promise<void>;
10
- declare class Agent<TParams, TTriggerEvent = never, TEmitEvent = never> {
11
- #private;
12
- constructor(logic: LogicFn$1<TParams, TTriggerEvent, TEmitEvent>, params: TParams, listensTo?: readonly string[]);
13
- getListensTo(): readonly string[];
14
- invoke(options?: {
15
- triggerEvent?: TTriggerEvent;
16
- emit?: (event: TEmitEvent) => void;
17
- }): Promise<void>;
18
- getId(): string;
19
- }
20
-
21
5
  /** Standard meta carried by every event */
22
6
  declare const EventMetaSchema: Schema.Struct<{
23
7
  runId: typeof Schema.String;
24
- contextId: Schema.optional<typeof Schema.String>;
8
+ contextId: typeof Schema.String;
25
9
  correlationId: Schema.optional<typeof Schema.String>;
26
10
  causationId: Schema.optional<typeof Schema.String>;
27
11
  ts: Schema.optional<typeof Schema.Number>;
28
12
  }>;
29
13
  type EventMeta = Schema.Schema.Type<typeof EventMetaSchema>;
14
+ /** Envelope-like shape for events (avoids circular dep with event-plane) */
15
+ type EnvelopeLike = {
16
+ name: string;
17
+ meta: EventMeta;
18
+ payload: unknown;
19
+ };
20
+ type RunEvents = readonly EnvelopeLike[];
21
+ type ContextEvents = {
22
+ /** All events in the context across all runs */
23
+ readonly all: readonly EnvelopeLike[];
24
+ /** Get events for a specific run */
25
+ byRun(runId: string): readonly EnvelopeLike[];
26
+ /** Map of runId -> events */
27
+ readonly map: ReadonlyMap<string, readonly EnvelopeLike[]>;
28
+ };
30
29
 
31
30
  type AgentNetworkEventDef<EventName extends string, PayloadSchema extends Schema.Schema.Any> = {
32
31
  readonly _tag: 'AgentNetworkEventDef';
@@ -85,6 +84,26 @@ declare const AgentNetworkEvent: {
85
84
  of<const EventName extends string, PS extends Schema.Schema.Any>(name: EventName, payload: PS): AgentNetworkEventDef<EventName, PS>;
86
85
  };
87
86
 
87
+ type LogicFn$1<TParams, TTriggerEvent, TEmitEvent> = (ctx: {
88
+ params: TParams;
89
+ triggerEvent: TTriggerEvent;
90
+ emit: (event: TEmitEvent) => void;
91
+ runEvents: RunEvents;
92
+ contextEvents: ContextEvents;
93
+ }) => Promise<void>;
94
+ declare class Agent<TParams, TTriggerEvent = never, TEmitEvent = never> {
95
+ #private;
96
+ constructor(logic: LogicFn$1<TParams, TTriggerEvent, TEmitEvent>, params: TParams, listensTo?: readonly string[]);
97
+ getListensTo(): readonly string[];
98
+ invoke(options?: {
99
+ triggerEvent?: TTriggerEvent;
100
+ emit?: (event: TEmitEvent) => void;
101
+ runEvents?: RunEvents;
102
+ contextEvents?: ContextEvents;
103
+ }): Promise<void>;
104
+ getId(): string;
105
+ }
106
+
88
107
  type BaseSchemaDefintion = Schema.Schema.Any;
89
108
 
90
109
  type EventDef$2 = AgentNetworkEventDef<string, Schema.Schema.Any>;
@@ -104,6 +123,8 @@ type LogicFn<TParams, TTriggerEvent, TEmitEvent> = (ctx: {
104
123
  params: TParams;
105
124
  triggerEvent: TTriggerEvent;
106
125
  emit: (event: TEmitEvent) => void;
126
+ runEvents: RunEvents;
127
+ contextEvents: ContextEvents;
107
128
  }) => Promise<void>;
108
129
  declare class AgentFactory<TParams = unknown, TListensTo extends EventDef$2 = never, TEmits extends EventDef$2 = never> {
109
130
  private _listensTo;
@@ -184,6 +205,8 @@ type EventPlane = {
184
205
  readonly publish: (channel: ChannelName, envelope: Envelope) => Effect.Effect<boolean>;
185
206
  readonly publishToChannels: (channels: readonly ConfiguredChannel[], envelope: Envelope) => Effect.Effect<boolean>;
186
207
  readonly subscribe: (channel: ChannelName) => Effect.Effect<Queue.Dequeue<Envelope>, never, Scope.Scope>;
208
+ readonly getRunEvents: (runId: string, contextId: string) => RunEvents;
209
+ readonly getContextEvents: (contextId: string) => ContextEvents;
187
210
  readonly shutdown: Effect.Effect<void>;
188
211
  };
189
212
 
@@ -195,6 +218,10 @@ type ExposeRequest = {
195
218
  req?: unknown;
196
219
  /** Express res (when using ExpressEndpoint) */
197
220
  res?: unknown;
221
+ /** Set by adapters via requestToContextId. Correlation ID between runs. */
222
+ contextId?: string;
223
+ /** Set by adapters via requestToRunId. Unique per run. */
224
+ runId?: string;
198
225
  };
199
226
  /** Auth result: allow or deny with optional status */
200
227
  type AuthResult = {
@@ -211,10 +238,21 @@ type ExposeSelect = {
211
238
  /** Event names to filter. Empty = all events. */
212
239
  events?: string[];
213
240
  };
241
+ /** Unbound event shape (name + payload, no meta) - use eventDef.make(payload) to create */
242
+ type UnboundEvent = {
243
+ name: string;
244
+ payload: unknown;
245
+ };
214
246
  /** Context passed to onRequest callback */
215
247
  type OnRequestContext<T = unknown> = {
216
- /** Emit the start event. Call with no arg to use default payload (request body), or pass custom payload. */
217
- emitStartEvent: (payload?: T) => void;
248
+ setRunId: (id: string) => void;
249
+ setContextId: (id: string) => void;
250
+ /** Emit the start event. Pass { contextId, runId, event } where event is the unbound version of one of triggerEvents (e.g. MessageEvent.make(payload)). */
251
+ emitStartEvent: (opts: {
252
+ contextId: string;
253
+ runId: string;
254
+ event: UnboundEvent;
255
+ }) => void;
218
256
  /** The raw request context */
219
257
  req: ExposeRequest;
220
258
  /** Pre-parsed request body (JSON for POST, or {} for GET) */
@@ -229,10 +267,9 @@ type ExposeOptions = {
229
267
  select?: ExposeSelect;
230
268
  /** Optional: use existing EventPlane instead of creating one per request */
231
269
  plane?: EventPlane;
232
- /** Event name when publishing the start event. Default: "request" */
233
- startEventName?: string;
234
- /** Called when a client connects, after plane is ready. Receives emitStartEvent (not the plane).
235
- * Call emitStartEvent() for default payload, emitStartEvent(mapped) for custom mapping, or omit to skip. */
270
+ /** Event definitions that can trigger a run (e.g. from AgentNetworkEvent.of). First is used for default emit. Default: "request" when omitted. */
271
+ triggerEvents?: ReadonlyArray<AgentNetworkEventDef<string, Schema.Schema.Any>>;
272
+ /** Called when a client connects, after plane is ready. Use setRunId/setContextId and emitStartEvent. */
236
273
  onRequest?: <T = unknown>(ctx: OnRequestContext<T>) => void | Promise<void>;
237
274
  };
238
275
  /** Protocol-agnostic stream source that adapters consume */
@@ -335,7 +372,7 @@ declare class AgentNetwork {
335
372
  *
336
373
  * @example
337
374
  * const api = network.expose({ protocol: "sse", auth, select });
338
- * export const GET = NextEndpoint.from(api).handler();
375
+ * export const GET = NextEndpoint.from(api, { requestToContextId, requestToRunId }).handler();
339
376
  */
340
377
  expose(options: ExposeOptions): ExposedAPI;
341
378
  /**
@@ -363,6 +400,11 @@ declare function toSSEStream(source: AsyncIterable<Envelope>, signal?: AbortSign
363
400
 
364
401
  /** Next.js App Router GET/POST handler signature */
365
402
  type NextGetHandler = (request: Request) => Promise<Response>;
403
+ /** Options for NextEndpoint.from() - required to define how request maps to contextId and runId */
404
+ type NextEndpointOptions = {
405
+ requestToContextId: (request: Request) => string;
406
+ requestToRunId: (request: Request) => string;
407
+ };
366
408
  /**
367
409
  * Adapter for Next.js App Router. Maps an ExposedAPI to a route handler
368
410
  * that streams events as SSE. Use for both GET and POST; POST with JSON body
@@ -370,12 +412,15 @@ type NextGetHandler = (request: Request) => Promise<Response>;
370
412
  *
371
413
  * @example
372
414
  * const api = agentNetwork.expose({ protocol: "sse", auth, select });
373
- * const handler = NextEndpoint.from(api).handler();
415
+ * const handler = NextEndpoint.from(api, {
416
+ * requestToContextId: (req) => req.headers.get('x-correlation-id') ?? crypto.randomUUID(),
417
+ * requestToRunId: () => crypto.randomUUID(),
418
+ * }).handler();
374
419
  * export const GET = handler;
375
420
  * export const POST = handler;
376
421
  */
377
422
  declare const NextEndpoint: {
378
- from(api: ExposedAPI): {
423
+ from(api: ExposedAPI, options: NextEndpointOptions): {
379
424
  handler(): NextGetHandler;
380
425
  };
381
426
  };
@@ -384,6 +429,11 @@ declare const NextEndpoint: {
384
429
  type ExpressRequest = {
385
430
  on(event: 'close', fn: () => void): void;
386
431
  };
432
+ /** Options for ExpressEndpoint.from() - required to define how request maps to contextId and runId */
433
+ type ExpressEndpointOptions = {
434
+ requestToContextId: (req: ExpressRequest) => string;
435
+ requestToRunId: (req: ExpressRequest) => string;
436
+ };
387
437
  /** Minimal Express-like response (compatible with express.Response) */
388
438
  type ExpressResponse = {
389
439
  setHeader(name: string, value: string | number): void;
@@ -402,12 +452,15 @@ type ExpressHandler = (req: ExpressRequest, res: ExpressResponse) => void | Prom
402
452
  *
403
453
  * @example
404
454
  * const api = agentNetwork.expose({ protocol: "sse", auth, select });
405
- * app.get("/events", ExpressEndpoint.from(api).handler());
455
+ * app.get("/events", ExpressEndpoint.from(api, {
456
+ * requestToContextId: (req) => req.headers?.['x-correlation-id'] ?? crypto.randomUUID(),
457
+ * requestToRunId: () => crypto.randomUUID(),
458
+ * }).handler());
406
459
  */
407
460
  declare const ExpressEndpoint: {
408
- from(api: ExposedAPI): {
461
+ from(api: ExposedAPI, options: ExpressEndpointOptions): {
409
462
  handler(): ExpressHandler;
410
463
  };
411
464
  };
412
465
 
413
- export { Agent, AgentBinding, AgentFactory, AgentNetwork, AgentNetworkEvent, AgentNetworkEventDef, AnyAgent, AuthResult, Channel, ChannelDef, ChannelName, ConfiguredChannel, EmitPayload, EventEnvelope, EventMeta, EventMetaSchema, EventPlane, ExposeAuthError, ExposeOptions, ExposeRequest, ExposeSelect, ExposedAPI, ExposedStream, ExpressEndpoint, ExpressHandler, ExpressRequest, ExpressResponse, NextEndpoint, NextGetHandler, OnRequestContext, SetupContext, Sink, SinkDef, SpawnCallbackContext, SpawnFn, SpawnerBuilder, StreamFactory, formatSSE, isHttpStreamSink, toSSEStream };
466
+ export { Agent, AgentBinding, AgentFactory, AgentNetwork, AgentNetworkEvent, AgentNetworkEventDef, AnyAgent, AuthResult, Channel, ChannelDef, ChannelName, ConfiguredChannel, ContextEvents, EmitPayload, EnvelopeLike, EventEnvelope, EventMeta, EventMetaSchema, EventPlane, ExposeAuthError, ExposeOptions, ExposeRequest, ExposeSelect, ExposedAPI, ExposedStream, ExpressEndpoint, ExpressEndpointOptions, ExpressHandler, ExpressRequest, ExpressResponse, NextEndpoint, NextEndpointOptions, NextGetHandler, OnRequestContext, RunEvents, SetupContext, Sink, SinkDef, SpawnCallbackContext, SpawnFn, SpawnerBuilder, StreamFactory, UnboundEvent, formatSSE, isHttpStreamSink, toSSEStream };
@@ -72,8 +72,66 @@ var Channel = {
72
72
  };
73
73
  }
74
74
  };
75
+
76
+ // src/helper/types/noop.ts
77
+ var asyncNoop = async () => {
78
+ };
79
+
80
+ // src/matrix/agent-network/stores/inmemory-network-store.ts
81
+ var createInMemoryNetworkStore = () => {
82
+ const store = /* @__PURE__ */ new Map();
83
+ return {
84
+ storeEvent: (contextId, runId, event) => {
85
+ let byRun = store.get(contextId);
86
+ if (!byRun) {
87
+ byRun = /* @__PURE__ */ new Map();
88
+ store.set(contextId, byRun);
89
+ }
90
+ let events = byRun.get(runId);
91
+ if (!events) {
92
+ events = [];
93
+ byRun.set(runId, events);
94
+ }
95
+ events.push(event);
96
+ },
97
+ getEvents: (contextId, runId) => {
98
+ const events = store.get(contextId)?.get(runId);
99
+ return events ? [...events] : [];
100
+ },
101
+ getContextEvents: (contextId) => {
102
+ const byRun = store.get(contextId);
103
+ const result = /* @__PURE__ */ new Map();
104
+ if (byRun) {
105
+ for (const [runId, events] of byRun) {
106
+ result.set(runId, [...events]);
107
+ }
108
+ }
109
+ return result;
110
+ },
111
+ getFullStore: () => {
112
+ const result = /* @__PURE__ */ new Map();
113
+ for (const [contextId, byRun] of store) {
114
+ const contextMap = /* @__PURE__ */ new Map();
115
+ for (const [runId, events] of byRun) {
116
+ contextMap.set(runId, [...events]);
117
+ }
118
+ result.set(contextId, contextMap);
119
+ }
120
+ return result;
121
+ },
122
+ persist: () => asyncNoop(),
123
+ load: () => asyncNoop()
124
+ };
125
+ };
126
+
127
+ // src/matrix/agent-network/event-plane.ts
75
128
  var DEFAULT_CAPACITY = 16;
76
- var createEventPlane = (network, capacity = DEFAULT_CAPACITY) => Effect.gen(function* () {
129
+ var createEventPlane = (options) => Effect.gen(function* () {
130
+ const {
131
+ network,
132
+ capacity = DEFAULT_CAPACITY,
133
+ store = createInMemoryNetworkStore()
134
+ } = options;
77
135
  const channels = network.getChannels();
78
136
  const pubsubs = /* @__PURE__ */ new Map();
79
137
  for (const channel of channels.values()) {
@@ -86,12 +144,42 @@ var createEventPlane = (network, capacity = DEFAULT_CAPACITY) => Effect.gen(func
86
144
  throw new Error(`Channel not found: ${channel}`);
87
145
  return p;
88
146
  };
89
- const publish = (channel, envelope) => PubSub.publish(getPubsub(channel), envelope);
90
- const publishToChannels = (targetChannels, envelope) => Effect.all(
91
- targetChannels.map((c) => publish(c.name, envelope)),
92
- { concurrency: "unbounded" }
93
- ).pipe(Effect.map((results) => results.every(Boolean)));
147
+ const recordEvent = (envelope) => {
148
+ const { contextId, runId } = envelope.meta;
149
+ store.storeEvent(contextId, runId, envelope);
150
+ };
151
+ const publishToPubSub = (channel, envelope) => PubSub.publish(getPubsub(channel), envelope);
152
+ const publish = (channel, envelope) => Effect.sync(() => recordEvent(envelope)).pipe(
153
+ Effect.flatMap(() => publishToPubSub(channel, envelope))
154
+ );
155
+ const publishToChannels = (targetChannels, envelope) => Effect.sync(() => recordEvent(envelope)).pipe(
156
+ Effect.flatMap(
157
+ () => Effect.all(
158
+ targetChannels.map((c) => publishToPubSub(c.name, envelope)),
159
+ { concurrency: "unbounded" }
160
+ )
161
+ ),
162
+ Effect.map((results) => results.every(Boolean))
163
+ );
94
164
  const subscribe = (channel) => PubSub.subscribe(getPubsub(channel));
165
+ const getRunEvents = (runId, contextId) => {
166
+ return store.getEvents(contextId, runId).slice();
167
+ };
168
+ const getContextEvents = (contextId) => {
169
+ const byRun = store.getContextEvents(contextId);
170
+ const map = /* @__PURE__ */ new Map();
171
+ const all = [];
172
+ for (const [runId, events] of byRun) {
173
+ const readonlyEvents = events.slice();
174
+ map.set(runId, readonlyEvents);
175
+ all.push(...readonlyEvents);
176
+ }
177
+ return {
178
+ all,
179
+ byRun: (runId) => map.get(runId) ?? [],
180
+ map
181
+ };
182
+ };
95
183
  const shutdown = Effect.all([...pubsubs.values()].map(PubSub.shutdown), {
96
184
  concurrency: "unbounded"
97
185
  }).pipe(Effect.asVoid);
@@ -99,6 +187,8 @@ var createEventPlane = (network, capacity = DEFAULT_CAPACITY) => Effect.gen(func
99
187
  publish,
100
188
  publishToChannels,
101
189
  subscribe,
190
+ getRunEvents,
191
+ getContextEvents,
102
192
  shutdown
103
193
  };
104
194
  });
@@ -109,6 +199,11 @@ var runSubscriber = (agent, publishesTo, dequeue, plane, emitQueue) => Effect.ge
109
199
  if (listensTo.length > 0 && !listensTo.includes(envelope.name)) {
110
200
  return;
111
201
  }
202
+ const runEvents = plane.getRunEvents(
203
+ envelope.meta.runId,
204
+ envelope.meta.contextId
205
+ );
206
+ const contextEvents = plane.getContextEvents(envelope.meta.contextId);
112
207
  yield* Effect.tryPromise({
113
208
  try: () => agent.invoke({
114
209
  triggerEvent: envelope,
@@ -131,7 +226,9 @@ var runSubscriber = (agent, publishesTo, dequeue, plane, emitQueue) => Effect.ge
131
226
  plane.publishToChannels(publishesTo, fullEnvelope)
132
227
  );
133
228
  }
134
- }
229
+ },
230
+ runEvents,
231
+ contextEvents
135
232
  }),
136
233
  catch: (e) => e
137
234
  });
@@ -225,7 +322,15 @@ function streamFromDequeue(take, signal, eventFilter) {
225
322
  };
226
323
  }
227
324
  function expose(network, options) {
228
- const { auth, select, plane: providedPlane, onRequest, startEventName = "request" } = options;
325
+ const {
326
+ auth,
327
+ select,
328
+ plane: providedPlane,
329
+ onRequest,
330
+ triggerEvents
331
+ } = options;
332
+ const triggerEventDef = triggerEvents?.[0];
333
+ const triggerEventName = triggerEventDef?.name ?? "request";
229
334
  const channels = resolveChannels(network, select);
230
335
  const eventFilter = select?.events;
231
336
  const mainChannel = network.getMainChannel();
@@ -236,7 +341,7 @@ function expose(network, options) {
236
341
  const payload = await extractPayload(req);
237
342
  const signal = req.request?.signal;
238
343
  const program = Effect.gen(function* () {
239
- const plane = providedPlane ?? (yield* createEventPlane(network));
344
+ const plane = providedPlane ?? (yield* createEventPlane({ network }));
240
345
  if (!providedPlane) {
241
346
  const emitQueue = yield* Queue.unbounded();
242
347
  yield* Effect.fork(
@@ -252,25 +357,46 @@ function expose(network, options) {
252
357
  yield* Effect.sleep("10 millis");
253
358
  }
254
359
  const targetChannel = mainChannel?.name ?? channels[0];
255
- const emitStartEvent = (p) => {
256
- const pld = p ?? payload;
360
+ let runId = req.runId ?? crypto.randomUUID();
361
+ let contextId = req.contextId ?? crypto.randomUUID();
362
+ const setRunId = (id) => {
363
+ runId = id;
364
+ };
365
+ const setContextId = (id) => {
366
+ contextId = id;
367
+ };
368
+ const emitStartEvent = (opts) => {
369
+ const meta = {
370
+ runId: opts.runId,
371
+ contextId: opts.contextId
372
+ };
257
373
  const envelope = {
258
- name: startEventName,
259
- meta: { runId: crypto.randomUUID() },
260
- payload: pld
374
+ name: opts.event.name,
375
+ meta,
376
+ payload: opts.event.payload
261
377
  };
262
- Effect.runPromise(plane.publish(targetChannel, envelope)).catch(() => {
263
- });
378
+ Effect.runPromise(plane.publish(targetChannel, envelope)).catch(
379
+ () => {
380
+ }
381
+ );
264
382
  };
265
383
  const dequeue = yield* plane.subscribe(channels[0]);
266
384
  if (onRequest) {
267
385
  yield* Effect.tryPromise(
268
- () => Promise.resolve(onRequest({ emitStartEvent, req, payload }))
386
+ () => Promise.resolve(
387
+ onRequest({
388
+ setRunId,
389
+ setContextId,
390
+ emitStartEvent,
391
+ req,
392
+ payload
393
+ })
394
+ )
269
395
  );
270
396
  } else if (!providedPlane) {
271
397
  const envelope = {
272
- name: startEventName,
273
- meta: { runId: crypto.randomUUID() },
398
+ name: triggerEventName,
399
+ meta: { runId, contextId },
274
400
  payload
275
401
  };
276
402
  yield* plane.publish(targetChannel, envelope);
@@ -409,7 +535,7 @@ var AgentNetwork = class _AgentNetwork {
409
535
  *
410
536
  * @example
411
537
  * const api = network.expose({ protocol: "sse", auth, select });
412
- * export const GET = NextEndpoint.from(api).handler();
538
+ * export const GET = NextEndpoint.from(api, { requestToContextId, requestToRunId }).handler();
413
539
  */
414
540
  expose(options) {
415
541
  return expose(this, options);
@@ -427,7 +553,7 @@ var AgentNetwork = class _AgentNetwork {
427
553
  }
428
554
  runScoped(network, capacity) {
429
555
  return Effect.gen(function* () {
430
- const plane = yield* createEventPlane(network, capacity);
556
+ const plane = yield* createEventPlane({ network, capacity });
431
557
  yield* Effect.fork(run(network, plane));
432
558
  return plane;
433
559
  });
@@ -435,7 +561,7 @@ var AgentNetwork = class _AgentNetwork {
435
561
  };
436
562
  var EventMetaSchema = Schema.Struct({
437
563
  runId: Schema.String,
438
- contextId: Schema.optional(Schema.String),
564
+ contextId: Schema.String,
439
565
  correlationId: Schema.optional(Schema.String),
440
566
  causationId: Schema.optional(Schema.String),
441
567
  ts: Schema.optional(Schema.Number)
@@ -458,9 +584,7 @@ var AgentNetworkEvent = {
458
584
  const makeBound = (meta, payload2) => Effect.runSync(
459
585
  decodeEnvelope({ name, meta, payload: payload2 })
460
586
  );
461
- const makeEffect = (payload2) => decodePayload(payload2).pipe(
462
- Effect.map((p) => ({ name, payload: p }))
463
- );
587
+ const makeEffect = (payload2) => decodePayload(payload2).pipe(Effect.map((p) => ({ name, payload: p })));
464
588
  const makeBoundEffect = (meta, payload2) => decodeEnvelope({ name, meta, payload: payload2 });
465
589
  const is = Schema.is(envelopeSchema);
466
590
  return {
@@ -493,13 +617,19 @@ var Agent = class {
493
617
  return __privateGet(this, _listensTo);
494
618
  }
495
619
  async invoke(options) {
496
- const { triggerEvent, emit } = options ?? {};
620
+ const { triggerEvent, emit, runEvents, contextEvents } = options ?? {};
497
621
  const emitFn = emit ?? ((_event) => {
498
622
  });
499
623
  await __privateGet(this, _logic).call(this, {
500
624
  params: __privateGet(this, _params),
501
625
  triggerEvent: triggerEvent ?? void 0,
502
- emit: emitFn
626
+ emit: emitFn,
627
+ runEvents: runEvents ?? [],
628
+ contextEvents: contextEvents ?? {
629
+ all: [],
630
+ byRun: () => [],
631
+ map: /* @__PURE__ */ new Map()
632
+ }
503
633
  });
504
634
  }
505
635
  getId() {
@@ -612,14 +742,19 @@ function toSSEStream(source, signal) {
612
742
 
613
743
  // src/matrix/io/adapters/next-endpoint.ts
614
744
  var NextEndpoint = {
615
- from(api) {
745
+ from(api, options) {
616
746
  if (api.protocol !== "sse") {
617
747
  throw new Error(`NextEndpoint: unsupported protocol "${api.protocol}"`);
618
748
  }
749
+ const { requestToContextId, requestToRunId } = options;
619
750
  return {
620
751
  handler() {
621
752
  return async (request) => {
622
- const req = { request };
753
+ const req = {
754
+ request,
755
+ contextId: requestToContextId(request),
756
+ runId: requestToRunId(request)
757
+ };
623
758
  try {
624
759
  const encoder = new TextEncoder();
625
760
  const { readable, writable } = new TransformStream();
@@ -664,12 +799,13 @@ var NextEndpoint = {
664
799
 
665
800
  // src/matrix/io/adapters/express-endpoint.ts
666
801
  var ExpressEndpoint = {
667
- from(api) {
802
+ from(api, options) {
668
803
  if (api.protocol !== "sse") {
669
804
  throw new Error(
670
805
  `ExpressEndpoint: unsupported protocol "${api.protocol}"`
671
806
  );
672
807
  }
808
+ const { requestToContextId, requestToRunId } = options;
673
809
  return {
674
810
  handler() {
675
811
  return async (req, res) => {
@@ -678,7 +814,9 @@ var ExpressEndpoint = {
678
814
  const exposeReq = {
679
815
  request: { signal: controller.signal },
680
816
  req,
681
- res
817
+ res,
818
+ contextId: requestToContextId(req),
819
+ runId: requestToRunId(req)
682
820
  };
683
821
  try {
684
822
  const encoder = new TextEncoder();