anpord 0.1.11 → 0.1.13
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 +56 -78
- package/dist/bin.cjs +211 -204
- package/dist/bin.mjs +211 -204
- package/dist/cli-runtime.cjs +2 -2
- package/dist/cli-runtime.d.cts +1 -1
- package/dist/cli-runtime.d.mts +1 -1
- package/dist/cli-runtime.mjs +2 -2
- package/dist/client-BfdjFtlV.mjs +305 -0
- package/dist/{client-C9m0uLCz.d.cts → client-BgRs8JvW.d.mts} +2150 -174
- package/dist/{client-TFCLuMv8.d.mts → client-BirFO3jz.d.cts} +2150 -174
- package/dist/client-C-P2I00z.cjs +346 -0
- package/dist/{compiler-DXlpU_In.mjs → compiler-D96wI7UP.mjs} +108 -75
- package/dist/{compiler-Ap8DM-JU.cjs → compiler-uwb1pkdK.cjs} +116 -83
- package/dist/config.cjs +1 -1
- package/dist/config.d.cts +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/config.mjs +1 -1
- package/dist/{errors-C9bQUcA3.mjs → errors-B0YknR5V.mjs} +3 -19
- package/dist/{errors-Boum34f5.cjs → errors-BX1wry8K.cjs} +3 -19
- package/dist/{errors-BK3f7Rdr.d.cts → errors-aGrd21jy.d.cts} +0 -3
- package/dist/{errors-BK3f7Rdr.d.mts → errors-aGrd21jy.d.mts} +0 -3
- package/dist/eval-judges-BkmiVLLq.cjs +59 -0
- package/dist/eval-judges-CwTvTq7N.mjs +42 -0
- package/dist/eval-judges-DPPUftbh.d.cts +48 -0
- package/dist/eval-judges-DPPUftbh.d.mts +48 -0
- package/dist/eval-validations-BRdoZrTQ.mjs +113 -0
- package/dist/eval-validations-_MlnQ_uv.cjs +148 -0
- package/dist/eval.cjs +1 -1
- package/dist/eval.d.cts +60 -6
- package/dist/eval.d.mts +60 -6
- package/dist/eval.mjs +1 -1
- package/dist/evals-B6aT3xgH.d.cts +1364 -0
- package/dist/evals-B6aT3xgH.d.mts +1364 -0
- package/dist/evals-Dcc_x6jW.mjs +582 -0
- package/dist/evals-DouMsrsM.cjs +737 -0
- package/dist/index.cjs +23 -99
- package/dist/index.d.cts +138 -34
- package/dist/index.d.mts +138 -34
- package/dist/index.mjs +23 -99
- package/dist/source.d.cts +1 -1
- package/dist/source.d.mts +1 -1
- package/dist/{types-oaMF6-E1.d.mts → types-Codjaq-o.d.mts} +146 -45
- package/dist/{types-H9L450Iu.d.cts → types-ISsteq95.d.cts} +146 -45
- package/dist/validator-runtime.cjs +238 -0
- package/dist/validator-runtime.d.cts +9 -0
- package/dist/validator-runtime.d.mts +9 -0
- package/dist/validator-runtime.mjs +237 -0
- package/dist/validators.cjs +10 -0
- package/dist/validators.d.cts +8 -0
- package/dist/validators.d.mts +8 -0
- package/dist/validators.mjs +9 -0
- package/package.json +11 -1
- package/dist/client-5K3dMI5Q.mjs +0 -849
- package/dist/client-Ci0woWLW.cjs +0 -890
- package/dist/evals-BEgEmfiO.d.cts +0 -603
- package/dist/evals-BEgEmfiO.d.mts +0 -603
- package/dist/harness-profile-BMjsN460.mjs +0 -43
- package/dist/harness-profile-CDQpPLPd.cjs +0 -78
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
const require_evals = require("./evals-DouMsrsM.cjs");
|
|
2
|
+
let _effect_platform = require("@effect/platform");
|
|
3
|
+
let effect = require("effect");
|
|
4
|
+
//#region ../schema/src/domain/prompts.ts
|
|
5
|
+
const ChannelName = effect.Schema.String.pipe(effect.Schema.minLength(1), effect.Schema.maxLength(36), effect.Schema.pattern(/^[a-z0-9][a-z0-9_-]*$/, { message: () => "Channel must be lowercase alphanumeric, optionally with - or _" }), effect.Schema.brand("ChannelName")).annotations({ description: "Addresses a version. `latest` is derived from the highest version rather than stored, so it cannot drift from the version table." });
|
|
6
|
+
ChannelName.make("production");
|
|
7
|
+
ChannelName.make("latest");
|
|
8
|
+
const PromptId = effect.Schema.String.pipe(effect.Schema.minLength(1), effect.Schema.maxLength(255), effect.Schema.pattern(/^[a-z0-9][a-z0-9/_-]*$/, { message: () => "Prompt id must be lowercase alphanumeric, optionally with / _ or -" }), effect.Schema.brand("PromptId"));
|
|
9
|
+
const PromptName = effect.Schema.String.pipe(effect.Schema.minLength(1), effect.Schema.maxLength(255), effect.Schema.brand("PromptName"));
|
|
10
|
+
const VersionNumber = effect.Schema.Int.pipe(effect.Schema.positive(), effect.Schema.brand("VersionNumber"));
|
|
11
|
+
effect.Schema.NumberFromString.pipe(effect.Schema.int(), effect.Schema.positive(), effect.Schema.brand("VersionNumber"));
|
|
12
|
+
effect.Schema.NumberFromString.pipe(effect.Schema.int(), effect.Schema.positive(), effect.Schema.lessThanOrEqualTo(100));
|
|
13
|
+
const Timestamp = effect.Schema.Union(effect.Schema.DateFromSelf, effect.Schema.Date);
|
|
14
|
+
const CommitMessage = effect.Schema.String.pipe(effect.Schema.maxLength(500));
|
|
15
|
+
const PromptContent = effect.Schema.String.pipe(effect.Schema.minLength(1), effect.Schema.maxLength(262144, { message: () => "Prompt content is longer than 256 KB" }));
|
|
16
|
+
const PromptDescription = effect.Schema.String.pipe(effect.Schema.maxLength(2e3));
|
|
17
|
+
const PromptConfig = effect.Schema.Record({
|
|
18
|
+
key: effect.Schema.String,
|
|
19
|
+
value: effect.Schema.Unknown
|
|
20
|
+
});
|
|
21
|
+
const Author = effect.Schema.Struct({
|
|
22
|
+
image: effect.Schema.NullOr(effect.Schema.String),
|
|
23
|
+
name: effect.Schema.String
|
|
24
|
+
});
|
|
25
|
+
effect.Schema.Struct({
|
|
26
|
+
author: effect.Schema.NullOr(Author),
|
|
27
|
+
channel: effect.Schema.NullOr(ChannelName),
|
|
28
|
+
commitMessage: effect.Schema.NullOr(CommitMessage),
|
|
29
|
+
config: PromptConfig,
|
|
30
|
+
content: effect.Schema.String,
|
|
31
|
+
createdAt: Timestamp,
|
|
32
|
+
id: PromptId,
|
|
33
|
+
name: PromptName,
|
|
34
|
+
version: VersionNumber,
|
|
35
|
+
versionId: effect.Schema.String
|
|
36
|
+
});
|
|
37
|
+
effect.Schema.Struct({
|
|
38
|
+
channel: ChannelName,
|
|
39
|
+
updatedAt: Timestamp,
|
|
40
|
+
updatedBy: effect.Schema.NullOr(Author),
|
|
41
|
+
version: VersionNumber
|
|
42
|
+
});
|
|
43
|
+
const PromptSummary = effect.Schema.Struct({
|
|
44
|
+
author: effect.Schema.NullOr(Author),
|
|
45
|
+
description: effect.Schema.NullOr(effect.Schema.String),
|
|
46
|
+
id: PromptId,
|
|
47
|
+
latestVersion: effect.Schema.NullOr(VersionNumber),
|
|
48
|
+
name: PromptName,
|
|
49
|
+
productionVersion: effect.Schema.NullOr(VersionNumber),
|
|
50
|
+
updatedAt: Timestamp
|
|
51
|
+
});
|
|
52
|
+
effect.Schema.Struct({
|
|
53
|
+
id: PromptId,
|
|
54
|
+
updatedAt: Timestamp
|
|
55
|
+
});
|
|
56
|
+
effect.Schema.Literal("all", "draft", "live");
|
|
57
|
+
effect.Schema.Literal("name", "updated");
|
|
58
|
+
effect.Schema.Struct({
|
|
59
|
+
items: effect.Schema.Array(PromptSummary),
|
|
60
|
+
nextCursor: effect.Schema.NullOr(effect.Schema.String)
|
|
61
|
+
});
|
|
62
|
+
effect.Schema.Struct({
|
|
63
|
+
commitMessage: effect.Schema.optional(CommitMessage),
|
|
64
|
+
config: effect.Schema.optional(PromptConfig),
|
|
65
|
+
content: PromptContent,
|
|
66
|
+
description: effect.Schema.optional(PromptDescription),
|
|
67
|
+
id: PromptId,
|
|
68
|
+
name: PromptName,
|
|
69
|
+
publish: effect.Schema.optional(effect.Schema.Boolean)
|
|
70
|
+
});
|
|
71
|
+
effect.Schema.Struct({
|
|
72
|
+
commitMessage: effect.Schema.optional(CommitMessage),
|
|
73
|
+
config: effect.Schema.optional(PromptConfig),
|
|
74
|
+
content: PromptContent,
|
|
75
|
+
publish: effect.Schema.optional(effect.Schema.Boolean)
|
|
76
|
+
});
|
|
77
|
+
effect.Schema.Struct({
|
|
78
|
+
commitMessage: effect.Schema.optional(CommitMessage),
|
|
79
|
+
config: effect.Schema.optional(PromptConfig),
|
|
80
|
+
content: PromptContent
|
|
81
|
+
});
|
|
82
|
+
effect.Schema.Struct({
|
|
83
|
+
description: effect.Schema.optional(PromptDescription),
|
|
84
|
+
id: effect.Schema.optional(PromptId),
|
|
85
|
+
name: effect.Schema.optional(PromptName)
|
|
86
|
+
});
|
|
87
|
+
effect.Schema.Struct({
|
|
88
|
+
channel: ChannelName,
|
|
89
|
+
version: VersionNumber
|
|
90
|
+
});
|
|
91
|
+
effect.Schema.Struct({
|
|
92
|
+
channel: effect.Schema.optional(ChannelName),
|
|
93
|
+
version: effect.Schema.optional(VersionNumber)
|
|
94
|
+
});
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region ../schema/src/domain/errors.ts
|
|
97
|
+
var NotFound = class extends effect.Schema.TaggedError()("NotFound", { message: effect.Schema.String }, _effect_platform.HttpApiSchema.annotations({ status: 404 })) {};
|
|
98
|
+
var Conflict = class extends effect.Schema.TaggedError()("Conflict", { message: effect.Schema.String }, _effect_platform.HttpApiSchema.annotations({ status: 409 })) {};
|
|
99
|
+
var BadRequest = class extends effect.Schema.TaggedError()("BadRequest", { message: effect.Schema.String }, _effect_platform.HttpApiSchema.annotations({ status: 400 })) {};
|
|
100
|
+
var Unauthorized = class extends effect.Schema.TaggedError()("Unauthorized", { message: effect.Schema.String }, _effect_platform.HttpApiSchema.annotations({ status: 401 })) {};
|
|
101
|
+
var Forbidden = class extends effect.Schema.TaggedError()("Forbidden", { message: effect.Schema.String }, _effect_platform.HttpApiSchema.annotations({ status: 403 })) {};
|
|
102
|
+
effect.Schema.TaggedError()("InternalError", { message: effect.Schema.String }, _effect_platform.HttpApiSchema.annotations({ status: 500 }));
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region ../schema/src/internal/authentication.ts
|
|
105
|
+
var CurrentActor = class extends effect.Context.Tag("@anpord/schema/CurrentActor")() {};
|
|
106
|
+
_effect_platform.HttpApiMiddleware.Tag()("@anpord/schema/Authentication", {
|
|
107
|
+
failure: Unauthorized,
|
|
108
|
+
provides: CurrentActor,
|
|
109
|
+
security: { session: _effect_platform.HttpApiSecurity.apiKey({
|
|
110
|
+
in: "cookie",
|
|
111
|
+
key: "anpord.session_token"
|
|
112
|
+
}) }
|
|
113
|
+
});
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region ../schema/src/public/authentication.ts
|
|
116
|
+
var ApiKeyAuthentication = class extends _effect_platform.HttpApiMiddleware.Tag()("@anpord/schema/ApiKeyAuthentication", {
|
|
117
|
+
failure: Unauthorized,
|
|
118
|
+
provides: CurrentActor,
|
|
119
|
+
security: { bearer: _effect_platform.HttpApiSecurity.bearer }
|
|
120
|
+
}) {};
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region ../schema/src/public/evals-api.ts
|
|
123
|
+
const EvalRunRequest = effect.Schema.Struct({ id: effect.Schema.String }).annotations({
|
|
124
|
+
description: "Select an eval run by id.",
|
|
125
|
+
identifier: "EvalRunRequest"
|
|
126
|
+
});
|
|
127
|
+
const EvalCellRequest = effect.Schema.Struct({ cellKey: effect.Schema.String }).annotations({
|
|
128
|
+
description: "Select an eval cell by its stable key.",
|
|
129
|
+
identifier: "EvalCellRequest"
|
|
130
|
+
});
|
|
131
|
+
const EvalModelsRequest = effect.Schema.Struct({
|
|
132
|
+
harness: require_evals.EvalHarness,
|
|
133
|
+
q: effect.Schema.optional(effect.Schema.String)
|
|
134
|
+
}).annotations({
|
|
135
|
+
description: "Select a harness whose available models should be listed.",
|
|
136
|
+
identifier: "EvalModelsRequest"
|
|
137
|
+
});
|
|
138
|
+
const PublicEvalSandbox = require_evals.EvalSandbox.annotations({
|
|
139
|
+
description: "The hosted sandbox a task runs in.",
|
|
140
|
+
identifier: "PublicEvalSandbox"
|
|
141
|
+
});
|
|
142
|
+
const ListEvalsRequest = effect.Schema.Struct({
|
|
143
|
+
cursor: effect.Schema.optional(effect.Schema.NullOr(require_evals.EvalPageCursor)),
|
|
144
|
+
limit: effect.Schema.optional(effect.Schema.Int)
|
|
145
|
+
}).annotations({
|
|
146
|
+
description: "Where to read from, and how much.",
|
|
147
|
+
identifier: "ListEvalsRequest"
|
|
148
|
+
});
|
|
149
|
+
const PublicEvalCase = effect.Schema.Struct({
|
|
150
|
+
cache: effect.Schema.optional(require_evals.CaseCache),
|
|
151
|
+
name: require_evals.EvalCaseName,
|
|
152
|
+
prepare: effect.Schema.optional(effect.Schema.NullOr(require_evals.EvalPrepare)),
|
|
153
|
+
source: effect.Schema.optional(require_evals.EvalSource),
|
|
154
|
+
validator: effect.Schema.optional(effect.Schema.NullOr(require_evals.EvalValidator)),
|
|
155
|
+
variables: effect.Schema.optional(require_evals.EvalVariables),
|
|
156
|
+
verify: effect.Schema.NullOr(require_evals.EvalVerify)
|
|
157
|
+
}).pipe(effect.Schema.filter(({ validator, verify }) => !(validator !== void 0 && validator !== null && verify !== null), { message: () => "Use either validator or verify, not both." })).annotations({
|
|
158
|
+
description: "A task, workspace source, setup command, and verifier.",
|
|
159
|
+
identifier: "StartEvalCase"
|
|
160
|
+
});
|
|
161
|
+
const PublicEvalTask = effect.Schema.Struct({
|
|
162
|
+
harness: require_evals.EvalHarness,
|
|
163
|
+
model: effect.Schema.String.pipe(effect.Schema.minLength(1)),
|
|
164
|
+
profile: effect.Schema.optional(require_evals.HarnessProfile),
|
|
165
|
+
sandbox: effect.Schema.optional(PublicEvalSandbox)
|
|
166
|
+
}).pipe(effect.Schema.filter(require_evals.profileFitsHarness, { message: () => require_evals.PROFILE_HARNESS_RULE })).annotations({
|
|
167
|
+
description: `A harness and model, with an optional sandbox and an optional profile layered on the harness. Omit the sandbox to use the default. ${require_evals.PROFILE_HARNESS_RULE}`,
|
|
168
|
+
identifier: "StartEvalTask"
|
|
169
|
+
});
|
|
170
|
+
const PublicStartEvalRequest = effect.Schema.Struct({
|
|
171
|
+
trigger: effect.Schema.optional(require_evals.EvalTrigger),
|
|
172
|
+
cases: effect.Schema.Array(PublicEvalCase).pipe(effect.Schema.minItems(1), effect.Schema.maxItems(100)),
|
|
173
|
+
name: effect.Schema.optional(require_evals.EvalName),
|
|
174
|
+
prompt: require_evals.EvalPrompt,
|
|
175
|
+
tasks: effect.Schema.Array(PublicEvalTask).pipe(effect.Schema.minItems(1), effect.Schema.maxItems(20)),
|
|
176
|
+
trials: effect.Schema.Int.pipe(effect.Schema.between(1, 10))
|
|
177
|
+
}).annotations({
|
|
178
|
+
description: `Start a grid with at most 100 total case, task, and trial combinations.`,
|
|
179
|
+
identifier: "StartEvalRequest"
|
|
180
|
+
});
|
|
181
|
+
var PublicEvalsGroup = class extends _effect_platform.HttpApiGroup.make("evals").add(_effect_platform.HttpApiEndpoint.post("list", "/evals.list").setPayload(ListEvalsRequest).addSuccess(require_evals.EvalRunPage).annotate(_effect_platform.OpenApi.Summary, "List eval runs").annotate(_effect_platform.OpenApi.Description, "Newest first. Pass the `next` cursor from a response to read the page after it; a null `next` means there are no more.")).add(_effect_platform.HttpApiEndpoint.post("start", "/evals.start").setPayload(PublicStartEvalRequest).addSuccess(require_evals.StartedEval).annotate(_effect_platform.OpenApi.Summary, "Start an eval run").annotate(_effect_platform.OpenApi.Description, `Starts the grid and returns its id while trials continue in the background. ${require_evals.PROFILE_HARNESS_RULE}`)).add(_effect_platform.HttpApiEndpoint.post("get", "/evals.get").setPayload(EvalRunRequest).addSuccess(require_evals.EvalRun).annotate(_effect_platform.OpenApi.Summary, "Get an eval run")).add(_effect_platform.HttpApiEndpoint.post("cellHistory", "/evals.cellHistory").setPayload(EvalCellRequest).addSuccess(effect.Schema.Array(require_evals.EvalCellHistoryEntry)).annotate(_effect_platform.OpenApi.Summary, "List a cell's history").annotate(_effect_platform.OpenApi.Description, "Returns the 20 most recent results.")).add(_effect_platform.HttpApiEndpoint.post("rerunCell", "/evals.rerunCell").setPayload(effect.Schema.extend(EvalRunRequest, effect.Schema.extend(EvalCellRequest, require_evals.RerunCellRequest))).addSuccess(require_evals.StartedEval).annotate(_effect_platform.OpenApi.Summary, "Rerun one cell")).add(_effect_platform.HttpApiEndpoint.post("models", "/evals.models").setPayload(EvalModelsRequest).addSuccess(require_evals.ModelCatalogue).annotate(_effect_platform.OpenApi.Summary, "List models available to the harness").annotate(_effect_platform.OpenApi.Description, "The command harness has no catalogue of its own, so its list is empty: the model is whatever the profile's run command reads from ANPORD_MODEL.")).addError(BadRequest).addError(Conflict).addError(Forbidden).addError(NotFound).middleware(ApiKeyAuthentication).annotate(_effect_platform.OpenApi.Title, "Evals").annotate(_effect_platform.OpenApi.Description, "Run cases across harness, model, and sandbox combinations and compare the results with their baselines.") {};
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region ../schema/src/public/requests.ts
|
|
184
|
+
const GetPromptRequest = effect.Schema.Struct({
|
|
185
|
+
channel: effect.Schema.optional(ChannelName),
|
|
186
|
+
id: PromptId,
|
|
187
|
+
includeVersions: effect.Schema.optional(effect.Schema.Boolean),
|
|
188
|
+
version: effect.Schema.optional(VersionNumber)
|
|
189
|
+
}).annotations({
|
|
190
|
+
description: "Resolve a prompt. Give a version to pin one, a channel to follow one, or neither for the organization's default channel.",
|
|
191
|
+
identifier: "GetPromptRequest"
|
|
192
|
+
});
|
|
193
|
+
effect.Schema.Struct({ id: PromptId }).annotations({
|
|
194
|
+
description: "Show a prompt's version history.",
|
|
195
|
+
identifier: "ListVersionsRequest"
|
|
196
|
+
});
|
|
197
|
+
const ListPromptsRequest = effect.Schema.Record({
|
|
198
|
+
key: effect.Schema.String,
|
|
199
|
+
value: effect.Schema.Never
|
|
200
|
+
}).annotations({
|
|
201
|
+
description: "No parameters; returns up to 100 prompts in the organization.",
|
|
202
|
+
identifier: "ListPromptsRequest"
|
|
203
|
+
});
|
|
204
|
+
const CreatePromptRequest = effect.Schema.Struct({
|
|
205
|
+
config: effect.Schema.optional(PromptConfig),
|
|
206
|
+
content: PromptContent,
|
|
207
|
+
description: effect.Schema.optional(effect.Schema.String),
|
|
208
|
+
id: PromptId,
|
|
209
|
+
message: effect.Schema.optional(CommitMessage),
|
|
210
|
+
name: PromptName
|
|
211
|
+
}).annotations({
|
|
212
|
+
description: "Create a prompt and publish its first version to the default channel.",
|
|
213
|
+
identifier: "CreatePromptRequest"
|
|
214
|
+
});
|
|
215
|
+
const UpdatePromptRequest = effect.Schema.Struct({
|
|
216
|
+
config: effect.Schema.optional(PromptConfig),
|
|
217
|
+
content: PromptContent,
|
|
218
|
+
id: PromptId,
|
|
219
|
+
message: effect.Schema.optional(CommitMessage)
|
|
220
|
+
}).annotations({
|
|
221
|
+
description: "Add a version to a prompt. The new version becomes latest, and omitted config is stored as an empty object.",
|
|
222
|
+
identifier: "UpdatePromptRequest"
|
|
223
|
+
});
|
|
224
|
+
const PromotePromptRequest = effect.Schema.Struct({
|
|
225
|
+
channel: ChannelName,
|
|
226
|
+
id: PromptId,
|
|
227
|
+
version: VersionNumber
|
|
228
|
+
}).annotations({
|
|
229
|
+
description: "Point a channel at a version.",
|
|
230
|
+
identifier: "PromotePromptRequest"
|
|
231
|
+
});
|
|
232
|
+
effect.Schema.Struct({ id: PromptId }).annotations({
|
|
233
|
+
description: "Archive a prompt. Existing selectors stay readable.",
|
|
234
|
+
identifier: "ArchivePromptRequest"
|
|
235
|
+
});
|
|
236
|
+
const Ok = effect.Schema.Struct({ ok: effect.Schema.Literal(true) }).annotations({
|
|
237
|
+
description: "The operation succeeded.",
|
|
238
|
+
identifier: "Ok"
|
|
239
|
+
});
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region ../schema/src/public/shapes.ts
|
|
242
|
+
const Instant = effect.Schema.DateTimeUtc.annotations({
|
|
243
|
+
description: "An ISO-8601 timestamp in UTC.",
|
|
244
|
+
identifier: "Instant",
|
|
245
|
+
jsonSchema: { format: "date-time" }
|
|
246
|
+
});
|
|
247
|
+
const PublicPrompt = effect.Schema.Struct({
|
|
248
|
+
channel: effect.Schema.NullOr(ChannelName),
|
|
249
|
+
config: PromptConfig,
|
|
250
|
+
content: effect.Schema.String,
|
|
251
|
+
createdAt: Instant,
|
|
252
|
+
id: PromptId,
|
|
253
|
+
message: effect.Schema.NullOr(CommitMessage),
|
|
254
|
+
name: PromptName,
|
|
255
|
+
version: VersionNumber
|
|
256
|
+
}).annotations({
|
|
257
|
+
description: "A prompt resolved at a specific version.",
|
|
258
|
+
identifier: "ResolvedPrompt"
|
|
259
|
+
});
|
|
260
|
+
const PublicVersion = effect.Schema.Struct({
|
|
261
|
+
createdAt: Instant,
|
|
262
|
+
message: effect.Schema.NullOr(CommitMessage),
|
|
263
|
+
version: VersionNumber
|
|
264
|
+
}).annotations({
|
|
265
|
+
description: "One entry in a prompt's history.",
|
|
266
|
+
identifier: "Version"
|
|
267
|
+
});
|
|
268
|
+
const PublicPromptWithVersions = effect.Schema.extend(PublicPrompt, effect.Schema.Struct({ versions: effect.Schema.optional(effect.Schema.Array(PublicVersion)) })).annotations({
|
|
269
|
+
description: "A prompt, with its version history when `includeVersions` is set.",
|
|
270
|
+
identifier: "Prompt"
|
|
271
|
+
});
|
|
272
|
+
const PublicPromptSummary = effect.Schema.Struct({
|
|
273
|
+
id: PromptId,
|
|
274
|
+
latestVersion: effect.Schema.NullOr(VersionNumber),
|
|
275
|
+
name: PromptName,
|
|
276
|
+
productionVersion: effect.Schema.NullOr(VersionNumber),
|
|
277
|
+
updatedAt: Instant
|
|
278
|
+
}).annotations({
|
|
279
|
+
description: "A prompt without its content.",
|
|
280
|
+
identifier: "PromptSummary"
|
|
281
|
+
});
|
|
282
|
+
const PromptList = effect.Schema.Struct({ data: effect.Schema.Array(PublicPromptSummary) }).annotations({
|
|
283
|
+
description: "Every prompt in the organization.",
|
|
284
|
+
identifier: "PromptList"
|
|
285
|
+
});
|
|
286
|
+
//#endregion
|
|
287
|
+
//#region ../schema/src/public/prompts-api.ts
|
|
288
|
+
var PublicPromptsGroup = class extends _effect_platform.HttpApiGroup.make("prompts").add(_effect_platform.HttpApiEndpoint.post("get", "/prompts.get").setPayload(GetPromptRequest).addSuccess(PublicPromptWithVersions).annotate(_effect_platform.OpenApi.Summary, "Resolve a prompt").annotate(_effect_platform.OpenApi.Description, "Returns the content a caller should send to a model. With no selector this follows the organization's default channel.")).add(_effect_platform.HttpApiEndpoint.post("list", "/prompts.list").setPayload(ListPromptsRequest).addSuccess(PromptList).annotate(_effect_platform.OpenApi.Summary, "List prompts").annotate(_effect_platform.OpenApi.Description, "Up to 100 prompts in the organization, without content.")).add(_effect_platform.HttpApiEndpoint.post("create", "/prompts.create").setPayload(CreatePromptRequest).addSuccess(PublicPromptWithVersions).annotate(_effect_platform.OpenApi.Summary, "Create a prompt").annotate(_effect_platform.OpenApi.Description, "Creates the prompt and its first version in one call.")).add(_effect_platform.HttpApiEndpoint.post("update", "/prompts.update").setPayload(UpdatePromptRequest).addSuccess(PublicPromptWithVersions).annotate(_effect_platform.OpenApi.Summary, "Add a version").annotate(_effect_platform.OpenApi.Description, "Content is versioned, so updating a prompt appends a version rather than overwriting one. Earlier versions stay readable.")).add(_effect_platform.HttpApiEndpoint.post("promote", "/prompts.promote").setPayload(PromotePromptRequest).addSuccess(Ok).annotate(_effect_platform.OpenApi.Summary, "Promote a version to a channel").annotate(_effect_platform.OpenApi.Description, "Points a channel, such as production, at a version. This is how a version goes live without callers changing anything.")).addError(BadRequest).addError(Forbidden).addError(Conflict).addError(NotFound).middleware(ApiKeyAuthentication).annotate(_effect_platform.OpenApi.Title, "Prompts").annotate(_effect_platform.OpenApi.Description, "Read and write prompts. Content is versioned, so writes append rather than overwrite, and channels decide which version callers receive.") {};
|
|
289
|
+
//#endregion
|
|
290
|
+
//#region ../schema/src/public/api.ts
|
|
291
|
+
var PublicApi = class extends _effect_platform.HttpApi.make("anpord-public").add(PublicEvalsGroup).add(PublicPromptsGroup).prefix("/v1").annotate(_effect_platform.OpenApi.Title, "Anpord API").annotate(_effect_platform.OpenApi.Version, "1.0.0").annotate(_effect_platform.OpenApi.Description, "Run agent evals and manage prompts. Every endpoint takes a JSON body over POST and authenticates with a bearer API key.").annotate(_effect_platform.OpenApi.Servers, [{
|
|
292
|
+
description: "Production",
|
|
293
|
+
url: "https://api.anpord.com"
|
|
294
|
+
}]) {};
|
|
295
|
+
//#endregion
|
|
296
|
+
//#region ../schema/src/public/client.ts
|
|
297
|
+
const DEFAULT_BASE_URL = "https://api.anpord.com";
|
|
298
|
+
const make = ({ apiKey, baseUrl = DEFAULT_BASE_URL }) => _effect_platform.HttpApiClient.make(PublicApi, {
|
|
299
|
+
baseUrl,
|
|
300
|
+
transformClient: _effect_platform.HttpClient.mapRequest(_effect_platform.HttpClientRequest.bearerToken(effect.Redacted.value(apiKey)))
|
|
301
|
+
});
|
|
302
|
+
var AnpordApi = class extends effect.Effect.Tag("@anpord/sdk/AnpordApi")() {};
|
|
303
|
+
const layer = (options) => effect.Layer.effect(AnpordApi, make(options)).pipe(effect.Layer.provide(_effect_platform.FetchHttpClient.layer));
|
|
304
|
+
//#endregion
|
|
305
|
+
Object.defineProperty(exports, "AnpordApi", {
|
|
306
|
+
enumerable: true,
|
|
307
|
+
get: function() {
|
|
308
|
+
return AnpordApi;
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
Object.defineProperty(exports, "ChannelName", {
|
|
312
|
+
enumerable: true,
|
|
313
|
+
get: function() {
|
|
314
|
+
return ChannelName;
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
Object.defineProperty(exports, "DEFAULT_BASE_URL", {
|
|
318
|
+
enumerable: true,
|
|
319
|
+
get: function() {
|
|
320
|
+
return DEFAULT_BASE_URL;
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
Object.defineProperty(exports, "PromptId", {
|
|
324
|
+
enumerable: true,
|
|
325
|
+
get: function() {
|
|
326
|
+
return PromptId;
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
Object.defineProperty(exports, "VersionNumber", {
|
|
330
|
+
enumerable: true,
|
|
331
|
+
get: function() {
|
|
332
|
+
return VersionNumber;
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
Object.defineProperty(exports, "layer", {
|
|
336
|
+
enumerable: true,
|
|
337
|
+
get: function() {
|
|
338
|
+
return layer;
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
Object.defineProperty(exports, "make", {
|
|
342
|
+
enumerable: true,
|
|
343
|
+
get: function() {
|
|
344
|
+
return make;
|
|
345
|
+
}
|
|
346
|
+
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { S as EvalSourceFiles, _ as HarnessProfile, b as ProfilePath, d as EvalValidator, g as EnvName, x as profileFitsHarness, y as PROFILE_LIMITS } from "./evals-Dcc_x6jW.mjs";
|
|
2
|
+
import { t as EvalJudge } from "./eval-judges-CwTvTq7N.mjs";
|
|
2
3
|
import { a as parseRepo, i as cloneUrlOf, r as repo } from "./source-Fg1h2VNn.mjs";
|
|
3
|
-
import { Data, Effect, Option, Schema } from "effect";
|
|
4
|
-
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
|
+
import { Config, Data, Effect, Option, Schema } from "effect";
|
|
5
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
6
|
import { existsSync, realpathSync } from "node:fs";
|
|
6
7
|
import { mkdtemp, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
7
8
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
@@ -11,12 +12,58 @@ import { tmpdir } from "node:os";
|
|
|
11
12
|
import { execFile } from "node:child_process";
|
|
12
13
|
import { promisify } from "node:util";
|
|
13
14
|
import { parse, stringify } from "smol-toml";
|
|
15
|
+
//#region src/evals/source-files.ts
|
|
16
|
+
const CODE_FILE = /\.(?:[cm]?[jt]s|[jt]sx)$/;
|
|
17
|
+
const sdkRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
18
|
+
const SourceMap = Schema.parseJson(Schema.Struct({
|
|
19
|
+
version: Schema.Literal(3),
|
|
20
|
+
sources: Schema.Array(Schema.String),
|
|
21
|
+
sourcesContent: Schema.Array(Schema.NullOr(Schema.String))
|
|
22
|
+
}));
|
|
23
|
+
const projectRoot = (entry) => {
|
|
24
|
+
let directory = dirname(entry);
|
|
25
|
+
while (!existsSync(resolve(directory, "package.json"))) {
|
|
26
|
+
const parent = dirname(directory);
|
|
27
|
+
if (parent === directory) return dirname(entry);
|
|
28
|
+
directory = parent;
|
|
29
|
+
}
|
|
30
|
+
return directory;
|
|
31
|
+
};
|
|
32
|
+
const sourceFiles = (map, entry) => {
|
|
33
|
+
const decoded = Schema.decodeUnknownSync(SourceMap)(map);
|
|
34
|
+
const root = realpathSync(projectRoot(entry));
|
|
35
|
+
const entryPath = relative(root, realpathSync(entry)).split(sep).join("/");
|
|
36
|
+
const files = decoded.sources.flatMap((source, index) => {
|
|
37
|
+
const absolute = resolve(dirname(entry), source);
|
|
38
|
+
const path = relative(root, absolute).split(sep).join("/");
|
|
39
|
+
const content = decoded.sourcesContent[index];
|
|
40
|
+
if (content == null || path.startsWith("../") || path.split("/").includes("node_modules") || absolute.startsWith(`${sdkRoot}${sep}`) || !CODE_FILE.test(path) || source.includes(":") || basename(path) === "anpord-eval-entry.ts") return [];
|
|
41
|
+
return [{
|
|
42
|
+
path,
|
|
43
|
+
content
|
|
44
|
+
}];
|
|
45
|
+
});
|
|
46
|
+
return Schema.decodeUnknownSync(EvalSourceFiles)(files.toSorted((a, b) => Number(b.path === entryPath) - Number(a.path === entryPath) || a.path.localeCompare(b.path)));
|
|
47
|
+
};
|
|
48
|
+
//#endregion
|
|
14
49
|
//#region src/evals/eval-bundle.ts
|
|
15
50
|
const authoringExports = ["export const defineEval = value => value;", `export { empty, files, repo } from "./source";`].join("\n");
|
|
16
51
|
const authoringDir = dirname(fileURLToPath(import.meta.url));
|
|
17
52
|
const ANPORD_MODULE = /^anpord$/;
|
|
18
53
|
const ANY_MODULE = /.*/;
|
|
19
54
|
const localModules = [
|
|
55
|
+
{
|
|
56
|
+
built: "validator-runtime.mjs",
|
|
57
|
+
filter: /^anpord\/validators\/runtime$/,
|
|
58
|
+
namespace: "anpord-validator-runtime",
|
|
59
|
+
source: "validator-runtime.ts"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
built: "validators.mjs",
|
|
63
|
+
filter: /^anpord\/validators$/,
|
|
64
|
+
namespace: "anpord-validators",
|
|
65
|
+
source: "../validators.ts"
|
|
66
|
+
},
|
|
20
67
|
{
|
|
21
68
|
built: "cli.mjs",
|
|
22
69
|
filter: /^anpord\/cli$/,
|
|
@@ -84,6 +131,8 @@ const bundle = (contents, entry, options = {}) => Effect.tryPromise({
|
|
|
84
131
|
format: "esm",
|
|
85
132
|
metafile: true,
|
|
86
133
|
minify: options.minify,
|
|
134
|
+
outfile: resolve(dirname(entry), "anpord-bundle.mjs"),
|
|
135
|
+
sourcemap: options.captureSource ? "external" : false,
|
|
87
136
|
platform: "node",
|
|
88
137
|
resolveExtensions: [
|
|
89
138
|
".ts",
|
|
@@ -103,7 +152,8 @@ const bundle = (contents, entry, options = {}) => Effect.tryPromise({
|
|
|
103
152
|
write: false
|
|
104
153
|
}).then((result) => ({
|
|
105
154
|
inputs: Object.keys(result.metafile?.inputs ?? {}).map((path) => resolve(path)),
|
|
106
|
-
source: result.outputFiles
|
|
155
|
+
source: result.outputFiles.find((file) => file.path.endsWith(".mjs"))?.text ?? "",
|
|
156
|
+
...options.captureSource ? { sourceFiles: sourceFiles(result.outputFiles.find((file) => file.path.endsWith(".map"))?.text ?? "", entry) } : {}
|
|
107
157
|
})),
|
|
108
158
|
catch: (cause) => new Error(`Could not compile ${entry}`, { cause })
|
|
109
159
|
});
|
|
@@ -152,51 +202,12 @@ const packageProgram = (root, entry, source) => {
|
|
|
152
202
|
};
|
|
153
203
|
//#endregion
|
|
154
204
|
//#region src/evals/runner-source.ts
|
|
155
|
-
const
|
|
156
|
-
import {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
let stderr = "";
|
|
162
|
-
let stdout = "";
|
|
163
|
-
child.stderr.on("data", chunk => { stderr += chunk; });
|
|
164
|
-
child.stdout.on("data", chunk => { stdout += chunk; });
|
|
165
|
-
child.on("error", reject);
|
|
166
|
-
child.on("close", code => resolve({ exitCode: code ?? 1, stderr, stdout }));
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
const readOrEmpty = (path) =>
|
|
170
|
-
path === undefined ? Promise.resolve("") : readFile(path, "utf8").then(text => text, () => "");
|
|
171
|
-
|
|
172
|
-
const calls = async (path, key, value) => {
|
|
173
|
-
const text = await readOrEmpty(path);
|
|
174
|
-
const calls = text.trim() === "" ? [] : text.trim().split("\\n").map((line) => JSON.parse(line));
|
|
175
|
-
return value === undefined ? calls : calls.filter((call) => call[key] === value);
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
const context = {
|
|
179
|
-
answer: () => readOrEmpty(process.env.ANPORD_ANSWER_FILE),
|
|
180
|
-
cli: { calls: cli => calls(".anpord/cli-calls.jsonl", "cli", cli) },
|
|
181
|
-
exec,
|
|
182
|
-
exists: path => access(path).then(() => true, () => false),
|
|
183
|
-
mcp: { calls: server => calls(".anpord/mcp-calls.jsonl", "server", server) },
|
|
184
|
-
readText: path => readFile(path, "utf8"),
|
|
185
|
-
prepared: JSON.parse(process.env.ANPORD_PREPARE_VALUE ?? "{}"),
|
|
186
|
-
transcript: () => readOrEmpty(process.env.ANPORD_TRANSCRIPT_FILE),
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
try {
|
|
190
|
-
const raw = await validate(context);
|
|
191
|
-
const result = typeof raw === "boolean" ? { passed: raw } : raw;
|
|
192
|
-
if (typeof result?.passed !== "boolean") throw new Error("A validator must return a boolean or { passed, message? }");
|
|
193
|
-
console.log("ANPORD_VALIDATOR_RESULT=" + JSON.stringify(result));
|
|
194
|
-
} catch (error) {
|
|
195
|
-
console.error(error instanceof Error ? error.stack : String(error));
|
|
196
|
-
process.exitCode = 1;
|
|
197
|
-
}
|
|
198
|
-
`;
|
|
199
|
-
const validatorEntry = (module, name) => `import { ${name} as validate } from ${JSON.stringify(module)};\n${runtime}`;
|
|
205
|
+
const validatorCaseEntry = (entry, index, names = []) => `import definition from ${JSON.stringify(entry)};
|
|
206
|
+
import { runValidators } from "anpord/validators/runtime";
|
|
207
|
+
const selected = definition.cases[${index}].validate;
|
|
208
|
+
const names = ${JSON.stringify(names)};
|
|
209
|
+
const checks = (Array.isArray(selected) ? selected : [selected]).flatMap((validate, index) => typeof validate === "function" ? [{ index, name: names.find(check => check.index === index)?.name ?? "Validator " + (index + 1), validate }] : []);
|
|
210
|
+
await runValidators(checks, definition.captureValidation !== false);`;
|
|
200
211
|
const prepareRuntime = `
|
|
201
212
|
import { access, readFile } from "node:fs/promises";
|
|
202
213
|
import { spawn } from "node:child_process";
|
|
@@ -247,11 +258,12 @@ import { runMcpServer } from "anpord/mcp/runtime";
|
|
|
247
258
|
const server = definition.mcp?.[${index}];
|
|
248
259
|
if (server === undefined) throw new Error("MCP server ${index} is missing");
|
|
249
260
|
runMcpServer(server);`;
|
|
250
|
-
const cliEntry = (entry, index) => `import
|
|
261
|
+
const cliEntry = (entry, index) => `import { fileURLToPath } from "node:url";
|
|
262
|
+
import definition from ${JSON.stringify(entry)};
|
|
251
263
|
import { runCli } from "anpord/cli/runtime";
|
|
252
264
|
const cli = definition.cli?.[${index}];
|
|
253
265
|
if (cli === undefined) throw new Error("CLI ${index} is missing");
|
|
254
|
-
await runCli(cli);`;
|
|
266
|
+
await runCli(cli, fileURLToPath(new URL("../../cli-calls.jsonl", import.meta.url)));`;
|
|
255
267
|
//#endregion
|
|
256
268
|
//#region src/evals/cli-profile.ts
|
|
257
269
|
const compileClis = (entry, definitions) => Effect.gen(function* () {
|
|
@@ -287,6 +299,40 @@ const withClis = (task, clis) => {
|
|
|
287
299
|
};
|
|
288
300
|
};
|
|
289
301
|
//#endregion
|
|
302
|
+
//#region src/evals/compile-validator.ts
|
|
303
|
+
const compileValidator = (entry, subject, caseIndex, captureSource, captureValidation = true) => Effect.gen(function* () {
|
|
304
|
+
if (subject.validate === void 0) return null;
|
|
305
|
+
const validations = Array.isArray(subject.validate) ? subject.validate : [subject.validate];
|
|
306
|
+
if (validations.length === 0 || validations.length > 20) return yield* Effect.fail(/* @__PURE__ */ new Error("Use between 1 and 20 validators"));
|
|
307
|
+
const judges = yield* Effect.forEach(validations.filter((value) => typeof value !== "function"), (value) => Schema.decodeUnknown(EvalJudge)(value, { onExcessProperty: "error" }));
|
|
308
|
+
if (new Set(judges.map(({ name }) => name)).size !== judges.length) return yield* Effect.fail(/* @__PURE__ */ new Error("Judge names must be unique within a case"));
|
|
309
|
+
const manifest = validations.flatMap((value, index) => typeof value === "function" ? [{
|
|
310
|
+
index,
|
|
311
|
+
name: value.name || `Validator ${index + 1}`
|
|
312
|
+
}] : []);
|
|
313
|
+
const hasCode = manifest.length > 0;
|
|
314
|
+
const compiled = yield* bundle(hasCode ? validatorCaseEntry(entry, caseIndex, manifest) : definitionEntry(entry), entry, {
|
|
315
|
+
minify: true,
|
|
316
|
+
captureSource
|
|
317
|
+
});
|
|
318
|
+
const checks = hasCode ? [{
|
|
319
|
+
name: typeof subject.validate === "function" ? subject.validate.name || subject.name : subject.name,
|
|
320
|
+
source: compiled.source,
|
|
321
|
+
manifest,
|
|
322
|
+
capture: captureValidation
|
|
323
|
+
}] : [];
|
|
324
|
+
return yield* Schema.decodeUnknown(EvalValidator)({
|
|
325
|
+
...judges.length > 0 ? {
|
|
326
|
+
kind: "judged",
|
|
327
|
+
name: subject.name,
|
|
328
|
+
checks,
|
|
329
|
+
judges
|
|
330
|
+
} : checks[0],
|
|
331
|
+
sourceFiles: compiled.sourceFiles,
|
|
332
|
+
capture: captureValidation
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
//#endregion
|
|
290
336
|
//#region src/evals/definition-loader.ts
|
|
291
337
|
const loadDefinition = (entry) => bundle(definitionEntry(entry), entry).pipe(Effect.flatMap(({ inputs, source }) => Effect.acquireUseRelease(Effect.tryPromise(() => mkdtemp(join(tmpdir(), "anpord-eval-"))), (directory) => Effect.tryPromise({
|
|
292
338
|
try: async () => {
|
|
@@ -315,26 +361,25 @@ const isDefinition = (value) => Option.isSome(decodeShape(value));
|
|
|
315
361
|
//#region src/evals/local-repo.ts
|
|
316
362
|
const run = promisify(execFile);
|
|
317
363
|
const git = (args, cwd) => Effect.tryPromise(() => run("git", [...args], { cwd })).pipe(Effect.map(({ stdout }) => stdout.trim()), Effect.orElseSucceed(() => ""));
|
|
318
|
-
const environment = () => globalThis.process?.env ?? {};
|
|
319
364
|
const remoteUrl = (cwd) => Effect.gen(function* () {
|
|
320
|
-
const
|
|
365
|
+
const repository = yield* Config.string("GITHUB_REPOSITORY").pipe(Config.withDefault(""));
|
|
321
366
|
const origin = yield* git([
|
|
322
367
|
"remote",
|
|
323
368
|
"get-url",
|
|
324
369
|
"origin"
|
|
325
370
|
], cwd);
|
|
326
|
-
return origin === ""
|
|
371
|
+
return origin === "" ? repository : origin;
|
|
327
372
|
});
|
|
328
373
|
const fetchableRef = (cwd) => Effect.gen(function* () {
|
|
329
|
-
const
|
|
330
|
-
if (GITHUB_HEAD_REF !== void 0 && GITHUB_HEAD_REF !== "") return GITHUB_HEAD_REF;
|
|
374
|
+
const ci = yield* Config.boolean("GITHUB_ACTIONS").pipe(Config.withDefault(false));
|
|
331
375
|
const [head, onRemote] = yield* Effect.all([git(["rev-parse", "HEAD"], cwd), git([
|
|
332
376
|
"branch",
|
|
333
377
|
"--remotes",
|
|
334
378
|
"--contains",
|
|
335
379
|
"HEAD"
|
|
336
380
|
], cwd)], { concurrency: 2 });
|
|
337
|
-
|
|
381
|
+
if (ci && head === "") return yield* Effect.fail(/* @__PURE__ */ new Error("Check out the commit before running evals in GitHub Actions."));
|
|
382
|
+
return head === "" || !ci && onRemote === "" ? null : head;
|
|
338
383
|
});
|
|
339
384
|
const localRepo = (cwd) => Effect.gen(function* () {
|
|
340
385
|
const [remote, ref] = yield* Effect.all([remoteUrl(cwd), fetchableRef(cwd)], { concurrency: 2 });
|
|
@@ -542,14 +587,6 @@ const decodeManifest = (dir, text) => Schema.decodeUnknown(ManifestJson)(text).p
|
|
|
542
587
|
dir,
|
|
543
588
|
reason: issue.message
|
|
544
589
|
})));
|
|
545
|
-
/**
|
|
546
|
-
* A manifest value that names a regular file is replaced by that file's
|
|
547
|
-
* content; anything else is kept as written. Env values are always literal.
|
|
548
|
-
*
|
|
549
|
-
* A file outside the profile directory is refused rather than read: the
|
|
550
|
-
* manifest is shipped with the profile, and a prompt that only exists on one
|
|
551
|
-
* machine is not part of it.
|
|
552
|
-
*/
|
|
553
590
|
const inlined = (dir, value) => Effect.gen(function* () {
|
|
554
591
|
const target = resolve(dir, value);
|
|
555
592
|
const position = relative(dir, target);
|
|
@@ -589,7 +626,6 @@ const readProfileManifest = (dir) => Effect.gen(function* () {
|
|
|
589
626
|
const SHIPPED_ROOTS = ["home", "workspace"];
|
|
590
627
|
const SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set(["node_modules", ".git"]);
|
|
591
628
|
const isMissing = (cause) => cause instanceof Error && "code" in cause && cause.code === "ENOENT";
|
|
592
|
-
/** Every regular file below `current`, as a posix path relative to `dir`. */
|
|
593
629
|
const walk = async (dir, current) => {
|
|
594
630
|
const entries = await readdir(current, { withFileTypes: true });
|
|
595
631
|
return (await Promise.all(entries.map((entry) => {
|
|
@@ -612,7 +648,7 @@ const shippedPaths = (dir) => Effect.tryPromise({
|
|
|
612
648
|
}
|
|
613
649
|
});
|
|
614
650
|
const validPath = (path) => Schema.decodeUnknown(ProfilePath)(path).pipe(Effect.mapError(() => new ProfilePathInvalid({ path })));
|
|
615
|
-
/**
|
|
651
|
+
/** Nothing when the file holds a NUL byte and so is not text. */
|
|
616
652
|
const readShipped = (dir, path) => Effect.gen(function* () {
|
|
617
653
|
const bytes = yield* Effect.tryPromise({
|
|
618
654
|
catch: (cause) => new ProfileDirectoryUnreadable({
|
|
@@ -648,8 +684,6 @@ const fittingHarness = (base, profile) => {
|
|
|
648
684
|
step: "run"
|
|
649
685
|
});
|
|
650
686
|
};
|
|
651
|
-
/** The task a definition's `{ base, profile }` harness compiles to, with the
|
|
652
|
-
* profile directory read relative to the eval file. */
|
|
653
687
|
const profileTask = (entry, task) => Effect.gen(function* () {
|
|
654
688
|
const dir = resolve(dirname(entry), task.harness.profile.dir);
|
|
655
689
|
yield* Effect.tryPromise({
|
|
@@ -669,7 +703,7 @@ const profileTask = (entry, task) => Effect.gen(function* () {
|
|
|
669
703
|
harness: task.harness.base,
|
|
670
704
|
model: task.model,
|
|
671
705
|
profile,
|
|
672
|
-
|
|
706
|
+
sandbox: task.sandbox
|
|
673
707
|
};
|
|
674
708
|
}).pipe(Effect.withSpan("Eval.profileTask", { attributes: { profile: task.harness.profile.name } }));
|
|
675
709
|
//#endregion
|
|
@@ -678,7 +712,7 @@ const taskOf = (entry, task, clis, mcp) => Effect.gen(function* () {
|
|
|
678
712
|
const compiled = typeof task.harness === "string" ? {
|
|
679
713
|
harness: task.harness,
|
|
680
714
|
model: task.model,
|
|
681
|
-
|
|
715
|
+
sandbox: task.sandbox
|
|
682
716
|
} : yield* profileTask(entry, {
|
|
683
717
|
...task,
|
|
684
718
|
harness: task.harness
|
|
@@ -701,10 +735,9 @@ const compileEvalEffect = (path) => Effect.gen(function* () {
|
|
|
701
735
|
const clis = yield* compileClis(entry, definition.cli ?? []);
|
|
702
736
|
const mcp = yield* compileMcpServers(entry, definition.mcp ?? []);
|
|
703
737
|
const fallback = definition.source === void 0 && definition.cases.some((subject) => subject.source === void 0) ? yield* localRepo(dirname(entry)) : Option.none();
|
|
704
|
-
const cases = yield* Effect.forEach(definition.cases, (subject) => Effect.gen(function* () {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
const validator = hasValidator ? yield* bundledCaseModule(entry, loaded.inputs, subject.validate?.name || subject.name, validatorEntry) : null;
|
|
738
|
+
const cases = yield* Effect.forEach(definition.cases, (subject, caseIndex) => Effect.gen(function* () {
|
|
739
|
+
if (subject.validate !== void 0 === (typeof subject.verify === "string")) return yield* Effect.fail(/* @__PURE__ */ new Error(`${subject.name} must have exactly one of validate or verify`));
|
|
740
|
+
const validator = yield* compileValidator(entry, subject, caseIndex, definition.captureSource !== false, definition.captureValidation !== false);
|
|
708
741
|
const prepare = typeof subject.prepare === "function" ? yield* bundledCaseModule(entry, loaded.inputs, subject.prepare.name || `${subject.name}-prepare`, prepareEntry) : null;
|
|
709
742
|
return {
|
|
710
743
|
...subject.cache === void 0 ? {} : { cache: subject.cache },
|