@ultrst-armada/krnl 1.0.8 → 1.0.10

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.
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ DefaultExecutionController: () => DefaultExecutionController,
33
34
  EventBus: () => EventBus,
34
35
  FunctionalityFacade: () => FunctionalityFacade,
35
36
  FunctionalityOrchestration: () => FunctionalityOrchestration,
@@ -50,6 +51,7 @@ __export(index_exports, {
50
51
  ServiceRegistry: () => ServiceRegistry,
51
52
  ServiceRuntime: () => ServiceRuntime,
52
53
  ServiceStateStore: () => ServiceStateStore,
54
+ TelemetryController: () => TelemetryController,
53
55
  UdpProtocolAdapter: () => UdpProtocolAdapter,
54
56
  WebSocketProtocolAdapter: () => WebSocketProtocolAdapter,
55
57
  WorkerExecutionBoundary: () => WorkerExecutionBoundary,
@@ -58,7 +60,10 @@ __export(index_exports, {
58
60
  createServiceDefinition: () => createServiceDefinition,
59
61
  createServiceFacade: () => createServiceFacade,
60
62
  createServiceProxy: () => createServiceProxy,
63
+ deltaResources: () => deltaResources,
61
64
  gutts: () => gutts,
65
+ sampleResources: () => sampleResources,
66
+ telemetryNow: () => telemetryNow,
62
67
  validateOrchestrationDAG: () => validateOrchestrationDAG,
63
68
  validateServiceDefinition: () => validateServiceDefinition
64
69
  });
@@ -128,6 +133,227 @@ var LifecycleManager = class {
128
133
  }
129
134
  };
130
135
 
136
+ // src/telemetry/TelemetryController.ts
137
+ var import_node_crypto = require("crypto");
138
+
139
+ // src/telemetry/TelemetryResources.ts
140
+ var runtimeProcess = typeof globalThis !== "undefined" ? globalThis.process : void 0;
141
+ var runtimePerformance = typeof globalThis !== "undefined" ? globalThis.performance : void 0;
142
+ function telemetryNow() {
143
+ return runtimePerformance?.now ? runtimePerformance.now() : Date.now();
144
+ }
145
+ function sampleResources() {
146
+ const memory = runtimeProcess?.memoryUsage?.();
147
+ const cpu = runtimeProcess?.cpuUsage?.();
148
+ const eventLoop = runtimePerformance?.eventLoopUtilization?.();
149
+ return {
150
+ cpuUserMicros: cpu?.user,
151
+ cpuSystemMicros: cpu?.system,
152
+ heapUsedBytes: memory?.heapUsed,
153
+ heapTotalBytes: memory?.heapTotal,
154
+ rssBytes: memory?.rss,
155
+ externalBytes: memory?.external,
156
+ arrayBuffersBytes: memory?.arrayBuffers,
157
+ eventLoopUtilization: eventLoop?.utilization,
158
+ scope: memory || cpu || eventLoop ? "process" : "runtime"
159
+ };
160
+ }
161
+ function deltaResources(start, end) {
162
+ const delta = (a, b) => a === void 0 || b === void 0 ? void 0 : b - a;
163
+ return {
164
+ cpuUserMicros: delta(start.cpuUserMicros, end.cpuUserMicros),
165
+ cpuSystemMicros: delta(start.cpuSystemMicros, end.cpuSystemMicros),
166
+ heapUsedBytes: delta(start.heapUsedBytes, end.heapUsedBytes),
167
+ heapTotalBytes: delta(start.heapTotalBytes, end.heapTotalBytes),
168
+ rssBytes: delta(start.rssBytes, end.rssBytes),
169
+ externalBytes: delta(start.externalBytes, end.externalBytes),
170
+ arrayBuffersBytes: delta(start.arrayBuffersBytes, end.arrayBuffersBytes),
171
+ eventLoopUtilization: delta(start.eventLoopUtilization, end.eventLoopUtilization),
172
+ scope: start.scope
173
+ };
174
+ }
175
+
176
+ // src/telemetry/TelemetryController.ts
177
+ var id = (prefix) => `${prefix}_${(0, import_node_crypto.randomUUID)()}`;
178
+ function percentiles(values) {
179
+ if (!values.length) return { min: 0, mean: 0, p50: 0, p90: 0, p95: 0, p99: 0, max: 0 };
180
+ const sorted = [...values].sort((a, b) => a - b);
181
+ const pick = (p) => sorted[Math.min(sorted.length - 1, Math.floor((sorted.length - 1) * p))];
182
+ return {
183
+ min: sorted[0],
184
+ mean: sorted.reduce((sum, value) => sum + value, 0) / sorted.length,
185
+ p50: pick(0.5),
186
+ p90: pick(0.9),
187
+ p95: pick(0.95),
188
+ p99: pick(0.99),
189
+ max: sorted[sorted.length - 1]
190
+ };
191
+ }
192
+ var TelemetryController = class {
193
+ constructor(serviceId, options = {}) {
194
+ this.serviceId = serviceId;
195
+ this.mode = options.mode ?? "off";
196
+ this.maxSamples = Math.max(1, options.maxSamples ?? 2048);
197
+ this.maxRecentInvocations = Math.max(1, options.maxRecentInvocations ?? 100);
198
+ }
199
+ serviceId;
200
+ mode;
201
+ maxSamples;
202
+ maxRecentInvocations;
203
+ samples = [];
204
+ active = /* @__PURE__ */ new Map();
205
+ totalInvocationCount = 0;
206
+ totalSuccessCount = 0;
207
+ totalErrorCount = 0;
208
+ lastInvocationAt;
209
+ enable(mode = "standard") {
210
+ this.mode = mode;
211
+ }
212
+ disable() {
213
+ this.mode = "off";
214
+ this.active.clear();
215
+ }
216
+ setMode(mode) {
217
+ this.mode = mode;
218
+ if (mode === "off") this.active.clear();
219
+ }
220
+ getMode() {
221
+ return this.mode;
222
+ }
223
+ status() {
224
+ return {
225
+ enabled: this.mode !== "off",
226
+ mode: this.mode,
227
+ serviceId: this.serviceId,
228
+ invocationCount: this.totalInvocationCount,
229
+ activeInvocations: this.active.size,
230
+ lastInvocationAt: this.lastInvocationAt
231
+ };
232
+ }
233
+ begin(target, kind, correlationId, parentSpanId) {
234
+ if (this.mode === "off") {
235
+ return {
236
+ invocationId: "",
237
+ traceId: "",
238
+ spanId: "",
239
+ parentSpanId,
240
+ end: () => void 0
241
+ };
242
+ }
243
+ const invocationId = id("inv");
244
+ const spanId = id("span");
245
+ const traceId = parentSpanId ? this.findTraceId(parentSpanId) ?? id("trace") : id("trace");
246
+ const active = {
247
+ invocationId,
248
+ traceId,
249
+ spanId,
250
+ parentSpanId,
251
+ serviceId: this.serviceId,
252
+ target,
253
+ kind,
254
+ correlationId,
255
+ startedAt: telemetryNow(),
256
+ resourcesStart: this.mode === "standard" ? void 0 : sampleResources()
257
+ };
258
+ this.active.set(invocationId, active);
259
+ return {
260
+ invocationId,
261
+ traceId,
262
+ spanId,
263
+ parentSpanId,
264
+ end: (error) => this.finish(active, error)
265
+ };
266
+ }
267
+ reset() {
268
+ this.samples.length = 0;
269
+ this.active.clear();
270
+ this.totalInvocationCount = 0;
271
+ this.totalSuccessCount = 0;
272
+ this.totalErrorCount = 0;
273
+ this.lastInvocationAt = void 0;
274
+ }
275
+ snapshot() {
276
+ const invocations = this.samples.slice();
277
+ const durations = invocations.map((item) => item.durationMs);
278
+ const targetMap = /* @__PURE__ */ new Map();
279
+ for (const invocation of invocations) {
280
+ const key = `${invocation.kind}:${invocation.target}`;
281
+ const group = targetMap.get(key) ?? [];
282
+ group.push(invocation);
283
+ targetMap.set(key, group);
284
+ }
285
+ const targets = [...targetMap.values()].map((group) => ({
286
+ target: group[0].target,
287
+ kind: group[0].kind,
288
+ count: group.length,
289
+ successCount: group.filter((item) => item.status === "completed").length,
290
+ errorCount: group.filter((item) => item.status === "failed").length,
291
+ durationMs: percentiles(group.map((item) => item.durationMs)),
292
+ lastInvocationAt: group[group.length - 1]?.completedAt
293
+ }));
294
+ return {
295
+ serviceId: this.serviceId,
296
+ mode: this.mode,
297
+ capturedAt: Date.now(),
298
+ status: this.status(),
299
+ totals: {
300
+ invocationCount: this.totalInvocationCount,
301
+ successCount: this.totalSuccessCount,
302
+ errorCount: this.totalErrorCount,
303
+ durationMs: percentiles(durations)
304
+ },
305
+ targets,
306
+ activeInvocations: this.active.size,
307
+ recentInvocations: invocations.slice(-this.maxRecentInvocations)
308
+ };
309
+ }
310
+ functionality(name) {
311
+ return this.snapshot().targets.find((target) => target.kind === "functionality" && target.target === name);
312
+ }
313
+ functionalities() {
314
+ return this.snapshot().targets.filter((target) => target.kind === "functionality");
315
+ }
316
+ findTraceId(parentSpanId) {
317
+ for (let index = this.samples.length - 1; index >= 0; index -= 1) {
318
+ if (this.samples[index].spanId === parentSpanId) return this.samples[index].traceId;
319
+ }
320
+ for (const active of this.active.values()) {
321
+ if (active.spanId === parentSpanId) return active.traceId;
322
+ }
323
+ return void 0;
324
+ }
325
+ finish(active, error) {
326
+ if (!this.active.delete(active.invocationId)) return;
327
+ const completedAt = telemetryNow();
328
+ const resourcesEnd = this.mode === "standard" ? void 0 : sampleResources();
329
+ const invocation = {
330
+ invocationId: active.invocationId,
331
+ traceId: active.traceId,
332
+ spanId: active.spanId,
333
+ parentSpanId: active.parentSpanId,
334
+ serviceId: active.serviceId,
335
+ target: active.target,
336
+ kind: active.kind,
337
+ correlationId: active.correlationId,
338
+ startedAt: active.startedAt,
339
+ completedAt,
340
+ durationMs: Math.max(0, completedAt - active.startedAt),
341
+ status: error === void 0 ? "completed" : "failed",
342
+ error: error === void 0 ? void 0 : {
343
+ name: error instanceof Error ? error.name : "Error",
344
+ message: error instanceof Error ? error.message : String(error)
345
+ },
346
+ resources: active.resourcesStart && resourcesEnd ? { start: active.resourcesStart, end: resourcesEnd, delta: deltaResources(active.resourcesStart, resourcesEnd) } : void 0
347
+ };
348
+ this.samples.push(invocation);
349
+ this.totalInvocationCount += 1;
350
+ if (invocation.status === "completed") this.totalSuccessCount += 1;
351
+ else this.totalErrorCount += 1;
352
+ if (this.samples.length > this.maxSamples) this.samples.splice(0, this.samples.length - this.maxSamples);
353
+ this.lastInvocationAt = Date.now();
354
+ }
355
+ };
356
+
131
357
  // src/services/ServiceInstance.ts
132
358
  var ServiceInstance = class {
133
359
  constructor(definition) {
@@ -135,6 +361,7 @@ var ServiceInstance = class {
135
361
  this.id = definition.id;
136
362
  this.name = definition.name;
137
363
  this.version = definition.version;
364
+ this.telemetry = new TelemetryController(this.id);
138
365
  this.lifecycle = new LifecycleManager();
139
366
  if (definition.state) {
140
367
  this.stateStore = new ServiceStateStore(definition.state.initial);
@@ -144,6 +371,7 @@ var ServiceInstance = class {
144
371
  id;
145
372
  name;
146
373
  version;
374
+ telemetry;
147
375
  stateStore;
148
376
  lifecycle;
149
377
  initialized = false;
@@ -208,7 +436,19 @@ var ServiceInstance = class {
208
436
  if (!operation) {
209
437
  throw new Error("[Service:" + this.name + "] Operation '" + op + "' not found.");
210
438
  }
211
- return await operation.handler(input, ctx);
439
+ if (ctx.metadata?.__krnlTelemetryInternal === true) {
440
+ return await operation.handler(input, ctx);
441
+ }
442
+ const parentSpanId = typeof ctx.metadata?.__krnlTelemetryParentSpanId === "string" ? ctx.metadata.__krnlTelemetryParentSpanId : void 0;
443
+ const handle = this.telemetry.begin(op, "service", ctx.correlationId, parentSpanId);
444
+ try {
445
+ const output = await operation.handler(input, ctx);
446
+ handle.end();
447
+ return output;
448
+ } catch (error) {
449
+ handle.end(error);
450
+ throw error;
451
+ }
212
452
  }
213
453
  getState() {
214
454
  return this.stateStore?.getState() ?? Object.freeze({});
@@ -240,6 +480,7 @@ var ServiceProxy = class {
240
480
  this.id = definition.id;
241
481
  this.name = definition.name;
242
482
  this.version = definition.version;
483
+ this.telemetry = new TelemetryController(this.id);
243
484
  this.stateCache = { ...definition.state?.initial ?? {} };
244
485
  }
245
486
  definition;
@@ -248,6 +489,7 @@ var ServiceProxy = class {
248
489
  id;
249
490
  name;
250
491
  version;
492
+ telemetry;
251
493
  stateCache;
252
494
  eventHandlers = /* @__PURE__ */ new Map();
253
495
  lifecycle = new LifecycleManager();
@@ -305,11 +547,21 @@ var ServiceProxy = class {
305
547
  payload: input,
306
548
  timestamp: Date.now()
307
549
  };
308
- const response = await this.adapter.send(this.endpoint, envelope);
309
- if (response.error) {
310
- throw new Error("[ServiceProxy:" + this.name + "] Remote error: " + response.error);
550
+ const parentSpanId = typeof ctx.metadata?.__krnlTelemetryParentSpanId === "string" ? ctx.metadata.__krnlTelemetryParentSpanId : void 0;
551
+ const handle = this.telemetry.begin(op, "service", ctx.correlationId, parentSpanId);
552
+ try {
553
+ const response = await this.adapter.send(this.endpoint, envelope);
554
+ if (response.error) {
555
+ const error = new Error("[ServiceProxy:" + this.name + "] Remote error: " + response.error);
556
+ handle.end(error);
557
+ throw error;
558
+ }
559
+ handle.end();
560
+ return response.payload;
561
+ } catch (error) {
562
+ handle.end(error);
563
+ throw error;
311
564
  }
312
- return response.payload;
313
565
  }
314
566
  getState() {
315
567
  return Object.freeze({ ...this.stateCache });
@@ -457,22 +709,22 @@ var FunctionalityFacade = class {
457
709
  definition;
458
710
  eventBus;
459
711
  events;
460
- constructor(id, definition, options = {}) {
461
- if (!id || typeof id !== "string") {
712
+ constructor(id2, definition, options = {}) {
713
+ if (!id2 || typeof id2 !== "string") {
462
714
  throw new Error("[FunctionalityFacade] Functionality id must be a non-empty string.");
463
715
  }
464
716
  if (!definition || typeof definition.execute !== "function") {
465
- throw new Error(`[FunctionalityFacade:${id}] Functionality must define execute().`);
717
+ throw new Error(`[FunctionalityFacade:${id2}] Functionality must define execute().`);
466
718
  }
467
- this.id = id;
468
- this.name = definition.name || id;
719
+ this.id = id2;
720
+ this.name = definition.name || id2;
469
721
  this.description = definition.description || "";
470
722
  this.bubbleEvents = options.bubbleEvents ?? definition.bubbleEvents ?? true;
471
723
  this.definition = definition;
472
724
  this.eventBus = new EventBus();
473
725
  for (const reserved of ["triggered", "completed", "failed"]) {
474
726
  if (definition.events && reserved in definition.events) {
475
- throw new Error(`[FunctionalityFacade:${id}] Event '${reserved}' is reserved for functionality lifecycle.`);
727
+ throw new Error(`[FunctionalityFacade:${id2}] Event '${reserved}' is reserved for functionality lifecycle.`);
476
728
  }
477
729
  }
478
730
  const eventNames = [
@@ -586,11 +838,11 @@ var PriorityQueue = class {
586
838
  return item.run;
587
839
  }
588
840
  enqueue(run, options) {
589
- const { priority = 0, id } = options ?? {};
841
+ const { priority = 0, id: id2 } = options ?? {};
590
842
  const { size } = this;
591
843
  const element = {
592
844
  priority,
593
- id,
845
+ id: id2,
594
846
  run
595
847
  };
596
848
  if (size === 0) {
@@ -607,16 +859,16 @@ var PriorityQueue = class {
607
859
  const index = lowerBound(this.#queue, element, (a, b) => a.priority === b.priority ? 0 : b.priority - a.priority);
608
860
  this.#queue.splice(index, 0, element);
609
861
  }
610
- setPriority(id, priority) {
611
- const index = this.#findIndex((element) => element.id === id);
862
+ setPriority(id2, priority) {
863
+ const index = this.#findIndex((element) => element.id === id2);
612
864
  if (index === -1) {
613
- throw new ReferenceError(`No promise function with the id "${id}" exists in the queue.`);
865
+ throw new ReferenceError(`No promise function with the id "${id2}" exists in the queue.`);
614
866
  }
615
867
  if (this.#queue[index].priority === priority) {
616
868
  return;
617
869
  }
618
870
  const [item] = this.#queue.splice(index, 1);
619
- this.enqueue(item.run, { priority, id });
871
+ this.enqueue(item.run, { priority, id: id2 });
620
872
  }
621
873
  remove(idOrRun) {
622
874
  const index = this.#findIndex((element) => (typeof idOrRun === "string" ? element.id : element.run) === idOrRun);
@@ -1032,17 +1284,17 @@ var PQueue = class extends EventTarget {
1032
1284
  }
1033
1285
  }
1034
1286
  async #add(function_, options, waitingTask) {
1035
- const id = options.id ?? (this.#idAssigner++).toString();
1287
+ const id2 = options.id ?? (this.#idAssigner++).toString();
1036
1288
  options = {
1037
1289
  timeout: this.#timeout,
1038
1290
  ...options,
1039
- id
1291
+ id: id2
1040
1292
  };
1041
1293
  validateTimeout(options.timeout);
1042
1294
  if (options.priority !== void 0 && (typeof options.priority !== "number" || Number.isNaN(options.priority))) {
1043
1295
  throw new TypeError(`Expected \`priority\` to be a number, got \`${String(options.priority)}\` (${typeof options.priority})`);
1044
1296
  }
1045
- waitingTask.id = id;
1297
+ waitingTask.id = id2;
1046
1298
  waitingTask.priority = options.priority ?? 0;
1047
1299
  return new Promise((resolve, reject) => {
1048
1300
  if (options.signal?.aborted) {
@@ -1059,7 +1311,7 @@ var PQueue = class extends EventTarget {
1059
1311
  }
1060
1312
  this.#pending++;
1061
1313
  const runningTask = {
1062
- id,
1314
+ id: id2,
1063
1315
  priority: waitingTask.priority,
1064
1316
  startTime: Date.now(),
1065
1317
  timeout: options.timeout
@@ -1126,7 +1378,7 @@ var PQueue = class extends EventTarget {
1126
1378
  if (this.#queue instanceof PriorityQueue) {
1127
1379
  this.#queue.remove(run);
1128
1380
  } else {
1129
- this.#queue.remove(id);
1381
+ this.#queue.remove(id2);
1130
1382
  }
1131
1383
  reject(signal.reason);
1132
1384
  this.#processQueue();
@@ -1202,18 +1454,18 @@ var PQueue = class extends EventTarget {
1202
1454
  // '🦀' runs last
1203
1455
  ```
1204
1456
  */
1205
- setPriority(id, priority) {
1457
+ setPriority(id2, priority) {
1206
1458
  if (typeof priority !== "number" || !Number.isFinite(priority)) {
1207
1459
  throw new TypeError(`Expected \`priority\` to be a finite number, got \`${priority}\` (${typeof priority})`);
1208
1460
  }
1209
1461
  for (const waitingTask of this.#waitingTasks) {
1210
- if (waitingTask.id === id) {
1211
- this.#queue.setPriority(id, priority);
1462
+ if (waitingTask.id === id2) {
1463
+ this.#queue.setPriority(id2, priority);
1212
1464
  waitingTask.priority = priority;
1213
1465
  return;
1214
1466
  }
1215
1467
  }
1216
- throw new ReferenceError(`No promise function with the id "${id}" exists in the queue.`);
1468
+ throw new ReferenceError(`No promise function with the id "${id2}" exists in the queue.`);
1217
1469
  }
1218
1470
  /**
1219
1471
  Adds a sync or async task to the queue.
@@ -1556,7 +1808,7 @@ var TimeoutError = class extends DOMException {
1556
1808
  };
1557
1809
 
1558
1810
  // src/orchestration/canonical/KrnlQ.ts
1559
- var import_node_crypto = require("crypto");
1811
+ var import_node_crypto2 = require("crypto");
1560
1812
 
1561
1813
  // src/orchestration/canonical/model.ts
1562
1814
  function validateOrchestrationDAG(steps) {
@@ -1623,8 +1875,8 @@ function validateOrchestrationDAG(steps) {
1623
1875
  }
1624
1876
  }
1625
1877
  const queue = [];
1626
- for (const [id, deg] of inDegree.entries()) {
1627
- if (deg === 0) queue.push(id);
1878
+ for (const [id2, deg] of inDegree.entries()) {
1879
+ if (deg === 0) queue.push(id2);
1628
1880
  }
1629
1881
  const order = [];
1630
1882
  while (queue.length > 0) {
@@ -1760,7 +2012,7 @@ var KrnlWorkerPool = class {
1760
2012
  // src/orchestration/canonical/KrnlQ.ts
1761
2013
  function generateSecureId(prefix) {
1762
2014
  try {
1763
- return `${prefix}_${(0, import_node_crypto.randomUUID)()}`;
2015
+ return `${prefix}_${(0, import_node_crypto2.randomUUID)()}`;
1764
2016
  } catch {
1765
2017
  return `${prefix}_${Math.random().toString(36).substring(2, 11)}_${Date.now()}`;
1766
2018
  }
@@ -1828,9 +2080,9 @@ var KrnlQueue = class {
1828
2080
  if (this.jobs.size <= this.maxRetainedJobs) return;
1829
2081
  const excess = this.jobs.size - this.maxRetainedJobs;
1830
2082
  let pruned = 0;
1831
- for (const [id, record] of this.jobs.entries()) {
2083
+ for (const [id2, record] of this.jobs.entries()) {
1832
2084
  if (record.status === "completed" || record.status === "failed" || record.status === "cancelled") {
1833
- this.jobs.delete(id);
2085
+ this.jobs.delete(id2);
1834
2086
  pruned++;
1835
2087
  if (pruned >= excess) break;
1836
2088
  }
@@ -2444,6 +2696,7 @@ var ServiceFacade = class {
2444
2696
  defaultFrontend;
2445
2697
  instance;
2446
2698
  queue;
2699
+ telemetry;
2447
2700
  constructor(config) {
2448
2701
  if (!config || !config.id || typeof config.id !== "string") {
2449
2702
  throw new Error("[ServiceFacade] ServiceFacade requires a valid id.");
@@ -2473,6 +2726,7 @@ var ServiceFacade = class {
2473
2726
  operations: {}
2474
2727
  });
2475
2728
  }
2729
+ this.telemetry = this.instance.telemetry;
2476
2730
  this.queue = new KrnlQueue({
2477
2731
  queueName: `krnl_queue_${this.id}`,
2478
2732
  concurrency: config.concurrency ?? config.queueOptions?.concurrency ?? 10,
@@ -2516,6 +2770,8 @@ var ServiceFacade = class {
2516
2770
  */
2517
2771
  async call(op, input, ctx) {
2518
2772
  const correlationId = ctx?.correlationId || `corr_${Math.random().toString(36).substring(2, 11)}`;
2773
+ const telemetryParent = typeof ctx?.metadata?.__krnlTelemetryParentSpanId === "string" ? ctx.metadata.__krnlTelemetryParentSpanId : void 0;
2774
+ const telemetryHandle = this.telemetry.begin(op, "service", correlationId, telemetryParent);
2519
2775
  const commandId = `cmd_${this.id}_${op}_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
2520
2776
  const command = {
2521
2777
  id: commandId,
@@ -2525,26 +2781,48 @@ var ServiceFacade = class {
2525
2781
  idempotencyKey: ctx?.idempotencyKey,
2526
2782
  createdAt: Date.now()
2527
2783
  };
2528
- const result = await this.queue.executeCommand(command, async (payload, workerCtx) => {
2529
- WorkerExecutionBoundary.assertWorkerContext(workerCtx);
2530
- const functionality = this.functionalities[op];
2531
- if (functionality) {
2532
- return await functionality.execute(payload, {
2533
- serviceId: this.id,
2534
- functionalityId: functionality.id,
2784
+ try {
2785
+ const result = await this.queue.executeCommand(command, async (payload, workerCtx) => {
2786
+ WorkerExecutionBoundary.assertWorkerContext(workerCtx);
2787
+ const functionality = this.functionalities[op];
2788
+ if (functionality) {
2789
+ const functionalityTelemetry = this.telemetry.begin(
2790
+ functionality.name,
2791
+ "functionality",
2792
+ workerCtx.correlationId,
2793
+ telemetryHandle.spanId
2794
+ );
2795
+ try {
2796
+ return await functionality.execute(payload, {
2797
+ serviceId: this.id,
2798
+ functionalityId: functionality.id,
2799
+ correlationId: workerCtx.correlationId,
2800
+ state: this.instance.getState()
2801
+ });
2802
+ } catch (error) {
2803
+ functionalityTelemetry.end(error);
2804
+ throw error;
2805
+ } finally {
2806
+ functionalityTelemetry.end();
2807
+ }
2808
+ }
2809
+ return await this.instance.call(op, payload, {
2535
2810
  correlationId: workerCtx.correlationId,
2536
- state: this.instance.getState()
2811
+ idempotencyKey: command.idempotencyKey,
2812
+ metadata: { __krnlTelemetryInternal: true }
2537
2813
  });
2538
- }
2539
- return await this.instance.call(op, payload, {
2540
- correlationId: workerCtx.correlationId,
2541
- idempotencyKey: command.idempotencyKey
2542
2814
  });
2543
- });
2544
- if (result.status === "FAILED") {
2545
- throw new Error(result.error || `[ServiceFacade:${this.id}] Operation '${op}' execution failed.`);
2815
+ if (result.status === "FAILED") {
2816
+ const error = new Error(result.error || `[ServiceFacade:${this.id}] Operation '${op}' execution failed.`);
2817
+ telemetryHandle.end(error);
2818
+ throw error;
2819
+ }
2820
+ telemetryHandle.end();
2821
+ return result.data;
2822
+ } catch (error) {
2823
+ telemetryHandle.end(error);
2824
+ throw error;
2546
2825
  }
2547
- return result.data;
2548
2826
  }
2549
2827
  /**
2550
2828
  * External caller callable boundary for functionality orchestration execution.
@@ -2558,6 +2836,18 @@ var ServiceFacade = class {
2558
2836
  );
2559
2837
  }
2560
2838
  const correlationId = options.correlationId || `corr_${Math.random().toString(36).substring(2, 11)}`;
2839
+ const serviceTelemetryHandle = this.telemetry.begin(
2840
+ `orchestrate:${orchestrationName}`,
2841
+ "service",
2842
+ correlationId,
2843
+ typeof options.metadata?.__krnlTelemetryParentSpanId === "string" ? options.metadata.__krnlTelemetryParentSpanId : void 0
2844
+ );
2845
+ const telemetryHandle = this.telemetry.begin(
2846
+ orchestrationName,
2847
+ "orchestration",
2848
+ correlationId,
2849
+ serviceTelemetryHandle.spanId
2850
+ );
2561
2851
  const commandId = `cmd_orch_${this.id}_${orchestrationName}_${Date.now()}`;
2562
2852
  const command = {
2563
2853
  id: commandId,
@@ -2605,7 +2895,8 @@ var ServiceFacade = class {
2605
2895
  ...s.compensation,
2606
2896
  handler: async (compCtx) => {
2607
2897
  await this.call(s.compensation.target, compCtx.results[s.id], {
2608
- correlationId: compCtx.correlationId
2898
+ correlationId: compCtx.correlationId,
2899
+ metadata: { __krnlTelemetryParentSpanId: telemetryHandle.spanId }
2609
2900
  });
2610
2901
  }
2611
2902
  };
@@ -2621,7 +2912,8 @@ var ServiceFacade = class {
2621
2912
  stepPayload.input = stepCtx.results.input;
2622
2913
  }
2623
2914
  return await this.call(s.target, stepPayload, {
2624
- correlationId: stepCtx.correlationId
2915
+ correlationId: stepCtx.correlationId,
2916
+ metadata: { __krnlTelemetryParentSpanId: telemetryHandle.spanId }
2625
2917
  });
2626
2918
  }
2627
2919
  };
@@ -2641,7 +2933,8 @@ var ServiceFacade = class {
2641
2933
  const nestedResult = await this.orchestrate(childOrchId, childInput, {
2642
2934
  correlationId: childCtx.correlationId,
2643
2935
  timeoutMs: childOrch.timeoutMs,
2644
- abortSignal: options.abortSignal
2936
+ abortSignal: options.abortSignal,
2937
+ metadata: { __krnlTelemetryParentSpanId: telemetryHandle.spanId }
2645
2938
  });
2646
2939
  if (nestedResult.status !== "COMPLETED") {
2647
2940
  throw new Error(nestedResult.error || `Nested orchestration "${childOrchId}" failed.`);
@@ -2689,8 +2982,13 @@ var ServiceFacade = class {
2689
2982
  });
2690
2983
  }
2691
2984
  if (cmdResult.status === "FAILED" || orchestrationResult?.status === "FAILED") {
2692
- throw new Error(orchestrationResult?.error || cmdResult.error || `[ServiceFacade:${this.id}] Orchestration failed.`);
2985
+ const error = new Error(orchestrationResult?.error || cmdResult.error || `[ServiceFacade:${this.id}] Orchestration failed.`);
2986
+ telemetryHandle.end(error);
2987
+ serviceTelemetryHandle.end(error);
2988
+ throw error;
2693
2989
  }
2990
+ telemetryHandle.end();
2991
+ serviceTelemetryHandle.end();
2694
2992
  return cmdResult.data;
2695
2993
  }
2696
2994
  /**
@@ -3349,9 +3647,9 @@ var ServiceRuntime = class {
3349
3647
  // src/discovery/ServiceDiscovery.ts
3350
3648
  var ServiceDiscovery = class {
3351
3649
  peers = /* @__PURE__ */ new Map();
3352
- registerPeer(id, name, endpoints) {
3353
- this.peers.set(id, {
3354
- id,
3650
+ registerPeer(id2, name, endpoints) {
3651
+ this.peers.set(id2, {
3652
+ id: id2,
3355
3653
  name,
3356
3654
  endpoints,
3357
3655
  lastSeen: Date.now()
@@ -3360,8 +3658,8 @@ var ServiceDiscovery = class {
3360
3658
  getPeers() {
3361
3659
  return Array.from(this.peers.values());
3362
3660
  }
3363
- findPeer(id) {
3364
- return this.peers.get(id);
3661
+ findPeer(id2) {
3662
+ return this.peers.get(id2);
3365
3663
  }
3366
3664
  };
3367
3665
 
@@ -3815,8 +4113,31 @@ var FunctionalityOrchestration = class {
3815
4113
 
3816
4114
  // src/index.ts
3817
4115
  var gutts = __toESM(require("@dinilmusick/gutts"), 1);
4116
+
4117
+ // src/execution/execution-controller.ts
4118
+ var DefaultExecutionController = class {
4119
+ providers = /* @__PURE__ */ new Map();
4120
+ executions = /* @__PURE__ */ new Map();
4121
+ register(provider) {
4122
+ this.providers.set(provider.id, provider);
4123
+ }
4124
+ async execute(request, providerId) {
4125
+ const provider = providerId ? this.providers.get(providerId) : this.providers.values().next().value;
4126
+ if (!provider) throw new Error("No execution provider is registered.");
4127
+ const result = await provider.execute(request);
4128
+ this.executions.set(result.executionId, provider);
4129
+ return result;
4130
+ }
4131
+ async cancel(executionId) {
4132
+ const provider = this.executions.get(executionId);
4133
+ if (!provider) throw new Error(`Unknown execution: ${executionId}`);
4134
+ await provider.cancel(executionId);
4135
+ this.executions.delete(executionId);
4136
+ }
4137
+ };
3818
4138
  // Annotate the CommonJS export names for ESM import in node:
3819
4139
  0 && (module.exports = {
4140
+ DefaultExecutionController,
3820
4141
  EventBus,
3821
4142
  FunctionalityFacade,
3822
4143
  FunctionalityOrchestration,
@@ -3837,6 +4158,7 @@ var gutts = __toESM(require("@dinilmusick/gutts"), 1);
3837
4158
  ServiceRegistry,
3838
4159
  ServiceRuntime,
3839
4160
  ServiceStateStore,
4161
+ TelemetryController,
3840
4162
  UdpProtocolAdapter,
3841
4163
  WebSocketProtocolAdapter,
3842
4164
  WorkerExecutionBoundary,
@@ -3845,7 +4167,10 @@ var gutts = __toESM(require("@dinilmusick/gutts"), 1);
3845
4167
  createServiceDefinition,
3846
4168
  createServiceFacade,
3847
4169
  createServiceProxy,
4170
+ deltaResources,
3848
4171
  gutts,
4172
+ sampleResources,
4173
+ telemetryNow,
3849
4174
  validateOrchestrationDAG,
3850
4175
  validateServiceDefinition
3851
4176
  });