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