@effect-agent/testing 0.1.0-beta.9 → 0.1.0-beta.90
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.d.mts +106 -0
- package/dist/Certification.mjs +633 -0
- package/dist/Certification.mjs.map +1 -0
- package/dist/Chaos.d.mts +126 -0
- package/dist/Chaos.mjs +755 -0
- package/dist/Chaos.mjs.map +1 -0
- package/dist/CodeExecutorConformance.d.mts +33 -0
- package/dist/CodeExecutorConformance.mjs +231 -0
- package/dist/CodeExecutorConformance.mjs.map +1 -0
- package/dist/CodeExecutorSubstitute.d.mts +21 -0
- package/dist/CodeExecutorSubstitute.mjs +368 -0
- package/dist/CodeExecutorSubstitute.mjs.map +1 -0
- package/dist/DocsResearcher.d.mts +276 -0
- package/dist/DocsResearcher.mjs +490 -0
- package/dist/DocsResearcher.mjs.map +1 -0
- package/dist/ScriptedModel-DAvxIiud.d.mts +220 -0
- package/dist/ScriptedModel.d.mts +2 -0
- package/dist/ScriptedModel.mjs +155 -0
- package/dist/ScriptedModel.mjs.map +1 -0
- package/dist/TravelPlanner.d.mts +1680 -0
- package/dist/TravelPlanner.mjs +1963 -0
- package/dist/TravelPlanner.mjs.map +1 -0
- package/dist/deterministic-layers-D5owIoke.mjs +358 -0
- package/dist/deterministic-layers-D5owIoke.mjs.map +1 -0
- package/dist/index.d.mts +2 -3408
- package/dist/index.mjs +2 -4771
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/package.json +1 -48
- package/src/{certification.ts → Certification.ts} +366 -171
- package/src/{chaos.ts → Chaos.ts} +241 -127
- package/src/{code-executor-conformance.ts → CodeExecutorConformance.ts} +30 -7
- package/src/{code-executor-substitute.ts → CodeExecutorSubstitute.ts} +113 -46
- package/src/{fixtures/docs-researcher/index.ts → DocsResearcher.ts} +68 -5
- package/src/{scripted-model.ts → ScriptedModel.ts} +25 -29
- package/src/TravelPlanner.ts +232 -0
- package/src/fixtures/docs-researcher/definition.ts +20 -11
- package/src/fixtures/docs-researcher/harness.ts +41 -34
- package/src/fixtures/docs-researcher/mcp.ts +49 -3
- package/src/fixtures/travel-planner/definition.ts +15 -2
- package/src/fixtures/travel-planner/deterministic-layers.ts +47 -4
- package/src/fixtures/travel-planner/phase2.ts +4 -3
- package/src/fixtures/travel-planner/phase3.ts +19 -42
- package/src/fixtures/travel-planner/phase4.ts +24 -37
- package/src/fixtures/travel-planner/phase5.ts +35 -42
- package/src/fixtures/travel-planner/phase6.ts +191 -88
- package/src/fixtures/travel-planner/phase7.ts +4 -102
- package/src/fixtures/travel-planner/scenarios.ts +3 -4
- package/src/fixtures/travel-planner/subagents-durable.ts +35 -61
- package/src/fixtures/travel-planner/subagents.ts +36 -14
- package/src/index.ts +1 -11
- package/src/internal/certification-report.ts +25 -0
- package/dist/index.mjs.map +0 -1
- package/src/code-executor-conformance.d.ts +0 -30
- package/src/fixtures/travel-planner/index.ts +0 -11
- package/src/fixtures/warehouse/index.ts +0 -412
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Context, Effect, Layer, Ref, Schema, Stream } from "effect";
|
|
2
|
-
import { AiError, LanguageModel, Response } from "effect/unstable/ai";
|
|
2
|
+
import { AiError, LanguageModel, Response, Toolkit } from "effect/unstable/ai";
|
|
3
3
|
|
|
4
4
|
const ScriptedPartMetadata = Schema.Record(Schema.String, Schema.NullOr(Schema.Json));
|
|
5
|
+
|
|
5
6
|
const ScriptedPartBase = {
|
|
6
7
|
metadata: Schema.optionalKey(ScriptedPartMetadata),
|
|
7
8
|
};
|
|
9
|
+
|
|
8
10
|
const ScriptedToolCallPart = Schema.Struct({
|
|
9
11
|
...ScriptedPartBase,
|
|
10
12
|
type: Schema.Literal("tool-call"),
|
|
@@ -13,6 +15,7 @@ const ScriptedToolCallPart = Schema.Struct({
|
|
|
13
15
|
params: Schema.Unknown,
|
|
14
16
|
providerExecuted: Schema.optionalKey(Schema.Boolean),
|
|
15
17
|
});
|
|
18
|
+
|
|
16
19
|
const ScriptedToolResultPart = Schema.Struct({
|
|
17
20
|
...ScriptedPartBase,
|
|
18
21
|
type: Schema.Literal("tool-result"),
|
|
@@ -31,44 +34,25 @@ const ScriptedToolResultPart = Schema.Struct({
|
|
|
31
34
|
* performs the toolkit-specific decode when the scripted response is consumed.
|
|
32
35
|
*/
|
|
33
36
|
export const ScriptedGeneratePart = Schema.Union([
|
|
34
|
-
Schema.toEncoded(Response.
|
|
35
|
-
|
|
37
|
+
Schema.toEncoded(Response.Part(Toolkit.empty)),
|
|
38
|
+
// PartEncoded also admits these reasoning markers, which the Part schema omits.
|
|
36
39
|
Schema.toEncoded(Response.ReasoningDeltaPart),
|
|
37
40
|
Schema.toEncoded(Response.ReasoningEndPart),
|
|
38
41
|
ScriptedToolCallPart,
|
|
39
42
|
ScriptedToolResultPart,
|
|
40
|
-
Schema.toEncoded(Response.ToolApprovalRequestPart),
|
|
41
|
-
Schema.toEncoded(Response.FilePart),
|
|
42
|
-
Schema.toEncoded(Response.DocumentSourcePart),
|
|
43
|
-
Schema.toEncoded(Response.UrlSourcePart),
|
|
44
|
-
Schema.toEncoded(Response.ResponseMetadataPart),
|
|
45
|
-
Schema.toEncoded(Response.FinishPart),
|
|
46
43
|
]).annotate({ identifier: "ScriptedGeneratePart" });
|
|
44
|
+
|
|
47
45
|
export type ScriptedGeneratePart = typeof ScriptedGeneratePart.Type;
|
|
48
46
|
|
|
49
47
|
/**
|
|
50
48
|
* Schema for encoded Effect AI streaming response parts.
|
|
51
49
|
*/
|
|
52
50
|
export const ScriptedStreamPart = Schema.Union([
|
|
53
|
-
Schema.toEncoded(Response.
|
|
54
|
-
Schema.toEncoded(Response.TextDeltaPart),
|
|
55
|
-
Schema.toEncoded(Response.TextEndPart),
|
|
56
|
-
Schema.toEncoded(Response.ReasoningStartPart),
|
|
57
|
-
Schema.toEncoded(Response.ReasoningDeltaPart),
|
|
58
|
-
Schema.toEncoded(Response.ReasoningEndPart),
|
|
59
|
-
Schema.toEncoded(Response.ToolParamsStartPart),
|
|
60
|
-
Schema.toEncoded(Response.ToolParamsDeltaPart),
|
|
61
|
-
Schema.toEncoded(Response.ToolParamsEndPart),
|
|
51
|
+
Schema.toEncoded(Response.StreamPart(Toolkit.empty)),
|
|
62
52
|
ScriptedToolCallPart,
|
|
63
53
|
ScriptedToolResultPart,
|
|
64
|
-
Schema.toEncoded(Response.ToolApprovalRequestPart),
|
|
65
|
-
Schema.toEncoded(Response.FilePart),
|
|
66
|
-
Schema.toEncoded(Response.DocumentSourcePart),
|
|
67
|
-
Schema.toEncoded(Response.UrlSourcePart),
|
|
68
|
-
Schema.toEncoded(Response.ResponseMetadataPart),
|
|
69
|
-
Schema.toEncoded(Response.FinishPart),
|
|
70
|
-
Schema.toEncoded(Response.ErrorPart),
|
|
71
54
|
]).annotate({ identifier: "ScriptedStreamPart" });
|
|
55
|
+
|
|
72
56
|
export type ScriptedStreamPart = typeof ScriptedStreamPart.Type;
|
|
73
57
|
|
|
74
58
|
/** Controls whether a scripted stream completes, fails, or waits for interruption. */
|
|
@@ -79,12 +63,14 @@ export const ScriptedStreamTermination = Schema.Union([
|
|
|
79
63
|
}),
|
|
80
64
|
Schema.TaggedStruct("Hang", {}),
|
|
81
65
|
]);
|
|
66
|
+
|
|
82
67
|
export type ScriptedStreamTermination = typeof ScriptedStreamTermination.Type;
|
|
83
68
|
|
|
84
69
|
/** One non-streaming invocation and the encoded response parts it returns. */
|
|
85
70
|
export const ScriptedGenerateTurn = Schema.TaggedStruct("Generate", {
|
|
86
71
|
parts: Schema.Array(ScriptedGeneratePart),
|
|
87
72
|
});
|
|
73
|
+
|
|
88
74
|
export type ScriptedGenerateTurn = typeof ScriptedGenerateTurn.Type;
|
|
89
75
|
|
|
90
76
|
/** One streaming invocation with its encoded parts and terminal behavior. */
|
|
@@ -92,6 +78,7 @@ export const ScriptedStreamTurn = Schema.TaggedStruct("Stream", {
|
|
|
92
78
|
parts: Schema.Array(ScriptedStreamPart),
|
|
93
79
|
termination: ScriptedStreamTermination,
|
|
94
80
|
});
|
|
81
|
+
|
|
95
82
|
export type ScriptedStreamTurn = typeof ScriptedStreamTurn.Type;
|
|
96
83
|
|
|
97
84
|
/**
|
|
@@ -147,8 +134,10 @@ const runAssertion = Effect.fn("ScriptedModel.runAssertion")((
|
|
|
147
134
|
if (assertion === undefined) {
|
|
148
135
|
return Effect.void;
|
|
149
136
|
}
|
|
137
|
+
|
|
150
138
|
return Effect.suspend(() => {
|
|
151
139
|
const result = assertion(request);
|
|
140
|
+
|
|
152
141
|
return Effect.isEffect(result) ? result : Effect.void;
|
|
153
142
|
});
|
|
154
143
|
});
|
|
@@ -161,6 +150,7 @@ const takeTurn = Effect.fn("ScriptedModel.takeTurn")(
|
|
|
161
150
|
): Effect.Effect<ScriptedTurnInput, AiError.AiError> =>
|
|
162
151
|
Ref.modify(state, (current) => {
|
|
163
152
|
const turn = current.remaining[0];
|
|
153
|
+
|
|
164
154
|
if (turn === undefined) {
|
|
165
155
|
return [
|
|
166
156
|
undefined,
|
|
@@ -170,6 +160,7 @@ const takeTurn = Effect.fn("ScriptedModel.takeTurn")(
|
|
|
170
160
|
},
|
|
171
161
|
] as const;
|
|
172
162
|
}
|
|
163
|
+
|
|
173
164
|
return [
|
|
174
165
|
turn,
|
|
175
166
|
{
|
|
@@ -178,10 +169,9 @@ const takeTurn = Effect.fn("ScriptedModel.takeTurn")(
|
|
|
178
169
|
},
|
|
179
170
|
] as const;
|
|
180
171
|
}).pipe(
|
|
181
|
-
Effect.
|
|
182
|
-
turn
|
|
183
|
-
|
|
184
|
-
: Effect.succeed(turn),
|
|
172
|
+
Effect.filterOrFail(
|
|
173
|
+
(turn) => turn !== undefined,
|
|
174
|
+
() => scriptedError(kind, `Script exhausted before the ${kind} request`),
|
|
185
175
|
),
|
|
186
176
|
),
|
|
187
177
|
);
|
|
@@ -206,6 +196,7 @@ const streamForTurn = (
|
|
|
206
196
|
let stream: Stream.Stream<Response.StreamPartEncoded, AiError.AiError> = Stream.fromIterable(
|
|
207
197
|
turn.parts,
|
|
208
198
|
);
|
|
199
|
+
|
|
209
200
|
switch (turn.termination._tag) {
|
|
210
201
|
case "Complete": {
|
|
211
202
|
break;
|
|
@@ -227,6 +218,7 @@ const streamForTurn = (
|
|
|
227
218
|
if (turn.onStreamFinalize !== undefined) {
|
|
228
219
|
stream = stream.pipe(Stream.ensuring(turn.onStreamFinalize));
|
|
229
220
|
}
|
|
221
|
+
|
|
230
222
|
return stream;
|
|
231
223
|
};
|
|
232
224
|
|
|
@@ -262,16 +254,20 @@ export class ScriptedModel extends Context.Service<
|
|
|
262
254
|
generateText: (options) =>
|
|
263
255
|
Effect.gen(function* () {
|
|
264
256
|
const turn = yield* takeTurn(state, "generate", options);
|
|
257
|
+
|
|
265
258
|
yield* runAssertion(turn.assertRequest, options);
|
|
266
259
|
const generateTurn = yield* requireGenerateTurn(turn);
|
|
260
|
+
|
|
267
261
|
return [...generateTurn.parts];
|
|
268
262
|
}),
|
|
269
263
|
streamText: (options) =>
|
|
270
264
|
Stream.unwrap(
|
|
271
265
|
Effect.gen(function* () {
|
|
272
266
|
const turn = yield* takeTurn(state, "stream", options);
|
|
267
|
+
|
|
273
268
|
yield* runAssertion(turn.assertRequest, options);
|
|
274
269
|
const streamTurn = yield* requireStreamTurn(turn);
|
|
270
|
+
|
|
275
271
|
return streamForTurn(streamTurn);
|
|
276
272
|
}),
|
|
277
273
|
),
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/** Shared Travel Planner definitions, deterministic services, and durability fixtures. */
|
|
2
|
+
export {
|
|
3
|
+
AirportCode,
|
|
4
|
+
QuoteId,
|
|
5
|
+
TripRequest,
|
|
6
|
+
FlightQuery,
|
|
7
|
+
LodgingQuery,
|
|
8
|
+
ActivityQuery,
|
|
9
|
+
FlightOption,
|
|
10
|
+
LodgingOption,
|
|
11
|
+
ActivitySearchResult,
|
|
12
|
+
Itinerary,
|
|
13
|
+
TravelPlan,
|
|
14
|
+
FlightUnavailable,
|
|
15
|
+
LodgingUnavailable,
|
|
16
|
+
ActivityUnavailable,
|
|
17
|
+
GuidanceFailure,
|
|
18
|
+
FlightCatalog,
|
|
19
|
+
LodgingCatalog,
|
|
20
|
+
ActivityCatalog,
|
|
21
|
+
TravelGuidance,
|
|
22
|
+
SearchFlights,
|
|
23
|
+
SearchLodging,
|
|
24
|
+
SearchActivities,
|
|
25
|
+
TravelPlannerToolkit,
|
|
26
|
+
TravelPlannerToolkitLayer,
|
|
27
|
+
TravelPlanner,
|
|
28
|
+
} from "./fixtures/travel-planner/definition.ts";
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
CatalogLifecycleCounts,
|
|
32
|
+
CatalogLifecycle,
|
|
33
|
+
type TravelPlannerCompletionControls,
|
|
34
|
+
ReverseCompletionToolkitLayer,
|
|
35
|
+
FlightCatalogLayer,
|
|
36
|
+
LodgingCatalogLayer,
|
|
37
|
+
ActivityCatalogLayer,
|
|
38
|
+
BookingRef,
|
|
39
|
+
SupplierOperation,
|
|
40
|
+
SupplierBookingRecord,
|
|
41
|
+
SupplierUnavailable,
|
|
42
|
+
type SupplierBookRequest,
|
|
43
|
+
type SupplierHoldControls,
|
|
44
|
+
cancelBookingIdempotencyKey,
|
|
45
|
+
supplierBookingRefFor,
|
|
46
|
+
SupplierBookingDesk,
|
|
47
|
+
TravelGuidanceLayer,
|
|
48
|
+
DeterministicIdGeneratorLayer,
|
|
49
|
+
TravelPlannerRuntimeLayer,
|
|
50
|
+
} from "./fixtures/travel-planner/deterministic-layers.ts";
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
ItineraryHoldRequest,
|
|
54
|
+
ItineraryHold,
|
|
55
|
+
ItineraryHoldUnavailable,
|
|
56
|
+
ItineraryHoldGateway,
|
|
57
|
+
HoldItinerary,
|
|
58
|
+
TravelPlannerPhase2Toolkit,
|
|
59
|
+
TravelPlannerPhase2ToolkitLayer,
|
|
60
|
+
TravelPlannerPhase2,
|
|
61
|
+
} from "./fixtures/travel-planner/phase2.ts";
|
|
62
|
+
|
|
63
|
+
export {
|
|
64
|
+
phase3TravelPlannerThreadId,
|
|
65
|
+
phase3TravelPlannerProducerId,
|
|
66
|
+
phase3TravelPlannerRunId,
|
|
67
|
+
phase3TravelPlannerDefinitionDigests,
|
|
68
|
+
phase3TravelPlannerInitialBatch,
|
|
69
|
+
phase3TravelPlannerCompletionBatch,
|
|
70
|
+
phase3TravelPlannerBatches,
|
|
71
|
+
phase3TravelPlannerEncodedFixture,
|
|
72
|
+
TravelPlannerProjectionError,
|
|
73
|
+
travelPlanFromProjection,
|
|
74
|
+
makePhase3TravelPlannerCheckpoint,
|
|
75
|
+
} from "./fixtures/travel-planner/phase3.ts";
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
phase4TravelPlannerDeploymentId,
|
|
79
|
+
phase4TravelPlannerProducerId,
|
|
80
|
+
phase4TravelPlannerPrincipal,
|
|
81
|
+
phase4TravelPlannerDefinitionDigests,
|
|
82
|
+
phase4TravelPlannerSubmitOptions,
|
|
83
|
+
DurableSearchFlights,
|
|
84
|
+
DurableSearchLodging,
|
|
85
|
+
DurableSearchActivities,
|
|
86
|
+
TravelPlannerPhase4Toolkit,
|
|
87
|
+
TravelPlannerPhase4ToolkitLayer,
|
|
88
|
+
TravelPlannerPhase4,
|
|
89
|
+
makePhase4TravelPlannerAgent,
|
|
90
|
+
phase4TravelPlannerWorkerLayer,
|
|
91
|
+
TravelPlannerDurableEvidenceError,
|
|
92
|
+
travelPlanFromDurableSettlement,
|
|
93
|
+
normalizeDurableTravelPlannerEvidence,
|
|
94
|
+
} from "./fixtures/travel-planner/phase4.ts";
|
|
95
|
+
|
|
96
|
+
export {
|
|
97
|
+
phase5TravelPlannerDeploymentId,
|
|
98
|
+
phase5TravelPlannerProducerId,
|
|
99
|
+
phase5TravelPlannerPrincipal,
|
|
100
|
+
phase5TravelPlannerDefinitionDigests,
|
|
101
|
+
phase5TravelPlannerSubmitOptions,
|
|
102
|
+
TravelerRef,
|
|
103
|
+
FlightBookingRequest,
|
|
104
|
+
SupplierBookingConfirmation,
|
|
105
|
+
CancelBookingRequest,
|
|
106
|
+
CancellationConfirmation,
|
|
107
|
+
ItineraryBookingRequest,
|
|
108
|
+
ItineraryConfirmation,
|
|
109
|
+
TravelBookingReport,
|
|
110
|
+
bookFlightIdempotencyKey,
|
|
111
|
+
itineraryStepIdempotencyKey,
|
|
112
|
+
BookFlight,
|
|
113
|
+
CancelBooking,
|
|
114
|
+
BookItinerary,
|
|
115
|
+
TravelPlannerPhase5Toolkit,
|
|
116
|
+
TravelPlannerPhase5ToolkitLayer,
|
|
117
|
+
TravelSupplierReconcilerLayer,
|
|
118
|
+
TravelPlannerPhase5,
|
|
119
|
+
TravelPlannerBookingEvidenceError,
|
|
120
|
+
assertSettledBookingsExistAtSupplier,
|
|
121
|
+
phase5TravelPlannerWorkerLayer,
|
|
122
|
+
} from "./fixtures/travel-planner/phase5.ts";
|
|
123
|
+
|
|
124
|
+
export {
|
|
125
|
+
phase6TravelPlannerDeploymentId,
|
|
126
|
+
phase6TravelPlannerProducerPrefix,
|
|
127
|
+
phase6TravelPlannerProducerId,
|
|
128
|
+
phase6GatedPlannerDefinitionDigests,
|
|
129
|
+
type CrossPlatformEvidenceIdentity,
|
|
130
|
+
normalizeCrossPlatformTravelPlannerEvidence,
|
|
131
|
+
phase6FlightCallId,
|
|
132
|
+
phase6LodgingCallId,
|
|
133
|
+
phase6ActivityCallId,
|
|
134
|
+
phase6PlannerModel,
|
|
135
|
+
releasePhase6PlannerGate,
|
|
136
|
+
resetPhase6PlannerGate,
|
|
137
|
+
phase6GatedTrip,
|
|
138
|
+
phase6GatedPlannerModel,
|
|
139
|
+
phase6SupplierDesk,
|
|
140
|
+
phase6SupplierDeskLayer,
|
|
141
|
+
phase6SupplierReconcilerLayer,
|
|
142
|
+
phase6BookingToolCallId,
|
|
143
|
+
phase6BookingRef,
|
|
144
|
+
phase6BookingTrip,
|
|
145
|
+
phase6BookingModel,
|
|
146
|
+
phase6GuideInvocationCount,
|
|
147
|
+
phase6ResearchMission,
|
|
148
|
+
phase6ResearchDestination,
|
|
149
|
+
phase6ChildLookupCallId,
|
|
150
|
+
phase6CoordinatorModel,
|
|
151
|
+
releasePhase6ResearcherGate,
|
|
152
|
+
resetPhase6ResearcherGate,
|
|
153
|
+
phase6ResearcherModel,
|
|
154
|
+
makePhase6TravelPlannerBindings,
|
|
155
|
+
phase6TravelPlannerGoldenEvidence,
|
|
156
|
+
} from "./fixtures/travel-planner/phase6.ts";
|
|
157
|
+
|
|
158
|
+
export {
|
|
159
|
+
PHASE7_LIVE_GATE_ENV,
|
|
160
|
+
PHASE7_LIVE_CREDENTIAL_ENV,
|
|
161
|
+
type Phase7LiveGateEnvironment,
|
|
162
|
+
phase7LiveProfileEnabled,
|
|
163
|
+
} from "./fixtures/travel-planner/phase7.ts";
|
|
164
|
+
|
|
165
|
+
export {
|
|
166
|
+
phase1Trip,
|
|
167
|
+
expectedTravelPlan,
|
|
168
|
+
phase1HappyPathTurns,
|
|
169
|
+
} from "./fixtures/travel-planner/scenarios.ts";
|
|
170
|
+
|
|
171
|
+
export {
|
|
172
|
+
DestinationQuery,
|
|
173
|
+
DestinationFacts,
|
|
174
|
+
DestinationGuideUnavailable,
|
|
175
|
+
DestinationGuide,
|
|
176
|
+
LookupDestination,
|
|
177
|
+
DestinationResearcherToolkit,
|
|
178
|
+
DestinationResearcherToolkitLayer,
|
|
179
|
+
DestinationBrief,
|
|
180
|
+
DestinationReport,
|
|
181
|
+
DestinationResearcher,
|
|
182
|
+
destinationLookup,
|
|
183
|
+
destinationReportFor,
|
|
184
|
+
encodedDestinationReport,
|
|
185
|
+
DestinationGuideLayer,
|
|
186
|
+
DestinationResearchSupportLayer,
|
|
187
|
+
DestinationResearchRequest,
|
|
188
|
+
DestinationResearchFindings,
|
|
189
|
+
DestinationResearchFailed,
|
|
190
|
+
ResearchDispatchGate,
|
|
191
|
+
destinationResearchPolicy,
|
|
192
|
+
destinationResearchDelegation,
|
|
193
|
+
mapResearchChildFailure,
|
|
194
|
+
destinationResearchHandlersLayer,
|
|
195
|
+
ResearchMission,
|
|
196
|
+
DestinationRecommendation,
|
|
197
|
+
DestinationShortlist,
|
|
198
|
+
coordinatorConfidentialMarker,
|
|
199
|
+
missionConfidentialMarker,
|
|
200
|
+
TravelCoordinatorToolkit,
|
|
201
|
+
TravelCoordinator,
|
|
202
|
+
researchMission,
|
|
203
|
+
expectedDestinationShortlist,
|
|
204
|
+
type DestinationResearchCall,
|
|
205
|
+
coordinatorResearchTurn,
|
|
206
|
+
coordinatorShortlistTurn,
|
|
207
|
+
researcherHappyPathTurns,
|
|
208
|
+
type DestinationResearcherControls,
|
|
209
|
+
makeDestinationResearcherModel,
|
|
210
|
+
} from "./fixtures/travel-planner/subagents.ts";
|
|
211
|
+
|
|
212
|
+
export {
|
|
213
|
+
s2TravelPlannerDeploymentId,
|
|
214
|
+
s2TravelPlannerProducerId,
|
|
215
|
+
s2TravelPlannerPrincipal,
|
|
216
|
+
s2CoordinatorDigests,
|
|
217
|
+
s2ResearcherDigestStrings,
|
|
218
|
+
s2ResearcherDigests,
|
|
219
|
+
s2TravelPlannerSubmitOptions,
|
|
220
|
+
s2CoordinatorSubmitAgent,
|
|
221
|
+
durableResearchAllocation,
|
|
222
|
+
durableResearchCallId,
|
|
223
|
+
durableChildLookupCallId,
|
|
224
|
+
durableResearchFinding,
|
|
225
|
+
durableResearchShortlist,
|
|
226
|
+
encodedDestinationFacts,
|
|
227
|
+
makeInvocationCountingModel,
|
|
228
|
+
durableDestinationResearchHandlersLayer,
|
|
229
|
+
type DurableResearchHarnessOptions,
|
|
230
|
+
type DurableResearchHarness,
|
|
231
|
+
makeDurableResearchHarness,
|
|
232
|
+
} from "./fixtures/travel-planner/subagents-durable.ts";
|
|
@@ -1,7 +1,9 @@
|
|
|
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";
|
|
4
1
|
import { Context, Effect, Schema } from "effect";
|
|
2
|
+
import * as Agent from "effect-agent/agent";
|
|
3
|
+
import { AgentPolicy } from "effect-agent/agent-policy";
|
|
4
|
+
import { type RuntimeBinding } from "effect-agent/agent-runtime";
|
|
5
|
+
import * as Subagent from "effect-agent/subagent";
|
|
6
|
+
import { SubagentPolicy } from "effect-agent/subagent";
|
|
5
7
|
import { Tool, Toolkit } from "effect/unstable/ai";
|
|
6
8
|
|
|
7
9
|
// ---------------------------------------------------------------------------
|
|
@@ -16,10 +18,12 @@ import { Tool, Toolkit } from "effect/unstable/ai";
|
|
|
16
18
|
export const ResearchDocumentId = Schema.NonEmptyString.check(Schema.isMaxLength(64)).pipe(
|
|
17
19
|
Schema.brand("@effect-agent/testing/docs-researcher/ResearchDocumentId"),
|
|
18
20
|
);
|
|
21
|
+
|
|
19
22
|
export type ResearchDocumentId = typeof ResearchDocumentId.Type;
|
|
20
23
|
|
|
21
24
|
const BoundedTitle = Schema.NonEmptyString.check(Schema.isMaxLength(120));
|
|
22
25
|
const BoundedBody = Schema.NonEmptyString.check(Schema.isMaxLength(16 * 1024));
|
|
26
|
+
|
|
23
27
|
/** Bounded summary text: the ONLY child-derived text that may cross to the parent. */
|
|
24
28
|
export const BoundedSummary = Schema.NonEmptyString.check(Schema.isMaxLength(240));
|
|
25
29
|
|
|
@@ -66,6 +70,7 @@ export const FetchDocument = Tool.make("fetch_document", {
|
|
|
66
70
|
});
|
|
67
71
|
|
|
68
72
|
export const DocContentToolkit = Toolkit.make(FetchDocument);
|
|
73
|
+
|
|
69
74
|
export const docContentToolkitLayer = DocContentToolkit.toLayer({
|
|
70
75
|
fetch_document: (query) => Effect.flatMap(DocumentLibrary, (library) => library.fetch(query)),
|
|
71
76
|
});
|
|
@@ -73,11 +78,11 @@ export const docContentToolkitLayer = DocContentToolkit.toLayer({
|
|
|
73
78
|
// ---------------------------------------------------------------------------
|
|
74
79
|
// Deterministic corpus. Every body deliberately embeds BOTH a secret marker
|
|
75
80
|
// and a distinctive body phrase: the tests assert that neither ever reaches
|
|
76
|
-
// the parent
|
|
81
|
+
// the parent Thread, the parent prompts, or a redacted preview — only
|
|
77
82
|
// the bounded summary crosses the delegation boundary (SUB-015, SEC-008).
|
|
78
83
|
// ---------------------------------------------------------------------------
|
|
79
84
|
|
|
80
|
-
/** Never allowed outside a child
|
|
85
|
+
/** Never allowed outside a child Thread or an unredacted fixture value. */
|
|
81
86
|
export const docsDocumentBodySecret = "docs-vault-secret-771";
|
|
82
87
|
|
|
83
88
|
const decodeDocumentId = Schema.decodeSync(ResearchDocumentId);
|
|
@@ -109,7 +114,7 @@ const corpusEntries = new Map<string, CorpusEntry>(
|
|
|
109
114
|
document: ResearchDocument.make({
|
|
110
115
|
documentId: decodeDocumentId(entry.documentId),
|
|
111
116
|
title: entry.title,
|
|
112
|
-
body: `${entry.bodyPhrase}: internal working notes. ${docsDocumentBodySecret}. ${entry.summary} Raw notes stay inside the child
|
|
117
|
+
body: `${entry.bodyPhrase}: internal working notes. ${docsDocumentBodySecret}. ${entry.summary} Raw notes stay inside the child Thread.`,
|
|
113
118
|
}),
|
|
114
119
|
bodyPhrase: entry.bodyPhrase,
|
|
115
120
|
summary: entry.summary,
|
|
@@ -125,9 +130,11 @@ export const researchCorpusDocumentIds: ReadonlyArray<ResearchDocumentId> = [
|
|
|
125
130
|
|
|
126
131
|
const requireCorpusEntry = (documentId: string): CorpusEntry => {
|
|
127
132
|
const entry = corpusEntries.get(documentId);
|
|
133
|
+
|
|
128
134
|
if (entry === undefined) {
|
|
129
135
|
throw new Error(`No deterministic corpus entry exists for document ${documentId}`);
|
|
130
136
|
}
|
|
137
|
+
|
|
131
138
|
return entry;
|
|
132
139
|
};
|
|
133
140
|
|
|
@@ -136,6 +143,7 @@ export const researchDocumentLookup = (
|
|
|
136
143
|
query: DocumentQuery,
|
|
137
144
|
): Effect.Effect<ResearchDocument, DocumentUnavailable> => {
|
|
138
145
|
const entry = corpusEntries.get(query.documentId);
|
|
146
|
+
|
|
139
147
|
return entry === undefined
|
|
140
148
|
? Effect.fail(
|
|
141
149
|
DocumentUnavailable.make({
|
|
@@ -180,7 +188,7 @@ export const documentSummaryFor = (documentId: string): DocumentSummary =>
|
|
|
180
188
|
export const encodedDocumentSummary = (documentId: string): string =>
|
|
181
189
|
JSON.stringify(Schema.encodeSync(DocumentSummary)(documentSummaryFor(documentId)));
|
|
182
190
|
|
|
183
|
-
export const DocSummarizer = Agent.
|
|
191
|
+
export const DocSummarizer = Agent.make("doc-summarizer", {
|
|
184
192
|
input: SummaryBrief,
|
|
185
193
|
output: DocumentSummary,
|
|
186
194
|
instructions:
|
|
@@ -200,7 +208,7 @@ export const DocSummarizer = Agent.define("doc-summarizer", {
|
|
|
200
208
|
// Delegation Definition: the coordinator sees exactly one Tool with explicit
|
|
201
209
|
// projections and finite bounds. `projectResult` is the declassification
|
|
202
210
|
// boundary (SUB-015): only the bounded summary crosses; the fetched body —
|
|
203
|
-
// secret marker included — stays in the child
|
|
211
|
+
// secret marker included — stays in the child Thread.
|
|
204
212
|
// ---------------------------------------------------------------------------
|
|
205
213
|
|
|
206
214
|
export class SummaryRequest extends Schema.Class<SummaryRequest>("SummaryRequest")({
|
|
@@ -275,7 +283,7 @@ export const docsSummaryHandlersLayer = <Provider, ModelProvides, ModelRequires>
|
|
|
275
283
|
ModelRequires
|
|
276
284
|
>,
|
|
277
285
|
) =>
|
|
278
|
-
|
|
286
|
+
Subagent.layer(delegateDocumentSummary, childBinding, {
|
|
279
287
|
mapChildFailure: mapSummaryChildFailure,
|
|
280
288
|
durable: { targetDigests: docsSummarizerDigestStrings },
|
|
281
289
|
});
|
|
@@ -300,7 +308,7 @@ export const docsMissionConfidentialMarker = "docs-mission-dossier-42f";
|
|
|
300
308
|
|
|
301
309
|
export const DocsResearcherToolkit = Toolkit.make(delegateDocumentSummary.tool);
|
|
302
310
|
|
|
303
|
-
export const DocsResearcher = Agent.
|
|
311
|
+
export const DocsResearcher = Agent.make("docs-researcher", {
|
|
304
312
|
input: ResearchRequest,
|
|
305
313
|
output: ResearchDigest,
|
|
306
314
|
instructions: [
|
|
@@ -322,7 +330,7 @@ export const DocsResearcher = Agent.define("docs-researcher", {
|
|
|
322
330
|
|
|
323
331
|
/** The default two-document research mission. */
|
|
324
332
|
export const researchMissionRequest = ResearchRequest.make({
|
|
325
|
-
question: `Summarize the durability and subagent notes; keep ${docsMissionConfidentialMarker} inside the coordinator
|
|
333
|
+
question: `Summarize the durability and subagent notes; keep ${docsMissionConfidentialMarker} inside the coordinator thread.`,
|
|
326
334
|
documentIds: researchCorpusDocumentIds,
|
|
327
335
|
});
|
|
328
336
|
|
|
@@ -333,6 +341,7 @@ export const expectedResearchDigest = (
|
|
|
333
341
|
ResearchDigest.make({
|
|
334
342
|
findings: documentIds.map((documentId) => {
|
|
335
343
|
const summary = documentSummaryFor(documentId);
|
|
344
|
+
|
|
336
345
|
return SummaryFinding.make({
|
|
337
346
|
documentId: summary.documentId,
|
|
338
347
|
summary: summary.summary,
|