@kindgi/api 0.1.3 → 0.1.4-rc.1

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 (222) hide show
  1. package/dist/agent-binding.d.ts +26 -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 +27 -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 +20 -1
  20. package/dist/cost-binding.d.ts.map +1 -1
  21. package/dist/cost-binding.js +4 -0
  22. package/dist/cost-binding.js.map +1 -1
  23. package/dist/deploy-versions.d.ts +60 -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 +77 -0
  30. package/dist/derive-agent-version.d.ts.map +1 -0
  31. package/dist/derive-agent-version.js +149 -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 +18 -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 +37 -0
  41. package/dist/eval-run-binding.d.ts.map +1 -1
  42. package/dist/eval-run-binding.js.map +1 -1
  43. package/dist/eval-run-dispatcher.d.ts +41 -3
  44. package/dist/eval-run-dispatcher.d.ts.map +1 -1
  45. package/dist/eval-run-dispatcher.js +21 -15
  46. package/dist/eval-run-dispatcher.js.map +1 -1
  47. package/dist/eval-suite-binding.d.ts +1 -1
  48. package/dist/eval-suite-binding.d.ts.map +1 -1
  49. package/dist/eval-suite-binding.js +2 -0
  50. package/dist/eval-suite-binding.js.map +1 -1
  51. package/dist/flow-binding.d.ts +18 -4
  52. package/dist/flow-binding.d.ts.map +1 -1
  53. package/dist/flow-pins.d.ts +36 -0
  54. package/dist/flow-pins.d.ts.map +1 -0
  55. package/dist/flow-pins.js +81 -0
  56. package/dist/flow-pins.js.map +1 -0
  57. package/dist/guardrail-binding.d.ts +8 -0
  58. package/dist/guardrail-binding.d.ts.map +1 -1
  59. package/dist/handler-binding.d.ts +3 -0
  60. package/dist/handler-binding.d.ts.map +1 -1
  61. package/dist/index.d.ts +18 -6
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +8 -2
  64. package/dist/index.js.map +1 -1
  65. package/dist/judged-dispatcher.d.ts +138 -0
  66. package/dist/judged-dispatcher.d.ts.map +1 -0
  67. package/dist/judged-dispatcher.js +308 -0
  68. package/dist/judged-dispatcher.js.map +1 -0
  69. package/dist/judged-items.d.ts +86 -0
  70. package/dist/judged-items.d.ts.map +1 -0
  71. package/dist/judged-items.js +184 -0
  72. package/dist/judged-items.js.map +1 -0
  73. package/dist/judgment-binding.d.ts +316 -0
  74. package/dist/judgment-binding.d.ts.map +1 -0
  75. package/dist/judgment-binding.js +19 -0
  76. package/dist/judgment-binding.js.map +1 -0
  77. package/dist/openapi/generate.d.ts.map +1 -1
  78. package/dist/openapi/generate.js +4 -1
  79. package/dist/openapi/generate.js.map +1 -1
  80. package/dist/openapi/operations.d.ts.map +1 -1
  81. package/dist/openapi/operations.js +482 -13
  82. package/dist/openapi/operations.js.map +1 -1
  83. package/dist/openapi/schemas.d.ts +46 -0
  84. package/dist/openapi/schemas.d.ts.map +1 -1
  85. package/dist/openapi/schemas.js +1350 -175
  86. package/dist/openapi/schemas.js.map +1 -1
  87. package/dist/provider-binding.d.ts +12 -7
  88. package/dist/provider-binding.d.ts.map +1 -1
  89. package/dist/registry-read-only.d.ts +32 -0
  90. package/dist/registry-read-only.d.ts.map +1 -0
  91. package/dist/registry-read-only.js +22 -0
  92. package/dist/registry-read-only.js.map +1 -0
  93. package/dist/routes/agents.d.ts +9 -1
  94. package/dist/routes/agents.d.ts.map +1 -1
  95. package/dist/routes/agents.js +181 -11
  96. package/dist/routes/agents.js.map +1 -1
  97. package/dist/routes/blocks.d.ts +19 -0
  98. package/dist/routes/blocks.d.ts.map +1 -0
  99. package/dist/routes/blocks.js +306 -0
  100. package/dist/routes/blocks.js.map +1 -0
  101. package/dist/routes/cost.d.ts.map +1 -1
  102. package/dist/routes/cost.js +47 -2
  103. package/dist/routes/cost.js.map +1 -1
  104. package/dist/routes/deployments.d.ts +3 -0
  105. package/dist/routes/deployments.d.ts.map +1 -1
  106. package/dist/routes/deployments.js +224 -55
  107. package/dist/routes/deployments.js.map +1 -1
  108. package/dist/routes/eval-comparison.d.ts +15 -0
  109. package/dist/routes/eval-comparison.d.ts.map +1 -0
  110. package/dist/routes/eval-comparison.js +123 -0
  111. package/dist/routes/eval-comparison.js.map +1 -0
  112. package/dist/routes/eval-runs.d.ts +7 -1
  113. package/dist/routes/eval-runs.d.ts.map +1 -1
  114. package/dist/routes/eval-runs.js +42 -3
  115. package/dist/routes/eval-runs.js.map +1 -1
  116. package/dist/routes/eval-versions.d.ts +25 -0
  117. package/dist/routes/eval-versions.d.ts.map +1 -0
  118. package/dist/routes/eval-versions.js +66 -0
  119. package/dist/routes/eval-versions.js.map +1 -0
  120. package/dist/routes/flows.d.ts +13 -1
  121. package/dist/routes/flows.d.ts.map +1 -1
  122. package/dist/routes/flows.js +48 -3
  123. package/dist/routes/flows.js.map +1 -1
  124. package/dist/routes/guardrails.d.ts.map +1 -1
  125. package/dist/routes/guardrails.js +4 -0
  126. package/dist/routes/guardrails.js.map +1 -1
  127. package/dist/routes/hierarchy-errors.d.ts +45 -0
  128. package/dist/routes/hierarchy-errors.d.ts.map +1 -0
  129. package/dist/routes/hierarchy-errors.js +47 -0
  130. package/dist/routes/hierarchy-errors.js.map +1 -0
  131. package/dist/routes/judged-suites.d.ts +20 -0
  132. package/dist/routes/judged-suites.d.ts.map +1 -0
  133. package/dist/routes/judged-suites.js +272 -0
  134. package/dist/routes/judged-suites.js.map +1 -0
  135. package/dist/routes/judgment-context.d.ts +22 -0
  136. package/dist/routes/judgment-context.d.ts.map +1 -0
  137. package/dist/routes/judgment-context.js +88 -0
  138. package/dist/routes/judgment-context.js.map +1 -0
  139. package/dist/routes/judgment-flow-context.d.ts +32 -0
  140. package/dist/routes/judgment-flow-context.d.ts.map +1 -0
  141. package/dist/routes/judgment-flow-context.js +195 -0
  142. package/dist/routes/judgment-flow-context.js.map +1 -0
  143. package/dist/routes/judgments.d.ts +41 -0
  144. package/dist/routes/judgments.d.ts.map +1 -0
  145. package/dist/routes/judgments.js +566 -0
  146. package/dist/routes/judgments.js.map +1 -0
  147. package/dist/routes/orgs.d.ts +5 -2
  148. package/dist/routes/orgs.d.ts.map +1 -1
  149. package/dist/routes/orgs.js +38 -22
  150. package/dist/routes/orgs.js.map +1 -1
  151. package/dist/routes/policies.d.ts.map +1 -1
  152. package/dist/routes/policies.js +12 -1
  153. package/dist/routes/policies.js.map +1 -1
  154. package/dist/routes/projects.d.ts +10 -2
  155. package/dist/routes/projects.d.ts.map +1 -1
  156. package/dist/routes/projects.js +94 -80
  157. package/dist/routes/projects.js.map +1 -1
  158. package/dist/routes/providers.d.ts.map +1 -1
  159. package/dist/routes/providers.js +6 -1
  160. package/dist/routes/providers.js.map +1 -1
  161. package/dist/routes/runs.js +25 -3
  162. package/dist/routes/runs.js.map +1 -1
  163. package/dist/routes/teams.d.ts +6 -2
  164. package/dist/routes/teams.d.ts.map +1 -1
  165. package/dist/routes/teams.js +83 -73
  166. package/dist/routes/teams.js.map +1 -1
  167. package/dist/routes/tools.d.ts.map +1 -1
  168. package/dist/routes/tools.js +4 -0
  169. package/dist/routes/tools.js.map +1 -1
  170. package/dist/tool-binding.d.ts +8 -0
  171. package/dist/tool-binding.d.ts.map +1 -1
  172. package/openapi.json +14253 -10099
  173. package/package.json +21 -21
  174. package/src/agent-binding.ts +28 -4
  175. package/src/agent-pins.ts +147 -0
  176. package/src/app.ts +81 -3
  177. package/src/block-binding.ts +137 -0
  178. package/src/block-pins.ts +148 -0
  179. package/src/cost-binding.ts +21 -1
  180. package/src/deploy-versions.ts +157 -0
  181. package/src/deployment-binding.ts +27 -3
  182. package/src/derive-agent-version.ts +217 -0
  183. package/src/errors.ts +18 -0
  184. package/src/eval-case-binding.ts +71 -0
  185. package/src/eval-run-binding.ts +40 -0
  186. package/src/eval-run-dispatcher.ts +60 -16
  187. package/src/eval-suite-binding.ts +2 -0
  188. package/src/flow-binding.ts +20 -4
  189. package/src/flow-pins.ts +113 -0
  190. package/src/guardrail-binding.ts +9 -0
  191. package/src/handler-binding.ts +3 -0
  192. package/src/index.ts +86 -2
  193. package/src/judged-dispatcher.ts +530 -0
  194. package/src/judged-items.ts +263 -0
  195. package/src/judgment-binding.ts +349 -0
  196. package/src/openapi/generate.ts +7 -1
  197. package/src/openapi/operations.ts +579 -13
  198. package/src/openapi/schemas.ts +1408 -128
  199. package/src/provider-binding.ts +12 -7
  200. package/src/registry-read-only.ts +43 -0
  201. package/src/routes/agents.ts +252 -19
  202. package/src/routes/blocks.ts +387 -0
  203. package/src/routes/cost.ts +55 -1
  204. package/src/routes/deployments.ts +291 -56
  205. package/src/routes/eval-comparison.ts +135 -0
  206. package/src/routes/eval-runs.ts +57 -3
  207. package/src/routes/eval-versions.ts +110 -0
  208. package/src/routes/flows.ts +70 -5
  209. package/src/routes/guardrails.ts +7 -0
  210. package/src/routes/hierarchy-errors.ts +60 -0
  211. package/src/routes/judged-suites.ts +363 -0
  212. package/src/routes/judgment-context.ts +128 -0
  213. package/src/routes/judgment-flow-context.ts +245 -0
  214. package/src/routes/judgments.ts +743 -0
  215. package/src/routes/orgs.ts +44 -27
  216. package/src/routes/policies.ts +19 -0
  217. package/src/routes/projects.ts +118 -96
  218. package/src/routes/providers.ts +5 -0
  219. package/src/routes/runs.ts +29 -3
  220. package/src/routes/teams.ts +104 -90
  221. package/src/routes/tools.ts +7 -0
  222. package/src/tool-binding.ts +9 -0
@@ -185,6 +185,16 @@ export const RunSchema: JsonSchema = {
185
185
  description: 'Set on a child run: the node in the parent run that started it.',
186
186
  },
187
187
  agent: { $ref: '#/components/schemas/RunAgent' },
188
+ replayOf: {
189
+ type: 'string',
190
+ format: 'uuid',
191
+ description: 'Set on a replay run (an eval run re-running a past run): the run it replays.',
192
+ },
193
+ evalRunId: {
194
+ type: 'string',
195
+ description: 'Set on a replay run: the eval run that started it.',
196
+ },
197
+ versions: { $ref: '#/components/schemas/FlowVersionOverrides' },
188
198
  publicAccessToken: {
189
199
  type: 'string',
190
200
  description:
@@ -928,8 +938,23 @@ export const AgentSchema: JsonSchema = {
928
938
  version: { type: 'string', description: 'Semver.' },
929
939
  name: { type: 'string' },
930
940
  description: { type: 'string' },
931
- instructions: { type: 'string' },
941
+ instructions: {
942
+ oneOf: [{ type: 'string', minLength: 1 }, { $ref: '#/components/schemas/PromptRef' }],
943
+ description:
944
+ 'The system prompt (a Liquid template), or a prompt block by range whose template and parameters are used instead (pinned at publish, `pins.prompts`).',
945
+ },
932
946
  parameters: { type: 'array', items: { $ref: '#/components/schemas/PromptParameter' } },
947
+ settings: {
948
+ type: 'array',
949
+ items: { $ref: '#/components/schemas/BlockRef' },
950
+ description:
951
+ 'Settings blocks the agent reads, by range: tools read them as `ToolContext.settings[\'<id>\']`, templates as `settings["<id>"]`. Pinned at publish (`pins.settings`).',
952
+ },
953
+ modelSettings: {
954
+ $ref: '#/components/schemas/BlockRef',
955
+ description:
956
+ "A model-settings block by range: its `temperature` and `maxOutputTokens` go into the turn's model calls. Pinned at publish.",
957
+ },
933
958
  capabilities: { type: 'array', items: { $ref: '#/components/schemas/Capability' } },
934
959
  tools: { type: 'array', items: { $ref: '#/components/schemas/ToolRef' } },
935
960
  retrieval: { type: 'array', items: { $ref: '#/components/schemas/RetrievalIntent' } },
@@ -951,6 +976,108 @@ export const AgentSchema: JsonSchema = {
951
976
  tags: { type: 'array', items: { type: 'string' } },
952
977
  output: { $ref: '#/components/schemas/AgentOutputSpec' },
953
978
  toolErrors: { $ref: '#/components/schemas/ToolErrorsSpec' },
979
+ pins: { $ref: '#/components/schemas/AgentPins' },
980
+ derivedFrom: { $ref: '#/components/schemas/VersionDerivation' },
981
+ unregisteredAt: {
982
+ type: 'string',
983
+ format: 'date-time',
984
+ description:
985
+ 'Present only on an unregistered version (`GET …/versions/{version}` reads those too). Unregister stops a version being chosen, not the pins that hold it: a new run naming it is refused, while a resumed run and a published version that pins it still run it.',
986
+ },
987
+ pinsDigest: {
988
+ type: 'string',
989
+ pattern: '^sha256:[0-9a-f]{64}$',
990
+ description:
991
+ "Set by the runtime with `pins`: `sha256:<hex>` of the pins' canonical JSON (sorted keys, no whitespace). Two agent versions with the same digest run the same blocks.",
992
+ },
993
+ },
994
+ };
995
+
996
+ export const VersionDerivationSchema: JsonSchema = {
997
+ description:
998
+ "Set by the runtime on an agent or flow version a deploy registered in place of the definition's version, which was registered already with other pins or content (versions never change). Never in the publish body.",
999
+ type: 'object',
1000
+ additionalProperties: false,
1001
+ required: ['version', 'reason'],
1002
+ properties: {
1003
+ version: { type: 'string', description: 'The version the definition names.' },
1004
+ reason: {
1005
+ type: 'string',
1006
+ enum: ['pins-changed', 'unpinned', 'version-taken', 'edited'],
1007
+ description:
1008
+ "`pins-changed`: a block it uses has a new version; `unpinned`: the definition's version was published before pins existed; `version-taken`: the definition's version holds another definition; `edited`: derived from `version` with some data-block pins swapped (`POST /v1/agents/{agentId}/versions`).",
1009
+ },
1010
+ label: { type: 'string', description: 'For `edited`: a short label for the version.' },
1011
+ by: { type: 'string', description: 'For `edited`: who derived it (`user:<id>`).' },
1012
+ },
1013
+ };
1014
+
1015
+ export const DeriveAgentVersionBodySchema: JsonSchema = {
1016
+ description:
1017
+ "Derive a new agent version from a pinned one with some data-block pins swapped: an expert's edit reaching an agent with no code change.",
1018
+ type: 'object',
1019
+ additionalProperties: false,
1020
+ required: ['from', 'pins'],
1021
+ properties: {
1022
+ from: { type: 'string', description: 'The version to derive from (it must be pinned).' },
1023
+ pins: { $ref: '#/components/schemas/AgentPinSwaps' },
1024
+ label: { type: 'string', description: 'A short label for the new version.' },
1025
+ projectId: {
1026
+ type: 'string',
1027
+ format: 'uuid',
1028
+ description: "The agent's project, when the runtime doesn't record it on the version.",
1029
+ },
1030
+ },
1031
+ };
1032
+
1033
+ const PinMapSchema: JsonSchema = {
1034
+ type: 'object',
1035
+ additionalProperties: { type: 'string' },
1036
+ };
1037
+
1038
+ export const AgentPinSwapsSchema: JsonSchema = {
1039
+ description:
1040
+ 'The data-block pins to swap, by block id → exact version. Only blocks the version already references; tool pins come from code.',
1041
+ type: 'object',
1042
+ additionalProperties: false,
1043
+ properties: {
1044
+ prompts: { ...PinMapSchema, description: 'Prompt block id → exact version.' },
1045
+ settings: { ...PinMapSchema, description: 'Settings block id → exact version.' },
1046
+ },
1047
+ };
1048
+
1049
+ export const AgentPinsSchema: JsonSchema = {
1050
+ description:
1051
+ 'The exact block versions an agent version runs: its lockfile. Set by the runtime when the version is published, never in the publish body: each tool range resolves once to the version every run of that agent version uses, so a new tool version reaches the agent only through a new agent version. Absent on a version published before pins existed (its ranges resolve per run).',
1052
+ type: 'object',
1053
+ additionalProperties: false,
1054
+ required: ['tools', 'prompts', 'settings'],
1055
+ properties: {
1056
+ tools: { ...PinMapSchema, description: 'Tool id → exact version.' },
1057
+ prompts: { ...PinMapSchema, description: 'Prompt block id → exact version.' },
1058
+ settings: { ...PinMapSchema, description: 'Settings block id → exact version.' },
1059
+ },
1060
+ };
1061
+
1062
+ export const PromptRefSchema: JsonSchema = {
1063
+ description: "A prompt block an agent's instructions come from, by id and semver range.",
1064
+ type: 'object',
1065
+ additionalProperties: false,
1066
+ required: ['prompt', 'version'],
1067
+ properties: {
1068
+ prompt: { type: 'string', description: 'The prompt block id.' },
1069
+ version: { type: 'string', description: 'A semver range (`^1.0.0`, `1.2.0`).' },
1070
+ },
1071
+ };
1072
+
1073
+ export const BlockRefSchema: JsonSchema = {
1074
+ description: 'A settings block an agent reads, by id and semver range.',
1075
+ type: 'object',
1076
+ additionalProperties: false,
1077
+ required: ['id', 'version'],
1078
+ properties: {
1079
+ id: { type: 'string', description: 'The settings block id.' },
1080
+ version: { type: 'string', description: 'A semver range (`^1.0.0`, `1.2.0`).' },
954
1081
  },
955
1082
  };
956
1083
 
@@ -976,8 +1103,23 @@ export const PublishAgentBodySchema: JsonSchema = {
976
1103
  name: { type: 'string' },
977
1104
  description: { type: 'string' },
978
1105
  projectId: ContentProjectIdProperty,
979
- instructions: { type: 'string' },
1106
+ instructions: {
1107
+ oneOf: [{ type: 'string', minLength: 1 }, { $ref: '#/components/schemas/PromptRef' }],
1108
+ description:
1109
+ 'The system prompt (a Liquid template), or a prompt block by range whose template and parameters are used instead (pinned at publish, `pins.prompts`).',
1110
+ },
980
1111
  parameters: { type: 'array', items: { $ref: '#/components/schemas/PromptParameter' } },
1112
+ settings: {
1113
+ type: 'array',
1114
+ items: { $ref: '#/components/schemas/BlockRef' },
1115
+ description:
1116
+ 'Settings blocks the agent reads, by range: tools read them as `ToolContext.settings[\'<id>\']`, templates as `settings["<id>"]`. Pinned at publish (`pins.settings`).',
1117
+ },
1118
+ modelSettings: {
1119
+ $ref: '#/components/schemas/BlockRef',
1120
+ description:
1121
+ "A model-settings block by range: its `temperature` and `maxOutputTokens` go into the turn's model calls. Pinned at publish.",
1122
+ },
981
1123
  capabilities: { type: 'array', items: { $ref: '#/components/schemas/Capability' } },
982
1124
  tools: { type: 'array', items: { $ref: '#/components/schemas/ToolRef' } },
983
1125
  retrieval: { type: 'array', items: { $ref: '#/components/schemas/RetrievalIntent' } },
@@ -1114,6 +1256,50 @@ export const FlowSchema: JsonSchema = {
1114
1256
  edges: { type: 'array', items: { $ref: '#/components/schemas/FlowEdge' } },
1115
1257
  maxParallelism: { type: 'integer', minimum: 1 },
1116
1258
  metadata: { type: 'object', additionalProperties: true },
1259
+ pins: { $ref: '#/components/schemas/FlowPins' },
1260
+ pinsDigest: {
1261
+ type: 'string',
1262
+ pattern: '^sha256:[0-9a-f]{64}$',
1263
+ description:
1264
+ "Set by the runtime with `pins`: `sha256:<hex>` of the pins' canonical JSON (sorted keys, no whitespace).",
1265
+ },
1266
+ derivedFrom: { $ref: '#/components/schemas/VersionDerivation' },
1267
+ unregisteredAt: {
1268
+ type: 'string',
1269
+ format: 'date-time',
1270
+ description:
1271
+ 'Present only on an unregistered version (`GET …/versions/{version}` reads those too). Unregister stops a version being chosen, not the pins that hold it: a new run naming it is refused, while a resumed run and a published version that pins it still run it.',
1272
+ },
1273
+ },
1274
+ };
1275
+
1276
+ export const FlowPinsSchema: JsonSchema = {
1277
+ description:
1278
+ 'The exact tool and agent versions a flow version runs: its lockfile. Set by the runtime when the version is published, never in the publish body: each tool the flow runs, and each agent it runs at no named version, resolves once to its latest version then, which every run of that flow version uses. Absent on a version published before pins existed (it binds the latest versions per run).',
1279
+ type: 'object',
1280
+ additionalProperties: false,
1281
+ required: ['tools', 'agents'],
1282
+ properties: {
1283
+ tools: { ...PinMapSchema, description: 'Tool id → exact version.' },
1284
+ agents: {
1285
+ ...PinMapSchema,
1286
+ description: 'Agent id → exact version, for agent nodes that name no version.',
1287
+ },
1288
+ },
1289
+ };
1290
+
1291
+ export const FlowVersionOverridesSchema: JsonSchema = {
1292
+ description:
1293
+ "Agents and tools a flow runs at other exact versions than the flow version's pins (\"this flow, with `acme.scorer` at 0.4.0\"), without publishing a new flow version: a comparison's flow candidate (`versions` on the start body and the run's `comparison`), and the flow runs that replay it (a run's `versions`). Each id must be an agent or tool the flow uses.",
1294
+ type: 'object',
1295
+ additionalProperties: false,
1296
+ properties: {
1297
+ tools: { ...PinMapSchema, description: 'Tool id → exact version.' },
1298
+ agents: {
1299
+ ...PinMapSchema,
1300
+ description:
1301
+ 'Agent id → exact version, for agent nodes with or without a version of their own.',
1302
+ },
1117
1303
  },
1118
1304
  };
1119
1305
 
@@ -1882,152 +2068,615 @@ export const ObservationCollectionPageSchema: JsonSchema = {
1882
2068
  },
1883
2069
  };
1884
2070
 
1885
- // ---------------- memory ----------------
2071
+ // ---------------- judgments + judge classes ----------------
1886
2072
 
1887
- export const FactScopeSchema: JsonSchema = {
1888
- type: 'object',
1889
- additionalProperties: true,
1890
- required: ['tenantId'],
2073
+ export const JudgeClassScopeSchema: JsonSchema = {
1891
2074
  description:
1892
- 'Fact scope object. `tenantId` is required; every optional key narrows the fact (`userId`, `orgId`, `projectId`, `threadId`, `sessionId`). Additional keys accepted for forward compatibility.',
1893
- properties: {
1894
- tenantId: { type: 'string' },
1895
- userId: { type: 'string' },
1896
- orgId: { type: 'string' },
1897
- projectId: { type: 'string' },
1898
- threadId: { type: 'string' },
1899
- sessionId: { type: 'string' },
1900
- },
2075
+ 'Where a judge class applies: the whole tenant, one project, or one agent in a project.',
2076
+ oneOf: [
2077
+ {
2078
+ type: 'object',
2079
+ additionalProperties: false,
2080
+ required: ['kind'],
2081
+ properties: { kind: { type: 'string', const: 'tenant' } },
2082
+ },
2083
+ {
2084
+ type: 'object',
2085
+ additionalProperties: false,
2086
+ required: ['kind', 'projectId'],
2087
+ properties: {
2088
+ kind: { type: 'string', const: 'project' },
2089
+ projectId: { type: 'string', minLength: 1 },
2090
+ },
2091
+ },
2092
+ {
2093
+ type: 'object',
2094
+ additionalProperties: false,
2095
+ required: ['kind', 'projectId', 'agentId'],
2096
+ properties: {
2097
+ kind: { type: 'string', const: 'agent' },
2098
+ projectId: { type: 'string', minLength: 1 },
2099
+ agentId: { type: 'string', minLength: 1 },
2100
+ },
2101
+ },
2102
+ ],
1901
2103
  };
1902
2104
 
1903
- export const RetentionSchema: JsonSchema = {
2105
+ export const JudgeClassSchema: JsonSchema = {
1904
2106
  type: 'object',
1905
2107
  additionalProperties: false,
2108
+ required: ['id', 'tenantId', 'scope', 'name', 'weight', 'createdAt', 'updatedAt'],
1906
2109
  properties: {
1907
- keepUntil: { type: 'string', format: 'date-time' },
1908
- keepDays: { type: 'integer', minimum: 1 },
1909
- legalHold: { type: 'boolean' },
2110
+ id: { type: 'string' },
2111
+ tenantId: { type: 'string' },
2112
+ scope: { $ref: '#/components/schemas/JudgeClassScope' },
2113
+ name: {
2114
+ type: 'string',
2115
+ description: 'The deployment\'s own word for the class: "expert", "user", "arbitrator".',
2116
+ },
2117
+ weight: {
2118
+ type: 'number',
2119
+ minimum: 0,
2120
+ description: 'How much a judgment of this class counts, relative to the others.',
2121
+ },
2122
+ description: { type: 'string' },
2123
+ createdAt: { type: 'string', format: 'date-time' },
2124
+ updatedAt: { type: 'string', format: 'date-time' },
2125
+ unregisteredAt: {
2126
+ type: 'string',
2127
+ format: 'date-time',
2128
+ description: 'Set when the class was retired.',
2129
+ },
1910
2130
  },
1911
2131
  };
1912
2132
 
1913
- export const SourceFreshnessSchema: JsonSchema = {
2133
+ export const JudgeClassCollectionPageSchema: JsonSchema = {
1914
2134
  type: 'object',
1915
2135
  additionalProperties: false,
2136
+ required: ['data', 'hasMore'],
1916
2137
  properties: {
1917
- ttlSeconds: { type: 'integer', minimum: 0 },
1918
- lastVerifiedAt: { type: 'string', format: 'date-time' },
1919
- etag: { type: 'string' },
1920
- sourceVersion: { type: 'string' },
2138
+ data: { type: 'array', items: { $ref: '#/components/schemas/JudgeClass' } },
2139
+ nextCursor: { type: 'string', description: 'Opaque cursor. Treat as opaque on the client.' },
2140
+ hasMore: { type: 'boolean' },
1921
2141
  },
1922
2142
  };
1923
2143
 
1924
- export const SourceRefreshSchema: JsonSchema = {
2144
+ export const CreateJudgeClassBodySchema: JsonSchema = {
1925
2145
  type: 'object',
1926
2146
  additionalProperties: false,
1927
- required: ['strategy'],
2147
+ required: ['scope', 'name', 'weight'],
1928
2148
  properties: {
1929
- strategy: { type: 'string', enum: ['on-read', 'background', 'manual'] },
1930
- handler: { type: 'string' },
1931
- priority: { type: 'integer' },
2149
+ scope: { $ref: '#/components/schemas/JudgeClassScope' },
2150
+ name: { type: 'string', minLength: 1, maxLength: 100 },
2151
+ weight: { type: 'number', minimum: 0 },
2152
+ description: { type: 'string' },
1932
2153
  },
1933
2154
  };
1934
2155
 
1935
- export const FactSourceSchema: JsonSchema = {
2156
+ export const UpdateJudgeClassBodySchema: JsonSchema = {
1936
2157
  type: 'object',
1937
2158
  additionalProperties: false,
1938
- required: ['kind', 'freshness', 'refresh'],
2159
+ minProperties: 1,
1939
2160
  properties: {
1940
- kind: {
1941
- type: 'string',
1942
- enum: ['http-api', 'blob', 'mcp-tool', 'external-db', 'user-input'],
1943
- },
1944
- uri: { type: 'string' },
1945
- freshness: { $ref: '#/components/schemas/SourceFreshness' },
1946
- refresh: { $ref: '#/components/schemas/SourceRefresh' },
2161
+ weight: { type: 'number', minimum: 0 },
2162
+ description: { type: 'string' },
1947
2163
  },
1948
2164
  };
1949
2165
 
1950
- export const FactSchema: JsonSchema = {
2166
+ export const UnregisterJudgeClassResultSchema: JsonSchema = {
1951
2167
  type: 'object',
1952
2168
  additionalProperties: false,
1953
- required: ['id', 'type', 'scope', 'version', 'createdAt'],
2169
+ required: ['judgeClassId', 'unregistered'],
1954
2170
  properties: {
1955
- id: { type: 'string', description: 'FactId.' },
1956
- type: {
1957
- type: 'string',
1958
- description: 'Fact type identifier (pack-defined; a few are framework-standard).',
1959
- },
1960
- scope: { $ref: '#/components/schemas/FactScope' },
1961
- version: {
1962
- type: 'integer',
1963
- minimum: 1,
1964
- description: 'Monotonic version within (scope, id). Supersession increments.',
1965
- },
1966
- createdAt: { type: 'string', format: 'date-time' },
1967
- updatedAt: { type: 'string', format: 'date-time' },
1968
- content: { description: 'Free-form structured payload.' },
1969
- contentRef: {
1970
- type: 'string',
1971
- description: '`blob://<provider>/<bucket>/<key>` when the payload is stored externally.',
1972
- },
1973
- contentHash: { type: 'string' },
1974
- size: { type: 'integer', minimum: 0 },
1975
- embeddingModel: { type: 'string' },
1976
- retention: { $ref: '#/components/schemas/Retention' },
1977
- source: { $ref: '#/components/schemas/FactSource' },
1978
- causedByLogId: { type: 'array', items: { type: 'string' } },
1979
- supersedes: {
1980
- type: 'string',
1981
- description: 'FactId of the predecessor when this row supersedes another.',
1982
- },
2171
+ judgeClassId: { type: 'string' },
2172
+ unregistered: { type: 'boolean', const: true },
1983
2173
  },
1984
2174
  };
1985
2175
 
1986
- export const FactCollectionPageSchema: JsonSchema = {
2176
+ export const JudgedSubjectSchema: JsonSchema = {
1987
2177
  type: 'object',
1988
2178
  additionalProperties: false,
1989
- required: ['data', 'hasMore'],
2179
+ required: ['kind', 'id', 'version'],
2180
+ description: 'What a judged run ran: an agent at a version, or a flow at a version.',
1990
2181
  properties: {
1991
- data: { type: 'array', items: { $ref: '#/components/schemas/Fact' } },
1992
- nextCursor: {
1993
- type: 'string',
1994
- description: 'Opaque cursor for the next page. Absent when `hasMore: false`.',
1995
- },
1996
- hasMore: { type: 'boolean' },
2182
+ kind: { type: 'string', enum: ['agent', 'flow'] },
2183
+ id: { type: 'string' },
2184
+ version: { type: 'string' },
1997
2185
  },
1998
2186
  };
1999
2187
 
2000
- export const WriteFactBodySchema: JsonSchema = {
2001
- description:
2002
- "Write a fact. `type` selects the retrieval-policy (which indexes populate); `scope.tenantId` MUST match the caller's tenant. Optional `retention` overrides tenant defaults; optional `contentHash` is a caller-supplied idempotence hint (runtime computes its own hash regardless).",
2188
+ export const JudgedItemSchema: JsonSchema = {
2003
2189
  type: 'object',
2004
2190
  additionalProperties: false,
2005
- required: ['type', 'scope', 'content'],
2191
+ required: ['key'],
2192
+ description: "The judged item of a run's output.",
2006
2193
  properties: {
2007
- type: { type: 'string', minLength: 1 },
2008
- scope: { $ref: '#/components/schemas/FactScope' },
2009
- content: { description: 'Free-form structured payload.' },
2010
- retention: { $ref: '#/components/schemas/Retention' },
2011
- contentHash: { type: 'string' },
2194
+ key: { type: 'string', minLength: 1, description: "The caller's stable id for the item." },
2195
+ pointer: {
2196
+ type: 'string',
2197
+ description:
2198
+ 'Where the item is in the run\'s output, as a JSON Pointer (RFC 6901), e.g. `/matches/2`. `""` is the whole output.',
2199
+ },
2200
+ rank: {
2201
+ type: 'integer',
2202
+ minimum: 0,
2203
+ description: "The item's position in a ranked list (0 = first).",
2204
+ },
2012
2205
  },
2013
2206
  };
2014
2207
 
2015
- export const SupersedeFactResultSchema: JsonSchema = {
2208
+ export const JudgmentAssertedBySchema: JsonSchema = {
2016
2209
  type: 'object',
2017
2210
  additionalProperties: false,
2018
- required: ['factId', 'superseded'],
2211
+ required: ['kind', 'id'],
2212
+ description: 'Who asserted a judgment: the authenticated caller, never a typed name.',
2019
2213
  properties: {
2020
- factId: { type: 'string' },
2021
- superseded: { type: 'boolean', const: true },
2214
+ kind: { type: 'string', enum: ['user', 'service'] },
2215
+ id: {
2216
+ type: 'string',
2217
+ description: 'A user id, or for a service token its token or session id.',
2218
+ },
2022
2219
  },
2023
2220
  };
2024
2221
 
2025
- export const RetrieveIntentSchema: JsonSchema = {
2026
- description:
2027
- 'Retrieval intent — mirrors `RetrievalIntent` from `@kindgi/agents`, widened for direct-HTTP use. `mode: "list"` returns a plain scoped list (no query). `mode: "keyword"` runs full-text search. `mode: "semantic"` runs vector similarity search — requires an embedding provider bound on the deployment; if unavailable, the route returns `400 bad-input`. `mode: "both"` unions keyword + semantic results, dedup by fact id.',
2222
+ export const JudgmentSchema: JsonSchema = {
2028
2223
  type: 'object',
2029
2224
  additionalProperties: false,
2030
- required: ['mode'],
2225
+ required: [
2226
+ 'id',
2227
+ 'tenantId',
2228
+ 'projectId',
2229
+ 'runId',
2230
+ 'subject',
2231
+ 'item',
2232
+ 'verdict',
2233
+ 'assertedBy',
2234
+ 'createdAt',
2235
+ ],
2236
+ properties: {
2237
+ id: { type: 'string' },
2238
+ tenantId: { type: 'string' },
2239
+ projectId: { type: 'string' },
2240
+ runId: { type: 'string' },
2241
+ subject: { $ref: '#/components/schemas/JudgedSubject' },
2242
+ item: { $ref: '#/components/schemas/JudgedItem' },
2243
+ verdict: { type: 'string', enum: ['yes', 'no'] },
2244
+ reason: { type: 'string' },
2245
+ judgeClassId: {
2246
+ type: 'string',
2247
+ description:
2248
+ 'The judge class the judgment is recorded under. Absent when unclassified (counts with weight 1).',
2249
+ },
2250
+ assertedBy: { $ref: '#/components/schemas/JudgmentAssertedBy' },
2251
+ participantId: {
2252
+ type: 'string',
2253
+ description:
2254
+ "The app's opaque id for its end user who judged, when an app judged on their behalf.",
2255
+ },
2256
+ createdAt: { type: 'string', format: 'date-time' },
2257
+ unregisteredAt: {
2258
+ type: 'string',
2259
+ format: 'date-time',
2260
+ description: 'Set when the judgment was removed or superseded.',
2261
+ },
2262
+ supersededBy: { type: 'string', description: 'The judgment that replaced this one.' },
2263
+ },
2264
+ };
2265
+
2266
+ export const JudgedRunContextSchema: JsonSchema = {
2267
+ type: 'object',
2268
+ additionalProperties: false,
2269
+ description:
2270
+ 'What a judged run needs besides its input to be replayed, captured when it was first judged. For an agent turn: the conversation before it, what its retrievals returned, and the decision at its session approval gate. For a flow run: its tool calls with their results.',
2271
+ properties: {
2272
+ history: {
2273
+ type: 'array',
2274
+ items: {},
2275
+ description:
2276
+ "The conversation's messages before the turn, oldest first (at most the last 200).",
2277
+ },
2278
+ historyTruncated: {
2279
+ type: 'boolean',
2280
+ description: 'Whether older messages were left out of `history`.',
2281
+ },
2282
+ retrieved: { description: "What the turn's retrievals returned." },
2283
+ sessionApproval: {
2284
+ type: 'object',
2285
+ additionalProperties: false,
2286
+ required: ['approved'],
2287
+ description:
2288
+ "The reviewer's decision at the turn's session approval gate, when the turn waited on one. A replay of the turn follows it.",
2289
+ properties: {
2290
+ approved: { type: 'boolean' },
2291
+ rationale: { type: 'string', description: "The reviewer's reason for a rejection." },
2292
+ },
2293
+ },
2294
+ flow: {
2295
+ type: 'object',
2296
+ additionalProperties: false,
2297
+ required: ['calls', 'steps'],
2298
+ description:
2299
+ "For a flow run: what it did, kept at its first judgment so it can be replayed. Every tool call it made with its result (at its tool nodes, in its agent steps' turns and in its sub-flows), at most 500, and its agent steps.",
2300
+ properties: {
2301
+ calls: {
2302
+ type: 'array',
2303
+ items: {
2304
+ type: 'object',
2305
+ additionalProperties: false,
2306
+ required: ['runId', 'toolId'],
2307
+ properties: {
2308
+ runId: {
2309
+ type: 'string',
2310
+ description:
2311
+ "The run that made it: the flow run, a sub-flow's, or an agent step's turn.",
2312
+ },
2313
+ nodeId: {
2314
+ type: 'string',
2315
+ description: 'The tool node that made it, or the agent step whose turn did.',
2316
+ },
2317
+ scope: { type: 'string', description: 'The loop iteration, in a loop body.' },
2318
+ toolId: { type: 'string' },
2319
+ arguments: {},
2320
+ result: {},
2321
+ },
2322
+ },
2323
+ },
2324
+ steps: {
2325
+ type: 'array',
2326
+ items: {
2327
+ type: 'object',
2328
+ additionalProperties: false,
2329
+ required: ['runId', 'agentId', 'agentVersion'],
2330
+ properties: {
2331
+ runId: { type: 'string' },
2332
+ nodeId: { type: 'string' },
2333
+ scope: { type: 'string' },
2334
+ agentId: { type: 'string' },
2335
+ agentVersion: { type: 'string' },
2336
+ retrieved: { description: "What the step's turn retrieved." },
2337
+ },
2338
+ },
2339
+ },
2340
+ truncated: { type: 'boolean', description: 'More calls were made than were kept.' },
2341
+ },
2342
+ },
2343
+ },
2344
+ };
2345
+
2346
+ export const JudgedRunCopySchema: JsonSchema = {
2347
+ type: 'object',
2348
+ additionalProperties: false,
2349
+ required: ['runId', 'subject', 'input', 'output', 'capturedAt'],
2350
+ description:
2351
+ "The stored copy of a judged run's input and output, taken when it was first judged.",
2352
+ properties: {
2353
+ runId: { type: 'string' },
2354
+ subject: { $ref: '#/components/schemas/JudgedSubject' },
2355
+ input: {},
2356
+ context: {
2357
+ $ref: '#/components/schemas/JudgedRunContext',
2358
+ },
2359
+ output: {},
2360
+ capturedAt: { type: 'string', format: 'date-time' },
2361
+ },
2362
+ };
2363
+
2364
+ export const JudgmentWithCopiesSchema: JsonSchema = {
2365
+ description: 'A judgment with the stored copies of what was judged.',
2366
+ allOf: [
2367
+ { $ref: '#/components/schemas/Judgment' },
2368
+ {
2369
+ type: 'object',
2370
+ required: ['run'],
2371
+ properties: {
2372
+ run: { $ref: '#/components/schemas/JudgedRunCopy' },
2373
+ itemValue: {
2374
+ description: "The judged item's value, when the judgment pointed at it.",
2375
+ },
2376
+ },
2377
+ },
2378
+ ],
2379
+ };
2380
+
2381
+ export const JudgmentCollectionPageSchema: JsonSchema = {
2382
+ type: 'object',
2383
+ additionalProperties: false,
2384
+ required: ['data', 'hasMore'],
2385
+ properties: {
2386
+ data: { type: 'array', items: { $ref: '#/components/schemas/Judgment' } },
2387
+ nextCursor: { type: 'string', description: 'Opaque cursor. Treat as opaque on the client.' },
2388
+ hasMore: { type: 'boolean' },
2389
+ },
2390
+ };
2391
+
2392
+ export const CreateJudgmentBodySchema: JsonSchema = {
2393
+ type: 'object',
2394
+ additionalProperties: false,
2395
+ required: ['runId', 'item', 'verdict'],
2396
+ properties: {
2397
+ runId: { type: 'string', minLength: 1 },
2398
+ item: { $ref: '#/components/schemas/JudgedItem' },
2399
+ verdict: { type: 'string', enum: ['yes', 'no'] },
2400
+ reason: { type: 'string', maxLength: 4000 },
2401
+ judgeClassId: {
2402
+ type: 'string',
2403
+ minLength: 1,
2404
+ description: 'Optional. When given it must exist and apply to the run.',
2405
+ },
2406
+ participantId: {
2407
+ type: 'string',
2408
+ minLength: 1,
2409
+ description: "An app's opaque id for its end user, when judging on their behalf.",
2410
+ },
2411
+ },
2412
+ };
2413
+
2414
+ export const UnregisterJudgmentResultSchema: JsonSchema = {
2415
+ type: 'object',
2416
+ additionalProperties: false,
2417
+ required: ['judgmentId', 'unregistered'],
2418
+ properties: {
2419
+ judgmentId: { type: 'string' },
2420
+ unregistered: { type: 'boolean', const: true },
2421
+ },
2422
+ };
2423
+
2424
+ export const JudgedItemSummarySchema: JsonSchema = {
2425
+ type: 'object',
2426
+ additionalProperties: false,
2427
+ required: ['key', 'yes', 'no', 'yesWeight', 'totalWeight', 'reasons'],
2428
+ description: "The judgments of one item of a case's output, summed up.",
2429
+ properties: {
2430
+ key: { type: 'string' },
2431
+ pointer: { type: 'string' },
2432
+ rank: { type: 'integer', minimum: 0 },
2433
+ yes: { type: 'integer', minimum: 0, description: 'How many judgments said yes.' },
2434
+ no: { type: 'integer', minimum: 0, description: 'How many judgments said no.' },
2435
+ yesWeight: {
2436
+ type: 'number',
2437
+ description: 'The weight behind "yes" (an unclassified judgment counts 1).',
2438
+ },
2439
+ totalWeight: { type: 'number', description: 'The weight behind all judgments of the item.' },
2440
+ reasons: {
2441
+ type: 'array',
2442
+ description: 'The reasons given, newest first.',
2443
+ items: {
2444
+ type: 'object',
2445
+ additionalProperties: false,
2446
+ required: ['verdict', 'reason'],
2447
+ properties: {
2448
+ verdict: { type: 'string', enum: ['yes', 'no'] },
2449
+ reason: { type: 'string' },
2450
+ },
2451
+ },
2452
+ },
2453
+ },
2454
+ };
2455
+
2456
+ export const JudgedEvalCaseSchema: JsonSchema = {
2457
+ type: 'object',
2458
+ additionalProperties: false,
2459
+ required: ['caseId', 'subject', 'input', 'output', 'items'],
2460
+ description:
2461
+ "One case of a `judged` eval suite: a copy of a judged run with its items' judgments summed up.",
2462
+ properties: {
2463
+ caseId: { type: 'string', description: "The judged run's id." },
2464
+ subject: { $ref: '#/components/schemas/JudgedSubject' },
2465
+ input: {},
2466
+ context: { $ref: '#/components/schemas/JudgedRunContext' },
2467
+ output: {},
2468
+ items: { type: 'array', items: { $ref: '#/components/schemas/JudgedItemSummary' } },
2469
+ },
2470
+ };
2471
+
2472
+ export const JudgedEvalCaseCollectionPageSchema: JsonSchema = {
2473
+ type: 'object',
2474
+ additionalProperties: false,
2475
+ required: ['data', 'hasMore'],
2476
+ properties: {
2477
+ data: { type: 'array', items: { $ref: '#/components/schemas/JudgedEvalCase' } },
2478
+ nextCursor: { type: 'string', description: 'Opaque cursor. Treat as opaque on the client.' },
2479
+ hasMore: { type: 'boolean' },
2480
+ },
2481
+ };
2482
+
2483
+ export const BuildJudgedSuiteBodySchema: JsonSchema = {
2484
+ type: 'object',
2485
+ additionalProperties: false,
2486
+ required: ['version', 'projectId'],
2487
+ description: 'Name the agent (`agentId`) or the flow (`flowId`) whose judged runs to use.',
2488
+ properties: {
2489
+ version: { type: 'string', description: 'Semver version to publish, e.g. `1.0.0`.' },
2490
+ projectId: { type: 'string', minLength: 1 },
2491
+ agentId: { type: 'string', minLength: 1 },
2492
+ agentVersion: { type: 'string', minLength: 1, description: 'Needs `agentId`.' },
2493
+ flowId: { type: 'string', minLength: 1 },
2494
+ since: {
2495
+ type: 'string',
2496
+ format: 'date-time',
2497
+ description: 'Runs first judged at or after this time.',
2498
+ },
2499
+ until: {
2500
+ type: 'string',
2501
+ format: 'date-time',
2502
+ description: 'Runs first judged before this time.',
2503
+ },
2504
+ judgeClassIds: {
2505
+ type: 'array',
2506
+ items: { type: 'string', minLength: 1 },
2507
+ description: 'Count only judgments recorded under these judge classes.',
2508
+ },
2509
+ minJudgments: {
2510
+ type: 'integer',
2511
+ minimum: 1,
2512
+ description: 'Leave out runs with fewer counted judgments. Default 1.',
2513
+ },
2514
+ description: { type: 'string' },
2515
+ },
2516
+ };
2517
+
2518
+ export const BuildJudgedSuiteResultSchema: JsonSchema = {
2519
+ type: 'object',
2520
+ additionalProperties: false,
2521
+ required: ['suiteId', 'version', 'kind', 'caseCount', 'truncated'],
2522
+ properties: {
2523
+ suiteId: { type: 'string' },
2524
+ version: { type: 'string' },
2525
+ kind: { type: 'string', enum: ['judged'] },
2526
+ caseCount: { type: 'integer', minimum: 0 },
2527
+ truncated: {
2528
+ type: 'boolean',
2529
+ description: 'Whether more judged runs matched than the 1000 cases a set holds.',
2530
+ },
2531
+ },
2532
+ };
2533
+
2534
+ // ---------------- memory ----------------
2535
+
2536
+ export const FactScopeSchema: JsonSchema = {
2537
+ type: 'object',
2538
+ additionalProperties: true,
2539
+ required: ['tenantId'],
2540
+ description:
2541
+ 'Fact scope object. `tenantId` is required; every optional key narrows the fact (`userId`, `orgId`, `projectId`, `threadId`, `sessionId`). Additional keys accepted for forward compatibility.',
2542
+ properties: {
2543
+ tenantId: { type: 'string' },
2544
+ userId: { type: 'string' },
2545
+ orgId: { type: 'string' },
2546
+ projectId: { type: 'string' },
2547
+ threadId: { type: 'string' },
2548
+ sessionId: { type: 'string' },
2549
+ },
2550
+ };
2551
+
2552
+ export const RetentionSchema: JsonSchema = {
2553
+ type: 'object',
2554
+ additionalProperties: false,
2555
+ properties: {
2556
+ keepUntil: { type: 'string', format: 'date-time' },
2557
+ keepDays: { type: 'integer', minimum: 1 },
2558
+ legalHold: { type: 'boolean' },
2559
+ },
2560
+ };
2561
+
2562
+ export const SourceFreshnessSchema: JsonSchema = {
2563
+ type: 'object',
2564
+ additionalProperties: false,
2565
+ properties: {
2566
+ ttlSeconds: { type: 'integer', minimum: 0 },
2567
+ lastVerifiedAt: { type: 'string', format: 'date-time' },
2568
+ etag: { type: 'string' },
2569
+ sourceVersion: { type: 'string' },
2570
+ },
2571
+ };
2572
+
2573
+ export const SourceRefreshSchema: JsonSchema = {
2574
+ type: 'object',
2575
+ additionalProperties: false,
2576
+ required: ['strategy'],
2577
+ properties: {
2578
+ strategy: { type: 'string', enum: ['on-read', 'background', 'manual'] },
2579
+ handler: { type: 'string' },
2580
+ priority: { type: 'integer' },
2581
+ },
2582
+ };
2583
+
2584
+ export const FactSourceSchema: JsonSchema = {
2585
+ type: 'object',
2586
+ additionalProperties: false,
2587
+ required: ['kind', 'freshness', 'refresh'],
2588
+ properties: {
2589
+ kind: {
2590
+ type: 'string',
2591
+ enum: ['http-api', 'blob', 'mcp-tool', 'external-db', 'user-input'],
2592
+ },
2593
+ uri: { type: 'string' },
2594
+ freshness: { $ref: '#/components/schemas/SourceFreshness' },
2595
+ refresh: { $ref: '#/components/schemas/SourceRefresh' },
2596
+ },
2597
+ };
2598
+
2599
+ export const FactSchema: JsonSchema = {
2600
+ type: 'object',
2601
+ additionalProperties: false,
2602
+ required: ['id', 'type', 'scope', 'version', 'createdAt'],
2603
+ properties: {
2604
+ id: { type: 'string', description: 'FactId.' },
2605
+ type: {
2606
+ type: 'string',
2607
+ description: 'Fact type identifier (pack-defined; a few are framework-standard).',
2608
+ },
2609
+ scope: { $ref: '#/components/schemas/FactScope' },
2610
+ version: {
2611
+ type: 'integer',
2612
+ minimum: 1,
2613
+ description: 'Monotonic version within (scope, id). Supersession increments.',
2614
+ },
2615
+ createdAt: { type: 'string', format: 'date-time' },
2616
+ updatedAt: { type: 'string', format: 'date-time' },
2617
+ content: { description: 'Free-form structured payload.' },
2618
+ contentRef: {
2619
+ type: 'string',
2620
+ description: '`blob://<provider>/<bucket>/<key>` when the payload is stored externally.',
2621
+ },
2622
+ contentHash: { type: 'string' },
2623
+ size: { type: 'integer', minimum: 0 },
2624
+ embeddingModel: { type: 'string' },
2625
+ retention: { $ref: '#/components/schemas/Retention' },
2626
+ source: { $ref: '#/components/schemas/FactSource' },
2627
+ causedByLogId: { type: 'array', items: { type: 'string' } },
2628
+ supersedes: {
2629
+ type: 'string',
2630
+ description: 'FactId of the predecessor when this row supersedes another.',
2631
+ },
2632
+ },
2633
+ };
2634
+
2635
+ export const FactCollectionPageSchema: JsonSchema = {
2636
+ type: 'object',
2637
+ additionalProperties: false,
2638
+ required: ['data', 'hasMore'],
2639
+ properties: {
2640
+ data: { type: 'array', items: { $ref: '#/components/schemas/Fact' } },
2641
+ nextCursor: {
2642
+ type: 'string',
2643
+ description: 'Opaque cursor for the next page. Absent when `hasMore: false`.',
2644
+ },
2645
+ hasMore: { type: 'boolean' },
2646
+ },
2647
+ };
2648
+
2649
+ export const WriteFactBodySchema: JsonSchema = {
2650
+ description:
2651
+ "Write a fact. `type` selects the retrieval-policy (which indexes populate); `scope.tenantId` MUST match the caller's tenant. Optional `retention` overrides tenant defaults; optional `contentHash` is a caller-supplied idempotence hint (runtime computes its own hash regardless).",
2652
+ type: 'object',
2653
+ additionalProperties: false,
2654
+ required: ['type', 'scope', 'content'],
2655
+ properties: {
2656
+ type: { type: 'string', minLength: 1 },
2657
+ scope: { $ref: '#/components/schemas/FactScope' },
2658
+ content: { description: 'Free-form structured payload.' },
2659
+ retention: { $ref: '#/components/schemas/Retention' },
2660
+ contentHash: { type: 'string' },
2661
+ },
2662
+ };
2663
+
2664
+ export const SupersedeFactResultSchema: JsonSchema = {
2665
+ type: 'object',
2666
+ additionalProperties: false,
2667
+ required: ['factId', 'superseded'],
2668
+ properties: {
2669
+ factId: { type: 'string' },
2670
+ superseded: { type: 'boolean', const: true },
2671
+ },
2672
+ };
2673
+
2674
+ export const RetrieveIntentSchema: JsonSchema = {
2675
+ description:
2676
+ 'Retrieval intent — mirrors `RetrievalIntent` from `@kindgi/agents`, widened for direct-HTTP use. `mode: "list"` returns a plain scoped list (no query). `mode: "keyword"` runs full-text search. `mode: "semantic"` runs vector similarity search — requires an embedding provider bound on the deployment; if unavailable, the route returns `400 bad-input`. `mode: "both"` unions keyword + semantic results, dedup by fact id.',
2677
+ type: 'object',
2678
+ additionalProperties: false,
2679
+ required: ['mode'],
2031
2680
  properties: {
2032
2681
  mode: { type: 'string', enum: ['list', 'keyword', 'semantic', 'both'] },
2033
2682
  query: {
@@ -2939,6 +3588,14 @@ export const ProviderMetadataSchema: JsonSchema = {
2939
3588
  description:
2940
3589
  "A fallback serves a capability only when no other provider satisfies it (e.g. `kindgi dev`'s scripted `dev-echo`); an agent turn routed to one carries a `fallback-provider` warning. Absent = `false`.",
2941
3590
  },
3591
+ labels: {
3592
+ type: 'object',
3593
+ maxProperties: 32,
3594
+ propertyNames: { pattern: '^[a-z0-9]([a-z0-9._/-]{0,61}[a-z0-9])?$' },
3595
+ additionalProperties: { type: 'string', maxLength: 256 },
3596
+ description:
3597
+ 'Bookkeeping, such as who manages the provider; the router ignores labels. At most 32 keys; a key is 1-63 lowercase letters and digits, with `.`, `-`, `_` or `/` inside; a value is at most 256 characters. The convention key `kindgi.com/managed-by` names the manager (`kindgi-dev`, `kindgi-deploy:<environment>`). Out of bounds: `400 invalid-provider`, reason `invalid-labels`.',
3598
+ },
2942
3599
  },
2943
3600
  };
2944
3601
 
@@ -3516,6 +4173,19 @@ export const CostAggregateResultSchema: JsonSchema = {
3516
4173
  groups: {
3517
4174
  type: 'array',
3518
4175
  items: { $ref: '#/components/schemas/CostAggregateGroup' },
4176
+ description:
4177
+ 'The most expensive groups first (`totalUsd` descending, ties by key), at most `limit`.',
4178
+ },
4179
+ totalGroups: {
4180
+ type: 'integer',
4181
+ minimum: 0,
4182
+ description:
4183
+ 'How many groups there were before the `limit` cap. Absent from a runtime before 0.1.5.',
4184
+ },
4185
+ truncated: {
4186
+ type: 'boolean',
4187
+ description:
4188
+ '`true` when there were more groups than `limit`: `groups` holds the most expensive ones, and `totalUsd` / `totalRecords` / `tokens` still cover every record. Absent from a runtime before 0.1.5.',
3519
4189
  },
3520
4190
  totalUsd: { type: 'number', minimum: 0 },
3521
4191
  totalRecords: { type: 'integer', minimum: 0 },
@@ -3803,7 +4473,7 @@ export const ReinstatePolicyVersionResultSchema: JsonSchema = {
3803
4473
  */
3804
4474
  export const EvalKindSchema: JsonSchema = {
3805
4475
  type: 'string',
3806
- enum: ['accuracy', 'pairwise', 'regression', 'human-review', 'benchmark', 'custom'],
4476
+ enum: ['accuracy', 'pairwise', 'regression', 'human-review', 'benchmark', 'custom', 'judged'],
3807
4477
  };
3808
4478
 
3809
4479
  /**
@@ -3833,72 +4503,204 @@ export const EvalSuiteSchema: JsonSchema = {
3833
4503
  type: 'object',
3834
4504
  additionalProperties: true,
3835
4505
  description:
3836
- 'Kind-specific suite body. For `accuracy`, typically `{ cases: [{ input, expectedOutput }], grader?: { adapterId, config? } }`. For `pairwise`, typically `{ prompts, variantA, variantB }`. For `regression`, typically `{ baseline, cases }`. For `human-review`, typically `{ rubric, reviewerRole }`. For `benchmark`, typically `{ benchmark: { name, version } }`. For `custom`, typically `{ handler: { modulePath, entrypointPath }, cases }`.',
4506
+ 'Kind-specific suite body. For `accuracy`, typically `{ cases: [{ input, expectedOutput }], grader?: { adapterId, config? } }`. For `pairwise`, typically `{ prompts, variantA, variantB }`. For `regression`, typically `{ baseline, cases }`. For `human-review`, typically `{ rubric, reviewerRole }`. For `benchmark`, typically `{ benchmark: { name, version } }`. For `custom`, typically `{ handler: { modulePath, entrypointPath }, cases }`.',
4507
+ },
4508
+ },
4509
+ };
4510
+
4511
+ export const EvalSuiteCollectionPageSchema: JsonSchema = {
4512
+ type: 'object',
4513
+ additionalProperties: false,
4514
+ required: ['data', 'hasMore'],
4515
+ properties: {
4516
+ data: {
4517
+ type: 'array',
4518
+ items: { $ref: '#/components/schemas/EvalSuite' },
4519
+ },
4520
+ nextCursor: { type: 'string' },
4521
+ hasMore: { type: 'boolean' },
4522
+ },
4523
+ };
4524
+
4525
+ export const PublishEvalSuiteBodySchema: JsonSchema = {
4526
+ type: 'object',
4527
+ additionalProperties: false,
4528
+ required: ['id', 'version', 'kind', 'spec', 'projectId'],
4529
+ properties: {
4530
+ id: { type: 'string', minLength: 1 },
4531
+ projectId: ContentProjectIdProperty,
4532
+ tenantId: {
4533
+ type: 'string',
4534
+ format: 'uuid',
4535
+ description:
4536
+ 'Optional. When present, must match the caller tenant (server-derived from the token). Cross-tenant publish is rejected.',
4537
+ },
4538
+ version: { type: 'string', pattern: '^\\d+\\.\\d+\\.\\d+$' },
4539
+ kind: { $ref: '#/components/schemas/EvalKind' },
4540
+ description: { type: 'string' },
4541
+ spec: { type: 'object', additionalProperties: true },
4542
+ },
4543
+ };
4544
+
4545
+ export const PublishEvalSuiteResultSchema: JsonSchema = {
4546
+ type: 'object',
4547
+ additionalProperties: false,
4548
+ required: ['suiteId', 'version'],
4549
+ properties: {
4550
+ suiteId: { type: 'string' },
4551
+ version: { type: 'string' },
4552
+ },
4553
+ };
4554
+
4555
+ export const UnregisterEvalSuiteResultSchema: JsonSchema = {
4556
+ type: 'object',
4557
+ additionalProperties: false,
4558
+ required: ['suiteId', 'version', 'unregistered'],
4559
+ properties: {
4560
+ suiteId: { type: 'string' },
4561
+ version: { type: 'string' },
4562
+ unregistered: { type: 'boolean', const: true },
4563
+ },
4564
+ };
4565
+
4566
+ export const ReinstateEvalSuiteVersionResultSchema: JsonSchema = {
4567
+ type: 'object',
4568
+ additionalProperties: false,
4569
+ required: ['suiteId', 'version', 'wasTombstoned'],
4570
+ properties: {
4571
+ suiteId: { type: 'string' },
4572
+ version: { type: 'string' },
4573
+ wasTombstoned: { type: 'boolean' },
4574
+ },
4575
+ };
4576
+
4577
+ // ---------------- data blocks ----------------
4578
+
4579
+ export const BlockKindSchema: JsonSchema = {
4580
+ type: 'string',
4581
+ enum: ['prompt', 'settings'],
4582
+ description:
4583
+ '`prompt`: a Liquid template an agent renders as its instructions. `settings`: a JSON object tools and templates read.',
4584
+ };
4585
+
4586
+ export const PromptBlockContentSchema: JsonSchema = {
4587
+ type: 'object',
4588
+ additionalProperties: false,
4589
+ required: ['template'],
4590
+ properties: {
4591
+ template: {
4592
+ type: 'string',
4593
+ minLength: 1,
4594
+ description:
4595
+ "Liquid, rendered as an agent's instructions are (same parameters and auto-injected variables).",
4596
+ },
4597
+ parameters: { type: 'array', items: { $ref: '#/components/schemas/PromptParameter' } },
4598
+ },
4599
+ };
4600
+
4601
+ export const SettingsBlockContentSchema: JsonSchema = {
4602
+ type: 'object',
4603
+ additionalProperties: false,
4604
+ required: ['values'],
4605
+ properties: {
4606
+ values: {
4607
+ type: 'object',
4608
+ additionalProperties: true,
4609
+ description:
4610
+ 'What tools read (`ToolContext.settings[<block id>]`) and templates read (`settings.<block id>.<key>`).',
4611
+ },
4612
+ schema: {
4613
+ type: 'object',
4614
+ additionalProperties: true,
4615
+ description:
4616
+ "JSON Schema (draft 2020-12) the values must satisfy. A later version's values must satisfy the latest version's schema too.",
4617
+ },
4618
+ },
4619
+ };
4620
+
4621
+ export const BlockSchema: JsonSchema = {
4622
+ description:
4623
+ 'A data block version: a prompt or settings, versioned like a tool (immutable versions, soft unregister). An agent version pins the block versions it uses when it is published. Belongs to one project and is authorized through it.',
4624
+ type: 'object',
4625
+ additionalProperties: false,
4626
+ required: ['id', 'version', 'kind', 'content', 'projectId', 'publishedAt'],
4627
+ properties: {
4628
+ id: { type: 'string', description: 'Dotted lowercase id (e.g. `acme.intake-prompt`).' },
4629
+ version: { type: 'string', pattern: '^\\d+\\.\\d+\\.\\d+$' },
4630
+ kind: { $ref: '#/components/schemas/BlockKind' },
4631
+ description: { type: 'string' },
4632
+ content: {
4633
+ oneOf: [
4634
+ { $ref: '#/components/schemas/PromptBlockContent' },
4635
+ { $ref: '#/components/schemas/SettingsBlockContent' },
4636
+ ],
4637
+ description: '`PromptBlockContent` for a prompt, `SettingsBlockContent` for settings.',
4638
+ },
4639
+ projectId: { type: 'string', format: 'uuid' },
4640
+ publishedAt: { type: 'string', format: 'date-time' },
4641
+ unregisteredAt: {
4642
+ type: 'string',
4643
+ format: 'date-time',
4644
+ description:
4645
+ 'Present only on an unregistered version; agent versions that pin it still read it.',
3837
4646
  },
3838
4647
  },
3839
4648
  };
3840
4649
 
3841
- export const EvalSuiteCollectionPageSchema: JsonSchema = {
4650
+ export const BlockCollectionPageSchema: JsonSchema = {
3842
4651
  type: 'object',
3843
4652
  additionalProperties: false,
3844
4653
  required: ['data', 'hasMore'],
3845
4654
  properties: {
3846
- data: {
3847
- type: 'array',
3848
- items: { $ref: '#/components/schemas/EvalSuite' },
3849
- },
4655
+ data: { type: 'array', items: { $ref: '#/components/schemas/Block' } },
3850
4656
  nextCursor: { type: 'string' },
3851
4657
  hasMore: { type: 'boolean' },
3852
4658
  },
3853
4659
  };
3854
4660
 
3855
- export const PublishEvalSuiteBodySchema: JsonSchema = {
4661
+ export const PublishBlockBodySchema: JsonSchema = {
3856
4662
  type: 'object',
3857
4663
  additionalProperties: false,
3858
- required: ['id', 'version', 'kind', 'spec', 'projectId'],
4664
+ required: ['projectId', 'id', 'version', 'kind', 'content'],
3859
4665
  properties: {
3860
- id: { type: 'string', minLength: 1 },
3861
4666
  projectId: ContentProjectIdProperty,
3862
- tenantId: {
3863
- type: 'string',
3864
- format: 'uuid',
3865
- description:
3866
- 'Optional. When present, must match the caller tenant (server-derived from the token). Cross-tenant publish is rejected.',
3867
- },
4667
+ id: { type: 'string', minLength: 1 },
3868
4668
  version: { type: 'string', pattern: '^\\d+\\.\\d+\\.\\d+$' },
3869
- kind: { $ref: '#/components/schemas/EvalKind' },
4669
+ kind: { $ref: '#/components/schemas/BlockKind' },
3870
4670
  description: { type: 'string' },
3871
- spec: { type: 'object', additionalProperties: true },
4671
+ content: {
4672
+ oneOf: [
4673
+ { $ref: '#/components/schemas/PromptBlockContent' },
4674
+ { $ref: '#/components/schemas/SettingsBlockContent' },
4675
+ ],
4676
+ },
3872
4677
  },
3873
4678
  };
3874
4679
 
3875
- export const PublishEvalSuiteResultSchema: JsonSchema = {
4680
+ export const PublishBlockResultSchema: JsonSchema = {
3876
4681
  type: 'object',
3877
4682
  additionalProperties: false,
3878
- required: ['suiteId', 'version'],
3879
- properties: {
3880
- suiteId: { type: 'string' },
3881
- version: { type: 'string' },
3882
- },
4683
+ required: ['blockId', 'version'],
4684
+ properties: { blockId: { type: 'string' }, version: { type: 'string' } },
3883
4685
  };
3884
4686
 
3885
- export const UnregisterEvalSuiteResultSchema: JsonSchema = {
4687
+ export const UnregisterBlockResultSchema: JsonSchema = {
3886
4688
  type: 'object',
3887
4689
  additionalProperties: false,
3888
- required: ['suiteId', 'version', 'unregistered'],
4690
+ required: ['blockId', 'version', 'unregistered'],
3889
4691
  properties: {
3890
- suiteId: { type: 'string' },
4692
+ blockId: { type: 'string' },
3891
4693
  version: { type: 'string' },
3892
4694
  unregistered: { type: 'boolean', const: true },
3893
4695
  },
3894
4696
  };
3895
4697
 
3896
- export const ReinstateEvalSuiteVersionResultSchema: JsonSchema = {
4698
+ export const ReinstateBlockResultSchema: JsonSchema = {
3897
4699
  type: 'object',
3898
4700
  additionalProperties: false,
3899
- required: ['suiteId', 'version', 'wasTombstoned'],
4701
+ required: ['blockId', 'version', 'wasTombstoned'],
3900
4702
  properties: {
3901
- suiteId: { type: 'string' },
4703
+ blockId: { type: 'string' },
3902
4704
  version: { type: 'string' },
3903
4705
  wasTombstoned: { type: 'boolean' },
3904
4706
  },
@@ -3936,6 +4738,389 @@ export const EvalRunFlowRefSchema: JsonSchema = {
3936
4738
  },
3937
4739
  };
3938
4740
 
4741
+ export const EvalBaselineSchema: JsonSchema = {
4742
+ description:
4743
+ "What a comparison compares the candidate against: `'recorded'` (each case's recorded output, what was judged), a version (`{ agentId, version }`, replayed under the same rules), or the version live in a scope (`{ live: { projectId?, segments? } }`). Only `'recorded'` runs today; the others are refused when the run starts.",
4744
+ oneOf: [
4745
+ { type: 'string', enum: ['recorded'] },
4746
+ {
4747
+ type: 'object',
4748
+ additionalProperties: false,
4749
+ required: ['agentId', 'version'],
4750
+ properties: { agentId: { type: 'string' }, version: { type: 'string' } },
4751
+ },
4752
+ {
4753
+ type: 'object',
4754
+ additionalProperties: false,
4755
+ required: ['live'],
4756
+ properties: {
4757
+ live: {
4758
+ type: 'object',
4759
+ additionalProperties: false,
4760
+ properties: {
4761
+ projectId: { type: 'string' },
4762
+ segments: { type: 'object', additionalProperties: { type: 'string' } },
4763
+ },
4764
+ },
4765
+ },
4766
+ },
4767
+ ],
4768
+ };
4769
+
4770
+ export const EvalComparisonSchema: JsonSchema = {
4771
+ type: 'object',
4772
+ additionalProperties: false,
4773
+ required: ['baseline', 'reads', 'repetitions', 'k'],
4774
+ description: "A comparison eval run's settings (a `judged` suite).",
4775
+ properties: {
4776
+ baseline: { $ref: '#/components/schemas/EvalBaseline' },
4777
+ reads: {
4778
+ type: 'string',
4779
+ enum: ['recorded', 'live'],
4780
+ description:
4781
+ "Whether replayed reads use the past run's results when it has them (`recorded`), or run live.",
4782
+ },
4783
+ repetitions: { type: 'integer', minimum: 1, maximum: 10 },
4784
+ k: { type: 'integer', minimum: 1, maximum: 100 },
4785
+ versions: { $ref: '#/components/schemas/FlowVersionOverrides' },
4786
+ },
4787
+ };
4788
+
4789
+ // ---------------- comparison results (a `judged` eval run's `result`) ----------------
4790
+
4791
+ const nullableNumber = { type: ['number', 'null'] } as const;
4792
+
4793
+ export const ComparisonMetricSchema: JsonSchema = {
4794
+ description:
4795
+ "One metric, the recorded runs beside the candidate. `null` where a side had no judged evidence; `n` / `weight` are the candidate's evidence (cases with judged items, and the judgment weight behind them), `baselineN` / `baselineWeight` the recorded side's.",
4796
+ type: 'object',
4797
+ additionalProperties: false,
4798
+ required: [
4799
+ 'baseline',
4800
+ 'candidate',
4801
+ 'delta',
4802
+ 'n',
4803
+ 'weight',
4804
+ 'baselineN',
4805
+ 'baselineWeight',
4806
+ 'direction',
4807
+ ],
4808
+ properties: {
4809
+ baseline: nullableNumber,
4810
+ candidate: nullableNumber,
4811
+ delta: nullableNumber,
4812
+ n: { type: 'integer', minimum: 0 },
4813
+ weight: { type: 'number', minimum: 0 },
4814
+ baselineN: { type: 'integer', minimum: 0 },
4815
+ baselineWeight: { type: 'number', minimum: 0 },
4816
+ direction: { type: 'string', enum: ['higher'] },
4817
+ k: {
4818
+ type: 'integer',
4819
+ minimum: 1,
4820
+ description: '`weightedPrecisionAtK`: the ranked items it looked at.',
4821
+ },
4822
+ spread: {
4823
+ type: 'number',
4824
+ description: "With more than one repetition: the candidate's max − min across them.",
4825
+ },
4826
+ },
4827
+ };
4828
+
4829
+ export const ComparisonCandidateSchema: JsonSchema = {
4830
+ description:
4831
+ 'What ran on the cases: an agent version, or a flow version (with any versions it swapped in).',
4832
+ oneOf: [
4833
+ {
4834
+ type: 'object',
4835
+ additionalProperties: false,
4836
+ required: ['kind', 'agentId', 'version'],
4837
+ properties: {
4838
+ kind: { type: 'string', enum: ['agent'] },
4839
+ agentId: { type: 'string' },
4840
+ version: { type: 'string' },
4841
+ },
4842
+ },
4843
+ {
4844
+ type: 'object',
4845
+ additionalProperties: false,
4846
+ required: ['kind', 'flowId', 'version'],
4847
+ properties: {
4848
+ kind: { type: 'string', enum: ['flow'] },
4849
+ flowId: { type: 'string' },
4850
+ version: { type: 'string' },
4851
+ versions: { $ref: '#/components/schemas/FlowVersionOverrides' },
4852
+ },
4853
+ },
4854
+ ],
4855
+ };
4856
+
4857
+ export const JudgedComparisonSummarySchema: JsonSchema = {
4858
+ description:
4859
+ 'What a comparison concluded: the candidate beside the recorded runs, the case counts, and the metrics. What a promotion gate reads.',
4860
+ type: 'object',
4861
+ additionalProperties: false,
4862
+ required: [
4863
+ 'evalRunId',
4864
+ 'status',
4865
+ 'completedAt',
4866
+ 'suite',
4867
+ 'candidate',
4868
+ 'baseline',
4869
+ 'scope',
4870
+ 'cases',
4871
+ 'diverged',
4872
+ 'refusedWrites',
4873
+ 'errors',
4874
+ 'stopped',
4875
+ 'reads',
4876
+ 'sampling',
4877
+ 'repetitions',
4878
+ 'metrics',
4879
+ ],
4880
+ properties: {
4881
+ evalRunId: { type: 'string' },
4882
+ status: { type: 'string', enum: ['completed', 'partial', 'failed'] },
4883
+ completedAt: { type: 'string', format: 'date-time' },
4884
+ suite: {
4885
+ type: 'object',
4886
+ additionalProperties: false,
4887
+ required: ['id', 'version'],
4888
+ properties: { id: { type: 'string' }, version: { type: 'string' } },
4889
+ },
4890
+ candidate: { $ref: '#/components/schemas/ComparisonCandidate' },
4891
+ baseline: {
4892
+ description:
4893
+ "What the candidate was compared with: `recorded` (the test set's recorded runs, with the versions that served them), or another version.",
4894
+ oneOf: [
4895
+ {
4896
+ type: 'object',
4897
+ additionalProperties: false,
4898
+ required: ['kind', 'versions'],
4899
+ properties: {
4900
+ kind: { type: 'string', enum: ['recorded'] },
4901
+ versions: {
4902
+ type: 'array',
4903
+ items: {
4904
+ type: 'object',
4905
+ additionalProperties: false,
4906
+ required: ['version', 'cases'],
4907
+ properties: {
4908
+ agentId: { type: 'string' },
4909
+ flowId: { type: 'string' },
4910
+ version: { type: 'string' },
4911
+ cases: { type: 'integer', minimum: 0 },
4912
+ },
4913
+ },
4914
+ },
4915
+ },
4916
+ },
4917
+ {
4918
+ type: 'object',
4919
+ additionalProperties: false,
4920
+ required: ['kind', 'agentId', 'version', 'via'],
4921
+ properties: {
4922
+ kind: { type: 'string', enum: ['version'] },
4923
+ agentId: { type: 'string' },
4924
+ version: { type: 'string' },
4925
+ via: { type: 'string', enum: ['explicit', 'live'] },
4926
+ liveScope: { type: 'object', additionalProperties: true },
4927
+ },
4928
+ },
4929
+ ],
4930
+ },
4931
+ scope: {
4932
+ type: 'object',
4933
+ additionalProperties: false,
4934
+ description: "Where the test set's judgments came from.",
4935
+ properties: { projectId: { type: 'string' } },
4936
+ },
4937
+ cases: { type: 'integer', minimum: 0 },
4938
+ diverged: {
4939
+ type: 'integer',
4940
+ minimum: 0,
4941
+ description: "Cases where a read with no recording ran live under `reads: 'recorded'`.",
4942
+ },
4943
+ refusedWrites: {
4944
+ type: 'integer',
4945
+ minimum: 0,
4946
+ description: 'Tool calls refused across the cases (what the candidate would have done).',
4947
+ },
4948
+ errors: { type: 'integer', minimum: 0, description: 'Cases none of whose repetitions ran.' },
4949
+ stopped: {
4950
+ type: 'integer',
4951
+ minimum: 0,
4952
+ description:
4953
+ "Flow cases that stopped at a write the replay refused: no output to score, so they're left out of the metrics.",
4954
+ },
4955
+ reads: { type: 'string', enum: ['recorded', 'live'] },
4956
+ sampling: {
4957
+ type: 'object',
4958
+ additionalProperties: false,
4959
+ required: ['models'],
4960
+ properties: {
4961
+ models: {
4962
+ type: 'array',
4963
+ description:
4964
+ "The models that answered the candidate's replays, and how many replays each.",
4965
+ items: {
4966
+ type: 'object',
4967
+ additionalProperties: false,
4968
+ required: ['providerId', 'model', 'runs'],
4969
+ properties: {
4970
+ providerId: { type: 'string' },
4971
+ model: { type: 'string' },
4972
+ runs: { type: 'integer', minimum: 0 },
4973
+ },
4974
+ },
4975
+ },
4976
+ },
4977
+ },
4978
+ repetitions: { type: 'integer', minimum: 1 },
4979
+ metrics: {
4980
+ type: 'object',
4981
+ additionalProperties: false,
4982
+ required: ['weightedYesShare', 'judgedCoverage', 'weightedPrecisionAtK'],
4983
+ properties: {
4984
+ weightedYesShare: { $ref: '#/components/schemas/ComparisonMetric' },
4985
+ judgedCoverage: { $ref: '#/components/schemas/ComparisonMetric' },
4986
+ weightedPrecisionAtK: { $ref: '#/components/schemas/ComparisonMetric' },
4987
+ },
4988
+ },
4989
+ },
4990
+ };
4991
+
4992
+ const outputScore = {
4993
+ type: 'object',
4994
+ additionalProperties: false,
4995
+ required: ['yesWeight', 'totalWeight', 'items', 'judgedItems', 'topK'],
4996
+ description:
4997
+ "An output's score: Σ yesWeight and Σ totalWeight over its judged items, and over those among the first `k` ranked items.",
4998
+ properties: {
4999
+ yesWeight: { type: 'number' },
5000
+ totalWeight: { type: 'number' },
5001
+ items: { type: 'integer', minimum: 0 },
5002
+ judgedItems: { type: 'integer', minimum: 0 },
5003
+ topK: {
5004
+ type: 'object',
5005
+ additionalProperties: false,
5006
+ required: ['yesWeight', 'totalWeight'],
5007
+ properties: { yesWeight: { type: 'number' }, totalWeight: { type: 'number' } },
5008
+ },
5009
+ },
5010
+ } as const;
5011
+
5012
+ export const ComparisonCaseResultSchema: JsonSchema = {
5013
+ description:
5014
+ "One case of a comparison: its replay runs, the scores, the items kept, dropped and new, the tool calls, and why it didn't run when it didn't.",
5015
+ type: 'object',
5016
+ additionalProperties: false,
5017
+ required: [
5018
+ 'caseId',
5019
+ 'runIds',
5020
+ 'baseline',
5021
+ 'candidate',
5022
+ 'diverged',
5023
+ 'refusedWrites',
5024
+ 'noContext',
5025
+ 'approvalSkipped',
5026
+ ],
5027
+ properties: {
5028
+ caseId: { type: 'string' },
5029
+ runIds: {
5030
+ type: 'array',
5031
+ items: { type: 'string' },
5032
+ description: "The candidate's replay runs, one per repetition.",
5033
+ },
5034
+ baseline: outputScore,
5035
+ candidate: { type: 'array', items: outputScore, description: 'One per repetition that ran.' },
5036
+ changes: {
5037
+ type: 'object',
5038
+ additionalProperties: false,
5039
+ required: ['kept', 'dropped', 'new'],
5040
+ description: "The first repetition's items against the judged ones.",
5041
+ properties: {
5042
+ kept: {
5043
+ type: 'array',
5044
+ items: {
5045
+ type: 'object',
5046
+ additionalProperties: false,
5047
+ required: ['key'],
5048
+ properties: {
5049
+ key: { type: 'string' },
5050
+ rankBefore: { type: 'integer' },
5051
+ rank: { type: 'integer' },
5052
+ },
5053
+ },
5054
+ },
5055
+ dropped: {
5056
+ type: 'array',
5057
+ items: {
5058
+ type: 'object',
5059
+ additionalProperties: false,
5060
+ required: ['key'],
5061
+ properties: { key: { type: 'string' }, rankBefore: { type: 'integer' } },
5062
+ },
5063
+ },
5064
+ new: {
5065
+ type: 'array',
5066
+ items: {
5067
+ type: 'object',
5068
+ additionalProperties: false,
5069
+ required: ['key', 'pointer'],
5070
+ properties: {
5071
+ key: { type: 'string' },
5072
+ pointer: { type: 'string' },
5073
+ rank: { type: 'integer' },
5074
+ },
5075
+ },
5076
+ },
5077
+ },
5078
+ },
5079
+ tools: {
5080
+ type: 'array',
5081
+ description: "The first repetition's tool calls, and what happened to each.",
5082
+ items: {
5083
+ type: 'object',
5084
+ additionalProperties: false,
5085
+ required: ['step', 'callId', 'toolId', 'toolVersion', 'arguments', 'source'],
5086
+ properties: {
5087
+ step: { type: 'integer', minimum: 0 },
5088
+ callId: { type: 'string' },
5089
+ toolId: { type: 'string' },
5090
+ toolVersion: { type: 'string' },
5091
+ arguments: {},
5092
+ source: { type: 'string', enum: ['live', 'recorded', 'refused'] },
5093
+ reason: { type: 'string' },
5094
+ },
5095
+ },
5096
+ },
5097
+ diverged: { type: 'boolean' },
5098
+ refusedWrites: { type: 'integer', minimum: 0 },
5099
+ noContext: { type: 'boolean' },
5100
+ approvalSkipped: { type: 'boolean' },
5101
+ error: { type: 'string' },
5102
+ stopped: {
5103
+ type: 'object',
5104
+ additionalProperties: false,
5105
+ required: ['toolId', 'arguments'],
5106
+ description: 'Set when the replay stopped at a refused write: what it would have done.',
5107
+ properties: { toolId: { type: 'string' }, arguments: {}, reason: { type: 'string' } },
5108
+ },
5109
+ },
5110
+ };
5111
+
5112
+ export const JudgedComparisonResultSchema: JsonSchema = {
5113
+ description:
5114
+ "A comparison's `result` (a `judged` eval run's): the summary and each case. `EvalRun.result` stays an open object, since each kind has its own; the clients read it as this (TS `comparisonOf(run)`, Python `comparison_of(run)`).",
5115
+ type: 'object',
5116
+ additionalProperties: false,
5117
+ required: ['summary', 'perCase'],
5118
+ properties: {
5119
+ summary: { $ref: '#/components/schemas/JudgedComparisonSummary' },
5120
+ perCase: { type: 'array', items: { $ref: '#/components/schemas/ComparisonCaseResult' } },
5121
+ },
5122
+ };
5123
+
3939
5124
  export const EvalRunSchema: JsonSchema = {
3940
5125
  type: 'object',
3941
5126
  additionalProperties: false,
@@ -3965,10 +5150,11 @@ export const EvalRunSchema: JsonSchema = {
3965
5150
  type: 'object',
3966
5151
  additionalProperties: true,
3967
5152
  description:
3968
- 'Kind-specific opaque JSON. For `accuracy`, contains `{ passCount, totalCount, meanScore, perCase[] }`. Other kinds define their own shapes as their dispatchers ship.',
5153
+ 'Kind-specific opaque JSON. For `accuracy`, contains `{ passCount, totalCount, meanScore, perCase[] }`. For `judged` (a comparison), `{ summary, perCase[] }`: the summary has the baseline (the versions behind the recorded runs) and the candidate (`{ kind: "agent", agentId, version }` or `{ kind: "flow", flowId, version, versions? }`), the case counts (`cases`, `diverged`, `refusedWrites`, `errors`, and `stopped`: flow cases that stopped at a write the replay refused, left out of the metrics), the models that answered, and `metrics` (`weightedYesShare`, `judgedCoverage`, `weightedPrecisionAtK`, each `{ baseline, candidate, delta, n, weight, baselineN, baselineWeight, direction, k?, spread? }`); each case has its replay runs, the scores, the items kept, dropped and new, the tool calls with what happened to each, and `stopped` (what it would have done) when it stopped. Other kinds define their own shapes as their dispatchers ship.',
3969
5154
  },
3970
5155
  error: { type: 'string' },
3971
5156
  correlationId: { type: 'string' },
5157
+ comparison: { $ref: '#/components/schemas/EvalComparison' },
3972
5158
  },
3973
5159
  };
3974
5160
 
@@ -3993,9 +5179,14 @@ export const StartEvalRunBodySchema: JsonSchema = {
3993
5179
  flowRef: { $ref: '#/components/schemas/EvalRunFlowRef' },
3994
5180
  dryRun: { type: 'boolean' },
3995
5181
  correlationId: { type: 'string' },
5182
+ baseline: { $ref: '#/components/schemas/EvalBaseline' },
5183
+ reads: { type: 'string', enum: ['recorded', 'live'] },
5184
+ repetitions: { type: 'integer', minimum: 1, maximum: 10 },
5185
+ k: { type: 'integer', minimum: 1, maximum: 100 },
5186
+ versions: { $ref: '#/components/schemas/FlowVersionOverrides' },
3996
5187
  },
3997
5188
  description:
3998
- 'Exactly one of `agentRef` or `flowRef` MUST be supplied. `dryRun: true` returns a plan preview without invoking the subject.',
5189
+ "Exactly one of `agentRef` or `flowRef` MUST be supplied. `dryRun: true` returns a plan preview without invoking the subject. For a `judged` suite (a test set), the run is a comparison: `agentRef` or `flowRef` with its `version` is the candidate, replayed on each case without doing anything the past run didn't (a flow stops at a write the replay refuses); `baseline` (default `'recorded'`), `reads` (default `recorded`), `repetitions` (default 1) and `k` (default 10) set how. With `flowRef`, `versions` runs the flow with some of its agents or tools at other versions; an id the flow doesn't use, or a version that isn't published, is refused (`400 validation-failed`, each under `details.issues`).",
3999
5190
  };
4000
5191
 
4001
5192
  export const StartEvalRunResultSchema: JsonSchema = {
@@ -4283,6 +5474,49 @@ const DeployedPrimitiveSchema: JsonSchema = {
4283
5474
  },
4284
5475
  };
4285
5476
 
5477
+ const DeployedVersionSchema: JsonSchema = {
5478
+ type: 'object',
5479
+ additionalProperties: false,
5480
+ required: ['id', 'version'],
5481
+ properties: {
5482
+ id: { type: 'string' },
5483
+ version: { type: 'string', description: 'The version the agent is registered as.' },
5484
+ authoredVersion: {
5485
+ type: 'string',
5486
+ description:
5487
+ "The version the agent's or flow's definition names, present when it differs from `version`: that version was registered already with other pins or content, and versions never change, so the deploy registered the next free version in its line (or an earlier deploy did).",
5488
+ },
5489
+ reason: {
5490
+ type: 'string',
5491
+ enum: ['pins-changed', 'unpinned', 'version-taken'],
5492
+ description:
5493
+ 'Why `version` differs from `authoredVersion`: `pins-changed` (a tool or agent it uses has a new version), `unpinned` (`authoredVersion` was published before pins existed), `version-taken` (`authoredVersion` is registered with other content).',
5494
+ },
5495
+ newVersion: {
5496
+ type: 'boolean',
5497
+ description: '`true`: this deploy registered `version`; `false`: an earlier deploy did.',
5498
+ },
5499
+ pinChanges: {
5500
+ type: 'array',
5501
+ description: "For `pins-changed`: the pins that differ from `authoredVersion`'s.",
5502
+ items: { $ref: '#/components/schemas/PinChange' },
5503
+ },
5504
+ },
5505
+ };
5506
+
5507
+ export const PinChangeSchema: JsonSchema = {
5508
+ description: 'One pin that differs between two versions of an agent or a flow.',
5509
+ type: 'object',
5510
+ additionalProperties: false,
5511
+ required: ['kind', 'id'],
5512
+ properties: {
5513
+ kind: { type: 'string', enum: ['tool', 'prompt', 'setting', 'agent'] },
5514
+ id: { type: 'string' },
5515
+ from: { type: 'string', description: "The earlier version's pin; absent when it had none." },
5516
+ to: { type: 'string', description: "The later version's pin; absent when it has none." },
5517
+ },
5518
+ };
5519
+
4286
5520
  /**
4287
5521
  * Exactly what a deployment shipped. Versions are immutable, so this
4288
5522
  * says which code the deployment made live.
@@ -4294,8 +5528,8 @@ export const DeploymentContentsSchema: JsonSchema = {
4294
5528
  properties: {
4295
5529
  tools: { type: 'array', items: DeployedPrimitiveSchema },
4296
5530
  guardrails: { type: 'array', items: DeployedPrimitiveSchema },
4297
- agents: { type: 'array', items: DeployedPrimitiveSchema },
4298
- flows: { type: 'array', items: DeployedPrimitiveSchema },
5531
+ agents: { type: 'array', items: DeployedVersionSchema },
5532
+ flows: { type: 'array', items: DeployedVersionSchema },
4299
5533
  },
4300
5534
  };
4301
5535
 
@@ -6270,6 +7504,27 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
6270
7504
  ['ObservationStatus', ObservationStatusSchema],
6271
7505
  ['Observation', ObservationSchema],
6272
7506
  ['ObservationCollectionPage', ObservationCollectionPageSchema],
7507
+ ['JudgeClassScope', JudgeClassScopeSchema],
7508
+ ['JudgeClass', JudgeClassSchema],
7509
+ ['JudgeClassCollectionPage', JudgeClassCollectionPageSchema],
7510
+ ['CreateJudgeClassBody', CreateJudgeClassBodySchema],
7511
+ ['UpdateJudgeClassBody', UpdateJudgeClassBodySchema],
7512
+ ['UnregisterJudgeClassResult', UnregisterJudgeClassResultSchema],
7513
+ ['JudgedSubject', JudgedSubjectSchema],
7514
+ ['JudgedItem', JudgedItemSchema],
7515
+ ['JudgmentAssertedBy', JudgmentAssertedBySchema],
7516
+ ['Judgment', JudgmentSchema],
7517
+ ['JudgedRunContext', JudgedRunContextSchema],
7518
+ ['JudgedRunCopy', JudgedRunCopySchema],
7519
+ ['JudgmentWithCopies', JudgmentWithCopiesSchema],
7520
+ ['JudgmentCollectionPage', JudgmentCollectionPageSchema],
7521
+ ['CreateJudgmentBody', CreateJudgmentBodySchema],
7522
+ ['UnregisterJudgmentResult', UnregisterJudgmentResultSchema],
7523
+ ['JudgedItemSummary', JudgedItemSummarySchema],
7524
+ ['JudgedEvalCase', JudgedEvalCaseSchema],
7525
+ ['JudgedEvalCaseCollectionPage', JudgedEvalCaseCollectionPageSchema],
7526
+ ['BuildJudgedSuiteBody', BuildJudgedSuiteBodySchema],
7527
+ ['BuildJudgedSuiteResult', BuildJudgedSuiteResultSchema],
6273
7528
  ['PromptParameter', PromptParameterSchema],
6274
7529
  ['RetrievalIntent', RetrievalIntentSchema],
6275
7530
  ['ConversationPolicy', ConversationPolicySchema],
@@ -6279,6 +7534,15 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
6279
7534
  ['AgentOutputSpec', AgentOutputSpecSchema],
6280
7535
  ['ToolErrorsSpec', ToolErrorsSpecSchema],
6281
7536
  ['Agent', AgentSchema],
7537
+ ['AgentPins', AgentPinsSchema],
7538
+ ['PromptRef', PromptRefSchema],
7539
+ ['BlockRef', BlockRefSchema],
7540
+ ['PinChange', PinChangeSchema],
7541
+ ['VersionDerivation', VersionDerivationSchema],
7542
+ ['DeriveAgentVersionBody', DeriveAgentVersionBodySchema],
7543
+ ['AgentPinSwaps', AgentPinSwapsSchema],
7544
+ ['FlowPins', FlowPinsSchema],
7545
+ ['FlowVersionOverrides', FlowVersionOverridesSchema],
6282
7546
  ['PublishAgentBody', PublishAgentBodySchema],
6283
7547
  ['PublishAgentResult', PublishAgentResultSchema],
6284
7548
  ['UnregisterAgentResult', UnregisterAgentResultSchema],
@@ -6428,9 +7692,25 @@ export const COMPONENT_SCHEMAS: ReadonlyArray<readonly [string, JsonSchema]> = [
6428
7692
  ['PublishEvalSuiteResult', PublishEvalSuiteResultSchema],
6429
7693
  ['UnregisterEvalSuiteResult', UnregisterEvalSuiteResultSchema],
6430
7694
  ['ReinstateEvalSuiteVersionResult', ReinstateEvalSuiteVersionResultSchema],
7695
+ ['BlockKind', BlockKindSchema],
7696
+ ['PromptBlockContent', PromptBlockContentSchema],
7697
+ ['SettingsBlockContent', SettingsBlockContentSchema],
7698
+ ['Block', BlockSchema],
7699
+ ['BlockCollectionPage', BlockCollectionPageSchema],
7700
+ ['PublishBlockBody', PublishBlockBodySchema],
7701
+ ['PublishBlockResult', PublishBlockResultSchema],
7702
+ ['UnregisterBlockResult', UnregisterBlockResultSchema],
7703
+ ['ReinstateBlockResult', ReinstateBlockResultSchema],
6431
7704
  ['EvalRunStatus', EvalRunStatusSchema],
6432
7705
  ['EvalRunAgentRef', EvalRunAgentRefSchema],
6433
7706
  ['EvalRunFlowRef', EvalRunFlowRefSchema],
7707
+ ['EvalBaseline', EvalBaselineSchema],
7708
+ ['EvalComparison', EvalComparisonSchema],
7709
+ ['ComparisonMetric', ComparisonMetricSchema],
7710
+ ['ComparisonCandidate', ComparisonCandidateSchema],
7711
+ ['JudgedComparisonSummary', JudgedComparisonSummarySchema],
7712
+ ['ComparisonCaseResult', ComparisonCaseResultSchema],
7713
+ ['JudgedComparisonResult', JudgedComparisonResultSchema],
6434
7714
  ['EvalRun', EvalRunSchema],
6435
7715
  ['EvalRunCollectionPage', EvalRunCollectionPageSchema],
6436
7716
  ['StartEvalRunBody', StartEvalRunBodySchema],