@effect-agent/testing 0.1.0-beta.44 → 0.1.0-beta.45
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/certification.mjs +8 -8
- package/dist/certification.mjs.map +1 -1
- package/dist/chaos.d.mts +1 -1
- package/dist/chaos.mjs +5 -3
- package/dist/chaos.mjs.map +1 -1
- package/dist/docs-researcher.d.mts +1 -1
- package/dist/docs-researcher.mjs.map +1 -1
- package/dist/travel-planner.d.mts +2 -2
- package/dist/travel-planner.mjs +1 -1
- package/dist/travel-planner.mjs.map +1 -1
- package/package.json +1 -1
- package/src/certification.ts +34 -25
- package/src/chaos.ts +15 -3
- package/src/fixtures/docs-researcher/harness.ts +1 -1
- package/src/fixtures/travel-planner/subagents-durable.ts +2 -2
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@effect-agent/testing","version":"0.1.0-beta.
|
|
1
|
+
{"name":"@effect-agent/testing","version":"0.1.0-beta.45","dependencies":{"@effect-agent/capabilities":"0.1.0-beta.45","@effect-agent/core":"0.1.0-beta.45","@effect-agent/engine":"0.1.0-beta.45","@effect-agent/sandbox":"0.1.0-beta.45","@effect-agent/thread":"0.1.0-beta.45"},"devDependencies":{"@effect-agent/platform-node":"0.1.0-beta.45","@effect-agent/storage-memory":"0.1.0-beta.45","@effect-agent/storage-sqlite":"0.1.0-beta.45","@effect/platform-node":"4.0.0-rc.112","@effect/sql-sqlite-node":"4.0.0-rc.112","@effect/vitest":"4.0.0-rc.112","effect":"4.0.0-rc.112","typescript":"7.0.2","vite-plus":"0.3.0"},"peerDependencies":{"effect":"^4.0.0-rc.112"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./certification":{"types":"./dist/certification.d.mts","default":"./dist/certification.mjs"},"./chaos":{"types":"./dist/chaos.d.mts","default":"./dist/chaos.mjs"},"./code-executor":{"types":"./dist/code-executor.d.mts","default":"./dist/code-executor.mjs"},"./fixtures/docs-researcher":{"types":"./dist/docs-researcher.d.mts","default":"./dist/docs-researcher.mjs"},"./fixtures/travel-planner":{"types":"./dist/travel-planner.d.mts","default":"./dist/travel-planner.mjs"}},"description":"Scripted models, deterministic fixtures, and adapter conformance kits for testing Effect Agent applications.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/danieljvdm/effect-agent.git","directory":"packages/testing"},"files":["dist","src"],"type":"module","publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test --passWithNoTests"}}
|
package/src/certification.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
type AgentId,
|
|
16
16
|
type SubmissionId,
|
|
17
17
|
} from "@effect-agent/core";
|
|
18
|
-
import { DurableStep, DurableStepError } from "@effect-agent/engine";
|
|
18
|
+
import { DurableStep, DurableStepError, RunToolAuthorization } from "@effect-agent/engine";
|
|
19
19
|
import {
|
|
20
20
|
ApprovalDecisionCommand,
|
|
21
21
|
ThreadExportRequest,
|
|
@@ -575,21 +575,23 @@ const makeCell = Effect.fn("Certification.makeCell")(function* (
|
|
|
575
575
|
const resolved = yield* DurableWorkerBinding.make(binding, DIGESTS);
|
|
576
576
|
const threadId = decodeThreadId(`certify-${slug}`);
|
|
577
577
|
|
|
578
|
-
const submitOne = (
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
578
|
+
const submitOne = Effect.fn("Certification.submitOne")(function* (
|
|
579
|
+
key: string,
|
|
580
|
+
question: string,
|
|
581
|
+
) {
|
|
582
|
+
const runtime = yield* DurableAgentRuntime;
|
|
583
|
+
|
|
584
|
+
return yield* runtime.submit(
|
|
585
|
+
{ definition: { id: plainDefinition.id, input: plainDefinition.input } },
|
|
586
|
+
{ question },
|
|
587
|
+
{
|
|
588
|
+
threadId,
|
|
589
|
+
principal: PRINCIPAL,
|
|
590
|
+
idempotencyKey: decodeIdempotencyKey(key),
|
|
591
|
+
definitions: DIGESTS,
|
|
592
|
+
},
|
|
593
|
+
);
|
|
594
|
+
});
|
|
593
595
|
|
|
594
596
|
const cell: CertificationCell = {
|
|
595
597
|
bindings: [resolved],
|
|
@@ -747,7 +749,6 @@ const runSweepCell = Effect.fn("Certification.runSweepCell")(function* (
|
|
|
747
749
|
batchProducers: ReadonlyMap<BatchId, ProducerId>,
|
|
748
750
|
leaseAdvance: Duration.Duration,
|
|
749
751
|
) {
|
|
750
|
-
const runtime = yield* DurableAgentRuntime;
|
|
751
752
|
const ledger = yield* SubmissionLedger;
|
|
752
753
|
const control = yield* DurableRuntimeFailpointTestControl;
|
|
753
754
|
const slug = `${scenario}-${location.replaceAll(":", "-")}`;
|
|
@@ -764,6 +765,16 @@ const runSweepCell = Effect.fn("Certification.runSweepCell")(function* (
|
|
|
764
765
|
|
|
765
766
|
const cell = yield* makeCell(scenario, slug);
|
|
766
767
|
|
|
768
|
+
const runtime = yield* DurableAgentRuntime.pipe(
|
|
769
|
+
Effect.provide(
|
|
770
|
+
DurableAgentRuntime.layerWithBindings(cell.bindings).pipe(
|
|
771
|
+
Layer.provide(RunToolAuthorization.allowAll),
|
|
772
|
+
),
|
|
773
|
+
),
|
|
774
|
+
);
|
|
775
|
+
|
|
776
|
+
const submit = cell.submit.pipe(Effect.provideService(DurableAgentRuntime, runtime));
|
|
777
|
+
|
|
767
778
|
// One-shot arm: the fault fires at most once anywhere in the cell (initial drive OR a
|
|
768
779
|
// re-drive round's public unblocking operation), modelling one crash at this boundary.
|
|
769
780
|
const fired = yield* Ref.make(false);
|
|
@@ -782,12 +793,12 @@ const runSweepCell = Effect.fn("Certification.runSweepCell")(function* (
|
|
|
782
793
|
|
|
783
794
|
// Submissions are idempotent (DUR-001): one replay recovers a submit-boundary fault.
|
|
784
795
|
let receipts: ReadonlyArray<Receipt>;
|
|
785
|
-
const firstSubmit = yield* Effect.exit(
|
|
796
|
+
const firstSubmit = yield* Effect.exit(submit);
|
|
786
797
|
|
|
787
798
|
if (Exit.isSuccess(firstSubmit)) {
|
|
788
799
|
receipts = firstSubmit.value;
|
|
789
800
|
} else {
|
|
790
|
-
const secondSubmit = yield* Effect.exit(
|
|
801
|
+
const secondSubmit = yield* Effect.exit(submit);
|
|
791
802
|
|
|
792
803
|
if (Exit.isFailure(secondSubmit)) {
|
|
793
804
|
yield* control.clear;
|
|
@@ -801,7 +812,7 @@ const runSweepCell = Effect.fn("Certification.runSweepCell")(function* (
|
|
|
801
812
|
}
|
|
802
813
|
const lanes = cell.lanes(receipts);
|
|
803
814
|
|
|
804
|
-
const driveLane = (lane: ThreadId) => runtime.processThreadResolved(lane
|
|
815
|
+
const driveLane = (lane: ThreadId) => runtime.processThreadResolved(lane);
|
|
805
816
|
|
|
806
817
|
const allSettled = Effect.gen(function* () {
|
|
807
818
|
for (const receipt of receipts) {
|
|
@@ -1008,7 +1019,9 @@ export const certifyDurableAdapters = <LedgerE = never, StoreE = never>(
|
|
|
1008
1019
|
}),
|
|
1009
1020
|
).pipe(Layer.provide(options.threadStore));
|
|
1010
1021
|
|
|
1011
|
-
|
|
1022
|
+
// RUN-036: certification uses the default-none Tool failure observer. Trusted application
|
|
1023
|
+
// reporting adds no durable transition and is verified separately from adapter certification.
|
|
1024
|
+
const environment = Layer.mergeAll(
|
|
1012
1025
|
options.submissionLedger,
|
|
1013
1026
|
capturingStore,
|
|
1014
1027
|
options.wakeScheduler ?? WakeScheduler.layerNoop,
|
|
@@ -1023,10 +1036,6 @@ export const certifyDurableAdapters = <LedgerE = never, StoreE = never>(
|
|
|
1023
1036
|
}),
|
|
1024
1037
|
);
|
|
1025
1038
|
|
|
1026
|
-
// RUN-036: certification uses the default-none Tool failure observer. Trusted application
|
|
1027
|
-
// reporting adds no durable transition and is verified separately from adapter certification.
|
|
1028
|
-
const environment = DurableAgentRuntime.layer.pipe(Layer.provideMerge(support));
|
|
1029
|
-
|
|
1030
1039
|
const leaseAdvance = Duration.millis(
|
|
1031
1040
|
Duration.toMillis(options.ownershipLeaseDuration ?? DEFAULT_OWNERSHIP_LEASE_DURATION) + 1_000,
|
|
1032
1041
|
);
|
package/src/chaos.ts
CHANGED
|
@@ -14,7 +14,12 @@ import {
|
|
|
14
14
|
TurnId,
|
|
15
15
|
type SubmissionId,
|
|
16
16
|
} from "@effect-agent/core";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
DurableStep,
|
|
19
|
+
DurableStepError,
|
|
20
|
+
RunToolAuthorization,
|
|
21
|
+
ToolExecutionClass,
|
|
22
|
+
} from "@effect-agent/engine";
|
|
18
23
|
import {
|
|
19
24
|
AbortCommand,
|
|
20
25
|
ApprovalDecisionCommand,
|
|
@@ -775,8 +780,15 @@ const makeLaneFixture = Effect.fn("Chaos.makeLaneFixture")(function* (
|
|
|
775
780
|
childLaneDigests(laneIndex),
|
|
776
781
|
);
|
|
777
782
|
|
|
778
|
-
const
|
|
779
|
-
|
|
783
|
+
const registeredRuntime = yield* DurableAgentRuntime.pipe(
|
|
784
|
+
Effect.provide(
|
|
785
|
+
DurableAgentRuntime.layerWithBindings([parentResolved, childResolved]).pipe(
|
|
786
|
+
Layer.provide(RunToolAuthorization.allowAll),
|
|
787
|
+
),
|
|
788
|
+
),
|
|
789
|
+
);
|
|
790
|
+
|
|
791
|
+
const driveResolved = (thread: ThreadId) => registeredRuntime.processThreadResolved(thread);
|
|
780
792
|
|
|
781
793
|
const fixture: LaneFixture = {
|
|
782
794
|
index: laneIndex,
|
|
@@ -190,7 +190,7 @@ export interface DocsResearcherHarnessOptions {
|
|
|
190
190
|
|
|
191
191
|
/** One durable coordinator/summarizer pair with observable counters and MCP evidence. */
|
|
192
192
|
export interface DocsResearcherHarness {
|
|
193
|
-
/**
|
|
193
|
+
/** Resolved registrations for the parent and child workers. */
|
|
194
194
|
readonly bindings: ReadonlyArray<ResolvedBinding>;
|
|
195
195
|
/** The validated MCP discovery the child toolkit registration was gated on. */
|
|
196
196
|
readonly discovery: McpDiscovery;
|
|
@@ -313,7 +313,7 @@ export interface DurableResearchHarnessOptions {
|
|
|
313
313
|
|
|
314
314
|
/** One durable coordinator/researcher pair with observable invocation counters. */
|
|
315
315
|
export interface DurableResearchHarness {
|
|
316
|
-
/** Host registrations for `
|
|
316
|
+
/** Host registrations for `NodeDurableAgentRuntimeOptions.bindings` (parent + child). */
|
|
317
317
|
readonly bindings: ReadonlyArray<ResolvedBinding>;
|
|
318
318
|
/** Total coordinator model invocations across every Attempt and runtime handle. */
|
|
319
319
|
readonly parentModelCalls: Effect.Effect<number>;
|
|
@@ -334,7 +334,7 @@ export interface DurableResearchHarness {
|
|
|
334
334
|
* guide, Turn 2 writes the report), and both worker Bindings captured with
|
|
335
335
|
* their requirement Contexts via `DurableWorkerBinding.make` under the exact
|
|
336
336
|
* fixture digests. The returned `bindings` are plain values: they can be
|
|
337
|
-
* registered with several `
|
|
337
|
+
* registered with several `NodeDurableAgentRuntime` stacks over the same SQLite
|
|
338
338
|
* file while the counters keep counting across all of them.
|
|
339
339
|
*/
|
|
340
340
|
export const makeDurableResearchHarness = (options?: DurableResearchHarnessOptions) =>
|