@kindgi/api 0.1.2 → 0.1.4-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 (250) hide show
  1. package/dist/agent-binding.d.ts +18 -4
  2. package/dist/agent-binding.d.ts.map +1 -1
  3. package/dist/agent-pins.d.ts +48 -0
  4. package/dist/agent-pins.d.ts.map +1 -0
  5. package/dist/agent-pins.js +102 -0
  6. package/dist/agent-pins.js.map +1 -0
  7. package/dist/app.d.ts +22 -0
  8. package/dist/app.d.ts.map +1 -1
  9. package/dist/app.js +22 -3
  10. package/dist/app.js.map +1 -1
  11. package/dist/block-binding.d.ts +132 -0
  12. package/dist/block-binding.d.ts.map +1 -0
  13. package/dist/block-binding.js +4 -0
  14. package/dist/block-binding.js.map +1 -0
  15. package/dist/block-pins.d.ts +22 -0
  16. package/dist/block-pins.d.ts.map +1 -0
  17. package/dist/block-pins.js +112 -0
  18. package/dist/block-pins.js.map +1 -0
  19. package/dist/cost-binding.d.ts +100 -5
  20. package/dist/cost-binding.d.ts.map +1 -1
  21. package/dist/cost-binding.js +10 -0
  22. package/dist/cost-binding.js.map +1 -1
  23. package/dist/deploy-versions.d.ts +58 -0
  24. package/dist/deploy-versions.d.ts.map +1 -0
  25. package/dist/deploy-versions.js +91 -0
  26. package/dist/deploy-versions.js.map +1 -0
  27. package/dist/deployment-binding.d.ts +24 -3
  28. package/dist/deployment-binding.d.ts.map +1 -1
  29. package/dist/derive-agent-version.d.ts +69 -0
  30. package/dist/derive-agent-version.d.ts.map +1 -0
  31. package/dist/derive-agent-version.js +139 -0
  32. package/dist/derive-agent-version.js.map +1 -0
  33. package/dist/errors.d.ts.map +1 -1
  34. package/dist/errors.js +17 -0
  35. package/dist/errors.js.map +1 -1
  36. package/dist/eval-case-binding.d.ts +65 -0
  37. package/dist/eval-case-binding.d.ts.map +1 -0
  38. package/dist/eval-case-binding.js +4 -0
  39. package/dist/eval-case-binding.js.map +1 -0
  40. package/dist/eval-run-binding.d.ts +30 -0
  41. package/dist/eval-run-binding.d.ts.map +1 -1
  42. package/dist/eval-run-dispatcher.d.ts +38 -3
  43. package/dist/eval-run-dispatcher.d.ts.map +1 -1
  44. package/dist/eval-run-dispatcher.js +21 -15
  45. package/dist/eval-run-dispatcher.js.map +1 -1
  46. package/dist/eval-suite-binding.d.ts +1 -1
  47. package/dist/eval-suite-binding.d.ts.map +1 -1
  48. package/dist/eval-suite-binding.js +2 -0
  49. package/dist/eval-suite-binding.js.map +1 -1
  50. package/dist/flow-binding.d.ts +10 -4
  51. package/dist/flow-binding.d.ts.map +1 -1
  52. package/dist/flow-pins.d.ts +36 -0
  53. package/dist/flow-pins.d.ts.map +1 -0
  54. package/dist/flow-pins.js +81 -0
  55. package/dist/flow-pins.js.map +1 -0
  56. package/dist/hitl-binding.d.ts +20 -5
  57. package/dist/hitl-binding.d.ts.map +1 -1
  58. package/dist/index.d.ts +19 -8
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +8 -2
  61. package/dist/index.js.map +1 -1
  62. package/dist/judged-dispatcher.d.ts +134 -0
  63. package/dist/judged-dispatcher.d.ts.map +1 -0
  64. package/dist/judged-dispatcher.js +297 -0
  65. package/dist/judged-dispatcher.js.map +1 -0
  66. package/dist/judged-items.d.ts +86 -0
  67. package/dist/judged-items.d.ts.map +1 -0
  68. package/dist/judged-items.js +184 -0
  69. package/dist/judged-items.js.map +1 -0
  70. package/dist/judgment-binding.d.ts +316 -0
  71. package/dist/judgment-binding.d.ts.map +1 -0
  72. package/dist/judgment-binding.js +19 -0
  73. package/dist/judgment-binding.js.map +1 -0
  74. package/dist/middleware/auth.d.ts +3 -2
  75. package/dist/middleware/auth.d.ts.map +1 -1
  76. package/dist/middleware/auth.js.map +1 -1
  77. package/dist/middleware/idempotency.d.ts +5 -1
  78. package/dist/middleware/idempotency.d.ts.map +1 -1
  79. package/dist/middleware/idempotency.js +8 -1
  80. package/dist/middleware/idempotency.js.map +1 -1
  81. package/dist/openapi/generate.d.ts.map +1 -1
  82. package/dist/openapi/generate.js +4 -1
  83. package/dist/openapi/generate.js.map +1 -1
  84. package/dist/openapi/operations.d.ts.map +1 -1
  85. package/dist/openapi/operations.js +543 -24
  86. package/dist/openapi/operations.js.map +1 -1
  87. package/dist/openapi/schemas.d.ts +58 -0
  88. package/dist/openapi/schemas.d.ts.map +1 -1
  89. package/dist/openapi/schemas.js +1058 -27
  90. package/dist/openapi/schemas.js.map +1 -1
  91. package/dist/provenance-binding.d.ts +27 -1
  92. package/dist/provenance-binding.d.ts.map +1 -1
  93. package/dist/provenance-binding.js.map +1 -1
  94. package/dist/provider-binding.d.ts +12 -7
  95. package/dist/provider-binding.d.ts.map +1 -1
  96. package/dist/reviewer-binding.d.ts +10 -2
  97. package/dist/reviewer-binding.d.ts.map +1 -1
  98. package/dist/reviewer-role.d.ts +13 -0
  99. package/dist/reviewer-role.d.ts.map +1 -0
  100. package/dist/reviewer-role.js +27 -0
  101. package/dist/reviewer-role.js.map +1 -0
  102. package/dist/routes/agents.d.ts +9 -1
  103. package/dist/routes/agents.d.ts.map +1 -1
  104. package/dist/routes/agents.js +175 -11
  105. package/dist/routes/agents.js.map +1 -1
  106. package/dist/routes/approvals.d.ts +5 -4
  107. package/dist/routes/approvals.d.ts.map +1 -1
  108. package/dist/routes/approvals.js +52 -16
  109. package/dist/routes/approvals.js.map +1 -1
  110. package/dist/routes/blocks.d.ts +19 -0
  111. package/dist/routes/blocks.d.ts.map +1 -0
  112. package/dist/routes/blocks.js +281 -0
  113. package/dist/routes/blocks.js.map +1 -0
  114. package/dist/routes/conversations.d.ts +7 -1
  115. package/dist/routes/conversations.d.ts.map +1 -1
  116. package/dist/routes/conversations.js +41 -1
  117. package/dist/routes/conversations.js.map +1 -1
  118. package/dist/routes/cost.d.ts.map +1 -1
  119. package/dist/routes/cost.js +142 -11
  120. package/dist/routes/cost.js.map +1 -1
  121. package/dist/routes/deployments.d.ts +3 -0
  122. package/dist/routes/deployments.d.ts.map +1 -1
  123. package/dist/routes/deployments.js +208 -55
  124. package/dist/routes/deployments.js.map +1 -1
  125. package/dist/routes/eval-comparison.d.ts +14 -0
  126. package/dist/routes/eval-comparison.d.ts.map +1 -0
  127. package/dist/routes/eval-comparison.js +87 -0
  128. package/dist/routes/eval-comparison.js.map +1 -0
  129. package/dist/routes/eval-runs.d.ts.map +1 -1
  130. package/dist/routes/eval-runs.js +8 -0
  131. package/dist/routes/eval-runs.js.map +1 -1
  132. package/dist/routes/flows.d.ts +13 -1
  133. package/dist/routes/flows.d.ts.map +1 -1
  134. package/dist/routes/flows.js +44 -3
  135. package/dist/routes/flows.js.map +1 -1
  136. package/dist/routes/hierarchy-errors.d.ts +35 -0
  137. package/dist/routes/hierarchy-errors.d.ts.map +1 -0
  138. package/dist/routes/hierarchy-errors.js +39 -0
  139. package/dist/routes/hierarchy-errors.js.map +1 -0
  140. package/dist/routes/identity.d.ts +7 -0
  141. package/dist/routes/identity.d.ts.map +1 -1
  142. package/dist/routes/identity.js +3 -2
  143. package/dist/routes/identity.js.map +1 -1
  144. package/dist/routes/judged-suites.d.ts +20 -0
  145. package/dist/routes/judged-suites.d.ts.map +1 -0
  146. package/dist/routes/judged-suites.js +272 -0
  147. package/dist/routes/judged-suites.js.map +1 -0
  148. package/dist/routes/judgment-context.d.ts +22 -0
  149. package/dist/routes/judgment-context.d.ts.map +1 -0
  150. package/dist/routes/judgment-context.js +88 -0
  151. package/dist/routes/judgment-context.js.map +1 -0
  152. package/dist/routes/judgment-flow-context.d.ts +32 -0
  153. package/dist/routes/judgment-flow-context.d.ts.map +1 -0
  154. package/dist/routes/judgment-flow-context.js +195 -0
  155. package/dist/routes/judgment-flow-context.js.map +1 -0
  156. package/dist/routes/judgments.d.ts +41 -0
  157. package/dist/routes/judgments.d.ts.map +1 -0
  158. package/dist/routes/judgments.js +566 -0
  159. package/dist/routes/judgments.js.map +1 -0
  160. package/dist/routes/orgs.d.ts +5 -2
  161. package/dist/routes/orgs.d.ts.map +1 -1
  162. package/dist/routes/orgs.js +38 -22
  163. package/dist/routes/orgs.js.map +1 -1
  164. package/dist/routes/policies.d.ts.map +1 -1
  165. package/dist/routes/policies.js +12 -1
  166. package/dist/routes/policies.js.map +1 -1
  167. package/dist/routes/projects.d.ts +10 -2
  168. package/dist/routes/projects.d.ts.map +1 -1
  169. package/dist/routes/projects.js +87 -79
  170. package/dist/routes/projects.js.map +1 -1
  171. package/dist/routes/provenance.d.ts.map +1 -1
  172. package/dist/routes/provenance.js +32 -1
  173. package/dist/routes/provenance.js.map +1 -1
  174. package/dist/routes/providers.d.ts.map +1 -1
  175. package/dist/routes/providers.js +6 -1
  176. package/dist/routes/providers.js.map +1 -1
  177. package/dist/routes/runs.d.ts +0 -7
  178. package/dist/routes/runs.d.ts.map +1 -1
  179. package/dist/routes/runs.js +65 -20
  180. package/dist/routes/runs.js.map +1 -1
  181. package/dist/routes/scope-params.d.ts +16 -1
  182. package/dist/routes/scope-params.d.ts.map +1 -1
  183. package/dist/routes/scope-params.js +28 -0
  184. package/dist/routes/scope-params.js.map +1 -1
  185. package/dist/routes/teams.d.ts +6 -2
  186. package/dist/routes/teams.d.ts.map +1 -1
  187. package/dist/routes/teams.js +77 -73
  188. package/dist/routes/teams.js.map +1 -1
  189. package/dist/types.d.ts +4 -3
  190. package/dist/types.d.ts.map +1 -1
  191. package/dist/webhook-endpoint-binding.d.ts +11 -0
  192. package/dist/webhook-endpoint-binding.d.ts.map +1 -1
  193. package/dist/webhook-endpoint-binding.js.map +1 -1
  194. package/openapi.json +13316 -9299
  195. package/package.json +21 -21
  196. package/src/agent-binding.ts +19 -4
  197. package/src/agent-pins.ts +147 -0
  198. package/src/app.ts +76 -3
  199. package/src/block-binding.ts +137 -0
  200. package/src/block-pins.ts +148 -0
  201. package/src/cost-binding.ts +116 -5
  202. package/src/deploy-versions.ts +157 -0
  203. package/src/deployment-binding.ts +27 -3
  204. package/src/derive-agent-version.ts +206 -0
  205. package/src/errors.ts +17 -0
  206. package/src/eval-case-binding.ts +71 -0
  207. package/src/eval-run-binding.ts +33 -0
  208. package/src/eval-run-dispatcher.ts +57 -16
  209. package/src/eval-suite-binding.ts +2 -0
  210. package/src/flow-binding.ts +11 -4
  211. package/src/flow-pins.ts +113 -0
  212. package/src/hitl-binding.ts +20 -4
  213. package/src/index.ts +88 -2
  214. package/src/judged-dispatcher.ts +507 -0
  215. package/src/judged-items.ts +263 -0
  216. package/src/judgment-binding.ts +349 -0
  217. package/src/middleware/auth.ts +3 -2
  218. package/src/middleware/idempotency.ts +7 -1
  219. package/src/openapi/generate.ts +7 -1
  220. package/src/openapi/operations.ts +615 -24
  221. package/src/openapi/schemas.ts +1157 -22
  222. package/src/provenance-binding.ts +42 -1
  223. package/src/provider-binding.ts +12 -7
  224. package/src/reviewer-binding.ts +10 -2
  225. package/src/reviewer-role.ts +35 -0
  226. package/src/routes/agents.ts +243 -19
  227. package/src/routes/approvals.ts +70 -19
  228. package/src/routes/blocks.ts +362 -0
  229. package/src/routes/conversations.ts +57 -1
  230. package/src/routes/cost.ts +159 -21
  231. package/src/routes/deployments.ts +266 -56
  232. package/src/routes/eval-comparison.ts +101 -0
  233. package/src/routes/eval-runs.ts +11 -0
  234. package/src/routes/flows.ts +63 -5
  235. package/src/routes/hierarchy-errors.ts +51 -0
  236. package/src/routes/identity.ts +10 -2
  237. package/src/routes/judged-suites.ts +363 -0
  238. package/src/routes/judgment-context.ts +128 -0
  239. package/src/routes/judgment-flow-context.ts +245 -0
  240. package/src/routes/judgments.ts +743 -0
  241. package/src/routes/orgs.ts +44 -27
  242. package/src/routes/policies.ts +19 -0
  243. package/src/routes/projects.ts +106 -95
  244. package/src/routes/provenance.ts +48 -1
  245. package/src/routes/providers.ts +5 -0
  246. package/src/routes/runs.ts +79 -22
  247. package/src/routes/scope-params.ts +35 -1
  248. package/src/routes/teams.ts +96 -90
  249. package/src/types.ts +4 -3
  250. package/src/webhook-endpoint-binding.ts +11 -0
@@ -0,0 +1,272 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ import { Hono } from 'hono';
4
+ import { ref, tuplesForCreate } from '@kindgi/authz';
5
+ import { statusFor, toWireError } from '../errors.js';
6
+ import { clampLimit } from './pagination.js';
7
+ /** The most cases a test set built from judgments holds. */
8
+ export const MAX_JUDGED_CASES = 1000;
9
+ const PAGE = 100;
10
+ const SEMVER_RE = /^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?$/;
11
+ /**
12
+ * Test sets built from judgments: `judged` eval suites.
13
+ *
14
+ * - `POST /v1/eval-suites/:suiteId/versions/from-judgments` builds and
15
+ * publishes a version whose cases are copies of judged runs (input,
16
+ * what the turn read, the judged output) with each item's judgments
17
+ * summed up, weighted by judge class (an unclassified judgment counts
18
+ * 1). Needs `admin` on the project, as publishing a suite does.
19
+ * - `GET /v1/eval-suites/:suiteId/versions/:version/cases` lists them.
20
+ */
21
+ export function judgedSuitesRouter(suites, judgments, cases, authorizer) {
22
+ const r = new Hono();
23
+ r.post('/:suiteId/versions/from-judgments', async (c) => {
24
+ const tenantId = c.get('tenantId');
25
+ const suiteId = c.req.param('suiteId');
26
+ const parsed = parseBuildBody(await c.req.json().catch(() => null));
27
+ if (parsed.kind === 'err')
28
+ return fail(c, 'bad-input', parsed.message);
29
+ const body = parsed.body;
30
+ if (authorizer !== undefined &&
31
+ !(await authorizer.can(c, 'admin', ref('project', body.projectId)))) {
32
+ return fail(c, 'permission-denied', 'Building a test set needs admin on the project.');
33
+ }
34
+ if (judgments.listJudgedRuns === undefined) {
35
+ return fail(c, 'test-sets-not-supported', 'This deployment cannot build test sets from judgments.');
36
+ }
37
+ const built = await buildCases(judgments, tenantId, body);
38
+ const principal = c.get('principal');
39
+ const creatorUserId = principal?.actor.kind === 'user' ? principal.actor.id : undefined;
40
+ const outcome = await suites.publish({
41
+ tenantId,
42
+ projectId: body.projectId,
43
+ suite: {
44
+ id: suiteId,
45
+ tenantId,
46
+ version: body.version,
47
+ kind: 'judged',
48
+ ...(body.description !== undefined && { description: body.description }),
49
+ spec: {
50
+ source: 'judgments',
51
+ // Where the judgments came from: a comparison's summary names it.
52
+ projectId: body.projectId,
53
+ query: body.query,
54
+ caseCount: built.cases.length,
55
+ truncated: built.truncated,
56
+ builtAt: new Date().toISOString(),
57
+ },
58
+ },
59
+ enqueueTuples: (id) => tuplesForCreate({ kind: 'eval_suite', id, tenantId, projectId: body.projectId }, creatorUserId),
60
+ });
61
+ if (outcome.kind === 'already-registered') {
62
+ return fail(c, 'eval-suite-already-registered', `Eval suite "${suiteId}" version "${body.version}" is already registered.`);
63
+ }
64
+ if (outcome.kind === 'project-not-found') {
65
+ return fail(c, 'bad-input', `\`projectId\` "${body.projectId}" is not a project here.`);
66
+ }
67
+ await cases.putCases({ tenantId, suiteId, version: body.version, cases: built.cases });
68
+ c.status(201);
69
+ return c.json({
70
+ suiteId,
71
+ version: body.version,
72
+ kind: 'judged',
73
+ caseCount: built.cases.length,
74
+ truncated: built.truncated,
75
+ });
76
+ });
77
+ r.get('/:suiteId/versions/:version/cases', async (c) => {
78
+ const tenantId = c.get('tenantId');
79
+ const suiteId = c.req.param('suiteId');
80
+ const version = c.req.param('version');
81
+ if (authorizer !== undefined &&
82
+ !(await authorizer.can(c, 'read', ref('eval_suite', suiteId)))) {
83
+ return fail(c, 'eval-suite-not-found', `No eval suite "${suiteId}".`);
84
+ }
85
+ const cursor = c.req.query('cursor');
86
+ const page = await cases.listCases({
87
+ tenantId,
88
+ suiteId,
89
+ version,
90
+ limit: clampLimit(c.req.query('limit'), 25, 100),
91
+ ...(cursor !== undefined && cursor.length > 0 && { cursor: cursor }),
92
+ });
93
+ return c.json({
94
+ data: page.data,
95
+ hasMore: page.hasMore,
96
+ ...(page.nextCursor !== undefined && { nextCursor: page.nextCursor }),
97
+ });
98
+ });
99
+ return r;
100
+ }
101
+ function fail(c, code, message) {
102
+ c.status(statusFor(code));
103
+ return c.json(toWireError({ code, message }, c.get('requestId')));
104
+ }
105
+ /** Each class's weight, read once (an unclassified judgment counts 1; a missing class too). */
106
+ function classWeights(judgments, tenantId) {
107
+ const weights = new Map();
108
+ return async (judgeClassId) => {
109
+ if (judgeClassId === undefined)
110
+ return 1;
111
+ const known = weights.get(judgeClassId);
112
+ if (known !== undefined)
113
+ return known;
114
+ const k = await judgments.getClass({ tenantId, judgeClassId, includeUnregistered: true });
115
+ const w = k?.weight ?? 1;
116
+ weights.set(judgeClassId, w);
117
+ return w;
118
+ };
119
+ }
120
+ function judgedRunFilter(tenantId, body) {
121
+ const { judgeClassIds: _ids, minJudgments: _min, ...runFilter } = body.query;
122
+ return { tenantId, projectId: body.projectId, ...runFilter };
123
+ }
124
+ /** Pages judged runs (newest first, up to MAX_JUDGED_CASES) and turns each into a case. */
125
+ async function buildCases(judgments, tenantId, body) {
126
+ const list = judgments.listJudgedRuns;
127
+ const weightOf = classWeights(judgments, tenantId);
128
+ const filter = judgedRunFilter(tenantId, body);
129
+ const cases = [];
130
+ let cursor;
131
+ for (;;) {
132
+ const page = await list({ ...filter, limit: PAGE, ...(cursor !== undefined && { cursor }) });
133
+ for (const judged of page.data) {
134
+ const built = await toCase(judged, body.query, weightOf);
135
+ if (built !== undefined)
136
+ cases.push(built);
137
+ if (cases.length >= MAX_JUDGED_CASES)
138
+ return { cases, truncated: true };
139
+ }
140
+ if (!page.hasMore || page.nextCursor === undefined)
141
+ return { cases, truncated: false };
142
+ cursor = page.nextCursor;
143
+ }
144
+ }
145
+ async function toCase(judged, q, weightOf) {
146
+ const kept = q.judgeClassIds === undefined
147
+ ? judged.judgments
148
+ : judged.judgments.filter((j) => j.judgeClassId !== undefined && q.judgeClassIds?.includes(j.judgeClassId));
149
+ if (kept.length === 0 || kept.length < (q.minJudgments ?? 1))
150
+ return undefined;
151
+ const byKey = new Map();
152
+ for (const j of kept)
153
+ byKey.set(j.item.key, [...(byKey.get(j.item.key) ?? []), j]);
154
+ const items = [];
155
+ for (const [key, list] of byKey)
156
+ items.push(await summarize(key, list, weightOf));
157
+ items.sort((a, b) => (a.rank ?? Number.MAX_SAFE_INTEGER) - (b.rank ?? Number.MAX_SAFE_INTEGER));
158
+ const run = judged.run;
159
+ return {
160
+ caseId: run.runId,
161
+ subject: run.subject,
162
+ input: run.input,
163
+ ...(run.context !== undefined && { context: run.context }),
164
+ output: run.output,
165
+ items,
166
+ };
167
+ }
168
+ async function summarize(key, judgments, weightOf) {
169
+ let yes = 0;
170
+ let no = 0;
171
+ let yesWeight = 0;
172
+ let totalWeight = 0;
173
+ for (const j of judgments) {
174
+ const w = await weightOf(j.judgeClassId);
175
+ totalWeight += w;
176
+ if (j.verdict === 'yes') {
177
+ yes += 1;
178
+ yesWeight += w;
179
+ }
180
+ else {
181
+ no += 1;
182
+ }
183
+ }
184
+ const first = judgments[0];
185
+ return {
186
+ key,
187
+ ...(first?.item.pointer !== undefined && { pointer: first.item.pointer }),
188
+ ...(first?.item.rank !== undefined && { rank: first.item.rank }),
189
+ yes,
190
+ no,
191
+ yesWeight,
192
+ totalWeight,
193
+ reasons: judgments.flatMap((j) => j.reason !== undefined ? [{ verdict: j.verdict, reason: j.reason }] : []),
194
+ };
195
+ }
196
+ const STRING_FILTERS = ['agentId', 'agentVersion', 'flowId', 'since', 'until'];
197
+ /** The string filters (agent, version, flow, time window); a message when one is malformed. */
198
+ function parseStringFilters(b) {
199
+ const query = {};
200
+ for (const field of STRING_FILTERS) {
201
+ const v = b[field];
202
+ if (v === undefined)
203
+ continue;
204
+ if (typeof v !== 'string' || v.length === 0)
205
+ return `${field} must be a non-empty string.`;
206
+ if ((field === 'since' || field === 'until') && Number.isNaN(Date.parse(v))) {
207
+ return `${field} must be an ISO 8601 time.`;
208
+ }
209
+ query[field] = v;
210
+ }
211
+ if (query.agentVersion !== undefined && query.agentId === undefined) {
212
+ return 'agentVersion needs agentId.';
213
+ }
214
+ return query;
215
+ }
216
+ /** Which judgments count: by class, and how many a run needs. */
217
+ function parseJudgmentFilters(b) {
218
+ const ids = b.judgeClassIds;
219
+ if (ids !== undefined &&
220
+ (!Array.isArray(ids) || ids.some((i) => typeof i !== 'string' || i.length === 0))) {
221
+ return 'judgeClassIds must be a list of judge class ids.';
222
+ }
223
+ const min = b.minJudgments;
224
+ if (min !== undefined && !(Number.isInteger(min) && min >= 1)) {
225
+ return 'minJudgments must be a whole number ≥ 1.';
226
+ }
227
+ return {
228
+ ...(ids !== undefined && { judgeClassIds: ids }),
229
+ ...(min !== undefined && { minJudgments: min }),
230
+ };
231
+ }
232
+ /** The optional judged-run filters; a message when one is malformed. */
233
+ function parseQuery(b) {
234
+ const strings = parseStringFilters(b);
235
+ if (typeof strings === 'string')
236
+ return strings;
237
+ const counted = parseJudgmentFilters(b);
238
+ if (typeof counted === 'string')
239
+ return counted;
240
+ return { ...strings, ...counted };
241
+ }
242
+ function parseBuildBody(raw) {
243
+ const err = (message) => ({ kind: 'err', message });
244
+ if (raw === null || typeof raw !== 'object')
245
+ return err('Send a JSON object.');
246
+ const b = raw;
247
+ if (typeof b.version !== 'string' || !SEMVER_RE.test(b.version)) {
248
+ return err('version is required: a semver such as "1.0.0".');
249
+ }
250
+ if (typeof b.projectId !== 'string' || b.projectId.length === 0) {
251
+ return err('projectId is required.');
252
+ }
253
+ if (b.agentId === undefined && b.flowId === undefined) {
254
+ return err('Name the agent (agentId) or the flow (flowId) whose judged runs to use.');
255
+ }
256
+ if (b.description !== undefined && typeof b.description !== 'string') {
257
+ return err('description must be a string.');
258
+ }
259
+ const query = parseQuery(b);
260
+ if (typeof query === 'string')
261
+ return err(query);
262
+ return {
263
+ kind: 'ok',
264
+ body: {
265
+ version: b.version,
266
+ projectId: b.projectId,
267
+ ...(typeof b.description === 'string' && { description: b.description }),
268
+ query,
269
+ },
270
+ };
271
+ }
272
+ //# sourceMappingURL=judged-suites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judged-suites.js","sourceRoot":"","sources":["../../src/routes/judged-suites.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type ConversationBinding } from '@kindgi/agents';
2
+ import type { RunBinding } from '@kindgi/runtime';
3
+ import type { TenantId } from '@kindgi/types';
4
+ import type { JudgedRunContext } from '../judgment-binding.js';
5
+ /** The most messages of conversation history a judged turn keeps. */
6
+ export declare const MAX_JUDGED_HISTORY = 200;
7
+ /**
8
+ * What a judged agent turn read besides its input, so it can be replayed
9
+ * faithfully later: the conversation before the turn, what its
10
+ * retrievals returned, and the decision at its session approval gate. Best effort and read-only: a part that can't be
11
+ * read is left out (the judgment never fails over it). `undefined` for
12
+ * a flow run, or when nothing could be read.
13
+ */
14
+ export declare function captureTurnContext(input: {
15
+ readonly tenantId: TenantId;
16
+ readonly runId: string;
17
+ readonly output: unknown;
18
+ readonly conversationId: string | undefined;
19
+ readonly runBinding: RunBinding;
20
+ readonly conversations: ConversationBinding | undefined;
21
+ }): Promise<JudgedRunContext | undefined>;
22
+ //# sourceMappingURL=judgment-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judgment-context.d.ts","sourceRoot":"","sources":["../../src/routes/judgment-context.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,mBAAmB,EAIzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,EAAyB,QAAQ,EAAE,MAAM,eAAe,CAAC;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,qEAAqE;AACrE,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAsFtC;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,mBAAmB,GAAG,SAAS,CAAC;CACzD,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAYxC"}
@@ -0,0 +1,88 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ import { RUN_RETRIEVALS_NODE, SESSION_GATE_RECORD, readGateDecision, } from '@kindgi/agents';
4
+ /** The most messages of conversation history a judged turn keeps. */
5
+ export const MAX_JUDGED_HISTORY = 200;
6
+ /** How many messages are read to find a turn's history. */
7
+ const HISTORY_READ_LIMIT = 1000;
8
+ function obj(value) {
9
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
10
+ ? value
11
+ : undefined;
12
+ }
13
+ /** The sequence of the first message the turn appended (its user message). */
14
+ function firstAppendedSequence(output) {
15
+ const appended = obj(output)?.appended;
16
+ if (!Array.isArray(appended))
17
+ return undefined;
18
+ const sequences = appended
19
+ .map((m) => obj(m)?.sequence)
20
+ .filter((s) => typeof s === 'number');
21
+ return sequences.length > 0 ? Math.min(...sequences) : undefined;
22
+ }
23
+ async function readHistory(conversations, tenantId, conversationId, before) {
24
+ const read = await conversations.readMessages({
25
+ tenantId,
26
+ conversationId: conversationId,
27
+ limit: HISTORY_READ_LIMIT,
28
+ });
29
+ if (read.kind === 'err')
30
+ return {};
31
+ const earlier = read.value.filter((m) => m.sequence < before);
32
+ const kept = earlier.slice(-MAX_JUDGED_HISTORY);
33
+ return {
34
+ history: kept,
35
+ ...(kept.length < earlier.length && { historyTruncated: true }),
36
+ };
37
+ }
38
+ /** What the turn's journal says it retrieved, and how its session approval was decided. */
39
+ async function readJournalParts(runBinding, tenantId, runId) {
40
+ const journal = await runBinding.readJournal(tenantId, runId);
41
+ if (journal.kind === 'err')
42
+ return {};
43
+ const entries = journal.value;
44
+ const step = entries.find((e) => e.kind === 'step.completed' &&
45
+ typeof e.nodeId === 'string' &&
46
+ (e.nodeId === RUN_RETRIEVALS_NODE || e.nodeId.endsWith(`/${RUN_RETRIEVALS_NODE}`)));
47
+ const retrieved = obj(obj(step?.payload)?.output)?.retrieved;
48
+ const sessionApproval = sessionApprovalOf(entries);
49
+ return {
50
+ ...(retrieved !== undefined && { retrieved }),
51
+ ...(sessionApproval !== undefined && { sessionApproval }),
52
+ };
53
+ }
54
+ /** The decision that resolved the turn's session approval gate, if it waited on one. */
55
+ function sessionApprovalOf(entries) {
56
+ const gate = entries.find((e) => e.kind === 'value.recorded' && obj(e.payload)?.key === SESSION_GATE_RECORD);
57
+ const tokenId = obj(obj(gate?.payload)?.value)?.waitTokenId;
58
+ if (typeof tokenId !== 'string')
59
+ return undefined;
60
+ const resumed = entries.find((e) => e.kind === 'wait.resumed' && obj(e.payload)?.tokenId === tokenId);
61
+ if (resumed === undefined)
62
+ return undefined;
63
+ const decision = readGateDecision(obj(resumed.payload)?.value);
64
+ return {
65
+ approved: decision.approved,
66
+ ...(!decision.approved &&
67
+ decision.rationale !== undefined && { rationale: decision.rationale }),
68
+ };
69
+ }
70
+ /**
71
+ * What a judged agent turn read besides its input, so it can be replayed
72
+ * faithfully later: the conversation before the turn, what its
73
+ * retrievals returned, and the decision at its session approval gate. Best effort and read-only: a part that can't be
74
+ * read is left out (the judgment never fails over it). `undefined` for
75
+ * a flow run, or when nothing could be read.
76
+ */
77
+ export async function captureTurnContext(input) {
78
+ const before = firstAppendedSequence(input.output);
79
+ const [history, journal] = await Promise.all([
80
+ input.conversations !== undefined && input.conversationId !== undefined && before !== undefined
81
+ ? readHistory(input.conversations, input.tenantId, input.conversationId, before).catch(() => ({}))
82
+ : Promise.resolve({}),
83
+ readJournalParts(input.runBinding, input.tenantId, input.runId).catch(() => ({})),
84
+ ]);
85
+ const context = { ...history, ...journal };
86
+ return Object.keys(context).length > 0 ? context : undefined;
87
+ }
88
+ //# sourceMappingURL=judgment-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judgment-context.js","sourceRoot":"","sources":["../../src/routes/judgment-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { RunBinding } from '@kindgi/runtime';
2
+ import type { TenantId } from '@kindgi/types';
3
+ import type { FlowRegistryBinding } from '../flow-binding.js';
4
+ import type { JudgedRunContext } from '../judgment-binding.js';
5
+ /** The most tool calls a judged flow run keeps. */
6
+ export declare const MAX_JUDGED_FLOW_CALLS = 500;
7
+ /**
8
+ * The tool calls an agent turn made, with their results, from its
9
+ * output's `appended` messages: each agent message's `toolCalls`, paired
10
+ * with the `tool` message that answered it.
11
+ */
12
+ export declare function turnToolCalls(output: unknown): readonly {
13
+ readonly toolId: string;
14
+ readonly arguments: unknown;
15
+ readonly result: unknown;
16
+ }[];
17
+ /**
18
+ * What a judged flow run did (`context.flow`): its tool calls with their
19
+ * results, and its agent steps' turns. `undefined` when nothing could be
20
+ * read.
21
+ */
22
+ export declare function captureFlowContext(input: {
23
+ readonly tenantId: TenantId;
24
+ readonly run: {
25
+ readonly runId: string;
26
+ readonly flowId: string;
27
+ readonly flowVersion: string;
28
+ };
29
+ readonly runBinding: RunBinding;
30
+ readonly flows: FlowRegistryBinding | undefined;
31
+ }): Promise<JudgedRunContext | undefined>;
32
+ //# sourceMappingURL=judgment-flow-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judgment-flow-context.d.ts","sourceRoot":"","sources":["../../src/routes/judgment-flow-context.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAmB,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,KAAK,EAAiB,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAGV,gBAAgB,EAEjB,MAAM,wBAAwB,CAAC;AAEhC,mDAAmD;AACnD,eAAO,MAAM,qBAAqB,MAAM,CAAC;AA4BzC;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,OAAO,GACd,SAAS;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAE,EAAE,CAuB/F;AAmID;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAChG,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,mBAAmB,GAAG,SAAS,CAAC;CACjD,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAmBxC"}
@@ -0,0 +1,195 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ import { isFanoutNode, isLoopNode } from '@kindgi/flow';
4
+ /** The most tool calls a judged flow run keeps. */
5
+ export const MAX_JUDGED_FLOW_CALLS = 500;
6
+ /** How deep into sub-flows the capture goes. */
7
+ const MAX_FLOW_DEPTH = 3;
8
+ /** The most child runs read per run. */
9
+ const MAX_CHILDREN = 100;
10
+ function obj(value) {
11
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
12
+ ? value
13
+ : undefined;
14
+ }
15
+ /** The tool each tool node runs, by node id: in loop bodies and fanout branches too. */
16
+ function toolNodes(flow) {
17
+ const tools = new Map();
18
+ const walk = (nodes) => {
19
+ for (const node of nodes) {
20
+ if (node.kind === 'tool')
21
+ tools.set(node.id, node.ref);
22
+ else if (isLoopNode(node))
23
+ walk(node.body.nodes);
24
+ else if (isFanoutNode(node)) {
25
+ for (const b of node.branches)
26
+ tools.set(b.handler, b.handler);
27
+ }
28
+ }
29
+ };
30
+ if (flow !== null)
31
+ walk(flow.nodes);
32
+ return tools;
33
+ }
34
+ /**
35
+ * The tool calls an agent turn made, with their results, from its
36
+ * output's `appended` messages: each agent message's `toolCalls`, paired
37
+ * with the `tool` message that answered it.
38
+ */
39
+ export function turnToolCalls(output) {
40
+ const appended = obj(output)?.appended;
41
+ if (!Array.isArray(appended))
42
+ return [];
43
+ const args = new Map();
44
+ for (const m of appended) {
45
+ const calls = obj(obj(m)?.content)?.toolCalls;
46
+ if (obj(m)?.role !== 'agent' || !Array.isArray(calls))
47
+ continue;
48
+ for (const call of calls) {
49
+ const id = obj(call)?.id;
50
+ if (typeof id === 'string')
51
+ args.set(id, obj(call)?.arguments);
52
+ }
53
+ }
54
+ return appended.flatMap((m) => {
55
+ const toolCall = obj(obj(m)?.toolCall);
56
+ const toolId = toolCall?.toolId;
57
+ const invocationId = toolCall?.invocationId;
58
+ if (obj(m)?.role !== 'tool' || typeof toolId !== 'string' || typeof invocationId !== 'string') {
59
+ return [];
60
+ }
61
+ return args.has(invocationId)
62
+ ? [{ toolId, arguments: args.get(invocationId), result: obj(m)?.content }]
63
+ : [];
64
+ });
65
+ }
66
+ /** Where a step sits: its loop iteration, when it's in a loop body. */
67
+ function scopeOf(loopContext) {
68
+ return loopContext === undefined || loopContext === null
69
+ ? undefined
70
+ : JSON.stringify(loopContext);
71
+ }
72
+ class Collector {
73
+ calls = [];
74
+ steps = [];
75
+ truncated = false;
76
+ add(call) {
77
+ if (this.calls.length >= MAX_JUDGED_FLOW_CALLS) {
78
+ this.truncated = true;
79
+ return;
80
+ }
81
+ this.calls.push(call);
82
+ }
83
+ }
84
+ /** A flow run's tool nodes' calls: each `step.completed` of a tool node, with its `step.started` input. */
85
+ async function nodeCalls(r, c, run) {
86
+ const [flow, journal] = await Promise.all([
87
+ r.flows?.getVersion({
88
+ tenantId: r.tenantId,
89
+ flowId: run.flowId,
90
+ version: run.flowVersion,
91
+ }) ?? Promise.resolve(null),
92
+ r.runBinding.readJournal(r.tenantId, run.runId),
93
+ ]);
94
+ const tools = toolNodes(flow);
95
+ if (journal.kind === 'err' || tools.size === 0)
96
+ return;
97
+ const inputs = new Map();
98
+ for (const e of journal.value) {
99
+ if (typeof e.nodeId !== 'string' || !tools.has(e.nodeId))
100
+ continue;
101
+ const payload = obj(e.payload) ?? {};
102
+ const scope = scopeOf(payload.loopContext);
103
+ const key = `${e.nodeId}\u0000${scope ?? ''}`;
104
+ if (e.kind === 'step.started')
105
+ inputs.set(key, payload.input);
106
+ if (e.kind === 'step.completed') {
107
+ c.add({
108
+ runId: run.runId,
109
+ nodeId: e.nodeId,
110
+ ...(scope !== undefined && { scope }),
111
+ toolId: tools.get(e.nodeId),
112
+ arguments: inputs.get(key),
113
+ result: payload.output,
114
+ });
115
+ }
116
+ }
117
+ }
118
+ /** An agent step's turn: its calls, and what it retrieved. */
119
+ async function stepTurn(r, c, child) {
120
+ const agent = child.agent;
121
+ if (agent === undefined)
122
+ return;
123
+ const output = child.output ?? (await r.runBinding.getRun(r.tenantId, child.runId))?.output ?? undefined;
124
+ const nodeId = child.parentNodeId ?? undefined;
125
+ const scope = child.parentScope ?? undefined;
126
+ const retrieved = obj(output)?.retrieved;
127
+ c.steps.push({
128
+ runId: child.runId,
129
+ ...(nodeId !== undefined && { nodeId }),
130
+ ...(scope !== undefined && scope !== '' && { scope }),
131
+ agentId: agent.id,
132
+ agentVersion: agent.version,
133
+ ...(retrieved !== undefined && { retrieved }),
134
+ });
135
+ for (const call of turnToolCalls(output)) {
136
+ c.add({
137
+ runId: child.runId,
138
+ ...(nodeId !== undefined && { nodeId }),
139
+ ...(scope !== undefined && scope !== '' && { scope }),
140
+ ...call,
141
+ });
142
+ }
143
+ }
144
+ /** A run's child runs (agent steps' turns, sub-flows); none when they can't be read. */
145
+ async function childrenOf(r, runId) {
146
+ try {
147
+ const page = await r.runBinding.listRuns({
148
+ tenantId: r.tenantId,
149
+ parent: { runId: runId },
150
+ limit: MAX_CHILDREN,
151
+ });
152
+ return page.data;
153
+ }
154
+ catch {
155
+ return [];
156
+ }
157
+ }
158
+ async function collectRun(r, c, run, depth) {
159
+ await nodeCalls(r, c, run).catch(() => undefined);
160
+ for (const child of await childrenOf(r, run.runId)) {
161
+ if (child.agent !== undefined) {
162
+ await stepTurn(r, c, child).catch(() => undefined);
163
+ }
164
+ else if (depth < MAX_FLOW_DEPTH) {
165
+ await collectRun(r, c, {
166
+ runId: child.runId,
167
+ flowId: child.flowId,
168
+ flowVersion: child.flowVersion,
169
+ }, depth + 1);
170
+ }
171
+ }
172
+ }
173
+ /**
174
+ * What a judged flow run did (`context.flow`): its tool calls with their
175
+ * results, and its agent steps' turns. `undefined` when nothing could be
176
+ * read.
177
+ */
178
+ export async function captureFlowContext(input) {
179
+ const c = new Collector();
180
+ try {
181
+ await collectRun({ tenantId: input.tenantId, runBinding: input.runBinding, flows: input.flows }, c, input.run, 0);
182
+ }
183
+ catch {
184
+ // Best effort: keep what was read.
185
+ }
186
+ if (c.calls.length === 0 && c.steps.length === 0)
187
+ return undefined;
188
+ const flow = {
189
+ calls: c.calls,
190
+ steps: c.steps,
191
+ ...(c.truncated && { truncated: true }),
192
+ };
193
+ return { flow };
194
+ }
195
+ //# sourceMappingURL=judgment-flow-context.js.map