@coder/aegis 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +40 -15
- package/lib/types/builder.d.ts +4 -1
- package/lib/types/schema.d.ts +2 -1
- package/package.json +6 -6
package/lib/index.js
CHANGED
|
@@ -238,14 +238,7 @@ var ExperimentBuilder = class {
|
|
|
238
238
|
strict(this.baseRepos.has(task.seed.base_repo), `task ${task.id}: base repo ${task.seed.base_repo} was not declared`);
|
|
239
239
|
validateTaskGraders(task, graders);
|
|
240
240
|
}
|
|
241
|
-
const
|
|
242
|
-
harness: this.config.subject.harness,
|
|
243
|
-
harness_version: this.config.subject.harnessVersion,
|
|
244
|
-
control_transport: this.config.subject.controlTransport,
|
|
245
|
-
model: this.config.subject.model,
|
|
246
|
-
allowed_tools: [...this.config.subject.allowedTools],
|
|
247
|
-
env: sortedStringRecord(this.config.subject.env ?? {})
|
|
248
|
-
};
|
|
241
|
+
const subjectFields = this.config.subject !== void 0 ? { subject: experimentSubjectDoc(this.config.subject) } : { subjects: codeUnitSortedSubjects(this.config.subjects ?? {}) };
|
|
249
242
|
const budget = {
|
|
250
243
|
max_usd: this.config.budget.maxUsd,
|
|
251
244
|
confirm_required: this.config.budget.confirmRequired,
|
|
@@ -262,7 +255,7 @@ var ExperimentBuilder = class {
|
|
|
262
255
|
backend: this.config.backend,
|
|
263
256
|
...backendOptions === void 0 ? {} : { backend_options: backendOptions },
|
|
264
257
|
hypothesis: this.config.hypothesis,
|
|
265
|
-
|
|
258
|
+
...subjectFields,
|
|
266
259
|
suite: suiteID,
|
|
267
260
|
grader_registry: ["graders/common.yaml"],
|
|
268
261
|
suites: suiteDocs,
|
|
@@ -595,12 +588,23 @@ function assertExperimentConfig(id, config) {
|
|
|
595
588
|
}
|
|
596
589
|
}
|
|
597
590
|
assertNonEmpty(`experiment ${id}.hypothesis`, config.hypothesis);
|
|
598
|
-
strict(config.subject
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
591
|
+
strict(config.subject === void 0 !== (config.subjects === void 0), `experiment ${id}: exactly one of subject or subjects must be set`);
|
|
592
|
+
if (config.subject !== void 0) {
|
|
593
|
+
strict(config.subject && typeof config.subject === "object", `experiment ${id}: subject is required`);
|
|
594
|
+
assertExperimentSubjectInput(`experiment ${id}.subject`, config.subject);
|
|
595
|
+
} else {
|
|
596
|
+
strict(config.subjects !== null && typeof config.subjects === "object" && !Array.isArray(config.subjects), `experiment ${id}.subjects must be an object`);
|
|
597
|
+
const subjectIDs = Object.keys(config.subjects ?? {});
|
|
598
|
+
strict(subjectIDs.length > 0, `experiment ${id}.subjects must declare at least one subject`);
|
|
599
|
+
for (const subjectID of subjectIDs) {
|
|
600
|
+
assertSafeID("subject", subjectID);
|
|
601
|
+
strict(!/^[0-9]+$/.test(subjectID), `experiment ${id}.subjects id ${JSON.stringify(subjectID)} must not be purely numeric: JSON object key order for integer-like keys diverges between emitters`);
|
|
602
|
+
strict(!subjectID.includes("__"), `experiment ${id}.subjects id ${JSON.stringify(subjectID)} must not contain "__": trial ids join task, subject, variant, and repeat segments with it`);
|
|
603
|
+
const subject = (config.subjects ?? {})[subjectID];
|
|
604
|
+
strict(subject && typeof subject === "object", `experiment ${id}.subjects[${JSON.stringify(subjectID)}] must be an object`);
|
|
605
|
+
assertExperimentSubjectInput(`experiment ${id}.subjects[${JSON.stringify(subjectID)}]`, subject);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
604
608
|
strict(Number.isInteger(config.repeats) && config.repeats > 0, `experiment ${id}: repeats must be a positive integer`);
|
|
605
609
|
strict(config.budget && typeof config.budget === "object", `experiment ${id}: budget is required`);
|
|
606
610
|
assertFiniteNumber(`experiment ${id}.budget.maxUsd`, config.budget.maxUsd);
|
|
@@ -613,6 +617,13 @@ function assertExperimentConfig(id, config) {
|
|
|
613
617
|
assertNonEmpty(`experiment ${id}.scheduling.order`, config.scheduling.order);
|
|
614
618
|
assertNonEmpty(`experiment ${id}.scheduling.retry`, config.scheduling.retry);
|
|
615
619
|
}
|
|
620
|
+
function assertExperimentSubjectInput(context, subject) {
|
|
621
|
+
assertNonEmpty(`${context}.harness`, subject.harness);
|
|
622
|
+
assertNonEmpty(`${context}.harnessVersion`, subject.harnessVersion);
|
|
623
|
+
assertNonEmpty(`${context}.controlTransport`, subject.controlTransport);
|
|
624
|
+
assertNonEmpty(`${context}.model`, subject.model);
|
|
625
|
+
assertStringArray(`${context}.allowedTools`, subject.allowedTools);
|
|
626
|
+
}
|
|
616
627
|
function assertGraderRef(context, grader) {
|
|
617
628
|
strict(grader && typeof grader === "object", `${context}: grader ref must be an object`);
|
|
618
629
|
strict(grader.kind === "aegis.grader-ref", `${context}: expected an Aegis grader helper result`);
|
|
@@ -825,6 +836,20 @@ function normalizePrompt(input) {
|
|
|
825
836
|
strict(content.length > 0, "prompt must not be blank");
|
|
826
837
|
return `${content}\n`;
|
|
827
838
|
}
|
|
839
|
+
function experimentSubjectDoc(subject) {
|
|
840
|
+
return {
|
|
841
|
+
harness: subject.harness,
|
|
842
|
+
harness_version: subject.harnessVersion,
|
|
843
|
+
control_transport: subject.controlTransport,
|
|
844
|
+
model: subject.model,
|
|
845
|
+
allowed_tools: [...subject.allowedTools],
|
|
846
|
+
env: sortedStringRecord(subject.env ?? {})
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
function codeUnitSortedSubjects(input) {
|
|
850
|
+
const entries = Object.entries(input).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
851
|
+
return Object.fromEntries(entries.map(([id, subject]) => [id, experimentSubjectDoc(subject)]));
|
|
852
|
+
}
|
|
828
853
|
function sortedStringRecord(input) {
|
|
829
854
|
const entries = Object.entries(input).sort(([a], [b]) => a.localeCompare(b));
|
|
830
855
|
for (const [key, value] of entries) {
|
package/lib/types/builder.d.ts
CHANGED
|
@@ -10,7 +10,10 @@ export interface ExperimentConfig {
|
|
|
10
10
|
backend: string;
|
|
11
11
|
backendOptions?: BackendOptionsInput;
|
|
12
12
|
hypothesis: string;
|
|
13
|
-
subject
|
|
13
|
+
/** Exactly one of subject or subjects must be set. */
|
|
14
|
+
subject?: ExperimentSubjectInput;
|
|
15
|
+
/** Multi-subject axis keyed by repo-safe subject id. */
|
|
16
|
+
subjects?: Record<string, ExperimentSubjectInput>;
|
|
14
17
|
repeats: number;
|
|
15
18
|
budget: BudgetInput;
|
|
16
19
|
primaryMetric: string;
|
package/lib/types/schema.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ export interface ExperimentDoc {
|
|
|
4
4
|
backend: string;
|
|
5
5
|
backend_options?: BackendOptionsDoc;
|
|
6
6
|
hypothesis: string;
|
|
7
|
-
subject
|
|
7
|
+
subject?: ExperimentSubjectDoc;
|
|
8
|
+
subjects?: Record<string, ExperimentSubjectDoc>;
|
|
8
9
|
suite: string;
|
|
9
10
|
grader_registry: string[];
|
|
10
11
|
suites: Record<string, SuiteDoc>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coder/aegis",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "aegis CLI and TypeScript eval-authoring facade (Go binary with embedded TS eval compiler and web UI, plus the @coder/aegis import surface)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
"url": "git+https://github.com/coder/aegis.git"
|
|
24
24
|
},
|
|
25
25
|
"optionalDependencies": {
|
|
26
|
-
"@coder/aegis-linux-x64": "0.
|
|
27
|
-
"@coder/aegis-linux-arm64": "0.
|
|
28
|
-
"@coder/aegis-darwin-x64": "0.
|
|
29
|
-
"@coder/aegis-darwin-arm64": "0.
|
|
30
|
-
"@coder/aegis-win32-x64": "0.
|
|
26
|
+
"@coder/aegis-linux-x64": "0.3.0",
|
|
27
|
+
"@coder/aegis-linux-arm64": "0.3.0",
|
|
28
|
+
"@coder/aegis-darwin-x64": "0.3.0",
|
|
29
|
+
"@coder/aegis-darwin-arm64": "0.3.0",
|
|
30
|
+
"@coder/aegis-win32-x64": "0.3.0"
|
|
31
31
|
}
|
|
32
32
|
}
|