@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/README.md +157 -2
- package/dist/index.d.ts +114 -35
- package/dist/index.js +172 -87
- package/dist/index.js.map +1 -1
- package/package.json +9 -13
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
|
-
|
|
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?.
|
|
690
|
-
|
|
691
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
872
|
+
const settled = await Promise.allSettled(
|
|
796
873
|
forkNode.branches.map(async (branch, i) => {
|
|
797
874
|
const prior = priorByName.get(branch.name);
|
|
798
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
863
|
-
|
|
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
|
-
|
|
866
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
...
|
|
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
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
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
|
-
...
|
|
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
|
-
...
|
|
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
|
-
...
|
|
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
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
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,
|