@m4trix/core 0.9.0 → 0.10.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.
@@ -1,4 +1,4 @@
1
- import { Brand, Schema, Effect, PubSub, Queue, Cause } from 'effect';
1
+ import { Brand, Schema, Tracer, Layer, Effect, Exit, PubSub, Queue, Cause } from 'effect';
2
2
  export { Schema as S } from 'effect';
3
3
  import { randomUUID } from 'crypto';
4
4
 
@@ -150,7 +150,16 @@ var createEventPlane = (options) => Effect.gen(function* () {
150
150
  };
151
151
  const publishToPubSub = (channel, envelope) => PubSub.publish(getPubsub(channel), envelope);
152
152
  const publish = (channel, envelope) => Effect.sync(() => recordEvent(envelope)).pipe(
153
- Effect.flatMap(() => publishToPubSub(channel, envelope))
153
+ Effect.flatMap(() => publishToPubSub(channel, envelope)),
154
+ Effect.withSpan("event.publish", {
155
+ attributes: {
156
+ "event.name": envelope.name,
157
+ "event.payload": payloadForSpan(envelope.payload),
158
+ channel,
159
+ runId: envelope.meta.runId,
160
+ contextId: envelope.meta.contextId
161
+ }
162
+ })
154
163
  );
155
164
  const publishToChannels = (targetChannels, envelope) => Effect.sync(() => recordEvent(envelope)).pipe(
156
165
  Effect.flatMap(
@@ -159,7 +168,15 @@ var createEventPlane = (options) => Effect.gen(function* () {
159
168
  { concurrency: "unbounded" }
160
169
  )
161
170
  ),
162
- Effect.map((results) => results.every(Boolean))
171
+ Effect.map((results) => results.every(Boolean)),
172
+ Effect.withSpan("event.publish", {
173
+ attributes: {
174
+ "event.name": envelope.name,
175
+ "event.payload": payloadForSpan(envelope.payload),
176
+ runId: envelope.meta.runId,
177
+ contextId: envelope.meta.contextId
178
+ }
179
+ })
163
180
  );
164
181
  const subscribe = (channel) => PubSub.subscribe(getPubsub(channel));
165
182
  const getRunEvents = (runId, contextId) => {
@@ -192,8 +209,17 @@ var createEventPlane = (options) => Effect.gen(function* () {
192
209
  shutdown
193
210
  };
194
211
  });
195
- var runSubscriber = (agent, publishesTo, dequeue, plane, emitQueue) => Effect.gen(function* () {
212
+ function payloadForSpan(payload, maxLen = 500) {
213
+ try {
214
+ const s = JSON.stringify(payload);
215
+ return s.length > maxLen ? `${s.slice(0, maxLen)}...` : s;
216
+ } catch {
217
+ return String(payload);
218
+ }
219
+ }
220
+ var runSubscriber = (agent, publishesTo, dequeue, plane, emitQueue, channelName) => Effect.gen(function* () {
196
221
  const listensTo = agent.getListensTo?.() ?? [];
222
+ const agentId = agent.getId();
197
223
  const processOne = () => Effect.gen(function* () {
198
224
  const envelope = yield* Queue.take(dequeue);
199
225
  if (listensTo.length > 0 && !listensTo.includes(envelope.name)) {
@@ -204,34 +230,51 @@ var runSubscriber = (agent, publishesTo, dequeue, plane, emitQueue) => Effect.ge
204
230
  envelope.meta.contextId
205
231
  );
206
232
  const contextEvents = plane.getContextEvents(envelope.meta.contextId);
207
- yield* Effect.tryPromise({
208
- try: () => agent.invoke({
209
- triggerEvent: envelope,
210
- emit: (userEvent) => {
211
- const fullEnvelope = {
212
- name: userEvent.name,
213
- meta: envelope.meta,
214
- payload: userEvent.payload
215
- };
216
- if (emitQueue) {
217
- Effect.runPromise(
218
- Queue.offer(emitQueue, {
219
- channels: publishesTo,
220
- envelope: fullEnvelope
221
- })
222
- ).catch(() => {
223
- });
224
- } else {
225
- Effect.runFork(
226
- plane.publishToChannels(publishesTo, fullEnvelope)
227
- );
228
- }
229
- },
230
- runEvents,
231
- contextEvents
232
- }),
233
- catch: (e) => e
234
- });
233
+ yield* Effect.withSpan("agent.listen", {
234
+ attributes: {
235
+ agentId,
236
+ "event.name": envelope.name,
237
+ "event.payload": payloadForSpan(envelope.payload),
238
+ ...channelName !== void 0 && { channel: channelName }
239
+ }
240
+ })(
241
+ Effect.withSpan("agent.invoke", {
242
+ attributes: {
243
+ agentId,
244
+ "event.name": envelope.name,
245
+ "event.payload": payloadForSpan(envelope.payload)
246
+ }
247
+ })(
248
+ Effect.tryPromise({
249
+ try: () => agent.invoke({
250
+ triggerEvent: envelope,
251
+ emit: (userEvent) => {
252
+ const fullEnvelope = {
253
+ name: userEvent.name,
254
+ meta: envelope.meta,
255
+ payload: userEvent.payload
256
+ };
257
+ if (emitQueue) {
258
+ Effect.runPromise(
259
+ Queue.offer(emitQueue, {
260
+ channels: publishesTo,
261
+ envelope: fullEnvelope
262
+ })
263
+ ).catch(() => {
264
+ });
265
+ } else {
266
+ Effect.runFork(
267
+ plane.publishToChannels(publishesTo, fullEnvelope)
268
+ );
269
+ }
270
+ },
271
+ runEvents,
272
+ contextEvents
273
+ }),
274
+ catch: (e) => e
275
+ })
276
+ )
277
+ );
235
278
  }).pipe(
236
279
  Effect.catchAllCause(
237
280
  (cause) => Cause.isInterrupted(cause) ? Effect.void : Effect.sync(() => {
@@ -253,7 +296,8 @@ var run = (network, plane, options) => Effect.gen(function* () {
253
296
  reg.publishesTo,
254
297
  dequeue,
255
298
  plane,
256
- emitQueue
299
+ emitQueue,
300
+ channel.name
257
301
  );
258
302
  }
259
303
  }
@@ -327,7 +371,8 @@ function expose(network, options) {
327
371
  select,
328
372
  plane: providedPlane,
329
373
  onRequest,
330
- triggerEvents
374
+ triggerEvents,
375
+ tracingLayer
331
376
  } = options;
332
377
  const triggerEventDef = triggerEvents?.[0];
333
378
  const triggerEventName = triggerEventDef?.name ?? "request";
@@ -341,7 +386,7 @@ function expose(network, options) {
341
386
  const payload = await extractPayload(req);
342
387
  const signal = req.request?.signal;
343
388
  const program = Effect.gen(function* () {
344
- const plane = providedPlane ?? (yield* createEventPlane({ network }));
389
+ const plane = providedPlane ?? (yield* createEventPlane({ network, store: network.getStore() }));
345
390
  if (!providedPlane) {
346
391
  const emitQueue = yield* Queue.unbounded();
347
392
  yield* Effect.fork(
@@ -409,7 +454,8 @@ function expose(network, options) {
409
454
  }
410
455
  return stream;
411
456
  });
412
- return Effect.runPromise(program.pipe(Effect.scoped));
457
+ const runnable = tracingLayer ? program.pipe(Effect.provide(tracingLayer), Effect.scoped) : program.pipe(Effect.scoped);
458
+ return Effect.runPromise(runnable);
413
459
  };
414
460
  return {
415
461
  protocol: "sse",
@@ -441,6 +487,7 @@ var AgentNetwork = class _AgentNetwork {
441
487
  this.channels = /* @__PURE__ */ new Map();
442
488
  this.agentRegistrations = /* @__PURE__ */ new Map();
443
489
  this.spawnerRegistrations = [];
490
+ this._store = createInMemoryNetworkStore();
444
491
  }
445
492
  /* ─── Public Static Factory ─── */
446
493
  static setup(callback) {
@@ -528,6 +575,10 @@ var AgentNetwork = class _AgentNetwork {
528
575
  getSpawnerRegistrations() {
529
576
  return this.spawnerRegistrations;
530
577
  }
578
+ /** Store defined at network setup time. Shared across all event planes created for this network. */
579
+ getStore() {
580
+ return this._store;
581
+ }
531
582
  /**
532
583
  * Expose the network as a streamable API (e.g. SSE). Returns an ExposedAPI
533
584
  * that adapters (NextEndpoint, ExpressEndpoint) consume to produce streamed
@@ -553,7 +604,11 @@ var AgentNetwork = class _AgentNetwork {
553
604
  }
554
605
  runScoped(network, capacity) {
555
606
  return Effect.gen(function* () {
556
- const plane = yield* createEventPlane({ network, capacity });
607
+ const plane = yield* createEventPlane({
608
+ network,
609
+ capacity,
610
+ store: network.getStore()
611
+ });
557
612
  yield* Effect.fork(run(network, plane));
558
613
  return plane;
559
614
  });
@@ -848,7 +903,79 @@ var ExpressEndpoint = {
848
903
  };
849
904
  }
850
905
  };
906
+ var randomHexString = (length) => {
907
+ const chars = "abcdef0123456789";
908
+ let result = "";
909
+ for (let i = 0; i < length; i++) {
910
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
911
+ }
912
+ return result;
913
+ };
914
+ var ConsoleSpan = class {
915
+ constructor(name, parent, context, links, startTime, kind, depth) {
916
+ this.name = name;
917
+ this.parent = parent;
918
+ this.context = context;
919
+ this.startTime = startTime;
920
+ this.kind = kind;
921
+ this.depth = depth;
922
+ this._tag = "Span";
923
+ this.sampled = true;
924
+ this.attributes = /* @__PURE__ */ new Map();
925
+ this.links = [];
926
+ this.traceId = parent._tag === "Some" ? parent.value.traceId : randomHexString(32);
927
+ this.spanId = randomHexString(16);
928
+ this.links = Array.from(links);
929
+ this.status = { _tag: "Started", startTime };
930
+ }
931
+ end(endTime, exit) {
932
+ if (this.status._tag === "Ended")
933
+ return;
934
+ const startTime = this.status.startTime;
935
+ const durationNs = endTime - startTime;
936
+ const durationMs = Number(durationNs) / 1e6;
937
+ const indent = " ".repeat(this.depth);
938
+ const attrs = Object.fromEntries(this.attributes);
939
+ const status = Exit.isSuccess(exit) ? "ok" : "error";
940
+ console.log(
941
+ `${indent}[trace] ${this.name} ${durationMs.toFixed(2)}ms (${status})`,
942
+ Object.keys(attrs).length > 0 ? attrs : ""
943
+ );
944
+ this.status = { _tag: "Ended", startTime, endTime, exit };
945
+ }
946
+ attribute(key, value) {
947
+ this.attributes.set(key, value);
948
+ }
949
+ event(_name, _startTime, _attributes) {
950
+ }
951
+ addLinks(links) {
952
+ this.links.push(...links);
953
+ }
954
+ };
955
+ function getDepth(parent) {
956
+ if (parent._tag === "None")
957
+ return 0;
958
+ const p = parent.value;
959
+ if (p._tag === "ExternalSpan")
960
+ return 0;
961
+ return 1 + getDepth(p.parent);
962
+ }
963
+ var consoleTracer = Tracer.make({
964
+ span: (name, parent, context, links, startTime, kind) => new ConsoleSpan(
965
+ name,
966
+ parent,
967
+ context,
968
+ links,
969
+ startTime,
970
+ kind,
971
+ getDepth(parent)
972
+ ),
973
+ context: (f) => f()
974
+ });
975
+ var consoleTracerLayer = Layer.setTracer(
976
+ consoleTracer
977
+ );
851
978
 
852
- export { Agent, AgentFactory, AgentNetwork, AgentNetworkEvent, Channel, ChannelName, ConfiguredChannel, EventMetaSchema, ExposeAuthError, ExpressEndpoint, NextEndpoint, Sink, formatSSE, isHttpStreamSink, toSSEStream };
979
+ export { Agent, AgentFactory, AgentNetwork, AgentNetworkEvent, Channel, ChannelName, ConfiguredChannel, EventMetaSchema, ExposeAuthError, ExpressEndpoint, NextEndpoint, Sink, consoleTracer, consoleTracerLayer, formatSSE, isHttpStreamSink, toSSEStream };
853
980
  //# sourceMappingURL=out.js.map
854
981
  //# sourceMappingURL=index.js.map