@tangle-network/agent-eval 0.119.1 → 0.120.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.
Files changed (33) hide show
  1. package/CHANGELOG.md +19 -3
  2. package/README.md +0 -26
  3. package/dist/benchmarks/index.d.ts +11 -5
  4. package/dist/benchmarks/index.js +4 -4
  5. package/dist/campaign/index.d.ts +93 -37
  6. package/dist/campaign/index.js +23 -7
  7. package/dist/{chunk-PSXJ32SR.js → chunk-32BZXMSO.js} +229 -118
  8. package/dist/chunk-32BZXMSO.js.map +1 -0
  9. package/dist/{chunk-XJ7JVCHB.js → chunk-3A246TSA.js} +2 -2
  10. package/dist/{chunk-XMBOU5W7.js → chunk-JN2FCO5W.js} +4 -5
  11. package/dist/chunk-JN2FCO5W.js.map +1 -0
  12. package/dist/{chunk-D7AEXSM5.js → chunk-PICTDURQ.js} +2 -2
  13. package/dist/{chunk-PAHNGS65.js → chunk-XDIRG3TO.js} +175 -11
  14. package/dist/chunk-XDIRG3TO.js.map +1 -0
  15. package/dist/contract/index.d.ts +52 -28
  16. package/dist/contract/index.js +350 -62
  17. package/dist/contract/index.js.map +1 -1
  18. package/dist/index.d.ts +22 -8
  19. package/dist/index.js +9 -5
  20. package/dist/index.js.map +1 -1
  21. package/dist/openapi.json +1 -1
  22. package/dist/rl.d.ts +11 -5
  23. package/dist/{run-campaign-OBXSN5WK.js → run-campaign-HNFPJET4.js} +2 -2
  24. package/package.json +1 -6
  25. package/dist/chunk-PAHNGS65.js.map +0 -1
  26. package/dist/chunk-PSXJ32SR.js.map +0 -1
  27. package/dist/chunk-XMBOU5W7.js.map +0 -1
  28. package/dist/primeintellect/index.d.ts +0 -311
  29. package/dist/primeintellect/index.js +0 -348
  30. package/dist/primeintellect/index.js.map +0 -1
  31. /package/dist/{chunk-XJ7JVCHB.js.map → chunk-3A246TSA.js.map} +0 -0
  32. /package/dist/{chunk-D7AEXSM5.js.map → chunk-PICTDURQ.js.map} +0 -0
  33. /package/dist/{run-campaign-OBXSN5WK.js.map → run-campaign-HNFPJET4.js.map} +0 -0
@@ -1,311 +0,0 @@
1
- type AgentProfileCellSchemaVersion = 'agent-profile-cell/v1';
2
- type AgentProfileDimensionValue = string | number | boolean | null;
3
- interface AgentProfileSource {
4
- /** Runtime/profile contract being fingerprinted, e.g. `agent-interface-profile`. */
5
- kind: string;
6
- /** sha256 over the canonical source profile object. */
7
- hash: string;
8
- }
9
- interface AgentProfileHarness {
10
- id: string;
11
- version?: string;
12
- hash?: string;
13
- }
14
- interface AgentProfileCell {
15
- schemaVersion: AgentProfileCellSchemaVersion;
16
- cellId: string;
17
- profileId: string;
18
- sourceProfile: AgentProfileSource;
19
- harness?: AgentProfileHarness;
20
- model?: string;
21
- promptHash?: string;
22
- dimensions?: Record<string, AgentProfileDimensionValue>;
23
- }
24
-
25
- type FailureClass = 'success' | 'reasoning_error' | 'tool_selection_error' | 'tool_argument_error' | 'tool_recovery_failure' | 'hallucination' | 'instruction_following' | 'safety_refusal_miss' | 'policy_violation' | 'budget_exceeded' | 'format_drift' | 'permission_escalation' | 'pii_leak' | 'cost_overrun' | 'timeout' | 'sandbox_failure' | 'missing_user_data' | 'missing_domain_data' | 'missing_codebase_context' | 'missing_runtime_context' | 'missing_credentials' | 'missing_integration_connection' | 'missing_integration_scope' | 'integration_approval_required' | 'integration_auth_expired' | 'integration_provider_failure' | 'bad_integration_manifest' | 'unsafe_integration_write_denied' | 'stale_external_data' | 'bad_retrieval' | 'insufficient_evidence' | 'contradictory_evidence' | 'ambiguous_user_intent' | 'knowledge_readiness_blocked' | 'unknown';
26
-
27
- /**
28
- * Paper-grade RunRecord schema + runtime validator.
29
- *
30
- * Every run that participates in a promotion gate, paper table, or
31
- * researcher loop SHOULD be recorded as a `RunRecord`. The mandatory
32
- * fields are exactly those the paper "Two Loops, Three Roles" requires
33
- * for reproducibility: who/what/when/cost/seed/hash, plus the search vs
34
- * holdout split tag and either a `searchScore` or a `holdoutScore`.
35
- *
36
- * This is intentionally NOT a replacement for the rich `Run` /
37
- * `ProposeReviewReport` / `ScenarioResult` types already in the
38
- * package. Those are runtime structures with full provenance. A
39
- * `RunRecord` is the analysis-time projection — the JSON-friendly
40
- * row you'd put in a parquet file or paste into a notebook.
41
- *
42
- * Validate at the boundary:
43
- *
44
- * const rec = validateRunRecord(rawJson) // throws on missing
45
- * const ok = isRunRecord(rawJson) // boolean check
46
- * const rec = parseRunRecordSafe(rawJson) // { ok, value | error }
47
- *
48
- * The validator runs in pure TS — zod is intentionally NOT a
49
- * dependency. Round-trip tested in `tests/run-record.test.ts`.
50
- */
51
-
52
- /** Search/dev/holdout split tag. 'search' is the paper-grade alias for the
53
- * combined train+test pool that the optimizer is allowed to read. */
54
- type RunSplitTag = 'search' | 'dev' | 'holdout';
55
- interface RunTokenUsage {
56
- input: number;
57
- /** All generated tokens charged as output, including reasoning tokens. */
58
- output: number;
59
- /** Reasoning-token subset of `output`, when the provider reports it. */
60
- reasoning?: number;
61
- /** Prompt tokens served from a provider cache. */
62
- cached?: number;
63
- /** Prompt tokens written into a provider cache. */
64
- cacheWrite?: number;
65
- }
66
- /**
67
- * How a run's USD amount was obtained.
68
- *
69
- * `costUsd` remains mandatory for wire compatibility. New producers should
70
- * always populate this discriminated union so a missing bill is never
71
- * mistaken for an observed zero-dollar run. For `uncaptured`, `costUsd` uses
72
- * the legacy `0` sentinel while this field carries the truthful null.
73
- */
74
- type RunCostProvenance = {
75
- kind: 'observed';
76
- usd: number;
77
- } | {
78
- kind: 'estimated';
79
- usd: number;
80
- } | {
81
- kind: 'uncaptured';
82
- usd: null;
83
- };
84
- interface RunJudgeMetadata {
85
- model: string;
86
- promptVersion: string;
87
- /** [0,1] confidence the judge declared. Constant judge confidence
88
- * across many runs is a fallback signal (see `canary.ts`). */
89
- confidence: number;
90
- /** True if the judge degraded to a fallback path (rules-only,
91
- * prior-call cache, etc.). The canary uses this to alert. */
92
- fallback: boolean;
93
- }
94
- /**
95
- * Per-judge / per-dimension breakdown for runs scored by an ensemble of
96
- * judges over a multi-dimensional rubric.
97
- *
98
- * The collapsed `outcome.searchScore` / `holdoutScore` carries the
99
- * composite the gate uses. The full breakdown belongs here so consumers
100
- * can answer "which judge disagreed?", "which dimension dragged the
101
- * composite down?", and "did half the panel fail?" without re-running.
102
- *
103
- * `perJudge[judgeId][dim]` is the canonical source; `perDimMean` and
104
- * `composite` are convenience projections — derivable but precomputed so
105
- * downstream IRR primitives (`interRaterReliability`,
106
- * `corpusInterRaterAgreement`) and reporters don't pay the same
107
- * aggregation twice.
108
- *
109
- * Fail-loud discipline: judges that errored out land in `failedJudges`
110
- * by id. A missing key in `perJudge` is ambiguous (silent zero vs not
111
- * run); the explicit list makes a partial-failure recorded as such.
112
- */
113
- interface JudgeScoresRecord {
114
- /** Per-judge per-dimension scores. `{ "kimi-k2.6": { helpfulness: 0.8, clarity: 0.7 }, ... }`. */
115
- perJudge: Record<string, Record<string, number>>;
116
- /** Per-dim mean across judges. Convenience — derivable from `perJudge`. */
117
- perDimMean: Record<string, number>;
118
- /** Composite mean across all dims and judges. Mirrors the score
119
- * the gate sees on `outcome.searchScore` / `holdoutScore`. */
120
- composite: number;
121
- /** Judges that errored or returned an unparseable verdict. Recorded
122
- * by id (e.g. `['glm-5.1']`) so a partial-failure case is explicit,
123
- * not inferred from missing keys in `perJudge`. */
124
- failedJudges?: string[];
125
- /** Free-form notes the judges emitted (joined across judges or
126
- * first-judge only — consumer's choice). */
127
- notes?: string;
128
- }
129
- interface RunOutcome {
130
- /** Score on the search/optimization split. Optional because a
131
- * holdout-only evaluation only fills `holdoutScore`. */
132
- searchScore?: number;
133
- /** Score on the held-out split. Optional because a search-only run
134
- * only fills `searchScore`. At least one must be present. */
135
- holdoutScore?: number;
136
- /** Bag of any other metric the run produced — judge dimensions,
137
- * pass/fail counters, latency stats, etc. Numeric only — keeps
138
- * reporters honest. */
139
- raw: Record<string, number>;
140
- /** Per-judge / per-dim breakdown. Consumers writing ensemble
141
- * judgements populate this; substrate primitives like
142
- * `interRaterReliability` and `corpusInterRaterAgreement` accept
143
- * these records as input. Optional — single-judge or scalar-only
144
- * runs leave it unset. */
145
- judgeScores?: JudgeScoresRecord;
146
- /** Authenticity / realness verdict — did the run build the REAL thing on the
147
- * intended infra, or fake it (see `./authenticity`)? Optional: only domains
148
- * with an authenticity config populate it. Carried in the corpus so the
149
- * flywheel / off-policy learning can optimize for real completion, not gamed
150
- * pass-rate. `score` is 0-1; `gated` is the anti-Goodhart flag — a gated run
151
- * must not count as a real success regardless of `score`. */
152
- realness?: {
153
- score: number;
154
- gated: boolean;
155
- reason?: string;
156
- };
157
- }
158
- /**
159
- * Mandatory paper-grade fields for a single evaluation run. Optional
160
- * fields are extension points; mandatory fields throw if missing.
161
- *
162
- * Hash discipline:
163
- * - `promptHash` is the sha256 of the EFFECTIVE prompt sent to the
164
- * model (after any steering bundle merge).
165
- * - `configHash` is the sha256 of the effective run config (model,
166
- * temperature, tools, judges, splits). The pair (promptHash,
167
- * configHash) uniquely identifies an experiment cell.
168
- *
169
- * Model snapshot discipline:
170
- * - `model` MUST encode a snapshot version. Bare aliases like
171
- * `claude-sonnet-4` or `gpt-4o` are banned — they remap silently.
172
- * Use `claude-sonnet-4-6@2025-04-15` or `gpt-4o-2024-11-20`.
173
- */
174
- interface RunRecord {
175
- /** UUID for the run. */
176
- runId: string;
177
- /** Logical experiment grouping (a treatment vs a baseline within
178
- * the same sweep should share `experimentId`). */
179
- experimentId: string;
180
- /** Stable identifier for the candidate (variant) being run. The
181
- * promotion gate compares two `candidateId`s on matched items. */
182
- candidateId: string;
183
- /** RNG seed for the run. Always recorded — silent re-seeding is
184
- * the most common cause of non-reproducible numbers. */
185
- seed: number;
186
- /** Model identifier WITH snapshot version. */
187
- model: string;
188
- /** sha256 of the effective prompt (post-steering). */
189
- promptHash: string;
190
- /** sha256 of the effective config. */
191
- configHash: string;
192
- /** Git SHA the harness was run from. */
193
- commitSha: string;
194
- /** End-to-end wall-clock duration in milliseconds. */
195
- wallMs: number;
196
- /** Time spent queued before execution started, if known. */
197
- queueMs?: number;
198
- /** Total USD cost. Mandatory — runs without a cost number are
199
- * unbounded by definition and must not be admitted into the gate.
200
- * `0` is retained as the compatibility sentinel for an uncaptured amount;
201
- * inspect `costProvenance` before treating it as observed. */
202
- costUsd: number;
203
- /** Observed, model-priced estimate, or genuinely uncaptured USD amount.
204
- * Optional only so existing serialized RunRecords remain valid. */
205
- costProvenance?: RunCostProvenance;
206
- /** Token usage breakdown. */
207
- tokenUsage: RunTokenUsage;
208
- /** Judge-side metadata, if a judge was used. */
209
- judgeMetadata?: RunJudgeMetadata;
210
- /** Per-split scores + raw bag. */
211
- outcome: RunOutcome;
212
- /** Canonical, cross-agent failure class drawn from the shared
213
- * `FAILURE_CLASSES` taxonomy. This is the aggregation key that makes
214
- * "which failure dominates across the whole fleet" answerable in ONE
215
- * vocabulary — every agent classifies against the same enum. Producers
216
- * set it via the substrate classifier; leave unset only when the failure
217
- * genuinely can't be classified. */
218
- failureClass?: FailureClass;
219
- /** Free-form domain-specific failure detail, scoped UNDER `failureClass`
220
- * (e.g. failureClass='tool_recovery_failure', failureMode='forge_build_unsatisfied').
221
- * The within-agent drill-down; `failureClass` is the cross-agent key. */
222
- failureMode?: string;
223
- /** Which split this run was drawn from. */
224
- splitTag: RunSplitTag;
225
- /**
226
- * Stable scenario identifier the run was scored against. Optional for
227
- * backwards compatibility, but **strongly recommended**: every primitive
228
- * that pairs runs by scenario (preferences, paired stats, BT tournament)
229
- * keys on this. The campaign artifact populates it canonically; legacy
230
- * runs without it fall back to inference from `outcome.raw.scenario_id`
231
- * or `experimentId`.
232
- */
233
- scenarioId?: string;
234
- /**
235
- * Canonical identity for the agent profile cell that produced this row:
236
- * profile artifact hash plus optional harness/model/prompt/reporting
237
- * dimensions. Use `agentProfile.cellId` to group persona sweeps and
238
- * longitudinal reports by the complete source profile, not by a loose
239
- * candidate label or opaque config hash.
240
- */
241
- agentProfile?: AgentProfileCell;
242
- }
243
-
244
- type PrimeIntellectJson = null | boolean | number | string | PrimeIntellectJson[] | {
245
- [key: string]: PrimeIntellectJson;
246
- };
247
- interface PrimeIntellectMessage {
248
- role: 'system' | 'user' | 'assistant' | 'tool';
249
- content: string;
250
- }
251
- interface PrimeIntellectScenario {
252
- id: string;
253
- prompt: string | readonly PrimeIntellectMessage[];
254
- answer?: string;
255
- requiredSubstrings?: readonly string[];
256
- split?: string;
257
- info?: Record<string, PrimeIntellectJson>;
258
- }
259
- interface PrimeIntellectDatasetRow {
260
- id: string;
261
- prompt: PrimeIntellectMessage[];
262
- answer?: string;
263
- required_substrings?: string[];
264
- split?: string;
265
- info: Record<string, PrimeIntellectJson>;
266
- }
267
- type PrimeIntellectScenarioMap = ReadonlyMap<string, PrimeIntellectScenario> | Record<string, PrimeIntellectScenario> | readonly PrimeIntellectScenario[];
268
- interface PrimeIntellectRowsFromRunRecordsOptions {
269
- records: readonly RunRecord[];
270
- scenarios: PrimeIntellectScenarioMap;
271
- requireScorable?: boolean;
272
- includeFailed?: boolean;
273
- }
274
- interface PrimeIntellectEnvironmentPackageInput {
275
- name: string;
276
- version?: string;
277
- description?: string;
278
- tags?: readonly string[];
279
- moduleName?: string;
280
- rows: readonly PrimeIntellectDatasetRow[];
281
- runRecords?: readonly RunRecord[];
282
- systemPrompt?: string;
283
- verifiersVersion?: string;
284
- dependencies?: readonly string[];
285
- readme?: string;
286
- }
287
- interface PrimeIntellectPackageFile {
288
- path: string;
289
- content: string;
290
- }
291
- interface PrimeIntellectPackageManifest {
292
- schemaVersion: 1;
293
- name: string;
294
- moduleName: string;
295
- version: string;
296
- rowCount: number;
297
- runRecordCount: number;
298
- artifactKinds: readonly ['environment', 'dataset', 'run_records'];
299
- }
300
- interface PrimeIntellectEnvironmentPackage {
301
- files: PrimeIntellectPackageFile[];
302
- manifest: PrimeIntellectPackageManifest;
303
- }
304
- declare class PrimeIntellectBridgeError extends Error {
305
- constructor(message: string);
306
- }
307
- declare function primeIntellectRowsFromRunRecords(options: PrimeIntellectRowsFromRunRecordsOptions): PrimeIntellectDatasetRow[];
308
- declare function buildPrimeIntellectEnvironmentPackage(input: PrimeIntellectEnvironmentPackageInput): PrimeIntellectEnvironmentPackage;
309
- declare function writePrimeIntellectEnvironmentPackage(root: string, input: PrimeIntellectEnvironmentPackageInput): Promise<PrimeIntellectEnvironmentPackage>;
310
-
311
- export { PrimeIntellectBridgeError, type PrimeIntellectDatasetRow, type PrimeIntellectEnvironmentPackage, type PrimeIntellectEnvironmentPackageInput, type PrimeIntellectJson, type PrimeIntellectMessage, type PrimeIntellectPackageFile, type PrimeIntellectPackageManifest, type PrimeIntellectRowsFromRunRecordsOptions, type PrimeIntellectScenario, type PrimeIntellectScenarioMap, buildPrimeIntellectEnvironmentPackage, primeIntellectRowsFromRunRecords, writePrimeIntellectEnvironmentPackage };
@@ -1,348 +0,0 @@
1
- import {
2
- validateRunRecord
3
- } from "../chunk-S3UZOQ5Y.js";
4
- import "../chunk-MA6HLL3S.js";
5
- import "../chunk-XJYR7XFV.js";
6
- import "../chunk-VSMTAMNK.js";
7
- import "../chunk-ONWEPEDO.js";
8
- import "../chunk-PZ5AY32C.js";
9
-
10
- // src/primeintellect/index.ts
11
- import { mkdir, writeFile } from "fs/promises";
12
- import { dirname, join } from "path";
13
- var PrimeIntellectBridgeError = class extends Error {
14
- constructor(message) {
15
- super(message);
16
- this.name = "PrimeIntellectBridgeError";
17
- }
18
- };
19
- function primeIntellectRowsFromRunRecords(options) {
20
- const scenarioById = normalizeScenarios(options.scenarios);
21
- const requireScorable = options.requireScorable ?? true;
22
- const includeFailed = options.includeFailed ?? true;
23
- const rows = [];
24
- for (const record of options.records) {
25
- const validRecord = validateRunRecord(record);
26
- if (!includeFailed && validRecord.failureMode) continue;
27
- const scenarioId = validRecord.scenarioId;
28
- if (!scenarioId) {
29
- throw new PrimeIntellectBridgeError(
30
- `RunRecord ${validRecord.runId} is missing scenarioId; PrimeIntellect rows need stable task ids`
31
- );
32
- }
33
- const scenario = scenarioById.get(scenarioId);
34
- if (!scenario) {
35
- throw new PrimeIntellectBridgeError(
36
- `RunRecord ${validRecord.runId} references unknown scenarioId ${JSON.stringify(scenarioId)}`
37
- );
38
- }
39
- const hasAnswer = typeof scenario.answer === "string" && scenario.answer.trim().length > 0;
40
- const hasRequiredSubstrings = (scenario.requiredSubstrings?.length ?? 0) > 0;
41
- if (requireScorable && !hasAnswer && !hasRequiredSubstrings) {
42
- throw new PrimeIntellectBridgeError(
43
- `Scenario ${scenario.id} has no answer or requiredSubstrings; generated environments would always score 0`
44
- );
45
- }
46
- const score = validRecord.outcome.holdoutScore ?? validRecord.outcome.searchScore ?? null;
47
- const split = scenario.split ?? validRecord.splitTag;
48
- const tangleInfo = {
49
- run_id: validRecord.runId,
50
- experiment_id: validRecord.experimentId,
51
- candidate_id: validRecord.candidateId,
52
- scenario_id: scenarioId,
53
- split,
54
- score,
55
- cost_usd: validRecord.costUsd,
56
- wall_ms: validRecord.wallMs,
57
- failure_mode: validRecord.failureMode ?? null,
58
- model: validRecord.model,
59
- commit_sha: validRecord.commitSha
60
- };
61
- rows.push({
62
- id: `${scenarioId}:${validRecord.runId}`,
63
- prompt: normalizePrompt(scenario.prompt),
64
- ...hasAnswer ? { answer: scenario.answer } : {},
65
- ...hasRequiredSubstrings ? { required_substrings: [...scenario.requiredSubstrings ?? []] } : {},
66
- split,
67
- info: {
68
- ...scenario.info ?? {},
69
- tangle: tangleInfo
70
- }
71
- });
72
- }
73
- return rows;
74
- }
75
- function buildPrimeIntellectEnvironmentPackage(input) {
76
- if (input.rows.length === 0) {
77
- throw new PrimeIntellectBridgeError("cannot build a PrimeIntellect environment with zero rows");
78
- }
79
- for (const record of input.runRecords ?? []) {
80
- validateRunRecord(record);
81
- }
82
- const moduleName = input.moduleName ?? toPythonModuleName(input.name);
83
- if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(moduleName)) {
84
- throw new PrimeIntellectBridgeError(
85
- `moduleName ${JSON.stringify(moduleName)} is not a valid Python module name`
86
- );
87
- }
88
- const version = input.version ?? "0.1.0";
89
- const description = input.description ?? "PrimeIntellect Verifiers environment exported from Tangle runs.";
90
- const verifiersVersion = input.verifiersVersion ?? ">=0.2.0,<0.3.0";
91
- const dependencies = unique([
92
- "datasets",
93
- `verifiers${verifiersVersion}`,
94
- ...input.dependencies ?? []
95
- ]);
96
- const tags = unique(["tangle", "agent-eval", ...input.tags ?? []]);
97
- const manifest = {
98
- schemaVersion: 1,
99
- name: input.name,
100
- moduleName,
101
- version,
102
- rowCount: input.rows.length,
103
- runRecordCount: input.runRecords?.length ?? 0,
104
- artifactKinds: ["environment", "dataset", "run_records"]
105
- };
106
- const files = [
107
- {
108
- path: "pyproject.toml",
109
- content: renderPyproject({
110
- name: input.name,
111
- version,
112
- description,
113
- dependencies,
114
- tags
115
- })
116
- },
117
- {
118
- path: "README.md",
119
- content: input.readme ?? renderReadme({ name: input.name, description })
120
- },
121
- {
122
- path: `${moduleName}.py`,
123
- content: renderEnvironmentModule({
124
- systemPrompt: input.systemPrompt
125
- })
126
- },
127
- {
128
- path: "data/dataset.jsonl",
129
- content: toJsonl(input.rows)
130
- },
131
- {
132
- path: "data/run_records.jsonl",
133
- content: toJsonl(input.runRecords ?? [])
134
- },
135
- {
136
- path: "tangle-primeintellect-manifest.json",
137
- content: `${stableJson(manifest)}
138
- `
139
- }
140
- ];
141
- return { files, manifest };
142
- }
143
- async function writePrimeIntellectEnvironmentPackage(root, input) {
144
- const pkg = buildPrimeIntellectEnvironmentPackage(input);
145
- await Promise.all(
146
- pkg.files.map(async (file) => {
147
- const target = join(root, file.path);
148
- await mkdir(dirname(target), { recursive: true });
149
- await writeFile(target, file.content, "utf8");
150
- })
151
- );
152
- return pkg;
153
- }
154
- function normalizeScenarios(scenarios) {
155
- const map = /* @__PURE__ */ new Map();
156
- if (scenarios instanceof Map) {
157
- for (const [id, scenario] of scenarios.entries()) {
158
- map.set(id, { ...scenario, id: scenario.id ?? id });
159
- }
160
- return map;
161
- }
162
- const values = Array.isArray(scenarios) ? scenarios : Object.values(scenarios);
163
- for (const scenario of values) {
164
- if (!scenario.id) {
165
- throw new PrimeIntellectBridgeError("every PrimeIntellect scenario needs an id");
166
- }
167
- if (map.has(scenario.id)) {
168
- throw new PrimeIntellectBridgeError(`duplicate PrimeIntellect scenario id ${scenario.id}`);
169
- }
170
- map.set(scenario.id, scenario);
171
- }
172
- return map;
173
- }
174
- function normalizePrompt(prompt) {
175
- if (typeof prompt === "string") {
176
- return [{ role: "user", content: prompt }];
177
- }
178
- return prompt.map((message) => ({ role: message.role, content: message.content }));
179
- }
180
- function toPythonModuleName(name) {
181
- return name.trim().toLowerCase().replace(/[^a-z0-9_]+/g, "_").replace(/^_+|_+$/g, "").replace(/^[0-9]/, "_$&");
182
- }
183
- function unique(values) {
184
- return [...new Set(values)];
185
- }
186
- function toJsonl(values) {
187
- if (values.length === 0) return "";
188
- return `${values.map((value) => stableJson(value)).join("\n")}
189
- `;
190
- }
191
- function stableJson(value) {
192
- return JSON.stringify(sortJson(value));
193
- }
194
- function sortJson(value) {
195
- if (Array.isArray(value)) return value.map(sortJson);
196
- if (value === null || typeof value !== "object") return value;
197
- return Object.fromEntries(
198
- Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, nested]) => [key, sortJson(nested)])
199
- );
200
- }
201
- function renderPyproject(input) {
202
- return `[project]
203
- name = ${tomlString(input.name)}
204
- version = ${tomlString(input.version)}
205
- description = ${tomlString(input.description)}
206
- readme = "README.md"
207
- requires-python = ">=3.11"
208
- license = "MIT"
209
- keywords = ${tomlArray(input.tags)}
210
- dependencies = ${tomlArray(input.dependencies)}
211
-
212
- [build-system]
213
- requires = ["hatchling"]
214
- build-backend = "hatchling.build"
215
-
216
- [tool.hatch.build]
217
- include = ["*.py", "README.md", "data/*.jsonl", "tangle-primeintellect-manifest.json"]
218
-
219
- [tool.uv]
220
- prerelease = "allow"
221
-
222
- [tool.verifiers.eval]
223
- num_examples = 5
224
- rollouts_per_example = 3
225
- `;
226
- }
227
- function renderReadme(input) {
228
- return `# ${input.name}
229
-
230
- ${input.description}
231
-
232
- Generated by \`@tangle-network/agent-eval/primeintellect\` from validated Tangle \`RunRecord\` rows.
233
-
234
- ## Files
235
-
236
- - \`data/dataset.jsonl\`: prompts and scoring references for PrimeIntellect Verifiers.
237
- - \`data/run_records.jsonl\`: original Tangle run rows for provenance and analysis.
238
- - \`tangle-primeintellect-manifest.json\`: export metadata.
239
-
240
- ## Local check
241
-
242
- \`\`\`sh
243
- uv pip install --prerelease=allow -e .
244
- uv run vf-eval ${input.name}
245
- \`\`\`
246
-
247
- ## Upload
248
-
249
- \`\`\`sh
250
- prime login
251
- prime env push
252
- \`\`\`
253
- `;
254
- }
255
- function renderEnvironmentModule(input) {
256
- const systemPrompt = input.systemPrompt === void 0 ? "None" : pyString(input.systemPrompt);
257
- return `import json
258
- import re
259
- from pathlib import Path
260
-
261
- from datasets import Dataset
262
- import verifiers as vf
263
-
264
-
265
- DATA_PATH = Path(__file__).parent / "data" / "dataset.jsonl"
266
- DEFAULT_SYSTEM_PROMPT = ${systemPrompt}
267
-
268
-
269
- def _load_rows(dataset_path=None, dataset_split=None):
270
- path = Path(dataset_path) if dataset_path is not None else DATA_PATH
271
- rows = []
272
- with path.open("r", encoding="utf-8") as handle:
273
- for line in handle:
274
- row = json.loads(line)
275
- if dataset_split is None or row.get("split") == dataset_split:
276
- rows.append(row)
277
- if not rows:
278
- raise ValueError(f"No dataset rows found in {path} for split={dataset_split!r}")
279
- return rows
280
-
281
-
282
- def _message_text(message):
283
- if isinstance(message, dict):
284
- content = message.get("content", "")
285
- else:
286
- content = getattr(message, "content", "")
287
- if isinstance(content, list):
288
- return " ".join(
289
- str(part.get("text", part)) if isinstance(part, dict) else str(part)
290
- for part in content
291
- )
292
- return str(content)
293
-
294
-
295
- def _completion_text(completion):
296
- if isinstance(completion, str):
297
- return completion
298
- if isinstance(completion, list):
299
- return "\\n".join(_message_text(message) for message in completion)
300
- return _message_text(completion)
301
-
302
-
303
- def _normalize(text):
304
- return re.sub(r"\\s+", " ", str(text).strip().lower())
305
-
306
-
307
- async def tangle_reward(completion, answer=None, required_substrings=None, **kwargs):
308
- response = _normalize(_completion_text(completion))
309
- scores = []
310
- if answer:
311
- expected = _normalize(answer)
312
- scores.append(1.0 if expected == response or expected in response else 0.0)
313
- if required_substrings:
314
- required = [_normalize(item) for item in required_substrings]
315
- hits = sum(1 for item in required if item and item in response)
316
- scores.append(hits / len(required))
317
- return max(scores) if scores else 0.0
318
-
319
-
320
- def build_dataset(dataset_path=None, dataset_split=None):
321
- return Dataset.from_list(_load_rows(dataset_path=dataset_path, dataset_split=dataset_split))
322
-
323
-
324
- def load_environment(dataset_path=None, dataset_split=None, system_prompt=DEFAULT_SYSTEM_PROMPT):
325
- rubric = vf.Rubric(funcs=[tangle_reward])
326
- return vf.SingleTurnEnv(
327
- dataset=lambda: build_dataset(dataset_path=dataset_path, dataset_split=dataset_split),
328
- system_prompt=system_prompt,
329
- rubric=rubric,
330
- )
331
- `;
332
- }
333
- function tomlString(value) {
334
- return JSON.stringify(value);
335
- }
336
- function tomlArray(values) {
337
- return `[${values.map(tomlString).join(", ")}]`;
338
- }
339
- function pyString(value) {
340
- return JSON.stringify(value);
341
- }
342
- export {
343
- PrimeIntellectBridgeError,
344
- buildPrimeIntellectEnvironmentPackage,
345
- primeIntellectRowsFromRunRecords,
346
- writePrimeIntellectEnvironmentPackage
347
- };
348
- //# sourceMappingURL=index.js.map