@tangle-network/agent-runtime 0.94.10 → 0.94.12

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 (59) hide show
  1. package/README.md +65 -1
  2. package/dist/agent.d.ts +2 -1
  3. package/dist/agent.js +2 -1
  4. package/dist/agent.js.map +1 -1
  5. package/dist/{agentic-generator-1g7GDba7.d.ts → agentic-generator-DDMM45kZ.d.ts} +46 -6
  6. package/dist/analyst-loop.d.ts +2 -1
  7. package/dist/backends-BO4Jqoe2.d.ts +134 -0
  8. package/dist/chunk-AEG3NGJ2.js +639 -0
  9. package/dist/chunk-AEG3NGJ2.js.map +1 -0
  10. package/dist/{chunk-GHXW56PO.js → chunk-D3H7F6L2.js} +136 -36
  11. package/dist/chunk-D3H7F6L2.js.map +1 -0
  12. package/dist/{chunk-7NCP74SL.js → chunk-PCURO3DL.js} +4 -4
  13. package/dist/chunk-PCURO3DL.js.map +1 -0
  14. package/dist/{chunk-YP6B7RZ2.js → chunk-U33YZ7B2.js} +6 -635
  15. package/dist/chunk-U33YZ7B2.js.map +1 -0
  16. package/dist/chunk-VYA2YEKA.js +1187 -0
  17. package/dist/chunk-VYA2YEKA.js.map +1 -0
  18. package/dist/{chunk-MXBQNVFE.js → chunk-XP5KDM3R.js} +5 -5
  19. package/dist/{completion-gate-BB4IZwyh.d.ts → completion-gate-D1gX1-hg.d.ts} +2 -2
  20. package/dist/conversation.d.ts +793 -0
  21. package/dist/conversation.js +56 -0
  22. package/dist/conversation.js.map +1 -0
  23. package/dist/{coordination-CyVQ61My.d.ts → coordination-Dr_axlAf.d.ts} +6 -5
  24. package/dist/environment-provider.d.ts +3 -2
  25. package/dist/{improve-DZeatcs7.d.ts → improve-BN3HyXIO.d.ts} +2 -2
  26. package/dist/index.d.ts +29 -943
  27. package/dist/index.js +58 -1159
  28. package/dist/index.js.map +1 -1
  29. package/dist/intelligence.d.ts +6 -5
  30. package/dist/intelligence.js +5 -5
  31. package/dist/knowledge.d.ts +8 -7
  32. package/dist/lifecycle.d.ts +3 -3
  33. package/dist/lifecycle.js +1 -1
  34. package/dist/{local-harness-ZLMkKdZc.d.ts → local-harness-ZqCx51u7.d.ts} +1 -1
  35. package/dist/{loop-runner-bin-DA3ccCAs.d.ts → loop-runner-bin-BRQSQdHa.d.ts} +2 -2
  36. package/dist/loop-runner-bin.d.ts +7 -6
  37. package/dist/loop-runner-bin.js +4 -3
  38. package/dist/loops.d.ts +16 -15
  39. package/dist/loops.js +2 -1
  40. package/dist/mcp/index.d.ts +11 -10
  41. package/dist/mcp/index.js +2 -1
  42. package/dist/mcp/index.js.map +1 -1
  43. package/dist/{mcp-serve-verifier-BO4MEsR3.d.ts → mcp-serve-verifier-DQQDbuyz.d.ts} +1 -1
  44. package/dist/{openai-tools-0wACz8f8.d.ts → openai-tools-fnj6SRVg.d.ts} +1 -1
  45. package/dist/primeintellect/index.d.ts +214 -0
  46. package/dist/primeintellect/index.js +1120 -0
  47. package/dist/primeintellect/index.js.map +1 -0
  48. package/dist/profiles.d.ts +2 -1
  49. package/dist/{sanitize-Dcbjp0tU.d.ts → sanitize-BTSsdBXw.d.ts} +1 -1
  50. package/dist/{supervise-BaEsCHNh.d.ts → supervise-DmYOug5f.d.ts} +4 -4
  51. package/dist/{types-CogNCaw7.d.ts → types-1d5QGK3t.d.ts} +1 -1
  52. package/dist/types-BwoZWq-i.d.ts +510 -0
  53. package/dist/{types-CKmyZ9TP.d.ts → types-ByAYqlVb.d.ts} +3 -509
  54. package/dist/{worktree-fanout-Do2YbtFD.d.ts → worktree-fanout-CPprU-qI.d.ts} +4 -4
  55. package/package.json +15 -3
  56. package/dist/chunk-7NCP74SL.js.map +0 -1
  57. package/dist/chunk-GHXW56PO.js.map +0 -1
  58. package/dist/chunk-YP6B7RZ2.js.map +0 -1
  59. /package/dist/{chunk-MXBQNVFE.js.map → chunk-XP5KDM3R.js.map} +0 -0
@@ -0,0 +1,1120 @@
1
+ import {
2
+ createOpenAICompatibleBackend
3
+ } from "../chunk-AEG3NGJ2.js";
4
+ import "../chunk-YEJR7IXO.js";
5
+ import "../chunk-DGUM43GV.js";
6
+
7
+ // src/primeintellect/package.ts
8
+ import { createHash, randomUUID } from "crypto";
9
+ import { mkdir, readFile, rename, rm, stat, writeFile } from "fs/promises";
10
+ import { basename, dirname, isAbsolute, join, normalize, relative, resolve, sep } from "path";
11
+ import { canonicalJson } from "@tangle-network/agent-eval";
12
+
13
+ // src/primeintellect/validation.ts
14
+ function validatePrimeIntellectPrompt(value, path) {
15
+ if (typeof value === "string" && value.length > 0) return value;
16
+ if (!Array.isArray(value) || value.length === 0) {
17
+ throw new Error(`${path} must be a non-empty string or message array`);
18
+ }
19
+ for (const [index, message] of value.entries()) {
20
+ validateMessage(message, `${path}[${index}]`);
21
+ }
22
+ return value;
23
+ }
24
+ function validatePrimeIntellectJson(value, path) {
25
+ if (value === null || ["string", "boolean"].includes(typeof value)) return;
26
+ if (typeof value === "number") {
27
+ if (!Number.isFinite(value)) throw new Error(`${path} contains a non-finite number`);
28
+ return;
29
+ }
30
+ if (Array.isArray(value)) {
31
+ value.forEach((entry, index) => {
32
+ validatePrimeIntellectJson(entry, `${path}[${index}]`);
33
+ });
34
+ return;
35
+ }
36
+ if (typeof value === "object") {
37
+ for (const [key, entry] of Object.entries(value)) {
38
+ validatePrimeIntellectJson(entry, `${path}.${key}`);
39
+ }
40
+ return;
41
+ }
42
+ throw new Error(`${path} is not JSON serializable`);
43
+ }
44
+ function validatePrimeIntellectJsonObject(value, path) {
45
+ const output = record(value, path);
46
+ validatePrimeIntellectJson(output, path);
47
+ return output;
48
+ }
49
+ function validateMessage(value, path) {
50
+ const message = record(value, path);
51
+ const role = message.role;
52
+ if (!["system", "user", "assistant", "tool"].includes(String(role))) {
53
+ throw new Error(`${path}.role is invalid`);
54
+ }
55
+ if (role === "system" || role === "user") {
56
+ assertOnlyKeys(message, ["role", "content"], path);
57
+ validateContent(message.content, `${path}.content`);
58
+ } else if (role === "assistant") {
59
+ assertOnlyKeys(
60
+ message,
61
+ ["role", "content", "reasoning_content", "tool_calls", "provider_state"],
62
+ path
63
+ );
64
+ optionalNullableString(message.content, `${path}.content`);
65
+ optionalNullableString(message.reasoning_content, `${path}.reasoning_content`);
66
+ if (message.tool_calls !== void 0) {
67
+ validateToolCalls(message.tool_calls, `${path}.tool_calls`);
68
+ }
69
+ if (message.provider_state !== void 0) {
70
+ validateProviderState(message.provider_state, `${path}.provider_state`);
71
+ }
72
+ } else {
73
+ assertOnlyKeys(message, ["role", "tool_call_id", "content", "name"], path);
74
+ nonEmptyString(message.tool_call_id, `${path}.tool_call_id`);
75
+ if (message.name !== void 0 && typeof message.name !== "string") {
76
+ throw new Error(`${path}.name must be a string`);
77
+ }
78
+ validateContent(message.content, `${path}.content`);
79
+ }
80
+ validatePrimeIntellectJson(message, path);
81
+ }
82
+ function validateToolCalls(value, path) {
83
+ if (!Array.isArray(value)) throw new Error(`${path} must be an array`);
84
+ for (const [index, rawCall] of value.entries()) {
85
+ const call = record(rawCall, `${path}[${index}]`);
86
+ assertOnlyKeys(call, ["id", "name", "arguments"], `${path}[${index}]`);
87
+ for (const field of ["id", "name", "arguments"]) {
88
+ nonEmptyString(call[field], `${path}[${index}].${field}`);
89
+ }
90
+ }
91
+ }
92
+ function validateProviderState(value, path) {
93
+ if (!Array.isArray(value)) throw new Error(`${path} must be an array`);
94
+ for (const [index, rawState] of value.entries()) {
95
+ const state = record(rawState, `${path}[${index}]`);
96
+ validatePrimeIntellectJson(state, `${path}[${index}]`);
97
+ }
98
+ }
99
+ function validateContent(value, path) {
100
+ if (typeof value === "string") return;
101
+ if (!Array.isArray(value) || value.length === 0) {
102
+ throw new Error(`${path} must be a string or non-empty content array`);
103
+ }
104
+ for (const [index, rawPart] of value.entries()) {
105
+ const part = record(rawPart, `${path}[${index}]`);
106
+ if (part.type === "text" && typeof part.text === "string") {
107
+ assertOnlyKeys(part, ["type", "text"], `${path}[${index}]`);
108
+ continue;
109
+ }
110
+ const image = part.image_url;
111
+ if (part.type === "image_url" && image !== null && typeof image === "object" && !Array.isArray(image) && typeof image.url === "string") {
112
+ assertOnlyKeys(part, ["type", "image_url"], `${path}[${index}]`);
113
+ assertOnlyKeys(image, ["url"], `${path}[${index}].image_url`);
114
+ continue;
115
+ }
116
+ throw new Error(`${path}[${index}] is not a supported text or image_url content part`);
117
+ }
118
+ }
119
+ function optionalNullableString(value, path) {
120
+ if (value !== void 0 && value !== null && typeof value !== "string") {
121
+ throw new Error(`${path} must be a string or null`);
122
+ }
123
+ }
124
+ function nonEmptyString(value, path) {
125
+ if (typeof value !== "string" || value.length === 0) {
126
+ throw new Error(`${path} must be a non-empty string`);
127
+ }
128
+ return value;
129
+ }
130
+ function record(value, path) {
131
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
132
+ throw new Error(`${path} must be an object`);
133
+ }
134
+ return value;
135
+ }
136
+ function assertOnlyKeys(value, allowed, path) {
137
+ for (const key of Object.keys(value)) {
138
+ if (!allowed.includes(key)) throw new Error(`${path}.${key} is not supported`);
139
+ }
140
+ }
141
+
142
+ // src/primeintellect/package.ts
143
+ var VERIFIERS_RANGE = ">=0.2.0,<0.3.0";
144
+ var ENV_NAME = /^[A-Z_][A-Z0-9_]*$/;
145
+ var PACKAGE_NAME = /^[a-z][a-z0-9-]{0,62}$/;
146
+ var VERSION = /^\d+\.\d+\.\d+(?:[-+][a-zA-Z0-9.-]+)?$/;
147
+ var DEFAULT_MAX_TURNS = 16;
148
+ var DEFAULT_ROLLOUT_TIMEOUT = 3600;
149
+ var DEFAULT_SCORING_TIMEOUT = 300;
150
+ function createPrimeIntellectPackage(options) {
151
+ const validated = validateOptions(options);
152
+ const moduleName = validated.name.replaceAll("-", "_");
153
+ const rows = validated.tasks.map((task, idx) => taskRow(task, idx));
154
+ const runnerFiles = validated.runner.files ?? {};
155
+ const scoringFiles = validated.scoring.kind === "command" ? validated.scoring.files ?? {} : {};
156
+ const files = {
157
+ "pyproject.toml": renderPyproject(validated, moduleName),
158
+ "prime.eval.toml": renderPrimeConfig(validated, "eval"),
159
+ "prime.train.toml": renderPrimeConfig(validated, "train"),
160
+ "README.md": renderReadme(validated),
161
+ [`${moduleName}/__init__.py`]: renderInit(moduleName),
162
+ [`${moduleName}/taskset.py`]: renderTaskset(moduleName, validated.scoring),
163
+ [`${moduleName}/harness.py`]: renderHarness(moduleName),
164
+ [`${moduleName}/tasks.jsonl`]: `${rows.map((row) => JSON.stringify(row)).join("\n")}
165
+ `,
166
+ [`${moduleName}/runner.json`]: `${JSON.stringify(
167
+ {
168
+ command: validated.runner.command,
169
+ files: runnerFiles,
170
+ setup: validated.runner.setup ?? [],
171
+ forwardEnv: validated.runner.forwardEnv ?? []
172
+ },
173
+ null,
174
+ 2
175
+ )}
176
+ `
177
+ };
178
+ for (const [path, contents] of Object.entries(scoringFiles)) {
179
+ files[`${moduleName}/scoring/${path}`] = contents;
180
+ }
181
+ const filesSha256 = Object.fromEntries(
182
+ Object.entries(files).sort(([left], [right]) => left.localeCompare(right)).map(([path, contents]) => [path, sha256(contents)])
183
+ );
184
+ const manifest = {
185
+ schema: "tangle.primeintellect.package/v1",
186
+ name: validated.name,
187
+ moduleName,
188
+ version: validated.version,
189
+ verifiers: VERIFIERS_RANGE,
190
+ taskCount: validated.tasks.length,
191
+ splits: {
192
+ train: validated.tasks.filter((task) => task.split === "train").length,
193
+ eval: validated.tasks.filter((task) => task.split === "eval").length
194
+ },
195
+ taskIdsSha256: sha256(
196
+ validated.tasks.map((task) => `${task.split}:${task.id}`).sort().join("\n")
197
+ ),
198
+ filesSha256
199
+ };
200
+ files["manifest.json"] = `${JSON.stringify(manifest, null, 2)}
201
+ `;
202
+ return { manifest, files: Object.freeze(files) };
203
+ }
204
+ async function writePrimeIntellectPackage(bundle, outputDirectory, options = {}) {
205
+ const output = resolve(outputDirectory);
206
+ const parent = dirname(output);
207
+ await mkdir(parent, { recursive: true });
208
+ const replacing = await pathExists(output);
209
+ if (replacing) {
210
+ if (!options.replace) throw new Error(`PrimeIntellect output already exists: ${output}`);
211
+ await assertGeneratedPackage(output);
212
+ }
213
+ const temporary = join(parent, `.${basename(output)}.${randomUUID()}.tmp`);
214
+ const backup = replacing ? join(parent, `.${basename(output)}.${randomUUID()}.backup`) : void 0;
215
+ try {
216
+ await mkdir(temporary);
217
+ for (const [path, contents] of Object.entries(bundle.files)) {
218
+ assertRelativePath(path, "bundle file");
219
+ const target = resolve(temporary, path);
220
+ if (target !== temporary && !target.startsWith(`${temporary}${sep}`)) {
221
+ throw new Error(`bundle file escapes output directory: ${path}`);
222
+ }
223
+ await mkdir(dirname(target), { recursive: true });
224
+ await writeFile(target, contents, "utf8");
225
+ }
226
+ if (backup) await rename(output, backup);
227
+ try {
228
+ await rename(temporary, output);
229
+ } catch (error) {
230
+ if (backup) {
231
+ try {
232
+ await rename(backup, output);
233
+ } catch (restoreError) {
234
+ throw new AggregateError(
235
+ [error, restoreError],
236
+ `failed to install PrimeIntellect package and restore ${output}`
237
+ );
238
+ }
239
+ }
240
+ throw error;
241
+ }
242
+ if (backup) await rm(backup, { recursive: true });
243
+ } catch (error) {
244
+ await rm(temporary, { recursive: true, force: true });
245
+ throw error;
246
+ }
247
+ return output;
248
+ }
249
+ function validateOptions(options) {
250
+ if (!PACKAGE_NAME.test(options.name)) {
251
+ throw new Error("PrimeIntellect package name must match /^[a-z][a-z0-9-]{0,62}$/");
252
+ }
253
+ if (!VERSION.test(options.version)) {
254
+ throw new Error("PrimeIntellect package version must be a numeric semantic version");
255
+ }
256
+ if (!Array.isArray(options.tasks) || options.tasks.length === 0) {
257
+ throw new Error("PrimeIntellect package requires tasks");
258
+ }
259
+ const tasks = options.tasks;
260
+ const seen = /* @__PURE__ */ new Set();
261
+ const seenInputs = /* @__PURE__ */ new Map();
262
+ const splitCounts = { train: 0, eval: 0 };
263
+ for (const [index, task] of tasks.entries()) {
264
+ validateTask(task, index, options.scoring);
265
+ if (seen.has(task.id)) throw new Error(`duplicate PrimeIntellect task id: ${task.id}`);
266
+ seen.add(task.id);
267
+ const input = canonicalJson({
268
+ prompt: task.prompt,
269
+ systemPrompt: task.systemPrompt ?? null,
270
+ metadata: task.metadata ?? {}
271
+ });
272
+ const duplicate = seenInputs.get(input);
273
+ if (duplicate) {
274
+ throw new Error(
275
+ `PrimeIntellect tasks ${duplicate.id} (${duplicate.split}) and ${task.id} (${task.split}) expose the same public input`
276
+ );
277
+ }
278
+ seenInputs.set(input, { id: task.id, split: task.split });
279
+ splitCounts[task.split] += 1;
280
+ }
281
+ if (splitCounts.train === 0 || splitCounts.eval === 0) {
282
+ throw new Error("PrimeIntellect package requires non-empty, disjoint train and eval splits");
283
+ }
284
+ validateScoring(options.scoring);
285
+ validateCommand(options.runner.command, "runner.command");
286
+ validateFiles(options.runner.files ?? {}, "runner.files");
287
+ for (const [index, command] of (options.runner.setup ?? []).entries()) {
288
+ validateCommand(command, `runner.setup[${index}]`);
289
+ }
290
+ validateEnvNames(options.runner.forwardEnv ?? [], "runner.forwardEnv");
291
+ if (typeof options.runner.image !== "string" || options.runner.image.trim().length === 0) {
292
+ throw new Error("runner.image must be a non-empty container image");
293
+ }
294
+ if (/(^|:)latest$/i.test(options.runner.image)) {
295
+ throw new Error("runner.image must not use the mutable latest tag");
296
+ }
297
+ positiveInteger(options.maxTurns ?? DEFAULT_MAX_TURNS, "maxTurns");
298
+ for (const [name, value] of [
299
+ ["maxInputTokens", options.maxInputTokens],
300
+ ["maxOutputTokens", options.maxOutputTokens],
301
+ ["maxTotalTokens", options.maxTotalTokens]
302
+ ]) {
303
+ if (value !== void 0) positiveInteger(value, name);
304
+ }
305
+ positiveNumber(options.rolloutTimeoutSeconds ?? DEFAULT_ROLLOUT_TIMEOUT, "rolloutTimeoutSeconds");
306
+ positiveNumber(options.scoringTimeoutSeconds ?? DEFAULT_SCORING_TIMEOUT, "scoringTimeoutSeconds");
307
+ return options;
308
+ }
309
+ function validateTask(task, index, scoring) {
310
+ const path = `tasks[${index}]`;
311
+ if (typeof task.id !== "string" || task.id.trim().length === 0) {
312
+ throw new Error(`${path}.id must be a non-empty string`);
313
+ }
314
+ if (task.split !== "train" && task.split !== "eval") {
315
+ throw new Error(`${path}.split must be train or eval`);
316
+ }
317
+ const prompt = validatePrimeIntellectPrompt(task.prompt, `${path}.prompt`);
318
+ if (Array.isArray(prompt)) {
319
+ if (task.systemPrompt !== void 0 && prompt.some((message) => message.role === "system")) {
320
+ throw new Error(`${path} must not set systemPrompt and include a system message`);
321
+ }
322
+ }
323
+ if (task.systemPrompt !== void 0 && typeof task.systemPrompt !== "string") {
324
+ throw new Error(`${path}.systemPrompt must be a string`);
325
+ }
326
+ if (task.metadata !== void 0) {
327
+ validatePrimeIntellectJson(task.metadata, `${path}.metadata`);
328
+ }
329
+ if (scoring.kind !== "command") {
330
+ const answers = Array.isArray(task.answer) ? task.answer : [task.answer];
331
+ if (answers.length === 0 || answers.some((answer) => typeof answer !== "string" || answer.length === 0)) {
332
+ throw new Error(`${path}.answer is required for ${scoring.kind} scoring`);
333
+ }
334
+ }
335
+ }
336
+ function validateScoring(scoring) {
337
+ if (scoring.kind === "exact") return;
338
+ if (scoring.kind === "reference-judge") {
339
+ if (typeof scoring.model !== "string" || scoring.model.length === 0) {
340
+ throw new Error("reference-judge scoring requires a model");
341
+ }
342
+ return;
343
+ }
344
+ validateCommand(scoring.command, "scoring.command");
345
+ validateFiles(scoring.files ?? {}, "scoring.files");
346
+ validateEnvNames(scoring.forwardEnv ?? [], "scoring.forwardEnv");
347
+ positiveNumber(scoring.timeoutSeconds ?? DEFAULT_SCORING_TIMEOUT, "scoring.timeoutSeconds");
348
+ }
349
+ function validateCommand(command, path) {
350
+ if (!Array.isArray(command) || command.length === 0) {
351
+ throw new Error(`${path} must be a non-empty argv array`);
352
+ }
353
+ for (const [index, argument] of command.entries()) {
354
+ if (typeof argument !== "string" || argument.length === 0 || argument.includes("\0")) {
355
+ throw new Error(`${path}[${index}] must be a non-empty string without NUL bytes`);
356
+ }
357
+ }
358
+ }
359
+ function validateFiles(files, path) {
360
+ for (const [file, contents] of Object.entries(files)) {
361
+ assertRelativePath(file, path);
362
+ if (typeof contents !== "string") throw new Error(`${path}.${file} must be a string`);
363
+ }
364
+ }
365
+ function validateEnvNames(names, path) {
366
+ const seen = /* @__PURE__ */ new Set();
367
+ for (const [index, name] of names.entries()) {
368
+ if (!ENV_NAME.test(name)) throw new Error(`${path}[${index}] is not a valid environment name`);
369
+ if (seen.has(name)) throw new Error(`${path} contains duplicate name ${name}`);
370
+ seen.add(name);
371
+ }
372
+ }
373
+ function assertRelativePath(path, label) {
374
+ const normalized = normalize(path);
375
+ if (path.length === 0 || path.includes("\0") || isAbsolute(path) || normalized === ".." || normalized.startsWith(`..${sep}`) || relative(".", normalized).startsWith("..")) {
376
+ throw new Error(`${label} contains unsafe path: ${path}`);
377
+ }
378
+ }
379
+ function taskRow(task, idx) {
380
+ return {
381
+ idx,
382
+ name: task.id,
383
+ prompt: task.prompt,
384
+ system_prompt: task.systemPrompt ?? null,
385
+ split: task.split,
386
+ answer: task.answer ?? null,
387
+ metadata: task.metadata ?? {}
388
+ };
389
+ }
390
+ function renderPyproject(options, moduleName) {
391
+ const description = options.description ?? `PrimeIntellect tasks for ${options.name}`;
392
+ return `[project]
393
+ name = ${toml(options.name)}
394
+ version = ${toml(options.version)}
395
+ description = ${toml(description)}
396
+ requires-python = ">=3.11,<3.14"
397
+ dependencies = ["verifiers${VERIFIERS_RANGE}"]
398
+
399
+ [build-system]
400
+ requires = ["hatchling"]
401
+ build-backend = "hatchling.build"
402
+
403
+ [tool.hatch.build.targets.wheel]
404
+ packages = [${toml(moduleName)}]
405
+
406
+ [tool.uv]
407
+ prerelease = "allow"
408
+ `;
409
+ }
410
+ function renderPrimeConfig(options, split) {
411
+ const limits = [
412
+ `max_turns = ${options.maxTurns ?? DEFAULT_MAX_TURNS}`,
413
+ options.maxInputTokens === void 0 ? void 0 : `max_input_tokens = ${options.maxInputTokens}`,
414
+ options.maxOutputTokens === void 0 ? void 0 : `max_output_tokens = ${options.maxOutputTokens}`,
415
+ options.maxTotalTokens === void 0 ? void 0 : `max_total_tokens = ${options.maxTotalTokens}`
416
+ ].filter((line) => line !== void 0);
417
+ return `${limits.join("\n")}
418
+ push = false
419
+
420
+ [timeout]
421
+ rollout = ${options.rolloutTimeoutSeconds ?? DEFAULT_ROLLOUT_TIMEOUT}
422
+ scoring = ${options.scoringTimeoutSeconds ?? DEFAULT_SCORING_TIMEOUT}
423
+
424
+ [taskset]
425
+ id = ${toml(options.name)}
426
+ split = ${toml(split)}
427
+
428
+ [harness]
429
+ id = ${toml(options.name)}
430
+ program = ${tomlArray(options.runner.command)}
431
+ forward_env = ${tomlArray(options.runner.forwardEnv ?? [])}
432
+
433
+ [harness.runtime]
434
+ type = "docker"
435
+ image = ${toml(options.runner.image)}
436
+ `;
437
+ }
438
+ function renderInit(moduleName) {
439
+ return `from ${moduleName}.harness import TangleRuntimeHarness
440
+ from ${moduleName}.taskset import TangleTaskset
441
+
442
+ __all__ = ["TangleRuntimeHarness", "TangleTaskset"]
443
+ `;
444
+ }
445
+ function renderTaskset(moduleName, scoring) {
446
+ const config = scoringConfig(scoring);
447
+ return `import asyncio
448
+ import json
449
+ import math
450
+ import os
451
+ from importlib.resources import files
452
+ from pathlib import Path
453
+ from typing import Any, Literal
454
+
455
+ import verifiers.v1 as vf
456
+
457
+ SCORING = json.loads(${pythonString(JSON.stringify(config))})
458
+ PACKAGE_ROOT = Path(__file__).resolve().parent
459
+
460
+
461
+ class TangleTaskData(vf.TaskData):
462
+ split: Literal["train", "eval"]
463
+ answer: str | list[str] | None = None
464
+ metadata: dict[str, Any] = {}
465
+
466
+
467
+ class TangleTaskConfig(vf.TaskConfig):
468
+ scoring: Literal["exact", "reference-judge", "command"] = SCORING["kind"]
469
+ normalization: Literal["none", "trim", "trim-casefold"] = SCORING.get("normalization", "trim")
470
+ judge_model: str = SCORING.get("model", "openai/gpt-5.4-nano")
471
+ judge_prompt: str | None = SCORING.get("prompt")
472
+ judge_view: Literal["last_reply", "full_trace"] = SCORING.get("view", "last_reply")
473
+ score_program: list[str] = SCORING.get("command", [])
474
+ score_forward_env: list[str] = SCORING.get("forwardEnv", [])
475
+ score_timeout_seconds: float = SCORING.get("timeoutSeconds", 300)
476
+
477
+
478
+ def _normalize(value: str, mode: str) -> str:
479
+ if mode == "none":
480
+ return value
481
+ value = value.strip()
482
+ return value.casefold() if mode == "trim-casefold" else value
483
+
484
+
485
+ async def _run_score_command(config: TangleTaskConfig, data: TangleTaskData, trace: vf.Trace) -> float:
486
+ if not config.score_program:
487
+ raise ValueError("command scoring requires score_program")
488
+ safe_env = {
489
+ key: os.environ[key]
490
+ for key in ("PATH", "HOME", "TMPDIR", "LANG")
491
+ if key in os.environ
492
+ }
493
+ safe_env.update(
494
+ {key: os.environ[key] for key in config.score_forward_env if key in os.environ}
495
+ )
496
+ request = {
497
+ "protocol": "tangle.primeintellect.score/v1",
498
+ "task": data.model_dump(mode="json", exclude_none=True),
499
+ "trace": trace.model_dump(mode="json", exclude_none=True),
500
+ }
501
+ process = await asyncio.create_subprocess_exec(
502
+ *config.score_program,
503
+ cwd=PACKAGE_ROOT,
504
+ env=safe_env,
505
+ stdin=asyncio.subprocess.PIPE,
506
+ stdout=asyncio.subprocess.PIPE,
507
+ stderr=asyncio.subprocess.PIPE,
508
+ )
509
+ payload = json.dumps(request, separators=(",", ":")).encode()
510
+ try:
511
+ stdout, stderr = await asyncio.wait_for(
512
+ process.communicate(payload), timeout=config.score_timeout_seconds
513
+ )
514
+ except TimeoutError:
515
+ process.kill()
516
+ await process.communicate()
517
+ raise RuntimeError(
518
+ f"score command timed out after {config.score_timeout_seconds}s"
519
+ )
520
+ if process.returncode != 0:
521
+ detail = (stderr or stdout).decode(errors="replace").strip()[-2000:]
522
+ raise RuntimeError(f"score command exited {process.returncode}: {detail}")
523
+ try:
524
+ result = json.loads(stdout)
525
+ except json.JSONDecodeError as error:
526
+ raise ValueError(f"score command returned invalid JSON: {error}") from error
527
+ if not isinstance(result, dict):
528
+ raise ValueError("score command must return an object")
529
+ reward = result.get("reward")
530
+ if isinstance(reward, bool) or not isinstance(reward, (int, float)) or not math.isfinite(reward):
531
+ raise ValueError("score command reward must be a finite number")
532
+ metrics = result.get("metrics", {})
533
+ if not isinstance(metrics, dict):
534
+ raise ValueError("score command metrics must be an object")
535
+ for name, value in metrics.items():
536
+ if isinstance(value, bool) or not isinstance(value, (int, float)) or not math.isfinite(value):
537
+ raise ValueError(f"score command metric {name!r} must be a finite number")
538
+ trace.record_metrics(metrics)
539
+ return float(reward)
540
+
541
+
542
+ class TangleTask(vf.Task[TangleTaskData, vf.State, TangleTaskConfig]):
543
+ @vf.reward(weight=1.0)
544
+ async def task_reward(self, trace: vf.Trace) -> float:
545
+ if self.config.scoring == "command":
546
+ return await _run_score_command(self.config, self.data, trace)
547
+ if self.data.answer is None:
548
+ raise ValueError(f"task {self.data.name!r} has no reference answer")
549
+ if self.config.scoring == "reference-judge":
550
+ judge = vf.ReferenceJudge(
551
+ vf.ReferenceJudgeConfig(
552
+ model=self.config.judge_model,
553
+ prompt=self.config.judge_prompt,
554
+ view=self.config.judge_view,
555
+ )
556
+ )
557
+ return await judge.score(self.data, trace)
558
+ expected = self.data.answer if isinstance(self.data.answer, list) else [self.data.answer]
559
+ actual = _normalize(trace.last_reply, self.config.normalization)
560
+ return float(any(actual == _normalize(answer, self.config.normalization) for answer in expected))
561
+
562
+
563
+ class TangleTasksetConfig(vf.TasksetConfig):
564
+ split: Literal["train", "eval"] = "eval"
565
+ task: TangleTaskConfig = TangleTaskConfig()
566
+
567
+
568
+ class TangleTaskset(vf.Taskset[TangleTask, TangleTasksetConfig]):
569
+ def load(self) -> list[TangleTask]:
570
+ resource = files(${pythonString(moduleName)}).joinpath("tasks.jsonl")
571
+ tasks: list[TangleTask] = []
572
+ with resource.open("r", encoding="utf-8") as handle:
573
+ for line in handle:
574
+ if not line.strip():
575
+ continue
576
+ row = json.loads(line)
577
+ if row["split"] != self.config.split:
578
+ continue
579
+ tasks.append(TangleTask(TangleTaskData.model_validate(row), self.config.task))
580
+ if not tasks:
581
+ raise ValueError(f"task split {self.config.split!r} is empty")
582
+ return tasks
583
+
584
+
585
+ __all__ = ["TangleTaskset"]
586
+ `;
587
+ }
588
+ function renderHarness(moduleName) {
589
+ return `import json
590
+ from importlib.resources import files
591
+
592
+ import verifiers.v1 as vf
593
+
594
+ RUNNER = json.loads(files(${pythonString(moduleName)}).joinpath("runner.json").read_text(encoding="utf-8"))
595
+
596
+
597
+ class TangleRuntimeHarnessConfig(vf.HarnessConfig):
598
+ program: list[str] = RUNNER["command"]
599
+ setup_commands: list[list[str]] = RUNNER["setup"]
600
+ forward_env: list[str] = RUNNER["forwardEnv"]
601
+
602
+
603
+ class TangleRuntimeHarness(vf.Harness[TangleRuntimeHarnessConfig]):
604
+ APPENDS_SYSTEM_PROMPT = True
605
+ SUPPORTS_MCP = True
606
+ SUPPORTS_MESSAGE_PROMPT = True
607
+
608
+ async def setup(self, runtime: vf.Runtime) -> None:
609
+ for path, contents in RUNNER["files"].items():
610
+ await runtime.write(path, contents.encode())
611
+ for command in self.config.setup_commands:
612
+ result = await runtime.run(command, self.config.resolved_env)
613
+ if result.exit_code != 0:
614
+ detail = (result.stderr or result.stdout).strip()[-2000:]
615
+ raise RuntimeError(
616
+ f"runner setup command {command[0]!r} exited {result.exit_code}: {detail}"
617
+ )
618
+
619
+ async def launch(
620
+ self,
621
+ ctx: vf.ModelContext,
622
+ trace: vf.Trace,
623
+ runtime: vf.Runtime,
624
+ endpoint: str,
625
+ secret: str,
626
+ mcp_urls: dict[str, str],
627
+ ) -> vf.ProgramResult:
628
+ data = trace.task.data
629
+ public_task = {
630
+ "id": data.name or str(data.idx),
631
+ "split": data.split,
632
+ "prompt": data.prompt,
633
+ "metadata": data.metadata,
634
+ }
635
+ if data.system_prompt is not None:
636
+ public_task["systemPrompt"] = data.system_prompt
637
+ env = {
638
+ **self.config.resolved_env,
639
+ "OPENAI_BASE_URL": endpoint,
640
+ "OPENAI_API_KEY": secret,
641
+ "OPENAI_MODEL": ctx.model,
642
+ "TANGLE_PRIME_TASK_JSON": json.dumps(public_task, separators=(",", ":")),
643
+ "TANGLE_PRIME_MCP_SERVERS_JSON": json.dumps(mcp_urls, separators=(",", ":")),
644
+ }
645
+ if not self.config.program:
646
+ raise ValueError("Tangle runtime harness requires a program argv")
647
+ return await runtime.run_program(self.config.program, env)
648
+
649
+
650
+ __all__ = ["TangleRuntimeHarness"]
651
+ `;
652
+ }
653
+ function scoringConfig(scoring) {
654
+ if (scoring.kind === "exact") {
655
+ return { kind: scoring.kind, normalization: scoring.normalization ?? "trim" };
656
+ }
657
+ if (scoring.kind === "reference-judge") {
658
+ return {
659
+ kind: scoring.kind,
660
+ model: scoring.model,
661
+ prompt: scoring.prompt ?? null,
662
+ view: scoring.view ?? "last_reply"
663
+ };
664
+ }
665
+ return {
666
+ kind: scoring.kind,
667
+ command: [...scoring.command],
668
+ forwardEnv: [...scoring.forwardEnv ?? []],
669
+ timeoutSeconds: scoring.timeoutSeconds ?? DEFAULT_SCORING_TIMEOUT
670
+ };
671
+ }
672
+ function renderReadme(options) {
673
+ return `# ${options.name}
674
+
675
+ PrimeIntellect Verifiers v1 tasks that run the caller's Tangle agent program.
676
+
677
+ ## Evaluate
678
+
679
+ \`\`\`bash
680
+ uv run eval @ prime.eval.toml --model <provider/model-snapshot>
681
+ \`\`\`
682
+
683
+ ## Train
684
+
685
+ Use \`prime.train.toml\` as the environment config for Prime RL. The train and eval rows are disjoint and selected by \`taskset.split\`.
686
+
687
+ The runner receives only the prompt, metadata, intercepted model endpoint, and MCP URLs. Reference answers remain in the task process and are never written into the runner workspace or environment.
688
+ `;
689
+ }
690
+ function toml(value) {
691
+ return JSON.stringify(value);
692
+ }
693
+ function tomlArray(values) {
694
+ return `[${values.map(toml).join(", ")}]`;
695
+ }
696
+ function pythonString(value) {
697
+ return JSON.stringify(value);
698
+ }
699
+ function positiveInteger(value, path) {
700
+ if (!Number.isSafeInteger(value) || value <= 0)
701
+ throw new Error(`${path} must be a positive integer`);
702
+ }
703
+ function positiveNumber(value, path) {
704
+ if (!Number.isFinite(value) || value <= 0) throw new Error(`${path} must be positive`);
705
+ }
706
+ async function pathExists(path) {
707
+ try {
708
+ await stat(path);
709
+ return true;
710
+ } catch (error) {
711
+ if (error.code === "ENOENT") return false;
712
+ throw error;
713
+ }
714
+ }
715
+ async function assertGeneratedPackage(output) {
716
+ let manifest;
717
+ try {
718
+ manifest = JSON.parse(await readFile(join(output, "manifest.json"), "utf8"));
719
+ } catch (error) {
720
+ throw new Error(
721
+ `refusing to replace ${output}: it is not a generated PrimeIntellect package (${error instanceof Error ? error.message : String(error)})`
722
+ );
723
+ }
724
+ if (manifest === null || typeof manifest !== "object" || manifest.schema !== "tangle.primeintellect.package/v1") {
725
+ throw new Error(`refusing to replace ${output}: manifest schema does not match`);
726
+ }
727
+ }
728
+ function sha256(value) {
729
+ return createHash("sha256").update(value, "utf8").digest("hex");
730
+ }
731
+
732
+ // src/primeintellect/runner.ts
733
+ var ENV = {
734
+ task: "TANGLE_PRIME_TASK_JSON",
735
+ model: "OPENAI_MODEL",
736
+ baseUrl: "OPENAI_BASE_URL",
737
+ apiKey: "OPENAI_API_KEY",
738
+ mcpServers: "TANGLE_PRIME_MCP_SERVERS_JSON"
739
+ };
740
+ function readPrimeIntellectEpisodeContext(env = process.env) {
741
+ const rawTask = requiredEnv(env, ENV.task);
742
+ const rawMcp = env[ENV.mcpServers] ?? "{}";
743
+ const parsedTask = parseJson(rawTask, ENV.task);
744
+ const parsedMcp = parseJson(rawMcp, ENV.mcpServers);
745
+ const task = validatePublicTask(parsedTask);
746
+ const mcpServers = validateStringMap(parsedMcp, ENV.mcpServers);
747
+ return {
748
+ protocol: "tangle.primeintellect.episode/v1",
749
+ task,
750
+ model: {
751
+ name: requiredEnv(env, ENV.model),
752
+ baseUrl: requiredEnv(env, ENV.baseUrl),
753
+ apiKey: requiredEnv(env, ENV.apiKey)
754
+ },
755
+ mcpServers
756
+ };
757
+ }
758
+ function createPrimeIntellectBackend(context, options = {}) {
759
+ return createOpenAICompatibleBackend({
760
+ ...options,
761
+ apiKey: context.model.apiKey,
762
+ baseUrl: context.model.baseUrl,
763
+ model: context.model.name,
764
+ kind: options.kind ?? "primeintellect"
765
+ });
766
+ }
767
+ async function runPrimeIntellectProgram(run, options = {}) {
768
+ return run(readPrimeIntellectEpisodeContext(options.env));
769
+ }
770
+ function requiredEnv(env, name) {
771
+ const value = env[name];
772
+ if (typeof value !== "string" || value.length === 0) {
773
+ throw new Error(`PrimeIntellect runner requires ${name}`);
774
+ }
775
+ return value;
776
+ }
777
+ function parseJson(value, name) {
778
+ try {
779
+ return JSON.parse(value);
780
+ } catch (error) {
781
+ throw new Error(
782
+ `${name} must contain valid JSON: ${error instanceof Error ? error.message : String(error)}`
783
+ );
784
+ }
785
+ }
786
+ function validatePublicTask(value) {
787
+ const task = record2(value, ENV.task);
788
+ for (const privateField of ["answer", "reference", "scoring", "score"]) {
789
+ if (privateField in task) {
790
+ throw new Error(`${ENV.task} exposed private field ${privateField}`);
791
+ }
792
+ }
793
+ for (const field of Object.keys(task)) {
794
+ if (!["id", "split", "prompt", "systemPrompt", "metadata"].includes(field)) {
795
+ throw new Error(`${ENV.task}.${field} is not supported`);
796
+ }
797
+ }
798
+ const id = nonEmptyString2(task.id, `${ENV.task}.id`);
799
+ const split = validateSplit(task.split, `${ENV.task}.split`);
800
+ const prompt = validatePrimeIntellectPrompt(task.prompt, `${ENV.task}.prompt`);
801
+ const systemPrompt = optionalString(task.systemPrompt, `${ENV.task}.systemPrompt`);
802
+ if (systemPrompt !== void 0 && Array.isArray(prompt) && prompt.some((message) => message.role === "system")) {
803
+ throw new Error(`${ENV.task} must not set systemPrompt and include a system message`);
804
+ }
805
+ const metadata = task.metadata === void 0 ? void 0 : validatePrimeIntellectJsonObject(task.metadata, `${ENV.task}.metadata`);
806
+ return {
807
+ id,
808
+ split,
809
+ prompt,
810
+ ...systemPrompt !== void 0 ? { systemPrompt } : {},
811
+ ...metadata !== void 0 ? { metadata } : {}
812
+ };
813
+ }
814
+ function validateSplit(value, path) {
815
+ if (value !== "train" && value !== "eval") {
816
+ throw new Error(`${path} must be train or eval`);
817
+ }
818
+ return value;
819
+ }
820
+ function validateStringMap(value, path) {
821
+ const input = record2(value, path);
822
+ const output = {};
823
+ for (const [key, entry] of Object.entries(input)) {
824
+ if (typeof entry !== "string" || entry.length === 0) {
825
+ throw new Error(`${path}.${key} must be a non-empty string`);
826
+ }
827
+ output[key] = entry;
828
+ }
829
+ return output;
830
+ }
831
+ function record2(value, path) {
832
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
833
+ throw new Error(`${path} must be an object`);
834
+ }
835
+ return value;
836
+ }
837
+ function nonEmptyString2(value, path) {
838
+ if (typeof value !== "string" || value.length === 0) {
839
+ throw new Error(`${path} must be a non-empty string`);
840
+ }
841
+ return value;
842
+ }
843
+ function optionalString(value, path) {
844
+ if (value === void 0) return void 0;
845
+ if (typeof value !== "string") throw new Error(`${path} must be a string`);
846
+ return value;
847
+ }
848
+
849
+ // src/primeintellect/traces.ts
850
+ import { validateRunRecord } from "@tangle-network/agent-eval";
851
+ function parsePrimeIntellectTraces(jsonl) {
852
+ const traces = [];
853
+ for (const [lineIndex, line] of jsonl.split("\n").entries()) {
854
+ if (!line.trim()) continue;
855
+ let parsed;
856
+ try {
857
+ parsed = JSON.parse(line);
858
+ } catch (error) {
859
+ throw new Error(
860
+ `PrimeIntellect trace line ${lineIndex + 1} is invalid JSON: ${error instanceof Error ? error.message : String(error)}`
861
+ );
862
+ }
863
+ traces.push(validateTrace(parsed, lineIndex + 1));
864
+ }
865
+ if (traces.length === 0) throw new Error("PrimeIntellect traces.jsonl contains no traces");
866
+ return traces;
867
+ }
868
+ function importPrimeIntellectTraces(jsonl, defaults) {
869
+ return parsePrimeIntellectTraces(jsonl).map(
870
+ (trace) => primeIntellectTraceToRunRecord(trace, defaults)
871
+ );
872
+ }
873
+ function primeIntellectTraceToRunRecord(trace, options) {
874
+ const split = trace.task.data.split;
875
+ if (split !== "train" && split !== "eval") {
876
+ throw new Error(`PrimeIntellect trace ${trace.id} has no train/eval split`);
877
+ }
878
+ const reward = sumFinite(Object.values(trace.rewards), `trace ${trace.id} rewards`);
879
+ const usage = aggregateUsage([
880
+ ...trace.nodes.map((node) => node.usage).filter((value) => value != null),
881
+ ...trace.extra_usage ?? []
882
+ ]);
883
+ const errors = trace.errors ?? [];
884
+ const raw = {
885
+ reward,
886
+ "prime.turns": trace.nodes.filter((node) => node.sampled === true).length,
887
+ "prime.branches": countBranches(trace.nodes),
888
+ "prime.errors": errors.length,
889
+ "prime.completed": trace.is_completed ? 1 : 0,
890
+ "prime.cost_complete": usage.costComplete ? 1 : 0,
891
+ "prime.reported_cost_usd": usage.reportedCostUsd
892
+ };
893
+ for (const [name, value] of Object.entries(trace.rewards)) {
894
+ raw[`reward.${name}`] = finite(value, `trace ${trace.id} reward ${name}`);
895
+ }
896
+ for (const [name, value] of Object.entries(trace.metrics)) {
897
+ raw[`metric.${name}`] = finite(value, `trace ${trace.id} metric ${name}`);
898
+ }
899
+ const record3 = {
900
+ runId: trace.id,
901
+ experimentId: options.experimentId,
902
+ candidateId: options.candidateId,
903
+ seed: options.seed,
904
+ model: options.model,
905
+ promptHash: options.promptHash,
906
+ configHash: options.configHash,
907
+ commitSha: options.commitSha,
908
+ wallMs: traceWallMs(trace),
909
+ costUsd: usage.costComplete ? usage.reportedCostUsd : 0,
910
+ costProvenance: usage.costComplete ? { kind: "observed", usd: usage.reportedCostUsd } : { kind: "uncaptured", usd: null },
911
+ tokenUsage: {
912
+ input: usage.input,
913
+ output: usage.output,
914
+ ...usage.reasoning !== void 0 ? { reasoning: usage.reasoning } : {},
915
+ ...usage.cached !== void 0 ? { cached: usage.cached } : {}
916
+ },
917
+ outcome: split === "eval" ? { holdoutScore: reward, raw } : { searchScore: reward, raw },
918
+ splitTag: split === "eval" ? "holdout" : "search",
919
+ scenarioId: trace.task.data.name ?? String(trace.task.data.idx),
920
+ ...errors[0] ? { failureMode: `primeintellect:${errors[0].type}:${errors[0].message}` } : {}
921
+ };
922
+ return validateRunRecord(record3);
923
+ }
924
+ function validateTrace(value, line) {
925
+ const trace = object(value, `PrimeIntellect trace line ${line}`);
926
+ nonEmptyString3(trace.id, `PrimeIntellect trace line ${line}.id`);
927
+ const task = object(trace.task, `PrimeIntellect trace line ${line}.task`);
928
+ nonEmptyString3(task.type, `PrimeIntellect trace line ${line}.task.type`);
929
+ const data = object(task.data, `PrimeIntellect trace line ${line}.task.data`);
930
+ if (!Number.isSafeInteger(data.idx) || data.idx < 0) {
931
+ throw new Error(
932
+ `PrimeIntellect trace line ${line}.task.data.idx must be a non-negative integer`
933
+ );
934
+ }
935
+ if (!Array.isArray(trace.nodes)) {
936
+ throw new Error(`PrimeIntellect trace line ${line}.nodes must be an array`);
937
+ }
938
+ for (const [index, rawNode] of trace.nodes.entries()) {
939
+ const node = object(rawNode, `PrimeIntellect trace line ${line}.nodes[${index}]`);
940
+ const parent = node.parent;
941
+ if (parent !== void 0 && parent !== null && (!Number.isSafeInteger(parent) || parent < 0 || parent >= index)) {
942
+ throw new Error(
943
+ `PrimeIntellect trace line ${line}.nodes[${index}].parent must reference an earlier node`
944
+ );
945
+ }
946
+ if (node.sampled !== void 0 && typeof node.sampled !== "boolean") {
947
+ throw new Error(`PrimeIntellect trace line ${line}.nodes[${index}].sampled must be boolean`);
948
+ }
949
+ if (node.usage !== void 0 && node.usage !== null) {
950
+ validateUsage(node.usage, `PrimeIntellect trace line ${line}.nodes[${index}].usage`);
951
+ }
952
+ }
953
+ validateNumberMap(trace.rewards, `PrimeIntellect trace line ${line}.rewards`);
954
+ validateNumberMap(trace.metrics, `PrimeIntellect trace line ${line}.metrics`);
955
+ if (trace.extra_usage !== void 0 && !Array.isArray(trace.extra_usage)) {
956
+ throw new Error(`PrimeIntellect trace line ${line}.extra_usage must be an array`);
957
+ }
958
+ for (const [index, usage] of (trace.extra_usage ?? []).entries()) {
959
+ validateUsage(usage, `PrimeIntellect trace line ${line}.extra_usage[${index}]`);
960
+ }
961
+ if (trace.errors !== void 0 && !Array.isArray(trace.errors)) {
962
+ throw new Error(`PrimeIntellect trace line ${line}.errors must be an array`);
963
+ }
964
+ for (const [index, rawError] of (trace.errors ?? []).entries()) {
965
+ const error = object(rawError, `PrimeIntellect trace line ${line}.errors[${index}]`);
966
+ nonEmptyString3(error.type, `PrimeIntellect trace line ${line}.errors[${index}].type`);
967
+ nonEmptyString3(error.message, `PrimeIntellect trace line ${line}.errors[${index}].message`);
968
+ if (error.traceback !== void 0 && error.traceback !== null && typeof error.traceback !== "string") {
969
+ throw new Error(
970
+ `PrimeIntellect trace line ${line}.errors[${index}].traceback must be a string or null`
971
+ );
972
+ }
973
+ }
974
+ if (trace.is_completed !== void 0 && typeof trace.is_completed !== "boolean") {
975
+ throw new Error(`PrimeIntellect trace line ${line}.is_completed must be boolean`);
976
+ }
977
+ if (trace.stop_condition !== void 0 && trace.stop_condition !== null && typeof trace.stop_condition !== "string") {
978
+ throw new Error(`PrimeIntellect trace line ${line}.stop_condition must be a string or null`);
979
+ }
980
+ if (trace.timing !== void 0) validateTiming(trace.timing, line);
981
+ return value;
982
+ }
983
+ function validateTiming(value, line) {
984
+ const timing = object(value, `PrimeIntellect trace line ${line}.timing`);
985
+ optionalFinite(timing.start, `PrimeIntellect trace line ${line}.timing.start`);
986
+ for (const phase of ["setup", "generation", "finalize", "scoring"]) {
987
+ if (timing[phase] === void 0) continue;
988
+ const span = object(timing[phase], `PrimeIntellect trace line ${line}.timing.${phase}`);
989
+ optionalFinite(span.start, `PrimeIntellect trace line ${line}.timing.${phase}.start`);
990
+ optionalFinite(span.end, `PrimeIntellect trace line ${line}.timing.${phase}.end`);
991
+ }
992
+ }
993
+ function aggregateUsage(usages) {
994
+ let input = 0;
995
+ let output = 0;
996
+ let reasoning = 0;
997
+ let cached = 0;
998
+ let costUsd = 0;
999
+ let sawReasoning = false;
1000
+ let sawCached = false;
1001
+ let costsReported = 0;
1002
+ for (const [index, usage] of usages.entries()) {
1003
+ const prompt = nonNegative(usage.prompt_tokens, `usage[${index}].prompt_tokens`);
1004
+ const completion = nonNegative(usage.completion_tokens, `usage[${index}].completion_tokens`);
1005
+ const cachedInput = optionalNonNegative(
1006
+ usage.cached_input_tokens,
1007
+ `usage[${index}].cached_input_tokens`
1008
+ );
1009
+ const reasoningTokens = optionalNonNegative(
1010
+ usage.reasoning_tokens,
1011
+ `usage[${index}].reasoning_tokens`
1012
+ );
1013
+ const cost = optionalNonNegative(usage.cost, `usage[${index}].cost`);
1014
+ input += prompt + (cachedInput ?? 0);
1015
+ output += completion;
1016
+ if (cachedInput !== void 0) {
1017
+ cached += cachedInput;
1018
+ sawCached = true;
1019
+ }
1020
+ if (reasoningTokens !== void 0) {
1021
+ reasoning += reasoningTokens;
1022
+ sawReasoning = true;
1023
+ }
1024
+ if (cost !== void 0) {
1025
+ costUsd += cost;
1026
+ costsReported += 1;
1027
+ }
1028
+ }
1029
+ if (reasoning > output) {
1030
+ throw new Error(
1031
+ `PrimeIntellect reasoning token total ${reasoning} exceeds output total ${output}`
1032
+ );
1033
+ }
1034
+ return {
1035
+ input,
1036
+ output,
1037
+ ...sawReasoning ? { reasoning } : {},
1038
+ ...sawCached ? { cached } : {},
1039
+ reportedCostUsd: costUsd,
1040
+ costComplete: usages.length > 0 && costsReported === usages.length
1041
+ };
1042
+ }
1043
+ function validateUsage(value, path) {
1044
+ const usage = object(value, path);
1045
+ nonNegative(usage.prompt_tokens, `${path}.prompt_tokens`);
1046
+ nonNegative(usage.completion_tokens, `${path}.completion_tokens`);
1047
+ optionalNonNegative(usage.cached_input_tokens, `${path}.cached_input_tokens`);
1048
+ optionalNonNegative(usage.reasoning_tokens, `${path}.reasoning_tokens`);
1049
+ optionalNonNegative(usage.cost, `${path}.cost`);
1050
+ }
1051
+ function traceWallMs(trace) {
1052
+ const timing = trace.timing;
1053
+ if (!timing || typeof timing.start !== "number" || !Number.isFinite(timing.start)) return 0;
1054
+ const ends = [
1055
+ timing.setup?.end,
1056
+ timing.generation?.end,
1057
+ timing.finalize?.end,
1058
+ timing.scoring?.end
1059
+ ].filter((value) => typeof value === "number" && Number.isFinite(value));
1060
+ if (ends.length === 0) return 0;
1061
+ return Math.max(0, (Math.max(...ends) - timing.start) * 1e3);
1062
+ }
1063
+ function countBranches(nodes) {
1064
+ if (nodes.length === 0) return 0;
1065
+ const parents = new Set(
1066
+ nodes.map((node) => node.parent).filter(
1067
+ (parent) => Number.isSafeInteger(parent) && parent >= 0
1068
+ )
1069
+ );
1070
+ return nodes.reduce((count, _node, index) => count + (parents.has(index) ? 0 : 1), 0);
1071
+ }
1072
+ function validateNumberMap(value, path) {
1073
+ const map = object(value, path);
1074
+ for (const [key, entry] of Object.entries(map)) finite(entry, `${path}.${key}`);
1075
+ }
1076
+ function sumFinite(values, path) {
1077
+ return values.reduce((sum, value, index) => sum + finite(value, `${path}[${index}]`), 0);
1078
+ }
1079
+ function finite(value, path) {
1080
+ if (typeof value !== "number" || !Number.isFinite(value)) {
1081
+ throw new Error(`${path} must be a finite number`);
1082
+ }
1083
+ return value;
1084
+ }
1085
+ function nonNegative(value, path) {
1086
+ const parsed = finite(value, path);
1087
+ if (parsed < 0) throw new Error(`${path} must be non-negative`);
1088
+ return parsed;
1089
+ }
1090
+ function optionalNonNegative(value, path) {
1091
+ if (value === void 0 || value === null) return void 0;
1092
+ return nonNegative(value, path);
1093
+ }
1094
+ function optionalFinite(value, path) {
1095
+ if (value === void 0 || value === null) return void 0;
1096
+ return finite(value, path);
1097
+ }
1098
+ function object(value, path) {
1099
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
1100
+ throw new Error(`${path} must be an object`);
1101
+ }
1102
+ return value;
1103
+ }
1104
+ function nonEmptyString3(value, path) {
1105
+ if (typeof value !== "string" || value.length === 0) {
1106
+ throw new Error(`${path} must be a non-empty string`);
1107
+ }
1108
+ return value;
1109
+ }
1110
+ export {
1111
+ createPrimeIntellectBackend,
1112
+ createPrimeIntellectPackage,
1113
+ importPrimeIntellectTraces,
1114
+ parsePrimeIntellectTraces,
1115
+ primeIntellectTraceToRunRecord,
1116
+ readPrimeIntellectEpisodeContext,
1117
+ runPrimeIntellectProgram,
1118
+ writePrimeIntellectPackage
1119
+ };
1120
+ //# sourceMappingURL=index.js.map