@capybara-hq/kernel 0.0.0-stage → 0.1.0-rc.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 (631) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +2 -0
  3. package/README.md +20 -2
  4. package/bootstrap.json +22 -0
  5. package/dist/admin/admin.controller.d.ts +139 -0
  6. package/dist/admin/admin.controller.js +238 -0
  7. package/dist/admin/extensions.controller.d.ts +100 -0
  8. package/dist/admin/extensions.controller.js +226 -0
  9. package/dist/admin/setup.controller.d.ts +36 -0
  10. package/dist/admin/setup.controller.js +106 -0
  11. package/dist/admin/setup.service.d.ts +47 -0
  12. package/dist/admin/setup.service.js +90 -0
  13. package/dist/agents/agents.controller.d.ts +205 -0
  14. package/dist/agents/agents.controller.js +144 -0
  15. package/dist/agents/agents.service.d.ts +177 -0
  16. package/dist/agents/agents.service.js +677 -0
  17. package/dist/agents/definition.d.ts +198 -0
  18. package/dist/agents/definition.js +152 -0
  19. package/dist/agents/models.controller.d.ts +13 -0
  20. package/dist/agents/models.controller.js +31 -0
  21. package/dist/agents/templates.controller.d.ts +15 -0
  22. package/dist/agents/templates.controller.js +37 -0
  23. package/dist/agents/templates.d.ts +83 -0
  24. package/dist/agents/templates.js +173 -0
  25. package/dist/catalog/admin-catalog.controller.d.ts +143 -0
  26. package/dist/catalog/admin-catalog.controller.js +245 -0
  27. package/dist/catalog/catalog.service.d.ts +430 -0
  28. package/dist/catalog/catalog.service.js +882 -0
  29. package/dist/catalog/claude/agents.d.ts +27 -0
  30. package/dist/catalog/claude/agents.js +270 -0
  31. package/dist/catalog/claude/commands.d.ts +50 -0
  32. package/dist/catalog/claude/commands.js +179 -0
  33. package/dist/catalog/claude/manifest.d.ts +69 -0
  34. package/dist/catalog/claude/manifest.js +134 -0
  35. package/dist/catalog/claude/marketplace.d.ts +35 -0
  36. package/dist/catalog/claude/marketplace.js +194 -0
  37. package/dist/catalog/claude/mcp.d.ts +33 -0
  38. package/dist/catalog/claude/mcp.js +226 -0
  39. package/dist/catalog/claude/report.d.ts +86 -0
  40. package/dist/catalog/claude/report.js +121 -0
  41. package/dist/catalog/claude/translate.d.ts +56 -0
  42. package/dist/catalog/claude/translate.js +857 -0
  43. package/dist/catalog/cli.d.ts +46 -0
  44. package/dist/catalog/cli.js +211 -0
  45. package/dist/catalog/git-source.d.ts +127 -0
  46. package/dist/catalog/git-source.js +520 -0
  47. package/dist/catalog/marketplace-fetch.d.ts +99 -0
  48. package/dist/catalog/marketplace-fetch.js +203 -0
  49. package/dist/catalog/marketplaces.controller.d.ts +97 -0
  50. package/dist/catalog/marketplaces.controller.js +197 -0
  51. package/dist/catalog/marketplaces.service.d.ts +340 -0
  52. package/dist/catalog/marketplaces.service.js +1217 -0
  53. package/dist/catalog/org-catalog.controller.d.ts +128 -0
  54. package/dist/catalog/org-catalog.controller.js +277 -0
  55. package/dist/catalog/org-catalog.service.d.ts +246 -0
  56. package/dist/catalog/org-catalog.service.js +625 -0
  57. package/dist/catalog/plugin-import.d.ts +436 -0
  58. package/dist/catalog/plugin-import.js +1069 -0
  59. package/dist/catalog/plugin-install.d.ts +447 -0
  60. package/dist/catalog/plugin-install.js +1333 -0
  61. package/dist/catalog/plugin-package.d.ts +143 -0
  62. package/dist/catalog/plugin-package.js +382 -0
  63. package/dist/catalog/plugin-upgrade.d.ts +222 -0
  64. package/dist/catalog/plugin-upgrade.js +1219 -0
  65. package/dist/catalog/requests.service.d.ts +162 -0
  66. package/dist/catalog/requests.service.js +504 -0
  67. package/dist/catalog/schema-path.d.ts +7 -0
  68. package/dist/catalog/schema-path.js +63 -0
  69. package/dist/catalog/upgrade-targets.d.ts +59 -0
  70. package/dist/catalog/upgrade-targets.js +90 -0
  71. package/dist/catalog/versions.d.ts +31 -0
  72. package/dist/catalog/versions.js +44 -0
  73. package/dist/channels/actions.d.ts +37 -0
  74. package/dist/channels/actions.js +121 -0
  75. package/dist/channels/cards.d.ts +44 -0
  76. package/dist/channels/cards.js +156 -0
  77. package/dist/channels/connections.controller.d.ts +59 -0
  78. package/dist/channels/connections.controller.js +115 -0
  79. package/dist/channels/connections.service.d.ts +187 -0
  80. package/dist/channels/connections.service.js +534 -0
  81. package/dist/channels/features.d.ts +12 -0
  82. package/dist/channels/features.js +22 -0
  83. package/dist/channels/inbound.d.ts +120 -0
  84. package/dist/channels/inbound.js +332 -0
  85. package/dist/channels/outbound.d.ts +140 -0
  86. package/dist/channels/outbound.js +1125 -0
  87. package/dist/channels/phrases.d.ts +100 -0
  88. package/dist/channels/phrases.js +81 -0
  89. package/dist/channels/supervisor.d.ts +182 -0
  90. package/dist/channels/supervisor.js +625 -0
  91. package/dist/channels/threads.d.ts +29 -0
  92. package/dist/channels/threads.js +104 -0
  93. package/dist/channels/webhook-url.d.ts +16 -0
  94. package/dist/channels/webhook-url.js +34 -0
  95. package/dist/channels/webhook.controller.d.ts +19 -0
  96. package/dist/channels/webhook.controller.js +72 -0
  97. package/dist/channels/webhook.d.ts +73 -0
  98. package/dist/channels/webhook.js +274 -0
  99. package/dist/config/docs.d.ts +9 -0
  100. package/dist/config/docs.js +85 -0
  101. package/dist/config/env.d.ts +6 -0
  102. package/dist/config/env.js +73 -0
  103. package/dist/config/fields.d.ts +42 -0
  104. package/dist/config/fields.js +214 -0
  105. package/dist/config/file-source.d.ts +3 -0
  106. package/dist/config/file-source.js +31 -0
  107. package/dist/config/load.d.ts +20 -0
  108. package/dist/config/load.js +98 -0
  109. package/dist/config/nacos-source.d.ts +31 -0
  110. package/dist/config/nacos-source.js +229 -0
  111. package/dist/config/schema.d.ts +223 -0
  112. package/dist/config/schema.js +1151 -0
  113. package/dist/config/sources.d.ts +18 -0
  114. package/dist/config/sources.js +59 -0
  115. package/dist/config/types.d.ts +9 -0
  116. package/dist/config/types.js +7 -0
  117. package/dist/conversations/artifacts.d.ts +52 -0
  118. package/dist/conversations/artifacts.js +137 -0
  119. package/dist/conversations/attachments.controller.d.ts +28 -0
  120. package/dist/conversations/attachments.controller.js +96 -0
  121. package/dist/conversations/attachments.service.d.ts +180 -0
  122. package/dist/conversations/attachments.service.js +578 -0
  123. package/dist/conversations/conversations.controller.d.ts +288 -0
  124. package/dist/conversations/conversations.controller.js +607 -0
  125. package/dist/conversations/conversations.service.d.ts +321 -0
  126. package/dist/conversations/conversations.service.js +754 -0
  127. package/dist/conversations/event-log.d.ts +122 -0
  128. package/dist/conversations/event-log.js +259 -0
  129. package/dist/conversations/events.d.ts +856 -0
  130. package/dist/conversations/events.js +639 -0
  131. package/dist/conversations/files.d.ts +92 -0
  132. package/dist/conversations/files.js +213 -0
  133. package/dist/conversations/outputs-read.d.ts +34 -0
  134. package/dist/conversations/outputs-read.js +37 -0
  135. package/dist/conversations/queue.d.ts +169 -0
  136. package/dist/conversations/queue.js +527 -0
  137. package/dist/conversations/sandbox-status.d.ts +21 -0
  138. package/dist/conversations/sandbox-status.js +24 -0
  139. package/dist/conversations/selection.d.ts +46 -0
  140. package/dist/conversations/selection.js +75 -0
  141. package/dist/conversations/titles.d.ts +93 -0
  142. package/dist/conversations/titles.js +422 -0
  143. package/dist/ctx/bus.d.ts +16 -0
  144. package/dist/ctx/bus.js +101 -0
  145. package/dist/ctx/create-ctx.d.ts +109 -0
  146. package/dist/ctx/create-ctx.js +592 -0
  147. package/dist/ctx/kv.d.ts +4 -0
  148. package/dist/ctx/kv.js +31 -0
  149. package/dist/ctx/lock.d.ts +4 -0
  150. package/dist/ctx/lock.js +39 -0
  151. package/dist/ctx/namespace.d.ts +6 -0
  152. package/dist/ctx/namespace.js +12 -0
  153. package/dist/ctx/queue.d.ts +25 -0
  154. package/dist/ctx/queue.js +150 -0
  155. package/dist/ctx/secrets.d.ts +45 -0
  156. package/dist/ctx/secrets.js +175 -0
  157. package/dist/db/kernel-schema.d.ts +1122 -0
  158. package/dist/db/kernel-schema.js +5 -0
  159. package/dist/db/migrator.d.ts +28 -0
  160. package/dist/db/migrator.js +140 -0
  161. package/dist/db/pool.d.ts +21 -0
  162. package/dist/db/pool.js +28 -0
  163. package/dist/db/sql-statements.d.ts +34 -0
  164. package/dist/db/sql-statements.js +168 -0
  165. package/dist/errors.d.ts +210 -0
  166. package/dist/errors.js +212 -0
  167. package/dist/evals/budget.d.ts +61 -0
  168. package/dist/evals/budget.js +181 -0
  169. package/dist/evals/diff.d.ts +55 -0
  170. package/dist/evals/diff.js +133 -0
  171. package/dist/evals/judge.d.ts +53 -0
  172. package/dist/evals/judge.js +149 -0
  173. package/dist/evals/plan.d.ts +47 -0
  174. package/dist/evals/plan.js +77 -0
  175. package/dist/evals/reconstruct.d.ts +137 -0
  176. package/dist/evals/reconstruct.js +322 -0
  177. package/dist/evals/recorded-tools.d.ts +54 -0
  178. package/dist/evals/recorded-tools.js +167 -0
  179. package/dist/evals/run-replay.d.ts +86 -0
  180. package/dist/evals/run-replay.js +502 -0
  181. package/dist/evals/runs.controller.d.ts +100 -0
  182. package/dist/evals/runs.controller.js +199 -0
  183. package/dist/evals/runs.service.d.ts +275 -0
  184. package/dist/evals/runs.service.js +836 -0
  185. package/dist/evals/sets.controller.d.ts +61 -0
  186. package/dist/evals/sets.controller.js +183 -0
  187. package/dist/evals/sets.service.d.ts +128 -0
  188. package/dist/evals/sets.service.js +558 -0
  189. package/dist/evals/snapshot.d.ts +76 -0
  190. package/dist/evals/snapshot.js +207 -0
  191. package/dist/evals/step-replay.d.ts +113 -0
  192. package/dist/evals/step-replay.js +181 -0
  193. package/dist/evals/trajectory.controller.d.ts +41 -0
  194. package/dist/evals/trajectory.controller.js +88 -0
  195. package/dist/evals/trajectory.d.ts +144 -0
  196. package/dist/evals/trajectory.js +338 -0
  197. package/dist/evals/trajectory.service.d.ts +108 -0
  198. package/dist/evals/trajectory.service.js +323 -0
  199. package/dist/evals/worker.d.ts +101 -0
  200. package/dist/evals/worker.js +789 -0
  201. package/dist/extensions/admin-ops.d.ts +105 -0
  202. package/dist/extensions/admin-ops.js +353 -0
  203. package/dist/extensions/admin-view.d.ts +79 -0
  204. package/dist/extensions/admin-view.js +327 -0
  205. package/dist/extensions/approvals.d.ts +119 -0
  206. package/dist/extensions/approvals.js +205 -0
  207. package/dist/extensions/blobs.d.ts +45 -0
  208. package/dist/extensions/blobs.js +160 -0
  209. package/dist/extensions/bootstrap.d.ts +149 -0
  210. package/dist/extensions/bootstrap.js +441 -0
  211. package/dist/extensions/cli.d.ts +61 -0
  212. package/dist/extensions/cli.js +165 -0
  213. package/dist/extensions/config-json-schema.d.ts +9 -0
  214. package/dist/extensions/config-json-schema.js +73 -0
  215. package/dist/extensions/deployment-config.d.ts +138 -0
  216. package/dist/extensions/deployment-config.js +394 -0
  217. package/dist/extensions/enabled.d.ts +31 -0
  218. package/dist/extensions/enabled.js +55 -0
  219. package/dist/extensions/hooks.d.ts +161 -0
  220. package/dist/extensions/hooks.js +425 -0
  221. package/dist/extensions/host.d.ts +577 -0
  222. package/dist/extensions/host.js +2071 -0
  223. package/dist/extensions/inflight.d.ts +69 -0
  224. package/dist/extensions/inflight.js +277 -0
  225. package/dist/extensions/installs.d.ts +166 -0
  226. package/dist/extensions/installs.js +253 -0
  227. package/dist/extensions/instance.d.ts +167 -0
  228. package/dist/extensions/instance.js +329 -0
  229. package/dist/extensions/ledger.d.ts +30 -0
  230. package/dist/extensions/ledger.js +50 -0
  231. package/dist/extensions/lifecycle.d.ts +80 -0
  232. package/dist/extensions/lifecycle.js +152 -0
  233. package/dist/extensions/migrate-lock.d.ts +51 -0
  234. package/dist/extensions/migrate-lock.js +100 -0
  235. package/dist/extensions/org-config.controller.d.ts +24 -0
  236. package/dist/extensions/org-config.controller.js +59 -0
  237. package/dist/extensions/org-config.d.ts +169 -0
  238. package/dist/extensions/org-config.js +520 -0
  239. package/dist/extensions/package.d.ts +115 -0
  240. package/dist/extensions/package.js +246 -0
  241. package/dist/extensions/permission-set.d.ts +117 -0
  242. package/dist/extensions/permission-set.js +184 -0
  243. package/dist/extensions/permission-view.d.ts +194 -0
  244. package/dist/extensions/permission-view.js +284 -0
  245. package/dist/extensions/registry.d.ts +24 -0
  246. package/dist/extensions/registry.js +56 -0
  247. package/dist/extensions/resolve.d.ts +12 -0
  248. package/dist/extensions/resolve.js +71 -0
  249. package/dist/extensions/sources.d.ts +69 -0
  250. package/dist/extensions/sources.js +120 -0
  251. package/dist/extensions/sync.d.ts +40 -0
  252. package/dist/extensions/sync.js +242 -0
  253. package/dist/files/previewers.controller.d.ts +46 -0
  254. package/dist/files/previewers.controller.js +105 -0
  255. package/dist/files/previewers.d.ts +100 -0
  256. package/dist/files/previewers.js +250 -0
  257. package/dist/http/api.module.d.ts +114 -0
  258. package/dist/http/api.module.js +448 -0
  259. package/dist/http/app.d.ts +77 -0
  260. package/dist/http/app.js +170 -0
  261. package/dist/http/error.filter.d.ts +21 -0
  262. package/dist/http/error.filter.js +85 -0
  263. package/dist/http/gateway.module.d.ts +15 -0
  264. package/dist/http/gateway.module.js +13 -0
  265. package/dist/http/health.controller.d.ts +26 -0
  266. package/dist/http/health.controller.js +79 -0
  267. package/dist/http/nest-logger.d.ts +20 -0
  268. package/dist/http/nest-logger.js +28 -0
  269. package/dist/http/plugin-dispatch.d.ts +68 -0
  270. package/dist/http/plugin-dispatch.js +200 -0
  271. package/dist/http/tokens.d.ts +131 -0
  272. package/dist/http/tokens.js +131 -0
  273. package/dist/http/zod.pipe.d.ts +8 -0
  274. package/dist/http/zod.pipe.js +14 -0
  275. package/dist/identity/accounts.d.ts +93 -0
  276. package/dist/identity/accounts.js +367 -0
  277. package/dist/identity/api-tokens.d.ts +73 -0
  278. package/dist/identity/api-tokens.js +197 -0
  279. package/dist/identity/audit.d.ts +23 -0
  280. package/dist/identity/audit.js +41 -0
  281. package/dist/identity/auth.controller.d.ts +40 -0
  282. package/dist/identity/auth.controller.js +130 -0
  283. package/dist/identity/auth.guard.d.ts +41 -0
  284. package/dist/identity/auth.guard.js +162 -0
  285. package/dist/identity/binding.d.ts +47 -0
  286. package/dist/identity/binding.js +84 -0
  287. package/dist/identity/cookies.d.ts +16 -0
  288. package/dist/identity/cookies.js +32 -0
  289. package/dist/identity/credential-check.d.ts +17 -0
  290. package/dist/identity/credential-check.js +24 -0
  291. package/dist/identity/enterprise-admin.d.ts +14 -0
  292. package/dist/identity/enterprise-admin.js +27 -0
  293. package/dist/identity/external.d.ts +106 -0
  294. package/dist/identity/external.js +337 -0
  295. package/dist/identity/hash.d.ts +2 -0
  296. package/dist/identity/hash.js +3 -0
  297. package/dist/identity/login.d.ts +6 -0
  298. package/dist/identity/login.js +20 -0
  299. package/dist/identity/me.controller.d.ts +61 -0
  300. package/dist/identity/me.controller.js +159 -0
  301. package/dist/identity/passwords.d.ts +6 -0
  302. package/dist/identity/passwords.js +37 -0
  303. package/dist/identity/principal.d.ts +56 -0
  304. package/dist/identity/principal.js +38 -0
  305. package/dist/identity/rate-limit.d.ts +55 -0
  306. package/dist/identity/rate-limit.js +121 -0
  307. package/dist/identity/sessions.d.ts +84 -0
  308. package/dist/identity/sessions.js +306 -0
  309. package/dist/identity/settings.d.ts +121 -0
  310. package/dist/identity/settings.js +248 -0
  311. package/dist/identity/sso.controller.d.ts +59 -0
  312. package/dist/identity/sso.controller.js +192 -0
  313. package/dist/identity/sso.d.ts +83 -0
  314. package/dist/identity/sso.js +202 -0
  315. package/dist/inbox/inbox.service.d.ts +43 -0
  316. package/dist/inbox/inbox.service.js +57 -0
  317. package/dist/index.d.ts +67 -0
  318. package/dist/index.js +65 -0
  319. package/dist/kernel.d.ts +256 -0
  320. package/dist/kernel.js +1326 -0
  321. package/dist/log.d.ts +48 -0
  322. package/dist/log.js +229 -0
  323. package/dist/models/prices.d.ts +53 -0
  324. package/dist/models/prices.js +121 -0
  325. package/dist/models/purposes.controller.d.ts +19 -0
  326. package/dist/models/purposes.controller.js +56 -0
  327. package/dist/models/purposes.d.ts +140 -0
  328. package/dist/models/purposes.js +267 -0
  329. package/dist/net/proxy.d.ts +44 -0
  330. package/dist/net/proxy.js +162 -0
  331. package/dist/net/public-address.d.ts +60 -0
  332. package/dist/net/public-address.js +271 -0
  333. package/dist/net/safe-fetch.d.ts +38 -0
  334. package/dist/net/safe-fetch.js +140 -0
  335. package/dist/orgs/directory-sync.controller.d.ts +14 -0
  336. package/dist/orgs/directory-sync.controller.js +40 -0
  337. package/dist/orgs/directory-sync.d.ts +166 -0
  338. package/dist/orgs/directory-sync.js +558 -0
  339. package/dist/orgs/invitations.controller.d.ts +58 -0
  340. package/dist/orgs/invitations.controller.js +137 -0
  341. package/dist/orgs/invitations.service.d.ts +80 -0
  342. package/dist/orgs/invitations.service.js +217 -0
  343. package/dist/orgs/members.service.d.ts +63 -0
  344. package/dist/orgs/members.service.js +234 -0
  345. package/dist/orgs/offboarding.d.ts +141 -0
  346. package/dist/orgs/offboarding.js +398 -0
  347. package/dist/orgs/org-lock.d.ts +32 -0
  348. package/dist/orgs/org-lock.js +46 -0
  349. package/dist/orgs/org.guard.d.ts +35 -0
  350. package/dist/orgs/org.guard.js +95 -0
  351. package/dist/orgs/orgs.controller.d.ts +78 -0
  352. package/dist/orgs/orgs.controller.js +192 -0
  353. package/dist/orgs/orgs.service.d.ts +61 -0
  354. package/dist/orgs/orgs.service.js +209 -0
  355. package/dist/orgs/roles.d.ts +13 -0
  356. package/dist/orgs/roles.js +58 -0
  357. package/dist/orgs/settings.controller.d.ts +20 -0
  358. package/dist/orgs/settings.controller.js +53 -0
  359. package/dist/orgs/settings.service.d.ts +120 -0
  360. package/dist/orgs/settings.service.js +178 -0
  361. package/dist/packages/npm.d.ts +50 -0
  362. package/dist/packages/npm.js +218 -0
  363. package/dist/packages/provenance.d.ts +47 -0
  364. package/dist/packages/provenance.js +147 -0
  365. package/dist/packages/tgz.d.ts +76 -0
  366. package/dist/packages/tgz.js +225 -0
  367. package/dist/runtime/abort.d.ts +32 -0
  368. package/dist/runtime/abort.js +71 -0
  369. package/dist/runtime/checkpointer.d.ts +32 -0
  370. package/dist/runtime/checkpointer.js +243 -0
  371. package/dist/runtime/context/build.d.ts +254 -0
  372. package/dist/runtime/context/build.js +693 -0
  373. package/dist/runtime/context/claude-tools.d.ts +11 -0
  374. package/dist/runtime/context/claude-tools.js +24 -0
  375. package/dist/runtime/context/compaction.d.ts +26 -0
  376. package/dist/runtime/context/compaction.js +195 -0
  377. package/dist/runtime/context/pairing.d.ts +11 -0
  378. package/dist/runtime/context/pairing.js +82 -0
  379. package/dist/runtime/context/reminders.d.ts +5 -0
  380. package/dist/runtime/context/reminders.js +11 -0
  381. package/dist/runtime/context/skills.d.ts +105 -0
  382. package/dist/runtime/context/skills.js +283 -0
  383. package/dist/runtime/context/tokens.d.ts +19 -0
  384. package/dist/runtime/context/tokens.js +104 -0
  385. package/dist/runtime/conversation-lock.d.ts +40 -0
  386. package/dist/runtime/conversation-lock.js +97 -0
  387. package/dist/runtime/hook-calls.d.ts +84 -0
  388. package/dist/runtime/hook-calls.js +136 -0
  389. package/dist/runtime/langgraph-loop.d.ts +52 -0
  390. package/dist/runtime/langgraph-loop.js +247 -0
  391. package/dist/runtime/loop.d.ts +93 -0
  392. package/dist/runtime/loop.js +7 -0
  393. package/dist/runtime/maintenance.d.ts +80 -0
  394. package/dist/runtime/maintenance.js +147 -0
  395. package/dist/runtime/media-cache.d.ts +21 -0
  396. package/dist/runtime/media-cache.js +51 -0
  397. package/dist/runtime/model-call.d.ts +176 -0
  398. package/dist/runtime/model-call.js +1049 -0
  399. package/dist/runtime/providers.d.ts +86 -0
  400. package/dist/runtime/providers.js +224 -0
  401. package/dist/runtime/quota.d.ts +29 -0
  402. package/dist/runtime/quota.js +70 -0
  403. package/dist/runtime/run-finish.d.ts +45 -0
  404. package/dist/runtime/run-finish.js +69 -0
  405. package/dist/runtime/run-queue.d.ts +121 -0
  406. package/dist/runtime/run-queue.js +493 -0
  407. package/dist/runtime/run-worker.d.ts +138 -0
  408. package/dist/runtime/run-worker.js +805 -0
  409. package/dist/runtime/stream.controller.d.ts +34 -0
  410. package/dist/runtime/stream.controller.js +122 -0
  411. package/dist/runtime/stream.d.ts +63 -0
  412. package/dist/runtime/stream.js +262 -0
  413. package/dist/runtime/subagents/child.d.ts +80 -0
  414. package/dist/runtime/subagents/child.js +225 -0
  415. package/dist/runtime/subagents/definition.d.ts +103 -0
  416. package/dist/runtime/subagents/definition.js +392 -0
  417. package/dist/runtime/subagents/dispatch.d.ts +69 -0
  418. package/dist/runtime/subagents/dispatch.js +502 -0
  419. package/dist/runtime/subagents/limits.d.ts +23 -0
  420. package/dist/runtime/subagents/limits.js +34 -0
  421. package/dist/runtime/subagents/org-agents.d.ts +50 -0
  422. package/dist/runtime/subagents/org-agents.js +70 -0
  423. package/dist/runtime/subagents/preamble.d.ts +7 -0
  424. package/dist/runtime/subagents/preamble.js +11 -0
  425. package/dist/runtime/subagents/progress.d.ts +26 -0
  426. package/dist/runtime/subagents/progress.js +36 -0
  427. package/dist/runtime/subagents/roster.d.ts +55 -0
  428. package/dist/runtime/subagents/roster.js +111 -0
  429. package/dist/runtime/subagents/skill-fork.d.ts +123 -0
  430. package/dist/runtime/subagents/skill-fork.js +259 -0
  431. package/dist/runtime/usage-report.d.ts +163 -0
  432. package/dist/runtime/usage-report.js +550 -0
  433. package/dist/runtime/waits.d.ts +233 -0
  434. package/dist/runtime/waits.js +883 -0
  435. package/dist/sandbox/leases.d.ts +169 -0
  436. package/dist/sandbox/leases.js +515 -0
  437. package/dist/sandbox/lifecycle.d.ts +21 -0
  438. package/dist/sandbox/lifecycle.js +68 -0
  439. package/dist/sandbox/sandbox.service.d.ts +249 -0
  440. package/dist/sandbox/sandbox.service.js +908 -0
  441. package/dist/skills/catalog.d.ts +149 -0
  442. package/dist/skills/catalog.js +405 -0
  443. package/dist/skills/changes.controller.d.ts +56 -0
  444. package/dist/skills/changes.controller.js +136 -0
  445. package/dist/skills/changes.service.d.ts +175 -0
  446. package/dist/skills/changes.service.js +805 -0
  447. package/dist/skills/invocable.controller.d.ts +23 -0
  448. package/dist/skills/invocable.controller.js +50 -0
  449. package/dist/skills/invocation-keys.d.ts +23 -0
  450. package/dist/skills/invocation-keys.js +44 -0
  451. package/dist/skills/invoke.d.ts +135 -0
  452. package/dist/skills/invoke.js +286 -0
  453. package/dist/skills/package.d.ts +87 -0
  454. package/dist/skills/package.js +227 -0
  455. package/dist/skills/skills.controller.d.ts +40 -0
  456. package/dist/skills/skills.controller.js +110 -0
  457. package/dist/skills/skills.service.d.ts +192 -0
  458. package/dist/skills/skills.service.js +567 -0
  459. package/dist/storage/prefix.d.ts +36 -0
  460. package/dist/storage/prefix.js +104 -0
  461. package/dist/storage/purge.d.ts +27 -0
  462. package/dist/storage/purge.js +75 -0
  463. package/dist/storage/storage.service.d.ts +44 -0
  464. package/dist/storage/storage.service.js +145 -0
  465. package/dist/text.d.ts +13 -0
  466. package/dist/text.js +13 -0
  467. package/dist/tools/approvals.controller.d.ts +53 -0
  468. package/dist/tools/approvals.controller.js +128 -0
  469. package/dist/tools/approvals.service.d.ts +172 -0
  470. package/dist/tools/approvals.service.js +568 -0
  471. package/dist/tools/breaker.d.ts +28 -0
  472. package/dist/tools/breaker.js +72 -0
  473. package/dist/tools/builtins/agent.d.ts +81 -0
  474. package/dist/tools/builtins/agent.js +223 -0
  475. package/dist/tools/builtins/ask-user.d.ts +28 -0
  476. package/dist/tools/builtins/ask-user.js +139 -0
  477. package/dist/tools/builtins/read-tool-output.d.ts +18 -0
  478. package/dist/tools/builtins/read-tool-output.js +108 -0
  479. package/dist/tools/builtins/sandbox/bash.d.ts +16 -0
  480. package/dist/tools/builtins/sandbox/bash.js +137 -0
  481. package/dist/tools/builtins/sandbox/common.d.ts +114 -0
  482. package/dist/tools/builtins/sandbox/common.js +304 -0
  483. package/dist/tools/builtins/sandbox/deliver.d.ts +5 -0
  484. package/dist/tools/builtins/sandbox/deliver.js +180 -0
  485. package/dist/tools/builtins/sandbox/edit.d.ts +4 -0
  486. package/dist/tools/builtins/sandbox/edit.js +98 -0
  487. package/dist/tools/builtins/sandbox/glob-match.d.ts +25 -0
  488. package/dist/tools/builtins/sandbox/glob-match.js +240 -0
  489. package/dist/tools/builtins/sandbox/glob.d.ts +4 -0
  490. package/dist/tools/builtins/sandbox/glob.js +104 -0
  491. package/dist/tools/builtins/sandbox/grep.d.ts +9 -0
  492. package/dist/tools/builtins/sandbox/grep.js +133 -0
  493. package/dist/tools/builtins/sandbox/index.d.ts +12 -0
  494. package/dist/tools/builtins/sandbox/index.js +27 -0
  495. package/dist/tools/builtins/sandbox/names.d.ts +7 -0
  496. package/dist/tools/builtins/sandbox/names.js +20 -0
  497. package/dist/tools/builtins/sandbox/read.d.ts +8 -0
  498. package/dist/tools/builtins/sandbox/read.js +121 -0
  499. package/dist/tools/builtins/sandbox/write.d.ts +4 -0
  500. package/dist/tools/builtins/sandbox/write.js +88 -0
  501. package/dist/tools/builtins/skill-load.d.ts +53 -0
  502. package/dist/tools/builtins/skill-load.js +446 -0
  503. package/dist/tools/builtins/skill-write.d.ts +59 -0
  504. package/dist/tools/builtins/skill-write.js +244 -0
  505. package/dist/tools/builtins/tool-search.d.ts +31 -0
  506. package/dist/tools/builtins/tool-search.js +171 -0
  507. package/dist/tools/connector-content.controller.d.ts +34 -0
  508. package/dist/tools/connector-content.controller.js +78 -0
  509. package/dist/tools/connector-content.d.ts +104 -0
  510. package/dist/tools/connector-content.js +267 -0
  511. package/dist/tools/connectors.controller.d.ts +210 -0
  512. package/dist/tools/connectors.controller.js +234 -0
  513. package/dist/tools/connectors.service.d.ts +303 -0
  514. package/dist/tools/connectors.service.js +1102 -0
  515. package/dist/tools/credentials.d.ts +139 -0
  516. package/dist/tools/credentials.js +351 -0
  517. package/dist/tools/drift.d.ts +141 -0
  518. package/dist/tools/drift.js +539 -0
  519. package/dist/tools/elicitation.d.ts +81 -0
  520. package/dist/tools/elicitation.js +266 -0
  521. package/dist/tools/endpoint.d.ts +18 -0
  522. package/dist/tools/endpoint.js +115 -0
  523. package/dist/tools/info.d.ts +67 -0
  524. package/dist/tools/info.js +113 -0
  525. package/dist/tools/naming.d.ts +27 -0
  526. package/dist/tools/naming.js +47 -0
  527. package/dist/tools/oauth/discovery.d.ts +65 -0
  528. package/dist/tools/oauth/discovery.js +307 -0
  529. package/dist/tools/oauth/flow.d.ts +63 -0
  530. package/dist/tools/oauth/flow.js +237 -0
  531. package/dist/tools/oauth/oauth.controller.d.ts +31 -0
  532. package/dist/tools/oauth/oauth.controller.js +95 -0
  533. package/dist/tools/oauth/tokens.d.ts +111 -0
  534. package/dist/tools/oauth/tokens.js +258 -0
  535. package/dist/tools/outputs.d.ts +61 -0
  536. package/dist/tools/outputs.js +156 -0
  537. package/dist/tools/pipeline.d.ts +322 -0
  538. package/dist/tools/pipeline.js +1236 -0
  539. package/dist/tools/policy.d.ts +60 -0
  540. package/dist/tools/policy.js +236 -0
  541. package/dist/tools/questions.controller.d.ts +24 -0
  542. package/dist/tools/questions.controller.js +58 -0
  543. package/dist/tools/questions.service.d.ts +103 -0
  544. package/dist/tools/questions.service.js +295 -0
  545. package/dist/tools/redact.d.ts +20 -0
  546. package/dist/tools/redact.js +60 -0
  547. package/dist/tools/registry.d.ts +246 -0
  548. package/dist/tools/registry.js +481 -0
  549. package/dist/tools/resources.d.ts +16 -0
  550. package/dist/tools/resources.js +76 -0
  551. package/dist/tools/specs.d.ts +14 -0
  552. package/dist/tools/specs.js +31 -0
  553. package/dist/tools/validate.d.ts +20 -0
  554. package/dist/tools/validate.js +183 -0
  555. package/dist/tools/view.d.ts +43 -0
  556. package/dist/tools/view.js +225 -0
  557. package/dist/ui/embed-token.d.ts +31 -0
  558. package/dist/ui/embed-token.js +132 -0
  559. package/dist/ui/registry.d.ts +58 -0
  560. package/dist/ui/registry.js +90 -0
  561. package/dist/ui/ui-stream.d.ts +37 -0
  562. package/dist/ui/ui-stream.js +162 -0
  563. package/dist/ui/views.controller.d.ts +81 -0
  564. package/dist/ui/views.controller.js +261 -0
  565. package/dist/ui/views.d.ts +155 -0
  566. package/dist/ui/views.js +306 -0
  567. package/dist/version.d.ts +5 -0
  568. package/dist/version.js +6 -0
  569. package/package.json +67 -3
  570. package/src/migrations/0001_init.sql +8 -0
  571. package/src/migrations/0002_secrets.sql +8 -0
  572. package/src/migrations/0003_identity.sql +117 -0
  573. package/src/migrations/0004_plugin_org_config_nullable.sql +3 -0
  574. package/src/migrations/0005_agents.sql +27 -0
  575. package/src/migrations/0006_conversations.sql +37 -0
  576. package/src/migrations/0007_checkpoints.sql +26 -0
  577. package/src/migrations/0008_runs_trigger_seq.sql +3 -0
  578. package/src/migrations/0009_runs_active_unique.sql +4 -0
  579. package/src/migrations/0010_tools.sql +125 -0
  580. package/src/migrations/0011_approvals_spec.sql +10 -0
  581. package/src/migrations/0012_run_waits.sql +24 -0
  582. package/src/migrations/0013_app_tools_source.sql +4 -0
  583. package/src/migrations/0014_tool_specs.sql +8 -0
  584. package/src/migrations/0015_tool_drift.sql +20 -0
  585. package/src/migrations/0016_plugin_permissions.sql +11 -0
  586. package/src/migrations/0017_identity_sources.sql +6 -0
  587. package/src/migrations/0018_channels.sql +74 -0
  588. package/src/migrations/0019_identity_trust.sql +17 -0
  589. package/src/migrations/0020_channel_card_lookup.sql +10 -0
  590. package/src/migrations/0021_org_storage_purge.sql +9 -0
  591. package/src/migrations/0022_attachments.sql +29 -0
  592. package/src/migrations/0023_sandboxes.sql +37 -0
  593. package/src/migrations/0024_skills.sql +46 -0
  594. package/src/migrations/0025_skills_catalog_idx.sql +6 -0
  595. package/src/migrations/0026_skill_changes.sql +34 -0
  596. package/src/migrations/0027_model_prices.sql +18 -0
  597. package/src/migrations/0028_evals.sql +105 -0
  598. package/src/migrations/0029_model_purposes.sql +18 -0
  599. package/src/migrations/0030_plugin_installs.sql +73 -0
  600. package/src/migrations/0031_plugin_snapshot_source.sql +6 -0
  601. package/src/migrations/0032_plugin_deployment_configs.sql +10 -0
  602. package/src/migrations/0033_rename_apps_to_connectors.sql +25 -0
  603. package/src/migrations/0034_directory.sql +49 -0
  604. package/src/migrations/0035_catalogs.sql +40 -0
  605. package/src/migrations/0036_app_import_staging.sql +17 -0
  606. package/src/migrations/0037_directory_installs.sql +92 -0
  607. package/src/migrations/0038_channel_inbound_mode.sql +6 -0
  608. package/src/migrations/0039_channel_card_pending.sql +8 -0
  609. package/src/migrations/0040_usage_report_sweep.sql +10 -0
  610. package/src/migrations/0041_rename_plugins_to_extensions.sql +38 -0
  611. package/src/migrations/0042_rename_directory_to_catalog.sql +80 -0
  612. package/src/migrations/0043_rename_app_installs_to_plugin_installs.sql +20 -0
  613. package/src/migrations/0044_catalog_one_kind.sql +90 -0
  614. package/src/migrations/0045_plugin_dependencies.sql +9 -0
  615. package/src/migrations/0046_git_sources.sql +25 -0
  616. package/src/migrations/0047_marketplace_entry_heads.sql +7 -0
  617. package/src/migrations/0048_marketplace_entry_trees.sql +8 -0
  618. package/src/migrations/0049_plugin_upgrades.sql +37 -0
  619. package/src/migrations/0050_bootstrap.sql +53 -0
  620. package/src/migrations/0051_claude_compat.sql +26 -0
  621. package/src/migrations/0052_conversations_account_agent_idx.sql +5 -0
  622. package/src/migrations/0053_subagents.sql +73 -0
  623. package/src/migrations/0054_subagent_wait_expiry.sql +7 -0
  624. package/src/migrations/0055_subagent_parent_indexes.sql +10 -0
  625. package/src/migrations/0056_approval_reason.sql +3 -0
  626. package/src/migrations/0057_conversation_titles.sql +11 -0
  627. package/src/migrations/0058_conversation_selection.sql +4 -0
  628. package/src/migrations/0059_conversation_queue.sql +22 -0
  629. package/src/migrations/0060_file_previewers.sql +10 -0
  630. package/src/migrations/0061_queue_selection.sql +5 -0
  631. package/src/migrations/0062_queued_skill.sql +8 -0
@@ -0,0 +1,789 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { hostname } from "node:os";
3
+ import { isModelError, isRetryableKind } from "@capybara-hq/plugin-sdk";
4
+ import { DelayedError, Worker } from "bullmq";
5
+ import { sql } from "kysely";
6
+ import { loadTemplates } from "../agents/templates.js";
7
+ import { ApiError } from "../errors.js";
8
+ import { ExtensionUnloadedError } from "../extensions/inflight.js";
9
+ import { PurposeAttemptError } from "../models/purposes.js";
10
+ import { MediaUnavailableError, RunError } from "../runtime/model-call.js";
11
+ import { ProviderListError } from "../runtime/providers.js";
12
+ import { ORG_QUOTA_LEASE_MS } from "../runtime/quota.js";
13
+ import { bullConnection } from "../runtime/run-queue.js";
14
+ import { consumeTokens, recordOutcome, recountCases, runActive, skipPendingJudges, usageTokens, } from "./budget.js";
15
+ import { replyParts, structuralDiff } from "./diff.js";
16
+ import { JUDGE_PROVIDER_UNAVAILABLE, judge } from "./judge.js";
17
+ import { userRequestOf } from "./plan.js";
18
+ import { subagentCaseChanged, subagentStartedOf } from "./reconstruct.js";
19
+ import { deleteEvalConversation, ReplayClaimLost, replayRun, runBaseline, } from "./run-replay.js";
20
+ import { caseBase, EVAL_QUEUE_NAME, evalJobId, versionDefinition, } from "./runs.service.js";
21
+ import { readSnapshot, replayableCalls, toEvents } from "./snapshot.js";
22
+ import { ReplayAttemptError, replayStep, resolveCandidate, } from "./step-replay.js";
23
+ /**
24
+ * 评测 worker(C7,只在含 `worker` 角色的进程启动):领取 `cap-kernel-evals` 的任务,每个任务回放一个用例。
25
+ * - 运行不活跃(取消 / 达到上限 / 熔断 / 已结束)→ 该用例剩余结果标 `skipped`;
26
+ * - 组织并发配额 `capk:org-evals:<orgId>`(`evals.orgConcurrency`,成员为 jobId + 认领号)拿不到 → 延后 5000ms;
27
+ * - 每次请求前查 `runActive`(含组织 / agent 未删除)与认领;成功的请求在同一事务里写结果并 `consumeTokens`(越限即 `capped`),
28
+ * 发出后失败的尝试按估算同样 `consumeTokens`;
29
+ * - 可重试的错误重试 3 次,不可重试的结果标 `error`;连续 `evals.maxConsecutiveErrors` 条结果出错 → 运行 `failed`;
30
+ * - 结果按认领号(每次执行一个 uuid)写入:失去认领的旧执行写不进来(已发出请求的用量照样计入);
31
+ * - 结果写 done 时一并写结构差异(`diff`);开了评委时随后(运行仍活跃才)发一次评委请求,结论写进 `judge`,
32
+ * 用量同样 `consumeTokens`(请求失败按估算);
33
+ * - 用例做完重算 `cases_done`(已全部结束的用例数,幂等),达到总数且仍在执行 → `completed`。
34
+ * 多副本:状态全在 PG / Redis;崩溃的任务由 BullMQ stalled 机制交给别的 worker,`running` 的结果从头重做;
35
+ * 处理函数外的暂时故障(PG / Redis)按任务的 attempts 指数退避重试。
36
+ */
37
+ /** 拿不到组织配额时任务延后的毫秒数。 */
38
+ export const EVAL_QUOTA_RETRY_MS = 5000;
39
+ /** 可重试错误的最多重试次数。 */
40
+ export const EVAL_MAX_RETRIES = 3;
41
+ /** 第 n 次重试前的等待(毫秒);供应商给了 `retryAfterMs` 时取它(不超过 30 秒)。 */
42
+ const RETRY_DELAYS_MS = [1000, 2000, 4000];
43
+ const MAX_RETRY_AFTER_MS = 30_000;
44
+ const MAX_STALLED_COUNT = 3;
45
+ /** 供应商插件在调用途中被撤销(错误本身或其 cause)。 */
46
+ const isPluginUnloaded = (err) => err instanceof ExtensionUnloadedError ||
47
+ (err instanceof Error && err.cause instanceof ExtensionUnloadedError);
48
+ /** 回放出错的分类(与运行时的降级梯子同一套码)。 */
49
+ function classify(err) {
50
+ if (isModelError(err)) {
51
+ return {
52
+ retryable: isRetryableKind(err.kind),
53
+ code: `model.${err.kind}`,
54
+ message: err.message,
55
+ ...(err.retryAfterMs !== undefined && { retryAfterMs: err.retryAfterMs }),
56
+ };
57
+ }
58
+ if (err instanceof MediaUnavailableError) {
59
+ return { retryable: true, code: "run.storage_unavailable", message: err.message };
60
+ }
61
+ // 整轮回放的 loop 失败(降级梯子已在 loop 内重试过):沿用运行时的码
62
+ if (err instanceof RunError)
63
+ return { retryable: false, code: err.code, message: err.message };
64
+ // 供应商插件在请求途中被撤销 / 升级 / 重新加载:与运行时一致按可重试处理,重试时实时取到新实例
65
+ if (isPluginUnloaded(err) || err instanceof ProviderListError) {
66
+ return {
67
+ retryable: true,
68
+ code: "run.provider_unavailable",
69
+ message: err instanceof Error ? err.message : String(err),
70
+ };
71
+ }
72
+ if (err instanceof ApiError) {
73
+ const code = err.code === "agent.model_unavailable" ? "run.model_unavailable" : err.code;
74
+ return { retryable: false, code, message: err.message };
75
+ }
76
+ return {
77
+ retryable: false,
78
+ code: "run.provider_error",
79
+ message: err instanceof Error ? err.message : String(err),
80
+ };
81
+ }
82
+ /** 回放本身的失败(结果记 error);其余错误按崩溃处理(见 runWhole)。 */
83
+ const isReplayFailure = (err) => isModelError(err) ||
84
+ err instanceof RunError ||
85
+ err instanceof ApiError ||
86
+ err instanceof MediaUnavailableError ||
87
+ err instanceof ProviderListError ||
88
+ isPluginUnloaded(err);
89
+ class Aborted extends Error {
90
+ }
91
+ function sleep(ms, signal) {
92
+ return new Promise((resolve, reject) => {
93
+ if (signal.aborted)
94
+ return reject(new Aborted());
95
+ const onAbort = () => {
96
+ clearTimeout(t);
97
+ reject(new Aborted());
98
+ };
99
+ const t = setTimeout(() => {
100
+ signal.removeEventListener("abort", onAbort);
101
+ resolve();
102
+ }, ms);
103
+ signal.addEventListener("abort", onAbort, { once: true });
104
+ });
105
+ }
106
+ const UNFINISHED = ["pending", "running"];
107
+ /** 给评委看的回复:工具调用(名字与参数)在前,文本在后。 */
108
+ function renderReply(toolCalls, text) {
109
+ const calls = toolCalls.map((c) => `Tool call: ${c.name} ${JSON.stringify(c.input ?? null)}`);
110
+ return [...calls, text].filter((x) => x.length > 0).join("\n");
111
+ }
112
+ /** 一边(基线或候选)给评委看的内容:单步取回复的内容块,整轮取工具调用序列与最后的回复。 */
113
+ function sideOf(mode, v) {
114
+ if (mode === "step")
115
+ return replyParts(v?.content ?? []);
116
+ const r = v;
117
+ return { toolCalls: r?.toolCalls ?? [], text: replyParts(r?.finalContent ?? []).text };
118
+ }
119
+ /**
120
+ * 评委的输入(由结果里存的基线 / 候选得出,崩溃后补评委时同样可用):用户请求 = 该调用(整轮为原运行开始)之前
121
+ * 最近一条用户消息;回复 = 工具调用在前、文本在后。
122
+ */
123
+ function judgeInputOf(s, mode, modelCallSeq, baseline, candidate, rubric) {
124
+ const start = s.events.find((e) => e.runId === s.runId && e.type === "run_started");
125
+ const before = mode === "step" && modelCallSeq !== null
126
+ ? modelCallSeq
127
+ : (start?.seq ?? Number.POSITIVE_INFINITY);
128
+ const b = sideOf(mode, baseline);
129
+ const c = sideOf(mode, candidate);
130
+ return {
131
+ userRequest: userRequestOf(s, before),
132
+ baseline: renderReply(b.toolCalls, b.text),
133
+ candidate: renderReply(c.toolCalls, c.text),
134
+ rubric,
135
+ };
136
+ }
137
+ export class EvalWorker {
138
+ d;
139
+ worker;
140
+ conn;
141
+ /** 本进程在执行的任务:停机时中止,任务回到队列。 */
142
+ active = new Set();
143
+ closing = false;
144
+ constructor(d) {
145
+ this.d = d;
146
+ }
147
+ start() {
148
+ if (this.worker)
149
+ return;
150
+ const { runtime, evals } = this.d.config();
151
+ this.conn = bullConnection(this.d.redisUrl, this.d.log);
152
+ this.worker = new Worker(EVAL_QUEUE_NAME, (job, token) => this.process(job, token), {
153
+ name: `${hostname()}-${process.pid}`,
154
+ connection: this.conn,
155
+ concurrency: evals.workerConcurrency,
156
+ lockDuration: runtime.jobLockMs,
157
+ stalledInterval: runtime.stalledIntervalMs,
158
+ maxStalledCount: MAX_STALLED_COUNT,
159
+ });
160
+ this.worker.on("error", (err) => this.d.log.error("eval worker error", { err }));
161
+ this.worker.on("failed", (job, err) => {
162
+ if (!job)
163
+ return;
164
+ // 处理函数外的暂时故障(PG / Redis)由 BullMQ 按 attempts 指数退避重试;用尽(或 stalled 超限)才算失败
165
+ if (job.attemptsMade < (job.opts.attempts ?? 1) && !/stalled/i.test(err.message)) {
166
+ this.d.log.warn("eval job attempt failed; retrying", { jobId: job.id, err });
167
+ return;
168
+ }
169
+ this.d.log.error("eval job failed", { jobId: job.id, err });
170
+ // 任务不会再执行:该用例剩下的结果记 error,运行不因此卡住
171
+ void this.failCase(job.data, err).catch((e) => this.d.log.error("cannot mark failed eval job", { jobId: job.id, err: e }));
172
+ });
173
+ }
174
+ /** 停止领取;中止本进程在执行的任务(回到队列由别的 worker 接着做),在 budgetMs 内等它们退出。 */
175
+ async close(budgetMs) {
176
+ const worker = this.worker;
177
+ if (!worker)
178
+ return;
179
+ this.worker = undefined;
180
+ this.closing = true;
181
+ await worker.pause(true).catch(() => { });
182
+ for (const ac of this.active)
183
+ ac.abort();
184
+ let timer;
185
+ const done = await Promise.race([
186
+ worker.close().then(() => true),
187
+ new Promise((resolve) => {
188
+ timer = setTimeout(() => resolve(false), Math.max(0, budgetMs));
189
+ timer.unref();
190
+ }),
191
+ ]);
192
+ clearTimeout(timer);
193
+ if (!done)
194
+ await worker.close(true).catch(() => { });
195
+ this.conn?.disconnect();
196
+ }
197
+ async process(job, token) {
198
+ const data = job.data;
199
+ const { runId, orgId } = data;
200
+ const jobId = job.id ?? evalJobId(runId, data.caseId);
201
+ if (!(await runActive(this.d.db, runId))) {
202
+ await this.skipCase(data);
203
+ await recountCases(this.d.db, runId);
204
+ return;
205
+ }
206
+ const limit = this.d.config().evals.orgConcurrency;
207
+ // 每次执行一个新的认领号:失去认领(stalled 后被别的 worker 接手)的旧执行写不进结果(用量照样计入)。
208
+ // 配额成员 = 任务 id + 认领号:旧执行退出时只移除自己的名额,不会把接手执行的名额一起移掉
209
+ const claim = randomUUID();
210
+ const member = `${jobId}-${claim}`;
211
+ if (!(await this.d.quota.tryEnter(orgId, member, limit, ORG_QUOTA_LEASE_MS))) {
212
+ // 配额满:固定 5 秒后再试,不按事件唤醒。评测是后台批任务,几秒空等可以接受,换来没有跨副本通知
213
+ await job.moveToDelayed(Date.now() + (this.d.quotaRetryMs ?? EVAL_QUOTA_RETRY_MS), token);
214
+ throw new DelayedError();
215
+ }
216
+ const ac = new AbortController();
217
+ this.active.add(ac);
218
+ if (this.closing)
219
+ ac.abort();
220
+ const renew = setInterval(() => {
221
+ this.d.quota
222
+ .renew(orgId, member, ORG_QUOTA_LEASE_MS)
223
+ .catch((err) => this.d.log.warn("eval quota renew failed", { jobId, err }));
224
+ }, ORG_QUOTA_LEASE_MS / 3);
225
+ renew.unref();
226
+ try {
227
+ await this.d.db
228
+ .updateTable("eval_runs")
229
+ .set({ status: "running", started_at: sql `COALESCE(started_at, now())` })
230
+ .where("id", "=", runId)
231
+ .where("status", "=", "queued")
232
+ .execute();
233
+ await this.runCase(data, claim, ac.signal);
234
+ }
235
+ catch (err) {
236
+ if (ac.signal.aborted) {
237
+ // 停机:任务回到队列,`running` 的结果由接手的 worker 重做
238
+ await job.moveToDelayed(Date.now(), token);
239
+ throw new DelayedError();
240
+ }
241
+ throw err;
242
+ }
243
+ finally {
244
+ clearInterval(renew);
245
+ this.active.delete(ac);
246
+ await this.d.quota
247
+ .leave(orgId, member)
248
+ .catch((err) => this.d.log.warn("eval quota leave failed", { jobId, err }));
249
+ }
250
+ await recountCases(this.d.db, runId);
251
+ }
252
+ /** 单步回放每次请求前:运行仍在执行({@link runActive})且结果仍由本次执行认领。 */
253
+ async mayRequest(runId, resultId, claim) {
254
+ if (!(await runActive(this.d.db, runId)))
255
+ return "inactive";
256
+ const held = await this.d.db
257
+ .selectFrom("eval_results")
258
+ .select("id")
259
+ .where("id", "=", resultId)
260
+ .where("status", "=", "running")
261
+ .where("claimed_by", "=", claim)
262
+ .executeTakeFirst();
263
+ return held ? "ok" : "lost";
264
+ }
265
+ /**
266
+ * 一条结果出错:只在仍由本次执行认领时写入,然后计入熔断;熔断 → 该用例剩下的结果 skipped(其他用例的任务
267
+ * 看到运行不活跃也会跳过)。返回 true 表示本用例应停下(熔断或失去认领)。
268
+ */
269
+ async resultError(data, resultId, claim, error) {
270
+ const db = this.d.db;
271
+ const w = await db
272
+ .updateTable("eval_results")
273
+ .set({ status: "error", error: JSON.stringify(error), updated_at: sql `now()` })
274
+ .where("id", "=", resultId)
275
+ .where("status", "=", "running")
276
+ .where("claimed_by", "=", claim)
277
+ .executeTakeFirst();
278
+ if (Number(w.numUpdatedRows) === 0)
279
+ return true;
280
+ const { tripped } = await recordOutcome(db, data.runId, false, this.d.config().evals.maxConsecutiveErrors);
281
+ if (tripped) {
282
+ this.d.log.warn("eval run stopped after too many consecutive errors", { runId: data.runId });
283
+ await this.skipCase(data);
284
+ return true;
285
+ }
286
+ return false;
287
+ }
288
+ /** 回放一个用例的全部未结束结果(按调用顺序)。 */
289
+ async runCase(data, claim, signal) {
290
+ const { runId, caseId } = data;
291
+ const db = this.d.db;
292
+ const [row, run] = await Promise.all([
293
+ db.selectFrom("eval_cases").select("snapshot").where("id", "=", caseId).executeTakeFirst(),
294
+ db
295
+ .selectFrom("eval_runs")
296
+ .innerJoin("eval_sets", "eval_sets.id", "eval_runs.set_id")
297
+ .select(["eval_runs.candidate", "eval_runs.mode", "eval_runs.judge", "eval_sets.rubric"])
298
+ .where("eval_runs.id", "=", runId)
299
+ .executeTakeFirst(),
300
+ ]);
301
+ if (!row || !run)
302
+ return;
303
+ const grade = { judge: run.judge, rubric: run.rubric };
304
+ const s = readSnapshot(row.snapshot);
305
+ const candidate = run.candidate;
306
+ // 未结束的结果,以及已 done 但评委还没做的(上一次执行在评委之前崩溃 / 停机)
307
+ const pending = await db
308
+ .selectFrom("eval_results")
309
+ .select(["id", "model_call_seq", "status"])
310
+ .where("run_id", "=", runId)
311
+ .where("case_id", "=", caseId)
312
+ .where((eb) => eb.or([
313
+ eb("status", "in", [...UNFINISHED]),
314
+ eb.and([eb("status", "=", "done"), eb("judge_status", "=", "pending")]),
315
+ ]))
316
+ .orderBy("model_call_seq")
317
+ .execute();
318
+ if (pending.length === 0)
319
+ return;
320
+ const base = await caseBase(db, s);
321
+ const source = s.subagent !== undefined ? subagentStartedOf(toEvents(s))?.template.source : undefined;
322
+ const resolved = base
323
+ ? resolveCandidate(base, candidate, await versionDefinition(db, s.agentId, candidate.agentVersion), source)
324
+ : null;
325
+ if (resolved?.changed) {
326
+ const template = await currentTemplate(db, s);
327
+ if (template !== undefined)
328
+ resolved.subagentTemplate = template;
329
+ }
330
+ const mode = run.mode;
331
+ if (mode === "run") {
332
+ const [r] = pending;
333
+ if (!r)
334
+ return;
335
+ if (r.status === "done")
336
+ await this.judgeLeftover(data, r.id, claim, signal, s, mode, grade);
337
+ else
338
+ await this.runWhole(data, claim, signal, s, resolved, r.id, grade);
339
+ return;
340
+ }
341
+ const calls = new Map(replayableCalls(s).map((c) => [c.seq, c]));
342
+ for (const r of pending) {
343
+ if (signal.aborted)
344
+ throw new Aborted();
345
+ if (!(await runActive(db, runId))) {
346
+ await this.skipCase(data);
347
+ return;
348
+ }
349
+ if (r.status === "done") {
350
+ const j = await this.judgeLeftover(data, r.id, claim, signal, s, mode, grade);
351
+ if (j === "capped") {
352
+ await this.skipCase(data);
353
+ return;
354
+ }
355
+ continue;
356
+ }
357
+ const claimed = await db
358
+ .updateTable("eval_results")
359
+ .set({ status: "running", claimed_by: claim, updated_at: sql `now()` })
360
+ .where("id", "=", r.id)
361
+ .where("status", "in", [...UNFINISHED])
362
+ .returning("id")
363
+ .executeTakeFirst();
364
+ if (!claimed)
365
+ continue;
366
+ const call = calls.get(Number(r.model_call_seq));
367
+ if (!resolved || !call) {
368
+ const error = !resolved
369
+ ? {
370
+ code: "eval.definition_missing",
371
+ message: "The agent version of this case is missing",
372
+ }
373
+ : {
374
+ code: "eval.call_not_found",
375
+ message: "The model call is not replayable in this snapshot",
376
+ };
377
+ if (await this.resultError(data, r.id, claim, error))
378
+ return;
379
+ continue;
380
+ }
381
+ let out;
382
+ let failure;
383
+ for (let attempt = 0;; attempt++) {
384
+ // 每次请求前(含重试):运行仍在执行(取消 / 越限 / 熔断 / 组织或 agent 删除后不再发),且仍由本次执行认领
385
+ // (stalled 后被接手的旧执行不再发)
386
+ const may = await this.mayRequest(runId, r.id, claim);
387
+ if (may === "lost")
388
+ return;
389
+ if (may === "inactive") {
390
+ await this.skipCase(data);
391
+ return;
392
+ }
393
+ try {
394
+ out = await replayStep(this.d.replay, s, call, resolved, signal);
395
+ break;
396
+ }
397
+ catch (err) {
398
+ // 已发出的请求没有正常收完:按估算计入预算(与成功的请求走同一个原子累加,越限同样置 capped)。
399
+ // 不以认领为条件:钱已经花出去了
400
+ if (err instanceof ReplayAttemptError)
401
+ await consumeTokens(db, runId, err.tokens);
402
+ if (signal.aborted)
403
+ throw new Aborted();
404
+ const f = classify(err instanceof ReplayAttemptError ? err.cause : err);
405
+ if (!f.retryable || attempt >= EVAL_MAX_RETRIES) {
406
+ failure = f;
407
+ break;
408
+ }
409
+ const wait = Math.min(f.retryAfterMs ?? RETRY_DELAYS_MS[attempt] ?? 4000, MAX_RETRY_AFTER_MS);
410
+ await sleep(wait, signal);
411
+ }
412
+ }
413
+ if (!out) {
414
+ const f = failure;
415
+ if (await this.resultError(data, r.id, claim, { code: f.code, message: f.message })) {
416
+ return;
417
+ }
418
+ continue;
419
+ }
420
+ const result = out;
421
+ const tokens = usageTokens(result.candidate.usage);
422
+ const b = replyParts(result.baseline.content);
423
+ const c = replyParts(result.candidate.content);
424
+ const diff = structuralDiff({ ...b, stopReason: result.baseline.stopReason }, { ...c, stopReason: result.candidate.stopReason });
425
+ const outcome = await db.transaction().execute(async (trx) => {
426
+ // 只在仍由本次执行认领时写结果:stalled 后被接手的旧执行不覆盖结果。用量照样计入(请求确实发出且已付费,
427
+ // 与失败尝试一样不以认领为条件),走同一个原子 consumeTokens
428
+ const w = await trx
429
+ .updateTable("eval_results")
430
+ .set({
431
+ status: "done",
432
+ baseline: JSON.stringify(result.baseline),
433
+ candidate: JSON.stringify(result.candidate),
434
+ diff: JSON.stringify(diff),
435
+ // 开了评委:评委做完之前用例不算做完(recountCases 不计 pending 的评委)
436
+ judge_status: grade.judge ? "pending" : "none",
437
+ drift: result.drift,
438
+ error: null,
439
+ updated_at: sql `now()`,
440
+ })
441
+ .where("id", "=", r.id)
442
+ .where("status", "=", "running")
443
+ .where("claimed_by", "=", claim)
444
+ .executeTakeFirst();
445
+ if (Number(w.numUpdatedRows) === 0) {
446
+ await consumeTokens(trx, runId, tokens);
447
+ return "lost";
448
+ }
449
+ await recordOutcome(trx, runId, true, this.d.config().evals.maxConsecutiveErrors);
450
+ const { capped } = await consumeTokens(trx, runId, tokens);
451
+ return capped ? "capped" : "ok";
452
+ });
453
+ // 失去认领:这个用例已由别的执行接手,本次停下
454
+ if (outcome === "lost")
455
+ return;
456
+ if (outcome === "capped") {
457
+ await this.skipCase(data);
458
+ return;
459
+ }
460
+ if (grade.judge) {
461
+ const j = await this.judgeResult(data, r.id, claim, signal, judgeInputOf(s, mode, call.seq, result.baseline, result.candidate, grade.rubric));
462
+ if (j === "capped") {
463
+ await this.skipCase(data);
464
+ return;
465
+ }
466
+ }
467
+ }
468
+ }
469
+ /**
470
+ * 补做评委:结果已 done、`judge_status = 'pending'`(上一次执行在评委之前崩溃 / 停机)。按本次执行的认领号重新认领
471
+ * (条件仍是 done + pending),由结果里存的基线 / 候选得出评委输入;候选请求不重发。
472
+ */
473
+ async judgeLeftover(data, resultId, claim, signal, s, mode, grade) {
474
+ const row = await this.d.db
475
+ .updateTable("eval_results")
476
+ .set({ claimed_by: claim, updated_at: sql `now()` })
477
+ .where("id", "=", resultId)
478
+ .where("status", "=", "done")
479
+ .where("judge_status", "=", "pending")
480
+ .returning(["model_call_seq", "baseline", "candidate"])
481
+ .executeTakeFirst();
482
+ if (!row)
483
+ return "lost";
484
+ const seq = row.model_call_seq === null ? null : Number(row.model_call_seq);
485
+ return this.judgeResult(data, resultId, claim, signal, judgeInputOf(s, mode, seq, row.baseline, row.candidate, grade.rubric));
486
+ }
487
+ /**
488
+ * 评委(结果已写 done、`judge_status = 'pending'` 之后):
489
+ * - 运行不再活跃(取消 / 越限 / 熔断)→ 不发请求,评委记 `skipped`;
490
+ * - 先按用量(失败按估算)`consumeTokens`,不以认领为条件(请求确实发出了);再在仍由本次执行认领、且仍是 pending
491
+ * 时写结论(`judge_status` done / error)。写之前出 DB 错误按崩溃处理:重试时补评委(会再发一次评委请求);
492
+ * - 停机中止:已发出的评委请求按估算计费,任务回到队列,接手的执行补评委。
493
+ * 供应商插件在评委请求途中被撤销(`run.provider_unavailable`)→ 按估算计费后重试,至多 {@link EVAL_MAX_RETRIES} 次;
494
+ * 评委失败不计入熔断(结果本身是 done)。返回 `capped` 表示评委的用量让运行达到上限。
495
+ */
496
+ async judgeResult(data, resultId, claim, signal, input) {
497
+ const db = this.d.db;
498
+ if (!(await runActive(db, data.runId))) {
499
+ await db
500
+ .updateTable("eval_results")
501
+ .set({ judge_status: "skipped", updated_at: sql `now()` })
502
+ .where("id", "=", resultId)
503
+ .where("judge_status", "=", "pending")
504
+ .execute();
505
+ return "inactive";
506
+ }
507
+ await this.d.runReplay.hooks?.beforeJudge?.(data.runId);
508
+ let v;
509
+ for (let attempt = 0;; attempt++) {
510
+ try {
511
+ v = await judge({
512
+ purposes: this.d.purposes,
513
+ maxOutputTokens: this.d.config().evals.judgeMaxOutputTokens,
514
+ }, data.orgId, input, signal);
515
+ }
516
+ catch (err) {
517
+ // 中止时已发出的评委请求:按估算计费(与失败的回放尝试一致)
518
+ if (err instanceof PurposeAttemptError)
519
+ await consumeTokens(db, data.runId, err.tokens);
520
+ if (signal.aborted)
521
+ throw new Aborted();
522
+ throw err;
523
+ }
524
+ // 供应商插件在评委请求途中被撤销 / 升级:失败的尝试按估算计费,运行仍活跃时重试(实时取到新实例)
525
+ if (!("error" in v) ||
526
+ v.error !== JUDGE_PROVIDER_UNAVAILABLE ||
527
+ attempt >= EVAL_MAX_RETRIES) {
528
+ break;
529
+ }
530
+ const { capped } = await consumeTokens(db, data.runId, v.tokens);
531
+ if (capped || !(await runActive(db, data.runId))) {
532
+ await db
533
+ .updateTable("eval_results")
534
+ .set({ judge_status: "skipped", updated_at: sql `now()` })
535
+ .where("id", "=", resultId)
536
+ .where("judge_status", "=", "pending")
537
+ .execute();
538
+ return capped ? "capped" : "inactive";
539
+ }
540
+ await sleep(RETRY_DELAYS_MS[attempt] ?? 4000, signal);
541
+ }
542
+ const tokens = "error" in v ? v.tokens : usageTokens(v.usage);
543
+ const { capped } = await consumeTokens(db, data.runId, tokens);
544
+ const stored = "error" in v
545
+ ? {
546
+ error: v.error,
547
+ ...(v.provider !== undefined && { provider: v.provider }),
548
+ ...(v.model !== undefined && { model: v.model }),
549
+ }
550
+ : v;
551
+ await db
552
+ .updateTable("eval_results")
553
+ .set({
554
+ judge: JSON.stringify(stored),
555
+ judge_status: "error" in v ? "error" : "done",
556
+ updated_at: sql `now()`,
557
+ })
558
+ .where("id", "=", resultId)
559
+ .where("status", "=", "done")
560
+ .where("judge_status", "=", "pending")
561
+ .where("claimed_by", "=", claim)
562
+ .execute();
563
+ if (signal.aborted)
564
+ throw new Aborted();
565
+ return capped ? "capped" : "ok";
566
+ }
567
+ /**
568
+ * 整轮回放一个用例(一条结果)。认领结果后先删掉上一次执行留下的评测对话(崩溃重跑从头开始,C6),
569
+ * 再 {@link replayRun};计费在每次模型请求上完成(含失败与失去认领的请求)。
570
+ * - 运行不再活跃(取消 / 越限 / 熔断)→ 结果 skipped;失去认领 → 停下,不写;
571
+ * - 回放出错 → 结果 error 并计入熔断;停机 → 任务回到队列,接手的执行从头重跑。
572
+ */
573
+ async runWhole(data, claim, signal, s, resolved, resultId, grade) {
574
+ const { runId } = data;
575
+ const db = this.d.db;
576
+ if (!(await runActive(db, runId))) {
577
+ await this.skipCase(data);
578
+ return;
579
+ }
580
+ const claimed = await db
581
+ .updateTable("eval_results")
582
+ .set({ status: "running", claimed_by: claim, updated_at: sql `now()` })
583
+ .where("id", "=", resultId)
584
+ .where("status", "in", [...UNFINISHED])
585
+ .returning("eval_conversation_id")
586
+ .executeTakeFirst();
587
+ if (!claimed)
588
+ return;
589
+ if (claimed.eval_conversation_id !== null) {
590
+ await deleteEvalConversation(this.d.runReplay, claimed.eval_conversation_id);
591
+ }
592
+ if (!resolved) {
593
+ await this.resultError(data, resultId, claim, {
594
+ code: "eval.definition_missing",
595
+ message: "The agent version of this case is missing",
596
+ });
597
+ return;
598
+ }
599
+ const held = async (q = db) => (await q
600
+ .selectFrom("eval_results")
601
+ .select("id")
602
+ .where("id", "=", resultId)
603
+ .where("status", "=", "running")
604
+ .where("claimed_by", "=", claim)
605
+ .executeTakeFirst()) !== undefined;
606
+ let out;
607
+ try {
608
+ out = await replayRun({
609
+ ...this.d.runReplay,
610
+ stillClaimed: () => held(),
611
+ onSeeded: async (trx, conversationId) => {
612
+ const w = await trx
613
+ .updateTable("eval_results")
614
+ .set({ eval_conversation_id: conversationId, updated_at: sql `now()` })
615
+ .where("id", "=", resultId)
616
+ .where("status", "=", "running")
617
+ .where("claimed_by", "=", claim)
618
+ .executeTakeFirst();
619
+ return Number(w.numUpdatedRows) > 0;
620
+ },
621
+ }, s, resolved, runId, signal);
622
+ }
623
+ catch (err) {
624
+ if (signal.aborted)
625
+ throw new Aborted();
626
+ if (err instanceof ReplayClaimLost) {
627
+ if (!(await runActive(db, runId)))
628
+ await this.skipCase(data);
629
+ return;
630
+ }
631
+ // 意外错误(PG / Redis 暂时故障、进程内异常)按崩溃处理:抛给 BullMQ 按 attempts 重试,
632
+ // 下一次执行删掉这次的评测对话、从头重跑(C6);用尽后 failed 事件把结果记 error
633
+ if (!isReplayFailure(err))
634
+ throw err;
635
+ const f = classify(err);
636
+ await this.resultError(data, resultId, claim, { code: f.code, message: f.message });
637
+ return;
638
+ }
639
+ if (signal.aborted)
640
+ throw new Aborted();
641
+ if (out.outcome === "aborted") {
642
+ // 回放中途被停下(取消 / 越限 / 熔断 / 失去认领):结果不完整。运行不再活跃 → skipped;
643
+ // 运行仍活跃说明是失去认领,由接手的执行负责
644
+ if (!(await runActive(db, runId)))
645
+ await this.skipCase(data);
646
+ return;
647
+ }
648
+ // 回放已完整做完:即使最后一次请求的用量刚好越限(运行已 capped),结果照常记 done(只要仍持有认领)
649
+ if (!(await held()))
650
+ return;
651
+ const baseline = runBaseline(s);
652
+ // in DRIFT_ORDER: subagent_changed, then model_switched (the candidate replaced the person's
653
+ // switch), then tool_unmatched
654
+ const drift = [
655
+ ...(subagentCaseChanged(s, resolved) ? ["subagent_changed"] : []),
656
+ ...(resolved.overridesSwitch ? ["model_switched"] : []),
657
+ ...(out.unmatched > 0 ? ["tool_unmatched"] : []),
658
+ ];
659
+ const baseText = replyParts(baseline.finalContent).text;
660
+ const candText = replyParts(out.finalContent).text;
661
+ const diff = structuralDiff({ toolCalls: baseline.toolCalls, text: baseText, stopReason: baseline.stopReason }, { toolCalls: out.toolCalls, text: candText, stopReason: out.stopReason });
662
+ const written = await db.transaction().execute(async (trx) => {
663
+ const w = await trx
664
+ .updateTable("eval_results")
665
+ .set({
666
+ status: "done",
667
+ baseline: JSON.stringify(baseline),
668
+ candidate: JSON.stringify(out),
669
+ diff: JSON.stringify(diff),
670
+ judge_status: grade.judge ? "pending" : "none",
671
+ drift,
672
+ error: null,
673
+ eval_conversation_id: out.conversationId,
674
+ updated_at: sql `now()`,
675
+ })
676
+ .where("id", "=", resultId)
677
+ .where("status", "=", "running")
678
+ .where("claimed_by", "=", claim)
679
+ .executeTakeFirst();
680
+ if (Number(w.numUpdatedRows) === 0)
681
+ return false;
682
+ await recordOutcome(trx, runId, true, this.d.config().evals.maxConsecutiveErrors);
683
+ return true;
684
+ });
685
+ if (!written || !grade.judge)
686
+ return;
687
+ await this.judgeResult(data, resultId, claim, signal, judgeInputOf(s, "run", null, baseline, out, grade.rubric));
688
+ }
689
+ /**
690
+ * 该用例剩下的结果标 skipped。整轮回放留下的评测对话里若还有没结束的运行(上一次执行崩溃在回放中途),删掉它,
691
+ * 不留永远「执行中」的评测对话;已正常收尾(`run_aborted` / `run_finished`)的保留,轨迹里能看到停在哪里。
692
+ * 清理失败只记日志,不挡住标 skipped(残留的随评测集或组织删除清掉)。
693
+ */
694
+ async skipCase(data) {
695
+ const db = this.d.db;
696
+ const left = await db
697
+ .selectFrom("eval_results as er")
698
+ .select(["er.id", "er.eval_conversation_id"])
699
+ .where("er.run_id", "=", data.runId)
700
+ .where("er.case_id", "=", data.caseId)
701
+ .where("er.status", "in", [...UNFINISHED])
702
+ .where("er.eval_conversation_id", "is not", null)
703
+ .where((eb) => eb.exists(eb
704
+ .selectFrom("runs")
705
+ .select("runs.id")
706
+ .whereRef("runs.conversation_id", "=", "er.eval_conversation_id")
707
+ .where("runs.status", "in", ["queued", "running"])))
708
+ .execute();
709
+ for (const r of left) {
710
+ try {
711
+ await deleteEvalConversation(this.d.runReplay, r.eval_conversation_id);
712
+ await db
713
+ .updateTable("eval_results")
714
+ .set({ eval_conversation_id: null })
715
+ .where("id", "=", r.id)
716
+ .execute();
717
+ }
718
+ catch (err) {
719
+ this.d.log.warn("cannot delete the unfinished eval conversation of a skipped case", {
720
+ runId: data.runId,
721
+ caseId: data.caseId,
722
+ err,
723
+ });
724
+ }
725
+ }
726
+ await db
727
+ .updateTable("eval_results")
728
+ .set({ status: "skipped", updated_at: sql `now()` })
729
+ .where("run_id", "=", data.runId)
730
+ .where("case_id", "=", data.caseId)
731
+ .where("status", "in", [...UNFINISHED])
732
+ .execute();
733
+ await skipPendingJudges(db, data.runId, data.caseId);
734
+ }
735
+ /** BullMQ 判定任务失败(stalled 次数超限或重试用尽):剩下的结果记 error,再重算进度。 */
736
+ async failCase(data, err) {
737
+ const stalled = /stalled/i.test(err.message);
738
+ // 整轮回放:尝试用尽后不会再有执行来清理,删掉留下的半截评测对话
739
+ const left = await this.d.db
740
+ .selectFrom("eval_results")
741
+ .select("eval_conversation_id")
742
+ .where("run_id", "=", data.runId)
743
+ .where("case_id", "=", data.caseId)
744
+ .where("status", "in", [...UNFINISHED])
745
+ .where("eval_conversation_id", "is not", null)
746
+ .execute();
747
+ for (const r of left) {
748
+ // 清理失败不能挡住记错误(否则结果一直 running、运行卡住);残留的评测对话随评测集删除或组织删除清掉
749
+ try {
750
+ await deleteEvalConversation(this.d.runReplay, r.eval_conversation_id);
751
+ }
752
+ catch (e) {
753
+ this.d.log.warn("cannot delete the eval conversation of a failed eval job", {
754
+ runId: data.runId,
755
+ caseId: data.caseId,
756
+ err: e,
757
+ });
758
+ }
759
+ }
760
+ await this.d.db
761
+ .updateTable("eval_results")
762
+ .set({
763
+ status: "error",
764
+ error: JSON.stringify(stalled
765
+ ? { code: "eval.stalled", message: "The replay was interrupted too many times" }
766
+ : { code: "eval.internal", message: "The replay failed unexpectedly" }),
767
+ eval_conversation_id: null,
768
+ updated_at: sql `now()`,
769
+ })
770
+ .where("run_id", "=", data.runId)
771
+ .where("case_id", "=", data.caseId)
772
+ .where("status", "in", [...UNFINISHED])
773
+ .execute();
774
+ // 已 done 但评委一直没做成的:评委记 skipped(结果本身保留)
775
+ await skipPendingJudges(this.d.db, data.runId, data.caseId);
776
+ await recountCases(this.d.db, data.runId);
777
+ }
778
+ }
779
+ /**
780
+ * A plugin template's child case: the template's current version, which a new dispatch would use
781
+ * (a template removed since gets version 0, so it always differs). Undefined for other cases.
782
+ */
783
+ export async function currentTemplate(db, s) {
784
+ const t = subagentStartedOf(toEvents(s))?.template;
785
+ if (t?.source !== "plugin" || t.id === undefined)
786
+ return undefined;
787
+ const row = (await loadTemplates(db, s.orgId, [t.id])).get(t.id);
788
+ return { id: t.id, version: row?.version ?? 0 };
789
+ }