@noetaris/harness 0.4.0 → 0.6.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/index.js CHANGED
@@ -491,6 +491,54 @@ function createBuilderInstance(internals) {
491
491
  return builder;
492
492
  }
493
493
 
494
+ // src/agent/observer.ts
495
+ function reportObserverError(error, ctx, sink) {
496
+ if (sink !== void 0) {
497
+ try {
498
+ sink(error, ctx);
499
+ } catch (sinkError) {
500
+ console.error(`[harness] onObserverError sink threw while handling '${ctx.hookName}':`, sinkError);
501
+ }
502
+ return;
503
+ }
504
+ console.error(`[harness] observer hook '${ctx.hookName}' threw:`, error);
505
+ }
506
+ function safeInvoke(hookName, call, sink) {
507
+ try {
508
+ call();
509
+ } catch (error) {
510
+ reportObserverError(error, { hookName }, sink);
511
+ }
512
+ }
513
+ function composeObservers(observers, onObserverError) {
514
+ return {
515
+ onRunStart: (ctx) => {
516
+ for (const o of observers) safeInvoke("onRunStart", () => o.onRunStart?.(ctx), onObserverError);
517
+ },
518
+ onRunEnd: (ctx, event) => {
519
+ for (const o of observers) safeInvoke("onRunEnd", () => o.onRunEnd?.(ctx, event), onObserverError);
520
+ },
521
+ onStepStart: (ctx) => {
522
+ for (const o of observers) safeInvoke("onStepStart", () => o.onStepStart?.(ctx), onObserverError);
523
+ },
524
+ onStepEnd: (ctx, event) => {
525
+ for (const o of observers) safeInvoke("onStepEnd", () => o.onStepEnd?.(ctx, event), onObserverError);
526
+ },
527
+ onStepError: (ctx, event) => {
528
+ for (const o of observers) safeInvoke("onStepError", () => o.onStepError?.(ctx, event), onObserverError);
529
+ },
530
+ onInterrupt: (ctx, event) => {
531
+ for (const o of observers) safeInvoke("onInterrupt", () => o.onInterrupt?.(ctx, event), onObserverError);
532
+ },
533
+ onEvent: (ctx, type, payload) => {
534
+ for (const o of observers) safeInvoke("onEvent", () => o.onEvent?.(ctx, type, payload), onObserverError);
535
+ },
536
+ onStepSettled: (ctx, event) => {
537
+ for (const o of observers) safeInvoke("onStepSettled", () => o.onStepSettled?.(ctx, event), onObserverError);
538
+ }
539
+ };
540
+ }
541
+
494
542
  // src/agent/ctx-interrupt.ts
495
543
  var InterruptPause = class extends Error {
496
544
  interruptId;
@@ -523,11 +571,12 @@ function createInterruptFn(state, callCountRef, branchPath) {
523
571
  }
524
572
 
525
573
  // src/agent/ctx-emit.ts
526
- function createEmitFn(listeners, observer, stepCtxRef) {
574
+ function createEmitFn(listeners, observer, stepCtxRef, onObserverError) {
527
575
  return (name, payload) => {
528
576
  listeners[name]?.(payload);
529
577
  if (observer !== void 0 && stepCtxRef !== void 0 && stepCtxRef.current !== null) {
530
- observer.onEvent?.(stepCtxRef.current, name, payload);
578
+ const ctx = stepCtxRef.current;
579
+ safeInvoke("onEvent", () => observer.onEvent?.(ctx, name, payload), onObserverError);
531
580
  }
532
581
  };
533
582
  }
@@ -540,6 +589,7 @@ function extractRunListeners(resources) {
540
589
  }
541
590
 
542
591
  // src/loop/loop-executor.ts
592
+ var NOOP_OBSERVER = {};
543
593
  function isForkCursor(cursor) {
544
594
  return typeof cursor !== "string";
545
595
  }
@@ -598,9 +648,19 @@ function applyUpdate(state, update, schema, touchedKeys) {
598
648
  touchedKeys?.add(key);
599
649
  }
600
650
  }
651
+ function fireSettled(obs, stepCtx, stepStart, fields, onObserverError) {
652
+ const hook = obs?.onStepSettled;
653
+ if (hook === void 0) return;
654
+ const event = { ...fields, durationMs: Date.now() - stepStart };
655
+ safeInvoke("onStepSettled", () => hook(stepCtx, event), onObserverError);
656
+ }
657
+ function asError(e) {
658
+ return e instanceof Error ? e : new Error(String(e));
659
+ }
601
660
  async function runLoop(graph, state, ctx, schema, shouldStop, startCursor, callbacks) {
602
661
  const { onBeforeStep, onAfterStep, onError, onComplete, onInterrupt } = callbacks ?? {};
603
662
  const obs = callbacks?.observer;
663
+ const onObserverError = callbacks?.onObserverError;
604
664
  const implicitNextMap = buildImplicitNextMap(graph);
605
665
  if (!("$error" in state)) state.$error = null;
606
666
  if (!("$interrupt" in state)) state.$interrupt = null;
@@ -614,15 +674,15 @@ async function runLoop(graph, state, ctx, schema, shouldStop, startCursor, callb
614
674
  ...typeof ctx.instanceId === "string" ? { instanceId: ctx.instanceId } : {},
615
675
  ...callbacks?.branchPath !== void 0 && callbacks.branchPath.length > 0 ? { branchPath: callbacks.branchPath } : {}
616
676
  };
617
- obs?.onRunStart?.(runCtx);
677
+ safeInvoke("onRunStart", () => obs?.onRunStart?.(runCtx), onObserverError);
618
678
  const callCountRef = { current: 0 };
619
679
  const stepCtxRef = { current: null };
620
680
  ctx["interrupt"] = createInterruptFn(state, callCountRef, callbacks?.branchPath);
621
- ctx["emit"] = createEmitFn(callbacks?.listeners ?? {}, obs, stepCtxRef);
681
+ ctx["emit"] = createEmitFn(callbacks?.listeners ?? {}, obs, stepCtxRef, onObserverError);
622
682
  let cursor = startCursor ?? graph.entryStep;
623
683
  while (true) {
624
684
  if (shouldStop?.()) {
625
- obs?.onRunEnd?.(runCtx, { signal: "$stopped", durationMs: Date.now() - runStart });
685
+ safeInvoke("onRunEnd", () => obs?.onRunEnd?.(runCtx, { signal: "$stopped", durationMs: Date.now() - runStart }), onObserverError);
626
686
  return { state, signal: null, cursor, paused: true };
627
687
  }
628
688
  if (isForkCursor(cursor)) {
@@ -685,13 +745,17 @@ async function runLoop(graph, state, ctx, schema, shouldStop, startCursor, callb
685
745
  };
686
746
  stepCtxRef.current = stepCtx;
687
747
  const stepStart = Date.now();
688
- obs?.onStepStart?.(stepCtx);
689
- if (callbacks?.setStepContextSlots !== void 0) {
690
- for (const slot of callbacks.setStepContextSlots) {
691
- slot.setStepContext(stepCtx);
748
+ safeInvoke("onStepStart", () => obs?.onStepStart?.(stepCtx), onObserverError);
749
+ if (callbacks?.telemetrySlots !== void 0) {
750
+ const telemetry = { observer: obs ?? NOOP_OBSERVER, stepContext: stepCtx };
751
+ for (const { key, slot } of callbacks.telemetrySlots) {
752
+ ;
753
+ ctx[key] = slot.withTelemetry(telemetry);
692
754
  }
693
755
  }
694
756
  let runSucceeded = false;
757
+ let applied;
758
+ const settle = (fields) => fireSettled(obs, stepCtx, stepStart, { ...fields, ...applied !== void 0 ? { update: applied } : {} }, onObserverError);
695
759
  if (step.run !== void 0) {
696
760
  const hadResponses = Object.keys(state.$interruptResponses).length > 0;
697
761
  try {
@@ -700,6 +764,7 @@ async function runLoop(graph, state, ctx, schema, shouldStop, startCursor, callb
700
764
  ctx
701
765
  );
702
766
  applyUpdate(state, update, schema, callbacks?.touchedKeys);
767
+ applied = update;
703
768
  if (hadResponses) {
704
769
  state.$interrupt = null;
705
770
  state.$interruptResponses = {};
@@ -708,19 +773,20 @@ async function runLoop(graph, state, ctx, schema, shouldStop, startCursor, callb
708
773
  } catch (e) {
709
774
  if (isInterruptPause(e)) {
710
775
  onInterrupt?.(e.prompt, e.interruptId);
711
- obs?.onInterrupt?.(stepCtx, { prompt: e.prompt, interruptId: e.interruptId });
712
- obs?.onRunEnd?.(runCtx, { signal: "$interrupt", durationMs: Date.now() - runStart });
776
+ safeInvoke("onInterrupt", () => obs?.onInterrupt?.(stepCtx, { prompt: e.prompt, interruptId: e.interruptId }), onObserverError);
777
+ settle({ outcome: "interrupt", interrupt: { interruptId: e.interruptId, prompt: e.prompt }, next: { kind: "pause" } });
778
+ safeInvoke("onRunEnd", () => obs?.onRunEnd?.(runCtx, { signal: "$interrupt", durationMs: Date.now() - runStart }), onObserverError);
713
779
  return { state, signal: "$interrupt", cursor, paused: true };
714
780
  }
715
781
  state.$error = e instanceof Error ? e : new Error(String(e));
716
782
  onError?.(state.$error, cursor);
717
- obs?.onStepError?.(stepCtx, { error: state.$error, durationMs: Date.now() - stepStart });
783
+ safeInvoke("onStepError", () => obs?.onStepError?.(stepCtx, { error: state.$error, durationMs: Date.now() - stepStart }), onObserverError);
718
784
  }
719
785
  }
720
786
  if (runSucceeded) {
721
787
  state.$error = null;
722
788
  onAfterStep?.(cursor, state);
723
- obs?.onStepEnd?.(stepCtx, { durationMs: Date.now() - stepStart });
789
+ safeInvoke("onStepEnd", () => obs?.onStepEnd?.(stepCtx, { durationMs: Date.now() - stepStart }), onObserverError);
724
790
  }
725
791
  const callRoute = step.route !== void 0 && (runSucceeded || step.run === void 0 || step.errorAware);
726
792
  if (callRoute) {
@@ -730,31 +796,42 @@ async function runLoop(graph, state, ctx, schema, shouldStop, startCursor, callb
730
796
  signal = routeFn(state);
731
797
  } catch (e) {
732
798
  state.$error = e instanceof Error ? e : new Error(String(e));
733
- obs?.onRunEnd?.(runCtx, { signal: "$error", durationMs: Date.now() - runStart });
799
+ settle({ outcome: "error", error: state.$error, next: { kind: "pause" } });
800
+ safeInvoke("onRunEnd", () => obs?.onRunEnd?.(runCtx, { signal: "$error", durationMs: Date.now() - runStart }), onObserverError);
734
801
  return { state, signal: "$error", cursor, paused: true };
735
802
  }
803
+ const routed = runSucceeded || step.run === void 0 ? { outcome: "ok", signal } : { outcome: "error", signal, error: state.$error };
736
804
  const transition = step.transitions.find((t) => t.signal === signal);
737
805
  if (transition === void 0) {
738
- throw new UnknownSignalError(cursor, signal);
806
+ const unknownSignal = new UnknownSignalError(cursor, signal);
807
+ settle({ outcome: "error", signal, error: unknownSignal, next: { kind: "throw" } });
808
+ throw unknownSignal;
739
809
  }
740
810
  if (transition.target.kind === "end") {
811
+ settle({ ...routed, next: { kind: "end" } });
741
812
  onComplete?.(state, signal);
742
- obs?.onRunEnd?.(runCtx, { signal, durationMs: Date.now() - runStart });
813
+ safeInvoke("onRunEnd", () => obs?.onRunEnd?.(runCtx, { signal, durationMs: Date.now() - runStart }), onObserverError);
743
814
  return { state, signal, cursor: null, paused: false };
744
815
  }
816
+ settle({ ...routed, next: { kind: "step", name: transition.target.name } });
745
817
  cursor = transition.target.name;
746
818
  } else if (step.run !== void 0 && !runSucceeded) {
747
819
  if (graph.onError !== void 0) {
820
+ settle({ outcome: "error", error: state.$error, next: { kind: "step", name: graph.onError } });
748
821
  cursor = graph.onError;
749
822
  } else {
750
- obs?.onRunEnd?.(runCtx, { signal: "$error", durationMs: Date.now() - runStart });
823
+ settle({ outcome: "error", error: state.$error, next: { kind: "pause" } });
824
+ safeInvoke("onRunEnd", () => obs?.onRunEnd?.(runCtx, { signal: "$error", durationMs: Date.now() - runStart }), onObserverError);
751
825
  return { state, signal: "$error", cursor, paused: true };
752
826
  }
753
827
  } else {
754
828
  const next = step.next ?? implicitNextMap.get(cursor) ?? null;
755
829
  if (next === null) {
756
- throw new NoNextStepError(cursor);
830
+ const noNext = new NoNextStepError(cursor);
831
+ settle({ outcome: "error", error: noNext, next: { kind: "throw" } });
832
+ throw noNext;
757
833
  }
834
+ settle({ outcome: "ok", next: { kind: "step", name: next } });
758
835
  cursor = next;
759
836
  }
760
837
  }
@@ -792,16 +869,25 @@ async function dispatchFork(forkNode, priorBranches, outerState, outerCtx, schem
792
869
  );
793
870
  const { onBeforeStep: _outerOnBeforeStep, onAfterStep: _outerOnAfterStep, onComplete: _outerOnComplete, ...branchCallbacksRest } = callbacks ?? {};
794
871
  const branchCallbacksBase = callbacks !== void 0 ? branchCallbacksRest : void 0;
795
- const outcomes = await Promise.all(
872
+ const settled = await Promise.allSettled(
796
873
  forkNode.branches.map(async (branch, i) => {
797
874
  const prior = priorByName.get(branch.name);
798
- const outcome = await runBranch(branch, prior, outerState, outerCtx, schema, shouldStop, branchSignals[i], branchCallbacksBase);
875
+ let outcome;
876
+ try {
877
+ outcome = await runBranch(branch, prior, outerState, outerCtx, schema, shouldStop, branchSignals[i], branchCallbacksBase);
878
+ } catch (e) {
879
+ for (const controller of localAborts) controller.abort();
880
+ throw e;
881
+ }
799
882
  if (outcome.result.paused && outcome.result.signal === "$error") {
800
883
  for (const controller of localAborts) controller.abort();
801
884
  }
802
885
  return outcome;
803
886
  })
804
887
  );
888
+ const rejected = settled.find((r) => r.status === "rejected");
889
+ if (rejected !== void 0) throw rejected.reason;
890
+ const outcomes = settled.map((r) => r.value);
805
891
  const failed = outcomes.find((o) => o.result.paused && o.result.signal === "$error");
806
892
  if (failed !== void 0) {
807
893
  return { kind: "failed", error: failed.result.state.$error };
@@ -825,7 +911,8 @@ async function dispatchFork(forkNode, priorBranches, outerState, outerCtx, schem
825
911
  touchedKeys: [...o.touchedKeys]
826
912
  };
827
913
  });
828
- return { kind: "paused", forkCursor: { kind: "fork", fork: forkNode.name, branches } };
914
+ const interrupted = outcomes.some((o) => o.result.paused && o.result.signal === "$interrupt");
915
+ return { kind: "paused", forkCursor: { kind: "fork", fork: forkNode.name, branches }, interrupted };
829
916
  }
830
917
  const keyOwners = /* @__PURE__ */ new Map();
831
918
  for (const outcome of outcomes) {
@@ -849,7 +936,10 @@ async function dispatchFork(forkNode, priorBranches, outerState, outerCtx, schem
849
936
  }
850
937
  }
851
938
  }
852
- return { kind: "success" };
939
+ return {
940
+ kind: "success",
941
+ branches: outcomes.map((o) => ({ name: o.name, status: "done", touchedKeys: [...o.touchedKeys] }))
942
+ };
853
943
  }
854
944
  async function handleFork(forkNode, priorBranches, state, ctx, schema, shouldStop, callbacks, obs, runCtx, runStart, implicitNextMap, graph) {
855
945
  const stepCtx = {
@@ -859,29 +949,50 @@ async function handleFork(forkNode, priorBranches, state, ctx, schema, shouldSto
859
949
  ...callbacks?.branchPath !== void 0 && callbacks.branchPath.length > 0 ? { branchPath: callbacks.branchPath } : {}
860
950
  };
861
951
  const stepStart = Date.now();
862
- obs?.onStepStart?.(stepCtx);
863
- const dispatch = await dispatchFork(forkNode, priorBranches, state, ctx, schema, shouldStop, callbacks);
952
+ const onObserverError = callbacks?.onObserverError;
953
+ safeInvoke("onStepStart", () => obs?.onStepStart?.(stepCtx), onObserverError);
954
+ let dispatch;
955
+ try {
956
+ dispatch = await dispatchFork(forkNode, priorBranches, state, ctx, schema, shouldStop, callbacks);
957
+ } catch (e) {
958
+ fireSettled(obs, stepCtx, stepStart, { outcome: "error", error: asError(e), next: { kind: "throw" } }, onObserverError);
959
+ throw e;
960
+ }
864
961
  if (dispatch.kind === "paused") {
865
- obs?.onRunEnd?.(runCtx, { signal: "$interrupt", durationMs: Date.now() - runStart });
866
- return { done: true, result: { state, signal: "$interrupt", cursor: dispatch.forkCursor, paused: true } };
962
+ const fork = {
963
+ branches: dispatch.forkCursor.branches.map((b) => ({ name: b.name, status: b.status, touchedKeys: b.touchedKeys }))
964
+ };
965
+ if (dispatch.interrupted === true) {
966
+ fireSettled(obs, stepCtx, stepStart, { outcome: "interrupt", next: { kind: "pause" }, fork }, onObserverError);
967
+ safeInvoke("onRunEnd", () => obs?.onRunEnd?.(runCtx, { signal: "$interrupt", durationMs: Date.now() - runStart }), onObserverError);
968
+ return { done: true, result: { state, signal: "$interrupt", cursor: dispatch.forkCursor, paused: true } };
969
+ }
970
+ fireSettled(obs, stepCtx, stepStart, { outcome: "stopped", next: { kind: "pause" }, fork }, onObserverError);
971
+ safeInvoke("onRunEnd", () => obs?.onRunEnd?.(runCtx, { signal: "$stopped", durationMs: Date.now() - runStart }), onObserverError);
972
+ return { done: true, result: { state, signal: null, cursor: dispatch.forkCursor, paused: true } };
867
973
  }
868
974
  if (dispatch.kind === "failed") {
869
975
  state.$error = dispatch.error;
870
976
  callbacks?.onError?.(state.$error, forkNode.name);
871
- obs?.onStepError?.(stepCtx, { error: state.$error, durationMs: Date.now() - stepStart });
977
+ safeInvoke("onStepError", () => obs?.onStepError?.(stepCtx, { error: state.$error, durationMs: Date.now() - stepStart }), onObserverError);
872
978
  if (graph.onError !== void 0) {
979
+ fireSettled(obs, stepCtx, stepStart, { outcome: "error", error: state.$error, next: { kind: "step", name: graph.onError } }, onObserverError);
873
980
  return { done: false, nextCursor: graph.onError };
874
981
  }
875
- obs?.onRunEnd?.(runCtx, { signal: "$error", durationMs: Date.now() - runStart });
982
+ fireSettled(obs, stepCtx, stepStart, { outcome: "error", error: state.$error, next: { kind: "pause" } }, onObserverError);
983
+ safeInvoke("onRunEnd", () => obs?.onRunEnd?.(runCtx, { signal: "$error", durationMs: Date.now() - runStart }), onObserverError);
876
984
  return { done: true, result: { state, signal: "$error", cursor: forkNode.name, paused: true } };
877
985
  }
878
986
  state.$error = null;
879
- obs?.onStepEnd?.(stepCtx, { durationMs: Date.now() - stepStart });
987
+ safeInvoke("onStepEnd", () => obs?.onStepEnd?.(stepCtx, { durationMs: Date.now() - stepStart }), onObserverError);
880
988
  callbacks?.onAfterStep?.(forkNode.name, state);
881
989
  const next = forkNode.next ?? implicitNextMap.get(forkNode.name) ?? null;
882
990
  if (next === null) {
883
- throw new NoNextStepError(forkNode.name);
991
+ const noNext = new NoNextStepError(forkNode.name);
992
+ fireSettled(obs, stepCtx, stepStart, { outcome: "error", error: noNext, next: { kind: "throw" } }, onObserverError);
993
+ throw noNext;
884
994
  }
995
+ fireSettled(obs, stepCtx, stepStart, { outcome: "ok", next: { kind: "step", name: next }, fork: { branches: dispatch.branches } }, onObserverError);
885
996
  return { done: false, nextCursor: next };
886
997
  }
887
998
 
@@ -1315,12 +1426,24 @@ function extractRunEvents(resources) {
1315
1426
  }
1316
1427
 
1317
1428
  // src/agent/create-agent.ts
1318
- var NOOP_OBSERVER = {};
1429
+ function buildTelemetrySlots(entries) {
1430
+ const out = [];
1431
+ for (const [key, slot] of entries) {
1432
+ if (slot !== null && typeof slot === "object" && typeof slot["withTelemetry"] === "function") {
1433
+ out.push({ key, slot });
1434
+ }
1435
+ }
1436
+ return out;
1437
+ }
1319
1438
  function extractRunObserver(resources) {
1320
1439
  const raw = resources["observer"];
1321
1440
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
1322
1441
  return raw;
1323
1442
  }
1443
+ function extractRunErrorSink(resources) {
1444
+ const raw = resources["onObserverError"];
1445
+ return typeof raw === "function" ? raw : void 0;
1446
+ }
1324
1447
  var MissingLoopError = class extends Error {
1325
1448
  constructor() {
1326
1449
  super("harness has no loop \u2014 call h.loop() before createAgent(id, h, slots)");
@@ -1478,10 +1601,10 @@ function createAgent(id, h, slots, agentOptions) {
1478
1601
  runtimeKeys,
1479
1602
  requiredKeys
1480
1603
  };
1481
- const reservedRunKeys = /* @__PURE__ */ new Set(["sessionId", "signal", "events", "listeners", "observer", "claimOptions", "parentRunId"]);
1604
+ const reservedRunKeys = /* @__PURE__ */ new Set(["sessionId", "signal", "events", "listeners", "observer", "onObserverError", "claimOptions", "parentRunId"]);
1482
1605
  const inFlightSessions = /* @__PURE__ */ new Set();
1483
1606
  const interruptPendingSessions = /* @__PURE__ */ new Set();
1484
- const makeAgentResumeHandle = (resp, sId, iId, resumeOpts, observer, setStepContextSlots) => {
1607
+ const makeAgentResumeHandle = (resp, sId, iId, resumeOpts, observer, onObserverError, telemetrySlots) => {
1485
1608
  let _stopped = false;
1486
1609
  const abortController = new AbortController();
1487
1610
  const flag = {
@@ -1556,7 +1679,8 @@ function createAgent(id, h, slots, agentOptions) {
1556
1679
  ...resumeOpts?.onStoreError !== void 0 ? { onStoreError: resumeOpts.onStoreError } : {},
1557
1680
  ...leaseRef !== void 0 ? { leaseRef, claimTtlMs: claimOptions.ttlMs } : {},
1558
1681
  ...observer !== void 0 ? { observer } : {},
1559
- ...setStepContextSlots !== void 0 && setStepContextSlots.length > 0 ? { setStepContextSlots } : {}
1682
+ ...onObserverError !== void 0 ? { onObserverError } : {},
1683
+ ...telemetrySlots !== void 0 && telemetrySlots.length > 0 ? { telemetrySlots } : {}
1560
1684
  }
1561
1685
  );
1562
1686
  if (r.signal === "$interrupt") interruptPendingSessions.add(sId);
@@ -1652,17 +1776,11 @@ function createAgent(id, h, slots, agentOptions) {
1652
1776
  const events = extractRunEvents(resources);
1653
1777
  const listeners = extractRunListeners(resources);
1654
1778
  const observer = extractRunObserver(resources);
1655
- for (const slot of [...agentInternals.resolvedProviders.values(), ...Object.values(runtimeSlots)]) {
1656
- if (slot !== null && typeof slot === "object" && typeof slot["bindObserver"] === "function") {
1657
- slot.bindObserver(observer ?? NOOP_OBSERVER);
1658
- }
1659
- }
1660
- const setStepContextSlots = [];
1661
- for (const slot of [...agentInternals.resolvedProviders.values(), ...Object.values(runtimeSlots)]) {
1662
- if (slot !== null && typeof slot === "object" && typeof slot["setStepContext"] === "function") {
1663
- setStepContextSlots.push(slot);
1664
- }
1665
- }
1779
+ const onObserverError = extractRunErrorSink(resources);
1780
+ const telemetrySlots = buildTelemetrySlots([
1781
+ ...agentInternals.resolvedProviders.entries(),
1782
+ ...Object.entries(runtimeSlots)
1783
+ ]);
1666
1784
  const parentRunId = typeof resources["parentRunId"] === "string" ? resources["parentRunId"] : void 0;
1667
1785
  const options = {
1668
1786
  shouldStop: () => stopFlag.stopped,
@@ -1678,9 +1796,10 @@ function createAgent(id, h, slots, agentOptions) {
1678
1796
  ...events.onInterrupt !== void 0 ? { onInterrupt: events.onInterrupt } : {},
1679
1797
  ...Object.keys(listeners).length > 0 ? { listeners } : {},
1680
1798
  ...observer !== void 0 ? { observer } : {},
1799
+ ...onObserverError !== void 0 ? { onObserverError } : {},
1681
1800
  ...agentOptions?.instanceId !== void 0 ? { instanceId: agentOptions.instanceId } : {},
1682
1801
  ...parentRunId !== void 0 ? { parentRunId } : {},
1683
- ...setStepContextSlots.length > 0 ? { setStepContextSlots } : {}
1802
+ ...telemetrySlots.length > 0 ? { telemetrySlots } : {}
1684
1803
  };
1685
1804
  let lastResult = null;
1686
1805
  const execution = (async () => {
@@ -1797,7 +1916,8 @@ function createAgent(id, h, slots, agentOptions) {
1797
1916
  ...events.onInterrupt !== void 0 ? { onInterrupt: events.onInterrupt } : {},
1798
1917
  ...Object.keys(listeners).length > 0 ? { listeners } : {},
1799
1918
  ...observer !== void 0 ? { observer } : {},
1800
- ...setStepContextSlots.length > 0 ? { setStepContextSlots } : {}
1919
+ ...onObserverError !== void 0 ? { onObserverError } : {},
1920
+ ...telemetrySlots.length > 0 ? { telemetrySlots } : {}
1801
1921
  }
1802
1922
  );
1803
1923
  if (r2.signal === "$interrupt") interruptPendingSessions.add(sessionId);
@@ -1829,7 +1949,8 @@ function createAgent(id, h, slots, agentOptions) {
1829
1949
  ...events.onInterrupt !== void 0 ? { onInterrupt: events.onInterrupt } : {},
1830
1950
  ...Object.keys(listeners).length > 0 ? { listeners } : {},
1831
1951
  ...observer !== void 0 ? { observer } : {},
1832
- ...setStepContextSlots.length > 0 ? { setStepContextSlots } : {}
1952
+ ...onObserverError !== void 0 ? { onObserverError } : {},
1953
+ ...telemetrySlots.length > 0 ? { telemetrySlots } : {}
1833
1954
  }
1834
1955
  );
1835
1956
  if (r.signal === "$interrupt") interruptPendingSessions.add(sessionId);
@@ -1858,51 +1979,15 @@ function createAgent(id, h, slots, agentOptions) {
1858
1979
  const events = extractRunEvents(resources ?? {});
1859
1980
  const resumeOpts = events.onStoreError !== void 0 ? { onStoreError: events.onStoreError } : void 0;
1860
1981
  const observer = extractRunObserver(resources ?? {});
1861
- for (const slot of agentInternals.resolvedProviders.values()) {
1862
- if (slot !== null && typeof slot === "object" && typeof slot["bindObserver"] === "function") {
1863
- slot.bindObserver(observer ?? NOOP_OBSERVER);
1864
- }
1865
- }
1866
- const setStepContextSlots = [];
1867
- for (const slot of agentInternals.resolvedProviders.values()) {
1868
- if (slot !== null && typeof slot === "object" && typeof slot["setStepContext"] === "function") {
1869
- setStepContextSlots.push(slot);
1870
- }
1871
- }
1872
- return makeAgentResumeHandle(response, sessionId, interruptId, resumeOpts, observer ?? void 0, setStepContextSlots.length > 0 ? setStepContextSlots : void 0);
1982
+ const onObserverError = extractRunErrorSink(resources ?? {});
1983
+ const telemetrySlots = buildTelemetrySlots(agentInternals.resolvedProviders.entries());
1984
+ return makeAgentResumeHandle(response, sessionId, interruptId, resumeOpts, observer ?? void 0, onObserverError ?? void 0, telemetrySlots.length > 0 ? telemetrySlots : void 0);
1873
1985
  },
1874
1986
  status: (sessionId) => querySessionPhase(capturedStore, id, sessionId),
1875
1987
  [_agentInternals]: agentInternals
1876
1988
  };
1877
1989
  return agent;
1878
1990
  }
1879
-
1880
- // src/agent/observer.ts
1881
- function composeObservers(...observers) {
1882
- return {
1883
- onRunStart: (ctx) => {
1884
- for (const o of observers) o.onRunStart?.(ctx);
1885
- },
1886
- onRunEnd: (ctx, event) => {
1887
- for (const o of observers) o.onRunEnd?.(ctx, event);
1888
- },
1889
- onStepStart: (ctx) => {
1890
- for (const o of observers) o.onStepStart?.(ctx);
1891
- },
1892
- onStepEnd: (ctx, event) => {
1893
- for (const o of observers) o.onStepEnd?.(ctx, event);
1894
- },
1895
- onStepError: (ctx, event) => {
1896
- for (const o of observers) o.onStepError?.(ctx, event);
1897
- },
1898
- onInterrupt: (ctx, event) => {
1899
- for (const o of observers) o.onInterrupt?.(ctx, event);
1900
- },
1901
- onEvent: (ctx, type, payload) => {
1902
- for (const o of observers) o.onEvent?.(ctx, type, payload);
1903
- }
1904
- };
1905
- }
1906
1991
  export {
1907
1992
  LeaseExpiredError,
1908
1993
  LoopNotDefinedError,