@effect-agent/testing 0.1.0-beta.6 → 0.1.0-beta.61

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.
Files changed (54) hide show
  1. package/dist/Certification.d.mts +105 -0
  2. package/dist/Certification.mjs +590 -0
  3. package/dist/Certification.mjs.map +1 -0
  4. package/dist/Chaos.d.mts +126 -0
  5. package/dist/Chaos.mjs +755 -0
  6. package/dist/Chaos.mjs.map +1 -0
  7. package/dist/CodeExecutorConformance.d.mts +33 -0
  8. package/dist/CodeExecutorConformance.mjs +231 -0
  9. package/dist/CodeExecutorConformance.mjs.map +1 -0
  10. package/dist/CodeExecutorSubstitute.d.mts +21 -0
  11. package/dist/CodeExecutorSubstitute.mjs +364 -0
  12. package/dist/CodeExecutorSubstitute.mjs.map +1 -0
  13. package/dist/DocsResearcher.d.mts +270 -0
  14. package/dist/DocsResearcher.mjs +490 -0
  15. package/dist/DocsResearcher.mjs.map +1 -0
  16. package/dist/ScriptedModel-DAvxIiud.d.mts +220 -0
  17. package/dist/ScriptedModel.d.mts +2 -0
  18. package/dist/ScriptedModel.mjs +155 -0
  19. package/dist/ScriptedModel.mjs.map +1 -0
  20. package/dist/TravelPlanner.d.mts +1665 -0
  21. package/dist/TravelPlanner.mjs +1968 -0
  22. package/dist/TravelPlanner.mjs.map +1 -0
  23. package/dist/deterministic-layers-Eka0fMZq.mjs +358 -0
  24. package/dist/deterministic-layers-Eka0fMZq.mjs.map +1 -0
  25. package/dist/index.d.mts +2 -3378
  26. package/dist/index.mjs +2 -4766
  27. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  28. package/package.json +1 -48
  29. package/src/{certification.ts → Certification.ts} +251 -115
  30. package/src/{chaos.ts → Chaos.ts} +246 -122
  31. package/src/{code-executor-conformance.ts → CodeExecutorConformance.ts} +29 -6
  32. package/src/{code-executor-substitute.ts → CodeExecutorSubstitute.ts} +104 -42
  33. package/src/{fixtures/docs-researcher/index.ts → DocsResearcher.ts} +68 -5
  34. package/src/{scripted-model.ts → ScriptedModel.ts} +22 -25
  35. package/src/TravelPlanner.ts +232 -0
  36. package/src/fixtures/docs-researcher/definition.ts +19 -10
  37. package/src/fixtures/docs-researcher/harness.ts +41 -30
  38. package/src/fixtures/docs-researcher/mcp.ts +49 -3
  39. package/src/fixtures/travel-planner/definition.ts +15 -2
  40. package/src/fixtures/travel-planner/deterministic-layers.ts +47 -4
  41. package/src/fixtures/travel-planner/phase2.ts +4 -3
  42. package/src/fixtures/travel-planner/phase3.ts +18 -37
  43. package/src/fixtures/travel-planner/phase4.ts +23 -36
  44. package/src/fixtures/travel-planner/phase5.ts +38 -41
  45. package/src/fixtures/travel-planner/phase6.ts +192 -84
  46. package/src/fixtures/travel-planner/phase7.ts +4 -102
  47. package/src/fixtures/travel-planner/scenarios.ts +3 -4
  48. package/src/fixtures/travel-planner/subagents-durable.ts +33 -57
  49. package/src/fixtures/travel-planner/subagents.ts +35 -13
  50. package/src/index.ts +1 -11
  51. package/dist/index.mjs.map +0 -1
  52. package/src/code-executor-conformance.d.ts +0 -30
  53. package/src/fixtures/travel-planner/index.ts +0 -11
  54. package/src/fixtures/warehouse/index.ts +0 -412
@@ -1,33 +1,29 @@
1
1
  import {
2
2
  delegationAllocationFromPolicy,
3
- SubagentReservationsMemoryLive,
4
3
  SubagentRuntime,
5
- } from "@effect-agent/capabilities";
6
- import { Agent, type ConversationId } from "@effect-agent/core";
7
- import type { RuntimeBinding } from "@effect-agent/engine";
8
- import {
9
- DefinitionDigests,
10
- DeploymentId,
11
- Digest,
12
- DurableWorkerBinding,
13
- Principal,
14
- ProducerId,
15
- type DurableSubmitOptions,
16
- type IdempotencyKey,
17
- type ResolvedBinding,
18
- } from "@effect-agent/session";
4
+ } from "@effect-agent/capabilities/Subagent";
5
+ import { SubagentReservationsMemoryLive } from "@effect-agent/capabilities/SubagentReservations";
6
+ import * as Agent from "@effect-agent/core/Agent";
7
+ import { type ThreadId } from "@effect-agent/core/Identifiers";
8
+ import { type RuntimeBinding } from "@effect-agent/engine/AgentRuntime";
9
+ import { DurableWorkerBinding, type ResolvedBinding } from "@effect-agent/thread/AgentRegistration";
10
+ import { type DurableSubmitOptions } from "@effect-agent/thread/DurableAgentRuntime";
11
+ import { DefinitionDigests, DeploymentId, Digest, ProducerId } from "@effect-agent/thread/Records";
12
+ import { Principal, type IdempotencyKey } from "@effect-agent/thread/SubmissionLedger";
19
13
  import { Effect, Layer, Ref, Schema, Stream } from "effect";
20
14
  import { LanguageModel, Model, type Response, type Toolkit } from "effect/unstable/ai";
21
15
 
22
16
  import { DeterministicIdGeneratorLayer } from "./deterministic-layers.ts";
23
- import {
17
+ import type {
24
18
  DestinationBrief,
19
+ DestinationReport,
20
+ DestinationResearcherToolkit,
21
+ } from "./subagents.ts";
22
+ import {
25
23
  DestinationFacts,
26
24
  DestinationGuide,
27
25
  DestinationRecommendation,
28
- DestinationReport,
29
26
  DestinationResearcher,
30
- DestinationResearcherToolkit,
31
27
  DestinationResearcherToolkitLayer,
32
28
  destinationLookup,
33
29
  destinationReportFor,
@@ -40,46 +36,15 @@ import {
40
36
  TravelCoordinator,
41
37
  } from "./subagents.ts";
42
38
 
43
- // ---------------------------------------------------------------------------
44
- // S2 durability profile (spec/subagents.md §17): the S1 coordinator →
45
- // destination-researcher delegation re-run as ACCEPTED WORK on the Node/SQLite
46
- // runtime. The claim is `DN` durable attached Subagents only: establishment
47
- // and join are replay-safe by construction (SUB-016/SUB-019), a completed
48
- // child is never re-executed on a lost join acknowledgment, and NO claim of
49
- // exactly-once child external effects is made (rule 8; an unresolved ordinary
50
- // child Tool blocks as an Unknown Outcome instead, SUB-021). Cloudflare
51
- // equivalence is P6 scope and explicitly not claimed here.
52
- // ---------------------------------------------------------------------------
53
-
54
- export class TravelPlannerSubagentDurabilityProfile extends Schema.Class<TravelPlannerSubagentDurabilityProfile>(
55
- "@effect-agent/testing/travel-planner/TravelPlannerSubagentDurabilityProfile",
56
- )({
57
- deploymentClass: Schema.Literal("DN"),
58
- durableAttachedSubagents: Schema.Literal(true),
59
- canonicalSchemaVersion: Schema.Literal(1),
60
- /** Establishment/join replay converges on one child Receipt, Conversation, and join batch. */
61
- subagentReplaySafe: Schema.Literal(true),
62
- /** Never claimed (rule 8): child ordinary Tools stop at Unknown Outcomes, they do not replay. */
63
- childExternalEffectsExactlyOnce: Schema.Literal(false),
64
- /** The same conformance suite under DO eviction/alarms is P6 scope (spec §17 `DC`). */
65
- cloudflareEquivalence: Schema.Literal(false),
66
- }) {}
67
-
68
- export const s2TravelPlannerProfile = TravelPlannerSubagentDurabilityProfile.make({
69
- deploymentClass: "DN",
70
- durableAttachedSubagents: true,
71
- canonicalSchemaVersion: 1,
72
- subagentReplaySafe: true,
73
- childExternalEffectsExactlyOnce: false,
74
- cloudflareEquivalence: false,
75
- });
76
-
39
+ /** Registered coordinator and researcher bindings for durable delegation tests. */
77
40
  export const s2TravelPlannerDeploymentId = Schema.decodeSync(DeploymentId)(
78
41
  "travel-planner-s2-deployment",
79
42
  );
43
+
80
44
  export const s2TravelPlannerProducerId = Schema.decodeSync(ProducerId)(
81
45
  "travel-planner-s2-producer",
82
46
  );
47
+
83
48
  export const s2TravelPlannerPrincipal = Schema.decodeSync(Principal)("travel-planner-s2-principal");
84
49
 
85
50
  const digestOf = (character: string) => Schema.decodeSync(Digest)(character.repeat(64));
@@ -94,7 +59,7 @@ export const s2CoordinatorDigests = DefinitionDigests.make({
94
59
  /**
95
60
  * The exact child Binding digest strings the application declares on
96
61
  * `SubagentRuntimeOptions.durable.targetDigests` AND the host registers with
97
- * the `AgentBindingResolver` for the researcher Binding. The coordinator
62
+ * the host's binding array for the researcher Binding. The coordinator
98
63
  * stores and verifies them byte-for-byte (SUB-023); a host registration under
99
64
  * different strings is a `ChildCompatibilityFailure`, never a substitution.
100
65
  */
@@ -112,10 +77,10 @@ export const s2ResearcherDigests = DefinitionDigests.make({
112
77
 
113
78
  /** Durable admission options for one coordinator Submission on one mission lane. */
114
79
  export const s2TravelPlannerSubmitOptions = (
115
- conversationId: ConversationId,
80
+ threadId: ThreadId,
116
81
  idempotencyKey: IdempotencyKey,
117
82
  ): DurableSubmitOptions => ({
118
- conversationId,
83
+ threadId,
119
84
  principal: s2TravelPlannerPrincipal,
120
85
  idempotencyKey,
121
86
  definitions: s2CoordinatorDigests,
@@ -166,6 +131,7 @@ export const durableResearchShortlist = (destination: string): DestinationShortl
166
131
  */
167
132
  export const encodedDestinationFacts = (destination: string): unknown => {
168
133
  const report = destinationReportFor(destination);
134
+
169
135
  return Schema.encodeSync(DestinationFacts)(
170
136
  DestinationFacts.make({
171
137
  destination: report.destination,
@@ -193,6 +159,7 @@ export const makeInvocationCountingModel = (
193
159
  Effect.gen(function* () {
194
160
  const calls = yield* Ref.make(0);
195
161
  const prompts = yield* Ref.make<ReadonlyArray<string>>([]);
162
+
196
163
  const model = Model.make(
197
164
  "scripted",
198
165
  name,
@@ -204,16 +171,19 @@ export const makeInvocationCountingModel = (
204
171
  Stream.unwrap(
205
172
  Effect.gen(function* () {
206
173
  const call = yield* Ref.getAndUpdate(calls, (value) => value + 1);
174
+
207
175
  yield* Ref.update(prompts, (previous) => [
208
176
  ...previous,
209
177
  JSON.stringify(request.prompt.content),
210
178
  ]);
179
+
211
180
  return Stream.fromIterable(script(call));
212
181
  }),
213
182
  ),
214
183
  }),
215
184
  ),
216
185
  );
186
+
217
187
  return { model, calls: Ref.get(calls), prompts: Ref.get(prompts) };
218
188
  });
219
189
 
@@ -304,7 +274,7 @@ export interface DurableResearchHarnessOptions {
304
274
 
305
275
  /** One durable coordinator/researcher pair with observable invocation counters. */
306
276
  export interface DurableResearchHarness {
307
- /** Host registrations for `NodeDurableRuntimeOptions.bindings` (parent + child). */
277
+ /** Host registrations for `NodeDurableAgentRuntimeOptions.bindings` (parent + child). */
308
278
  readonly bindings: ReadonlyArray<ResolvedBinding>;
309
279
  /** Total coordinator model invocations across every Attempt and runtime handle. */
310
280
  readonly parentModelCalls: Effect.Effect<number>;
@@ -325,7 +295,7 @@ export interface DurableResearchHarness {
325
295
  * guide, Turn 2 writes the report), and both worker Bindings captured with
326
296
  * their requirement Contexts via `DurableWorkerBinding.make` under the exact
327
297
  * fixture digests. The returned `bindings` are plain values: they can be
328
- * registered with several `NodeDurableRuntime` stacks over the same SQLite
298
+ * registered with several `NodeDurableAgentRuntime` stacks over the same SQLite
329
299
  * file while the counters keep counting across all of them.
330
300
  */
331
301
  export const makeDurableResearchHarness = (options?: DurableResearchHarnessOptions) =>
@@ -334,6 +304,7 @@ export const makeDurableResearchHarness = (options?: DurableResearchHarnessOptio
334
304
  const focus = options?.focus ?? "museums";
335
305
 
336
306
  const guideInvocations = yield* Ref.make(0);
307
+
337
308
  const guideLayer = Layer.succeed(
338
309
  DestinationGuide,
339
310
  DestinationGuide.of({
@@ -343,6 +314,7 @@ export const makeDurableResearchHarness = (options?: DurableResearchHarnessOptio
343
314
  ),
344
315
  }),
345
316
  );
317
+
346
318
  const childToolkitLayer = DestinationResearcherToolkitLayer.pipe(
347
319
  Layer.provideMerge(guideLayer),
348
320
  );
@@ -350,6 +322,7 @@ export const makeDurableResearchHarness = (options?: DurableResearchHarnessOptio
350
322
  const childModel = yield* makeInvocationCountingModel("destination-researcher-s2", (call) =>
351
323
  call === 0 ? researcherLookupParts(destination) : researcherReportParts(destination),
352
324
  );
325
+
353
326
  const childBinding = Agent.withModel(DestinationResearcher, childModel.model);
354
327
 
355
328
  const parentModel = yield* makeInvocationCountingModel("travel-coordinator-s2", (call) =>
@@ -357,6 +330,7 @@ export const makeDurableResearchHarness = (options?: DurableResearchHarnessOptio
357
330
  ? delegationTurnParts(durableResearchCallId, destination, focus)
358
331
  : shortlistParts(durableResearchShortlist(destination)),
359
332
  );
333
+
360
334
  const parentBinding = Agent.withModel(TravelCoordinator, parentModel.model);
361
335
 
362
336
  const delegationLayer = durableDestinationResearchHandlersLayer(childBinding).pipe(
@@ -374,6 +348,7 @@ export const makeDurableResearchHarness = (options?: DurableResearchHarnessOptio
374
348
  parentBinding,
375
349
  s2CoordinatorDigests,
376
350
  ).pipe(Effect.provide(delegationLayer));
351
+
377
352
  const childResolved: ResolvedBinding = yield* DurableWorkerBinding.make(
378
353
  childBinding,
379
354
  options?.childRegistrationDigests ?? s2ResearcherDigests,
@@ -387,5 +362,6 @@ export const makeDurableResearchHarness = (options?: DurableResearchHarnessOptio
387
362
  childPrompts: childModel.prompts,
388
363
  guideInvocations: Ref.get(guideInvocations),
389
364
  };
365
+
390
366
  return harness;
391
367
  });
@@ -1,17 +1,18 @@
1
- import { Subagent, SubagentPolicy, SubagentRuntime } from "@effect-agent/capabilities";
2
- import { Agent, AgentPolicy } from "@effect-agent/core";
3
- import type { RuntimeBinding } from "@effect-agent/engine";
1
+ import * as Subagent from "@effect-agent/capabilities/Subagent";
2
+ import { SubagentPolicy, SubagentRuntime } from "@effect-agent/capabilities/Subagent";
3
+ import * as Agent from "@effect-agent/core/Agent";
4
+ import { AgentPolicy } from "@effect-agent/core/AgentPolicy";
5
+ import { type RuntimeBinding } from "@effect-agent/engine/AgentRuntime";
4
6
  import { Context, Deferred, Effect, Layer, Ref, Schema, Stream } from "effect";
5
7
  import { LanguageModel, Model, type Response, Tool, Toolkit } from "effect/unstable/ai";
6
8
 
7
- import type { ScriptedTurnInput } from "../../scripted-model.ts";
9
+ import type { ScriptedTurnInput } from "../../ScriptedModel.ts";
8
10
  import { AirportCode } from "./definition.ts";
9
11
  import { CatalogLifecycle } from "./deterministic-layers.ts";
10
12
 
11
13
  // ---------------------------------------------------------------------------
12
- // Destination Researcher: the S1 specialist child Agent
13
- // (spec/subagents.md §17 "deterministic scripted Travel Planner specialist
14
- // delegation"). The researcher is a normal Agent with one deterministic
14
+ // Destination Researcher: the S1 specialist child Agent.
15
+ // The researcher is a normal Agent with one deterministic
15
16
  // travel-service Tool; it never becomes a second child loop (SUB-001/003).
16
17
  // ---------------------------------------------------------------------------
17
18
 
@@ -51,6 +52,7 @@ export const LookupDestination = Tool.make("lookup_destination", {
51
52
  });
52
53
 
53
54
  export const DestinationResearcherToolkit = Toolkit.make(LookupDestination);
55
+
54
56
  export const DestinationResearcherToolkitLayer = DestinationResearcherToolkit.toLayer({
55
57
  lookup_destination: (query) => Effect.flatMap(DestinationGuide, (guide) => guide.lookup(query)),
56
58
  });
@@ -66,7 +68,7 @@ export class DestinationReport extends Schema.Class<DestinationReport>("Destinat
66
68
  advisory: Schema.NonEmptyString,
67
69
  }) {}
68
70
 
69
- export const DestinationResearcher = Agent.define("destination-researcher", {
71
+ export const DestinationResearcher = Agent.make("destination-researcher", {
70
72
  input: DestinationBrief,
71
73
  output: DestinationReport,
72
74
  instructions:
@@ -112,6 +114,7 @@ export const destinationLookup = (
112
114
  query: DestinationQuery,
113
115
  ): Effect.Effect<DestinationFacts, DestinationGuideUnavailable> => {
114
116
  const facts = guideFacts.get(query.destination);
117
+
115
118
  return facts === undefined
116
119
  ? Effect.fail(
117
120
  DestinationGuideUnavailable.make({
@@ -124,15 +127,18 @@ export const destinationLookup = (
124
127
 
125
128
  const requireDestinationFacts = (destination: string): DestinationFacts => {
126
129
  const facts = guideFacts.get(destination);
130
+
127
131
  if (facts === undefined) {
128
132
  throw new Error(`No deterministic guide entry exists for destination ${destination}`);
129
133
  }
134
+
130
135
  return facts;
131
136
  };
132
137
 
133
138
  /** The report the scripted researcher writes after consulting the guide. */
134
139
  export const destinationReportFor = (destination: string): DestinationReport => {
135
140
  const facts = requireDestinationFacts(destination);
141
+
136
142
  return DestinationReport.make({
137
143
  destination: facts.destination,
138
144
  highlights: facts.highlights,
@@ -147,7 +153,9 @@ export const DestinationGuideLayer = Layer.effect(
147
153
  DestinationGuide,
148
154
  Effect.gen(function* () {
149
155
  const lifecycle = yield* CatalogLifecycle;
156
+
150
157
  yield* Effect.acquireRelease(lifecycle.markAcquired, () => lifecycle.markFinalized);
158
+
151
159
  return DestinationGuide.of({ lookup: destinationLookup });
152
160
  }),
153
161
  );
@@ -159,7 +167,7 @@ export const DestinationResearchSupportLayer = Layer.mergeAll(
159
167
  );
160
168
 
161
169
  // ---------------------------------------------------------------------------
162
- // Delegation Definition (spec/subagents.md §4): the coordinator sees exactly
170
+ // Delegation Definition: the coordinator sees exactly
163
171
  // one Effect AI Tool with explicit input/result projections and finite bounds.
164
172
  // ---------------------------------------------------------------------------
165
173
 
@@ -189,7 +197,7 @@ export class DestinationResearchFailed extends Schema.TaggedError<DestinationRes
189
197
  * this gate before the handler reserves budget or spawns, so tests can order
190
198
  * concurrent delegation preflights without sleeps. It also keeps the
191
199
  * projection's construction requirements honestly visible in the handler
192
- * Layer's `R` (spec/subagents.md §4.1). The open Layer never waits.
200
+ * Layer's `R`. The open Layer never waits.
193
201
  */
194
202
  export class ResearchDispatchGate extends Context.Service<
195
203
  ResearchDispatchGate,
@@ -224,14 +232,16 @@ export const destinationResearchDelegation = Subagent.define("delegate_destinati
224
232
  prepareInput: (request) =>
225
233
  Effect.gen(function* () {
226
234
  const gate = yield* ResearchDispatchGate;
235
+
227
236
  yield* gate.awaitDispatch(request.destination);
237
+
228
238
  return DestinationBrief.make({
229
239
  destination: request.destination,
230
240
  focus: `research:${request.focus}`,
231
241
  });
232
242
  }),
233
243
  // The explicit declassification boundary (SUB-015): only the advisory
234
- // crosses to the parent; guide highlights stay in the child Conversation.
244
+ // crosses to the parent; guide highlights stay in the child Thread.
235
245
  projectResult: (report) =>
236
246
  Effect.succeed(
237
247
  DestinationResearchFindings.make({
@@ -292,7 +302,7 @@ export const missionConfidentialMarker = "traveler-dossier-19f";
292
302
 
293
303
  export const TravelCoordinatorToolkit = Toolkit.make(destinationResearchDelegation.tool);
294
304
 
295
- export const TravelCoordinator = Agent.define("travel-coordinator", {
305
+ export const TravelCoordinator = Agent.make("travel-coordinator", {
296
306
  input: ResearchMission,
297
307
  output: DestinationShortlist,
298
308
  instructions: [
@@ -314,7 +324,7 @@ export const TravelCoordinator = Agent.define("travel-coordinator", {
314
324
  });
315
325
 
316
326
  export const researchMission = Schema.decodeSync(ResearchMission)({
317
- request: `Shortlist one September culture city; keep ${missionConfidentialMarker} inside the coordinator conversation.`,
327
+ request: `Shortlist one September culture city; keep ${missionConfidentialMarker} inside the coordinator thread.`,
318
328
  candidates: ["LHR", "CDG"],
319
329
  });
320
330
 
@@ -461,19 +471,23 @@ export const makeDestinationResearcherModel = (destinations: ReadonlyArray<strin
461
471
  const lifecycle = yield* CatalogLifecycle;
462
472
  const prompts = yield* Ref.make<ReadonlyArray<string>>([]);
463
473
  const gates = new Map<string, ResearcherGates>();
474
+
464
475
  for (const destination of destinations) {
465
476
  gates.set(destination, {
466
477
  started: yield* Deferred.make<void>(),
467
478
  release: yield* Deferred.make<void>(),
468
479
  });
469
480
  }
481
+
470
482
  const gatesFor = (destination: string): Effect.Effect<ResearcherGates> =>
471
483
  Effect.suspend(() => {
472
484
  const entry = gates.get(destination);
485
+
473
486
  return entry === undefined
474
487
  ? Effect.die(new Error(`No researcher gates exist for destination ${destination}`))
475
488
  : Effect.succeed(entry);
476
489
  });
490
+
477
491
  const controls: DestinationResearcherControls = {
478
492
  awaitStarted: (destination) =>
479
493
  gatesFor(destination).pipe(Effect.flatMap((entry) => Deferred.await(entry.started))),
@@ -484,6 +498,7 @@ export const makeDestinationResearcherModel = (destinations: ReadonlyArray<strin
484
498
  ),
485
499
  prompts: Ref.get(prompts),
486
500
  };
501
+
487
502
  const model = Model.make(
488
503
  "scripted",
489
504
  "destination-researcher-scripted",
@@ -492,15 +507,18 @@ export const makeDestinationResearcherModel = (destinations: ReadonlyArray<strin
492
507
  Effect.gen(function* () {
493
508
  yield* Effect.acquireRelease(lifecycle.markAcquired, () => lifecycle.markFinalized);
494
509
  const turn = yield* Ref.make(0);
510
+
495
511
  return yield* LanguageModel.make({
496
512
  generateText: () => Effect.succeed([]),
497
513
  streamText: (options) =>
498
514
  Stream.unwrap(
499
515
  Effect.gen(function* () {
500
516
  const promptJson = JSON.stringify(options.prompt.content);
517
+
501
518
  const destination = destinations.find((candidate) =>
502
519
  promptJson.includes(candidate),
503
520
  );
521
+
504
522
  if (destination === undefined) {
505
523
  return yield* Effect.die(
506
524
  new Error("The researcher prompt names no scripted destination"),
@@ -508,12 +526,15 @@ export const makeDestinationResearcherModel = (destinations: ReadonlyArray<strin
508
526
  }
509
527
  const entry = yield* gatesFor(destination);
510
528
  const index = yield* Ref.getAndUpdate(turn, (value) => value + 1);
529
+
511
530
  if (index === 0) {
512
531
  yield* Ref.update(prompts, (previous) => [...previous, promptJson]);
513
532
  yield* Deferred.succeed(entry.started, undefined);
533
+
514
534
  return Stream.fromIterable(researcherLookupParts(destination));
515
535
  }
516
536
  yield* Deferred.await(entry.release);
537
+
517
538
  return Stream.fromIterable(researcherReportParts(destination));
518
539
  }),
519
540
  ),
@@ -521,5 +542,6 @@ export const makeDestinationResearcherModel = (destinations: ReadonlyArray<strin
521
542
  }),
522
543
  ),
523
544
  );
545
+
524
546
  return { controls, model };
525
547
  });
package/src/index.ts CHANGED
@@ -1,11 +1 @@
1
- export * from "./certification.ts";
2
- export * from "./chaos.ts";
3
- export * from "./code-executor-conformance.ts";
4
- export * from "./code-executor-substitute.ts";
5
- export * from "./fixtures/docs-researcher/index.ts";
6
- export * from "./fixtures/travel-planner/index.ts";
7
- // The warehouse fixture is NOT re-exported here: it depends on
8
- // `@effect/sql-sqlite-node` (`node:sqlite`), which workerd consumers of this
9
- // barrel (the Cloudflare certification suites) cannot load. Import it
10
- // directly from `@effect-agent/testing/src/fixtures/warehouse/index.ts`.
11
- export * from "./scripted-model.ts";
1
+ export * as ScriptedModel from "./ScriptedModel.ts";