@kortyx/agent 0.37.1 → 0.38.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.
package/dist/index.js CHANGED
@@ -161,67 +161,67 @@ var require_dist = __commonJS({
161
161
  });
162
162
  module2.exports = __toCommonJS2(index_exports2);
163
163
  var import_zod62 = require("zod");
164
- var import_zod12 = require("zod");
164
+ var import_zod14 = require("zod");
165
165
  var FEEDBACK_FILTERS = ["positive", "negative", "unrated"];
166
- var FeedbackSummarySchema = import_zod12.z.object({
167
- positive: import_zod12.z.number().int().nonnegative(),
168
- negative: import_zod12.z.number().int().nonnegative()
166
+ var FeedbackSummarySchema = import_zod14.z.object({
167
+ positive: import_zod14.z.number().int().nonnegative(),
168
+ negative: import_zod14.z.number().int().nonnegative()
169
169
  }).strict();
170
- var FeedbackReasonSchema = import_zod12.z.enum([
170
+ var FeedbackReasonSchema = import_zod14.z.enum([
171
171
  "incorrect",
172
172
  "irrelevant",
173
173
  "incomplete",
174
174
  "unsafe",
175
175
  "other"
176
176
  ]);
177
- var ReviewVerdictSchema = import_zod12.z.enum([
177
+ var ReviewVerdictSchema = import_zod14.z.enum([
178
178
  "correct",
179
179
  "partially-correct",
180
180
  "incorrect"
181
181
  ]);
182
- var runId = import_zod12.z.string().trim().min(1).max(512);
183
- var actorId = import_zod12.z.string().trim().min(1).max(256);
184
- var comment = import_zod12.z.string().trim().max(4e3).nullable().optional();
185
- var UserFeedbackRequestSchema = import_zod12.z.object({
182
+ var runId = import_zod14.z.string().trim().min(1).max(512);
183
+ var actorId = import_zod14.z.string().trim().min(1).max(256);
184
+ var comment = import_zod14.z.string().trim().max(4e3).nullable().optional();
185
+ var UserFeedbackRequestSchema = import_zod14.z.object({
186
186
  runId,
187
187
  actorId,
188
- value: import_zod12.z.union([import_zod12.z.literal(0), import_zod12.z.literal(1)]),
189
- reasons: import_zod12.z.array(FeedbackReasonSchema).max(5).optional(),
188
+ value: import_zod14.z.union([import_zod14.z.literal(0), import_zod14.z.literal(1)]),
189
+ reasons: import_zod14.z.array(FeedbackReasonSchema).max(5).optional(),
190
190
  comment
191
191
  }).strict();
192
192
  var ClearUserFeedbackRequestSchema = UserFeedbackRequestSchema.pick({
193
193
  runId: true,
194
194
  actorId: true
195
195
  });
196
- var StudioReviewRequestSchema = import_zod12.z.object({ value: ReviewVerdictSchema, comment }).strict();
197
- var BaseScoreSchema = import_zod12.z.object({
198
- id: import_zod12.z.string().uuid(),
199
- target: import_zod12.z.object({ type: import_zod12.z.literal("run"), runId }).strict(),
200
- environment: import_zod12.z.string().min(1),
201
- name: import_zod12.z.string().min(1),
202
- source: import_zod12.z.enum(["end-user", "human-review", "evaluator"]),
196
+ var StudioReviewRequestSchema = import_zod14.z.object({ value: ReviewVerdictSchema, comment }).strict();
197
+ var BaseScoreSchema = import_zod14.z.object({
198
+ id: import_zod14.z.string().uuid(),
199
+ target: import_zod14.z.object({ type: import_zod14.z.literal("run"), runId }).strict(),
200
+ environment: import_zod14.z.string().min(1),
201
+ name: import_zod14.z.string().min(1),
202
+ source: import_zod14.z.enum(["end-user", "human-review", "evaluator"]),
203
203
  actorId,
204
- reasons: import_zod12.z.array(FeedbackReasonSchema),
205
- comment: import_zod12.z.string().nullable(),
206
- createdAt: import_zod12.z.string().datetime({ offset: true }),
207
- updatedAt: import_zod12.z.string().datetime({ offset: true })
204
+ reasons: import_zod14.z.array(FeedbackReasonSchema),
205
+ comment: import_zod14.z.string().nullable(),
206
+ createdAt: import_zod14.z.string().datetime({ offset: true }),
207
+ updatedAt: import_zod14.z.string().datetime({ offset: true })
208
208
  }).strict();
209
- var StudioScoreSchema = import_zod12.z.discriminatedUnion("dataType", [
209
+ var StudioScoreSchema = import_zod14.z.discriminatedUnion("dataType", [
210
210
  BaseScoreSchema.extend({
211
- dataType: import_zod12.z.literal("BOOLEAN"),
212
- value: import_zod12.z.union([import_zod12.z.literal(0), import_zod12.z.literal(1)])
211
+ dataType: import_zod14.z.literal("BOOLEAN"),
212
+ value: import_zod14.z.union([import_zod14.z.literal(0), import_zod14.z.literal(1)])
213
213
  }),
214
214
  BaseScoreSchema.extend({
215
- dataType: import_zod12.z.literal("CATEGORICAL"),
216
- value: import_zod12.z.string()
215
+ dataType: import_zod14.z.literal("CATEGORICAL"),
216
+ value: import_zod14.z.string()
217
217
  }),
218
218
  BaseScoreSchema.extend({
219
- dataType: import_zod12.z.literal("NUMERIC"),
220
- value: import_zod12.z.number().finite()
219
+ dataType: import_zod14.z.literal("NUMERIC"),
220
+ value: import_zod14.z.number().finite()
221
221
  })
222
222
  ]);
223
- var StudioScoreResponseSchema = import_zod12.z.object({ score: StudioScoreSchema }).strict();
224
- var ClearScoreResponseSchema = import_zod12.z.object({ ok: import_zod12.z.literal(true) }).strict();
223
+ var StudioScoreResponseSchema = import_zod14.z.object({ score: StudioScoreSchema }).strict();
224
+ var ClearScoreResponseSchema = import_zod14.z.object({ ok: import_zod14.z.literal(true) }).strict();
225
225
  function summarizeUserFeedback(scores) {
226
226
  const feedback = { positive: 0, negative: 0 };
227
227
  for (const score of scores) {
@@ -1056,14 +1056,14 @@ var require_dist = __commonJS({
1056
1056
  payload: import_zod62.z.record(import_zod62.z.string(), import_zod62.z.unknown())
1057
1057
  }).strict().superRefine((event, ctx) => {
1058
1058
  if (!event.type.startsWith("tool.")) return;
1059
- const canonical2 = event.payload.version === 1 || [
1059
+ const canonical3 = event.payload.version === 1 || [
1060
1060
  "tool.denied",
1061
1061
  "tool.cancelled",
1062
1062
  "tool.reused",
1063
1063
  "tool.waiting",
1064
1064
  "tool.suspended"
1065
1065
  ].includes(event.type);
1066
- if (!canonical2) return;
1066
+ if (!canonical3) return;
1067
1067
  const parsed = ToolObservationSchema.strict().safeParse(event.payload);
1068
1068
  if (!parsed.success)
1069
1069
  for (const issue2 of parsed.error.issues)
@@ -1660,7 +1660,7 @@ var require_internal = __commonJS({
1660
1660
  });
1661
1661
  module2.exports = __toCommonJS2(internal_exports);
1662
1662
  var import_telemetry_contracts3 = require_dist();
1663
- var import_errors8 = require("@kortyx/core/errors");
1663
+ var import_errors16 = require("@kortyx/core/errors");
1664
1664
  var import_telemetry_contracts = require_dist();
1665
1665
  var encoder = new TextEncoder();
1666
1666
  var nativeStackGetter = Object.getOwnPropertyDescriptor(
@@ -1841,11 +1841,11 @@ var require_internal = __commonJS({
1841
1841
  const original = project ? project(error) : error;
1842
1842
  if (project && original === null) return null;
1843
1843
  const captured = visit(original, "#/data", 0);
1844
- const upstreamOmissions = (0, import_errors8.errorProperty)(original, "diagnosticOmissions");
1844
+ const upstreamOmissions = (0, import_errors16.errorProperty)(original, "diagnosticOmissions");
1845
1845
  if (Array.isArray(upstreamOmissions))
1846
1846
  for (const note of upstreamOmissions.slice(0, 1e3)) {
1847
- const path = (0, import_errors8.errorProperty)(note, "path");
1848
- const reason = (0, import_errors8.errorProperty)(note, "reason");
1847
+ const path = (0, import_errors16.errorProperty)(note, "path");
1848
+ const reason = (0, import_errors16.errorProperty)(note, "reason");
1849
1849
  if (typeof path === "string" && typeof reason === "string")
1850
1850
  omissions.push({
1851
1851
  path: (0, import_telemetry_contracts.redactDiagnosticText)(path).slice(0, 4096),
@@ -1912,7 +1912,7 @@ var require_internal = __commonJS({
1912
1912
  function isModelTraceSpan(name) {
1913
1913
  return name === "runReasonEngine" || name === "useReason";
1914
1914
  }
1915
- var import_node_crypto7 = require("crypto");
1915
+ var import_node_crypto8 = require("crypto");
1916
1916
  var import_core6 = require("@kortyx/core");
1917
1917
  var import_errors22 = require("@kortyx/core/errors");
1918
1918
  function safeSpan(span) {
@@ -1996,7 +1996,7 @@ var require_internal = __commonJS({
1996
1996
  var import_node2 = require("@kortyx/usage-telemetry/node");
1997
1997
  var package_default2 = {
1998
1998
  name: "@kortyx/hooks",
1999
- version: "0.34.1",
1999
+ version: "0.34.2",
2000
2000
  private: false,
2001
2001
  description: "Lifecycle hooks and extension points for Kortyx.",
2002
2002
  keywords: [
@@ -2090,7 +2090,7 @@ var require_internal = __commonJS({
2090
2090
  var toError = (value) => value instanceof Error ? value : new Error(String(value));
2091
2091
  var createRuntimeId = () => {
2092
2092
  try {
2093
- return (0, import_node_crypto7.randomUUID)();
2093
+ return (0, import_node_crypto8.randomUUID)();
2094
2094
  } catch {
2095
2095
  return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
2096
2096
  }
@@ -2144,7 +2144,7 @@ var require_internal = __commonJS({
2144
2144
  tools: Boolean(tools?.length),
2145
2145
  provider: args.model.provider.id
2146
2146
  });
2147
- const messages = args.messages !== void 0 ? args.messages : [
2147
+ const messages2 = args.messages !== void 0 ? args.messages : [
2148
2148
  ...typeof args.system === "string" && args.system.length > 0 ? [{ role: "system", content: args.system }] : [],
2149
2149
  { role: "user", content: String(args.input ?? "") }
2150
2150
  ];
@@ -2171,7 +2171,7 @@ var require_internal = __commonJS({
2171
2171
  },
2172
2172
  telemetry: {
2173
2173
  ...args.telemetry ?? {},
2174
- input: args.telemetry?.input ?? messages.map(
2174
+ input: args.telemetry?.input ?? messages2.map(
2175
2175
  ({ continuation: _continuation, raw: _raw, ...message }) => message
2176
2176
  )
2177
2177
  }
@@ -2233,7 +2233,7 @@ var require_internal = __commonJS({
2233
2233
  ...commonMeta
2234
2234
  });
2235
2235
  }
2236
- const response2 = await model.stream(messages);
2236
+ const response2 = await model.stream(messages2);
2237
2237
  for await (const chunk of response2) {
2238
2238
  (0, import_core6.throwIfExecutionAborted)(abortSignal);
2239
2239
  switch (chunk.type) {
@@ -2322,7 +2322,7 @@ var require_internal = __commonJS({
2322
2322
  endTrace(traceSpan, result2);
2323
2323
  return result2;
2324
2324
  }
2325
- const response = await model.invoke(messages);
2325
+ const response = await model.invoke(messages2);
2326
2326
  (0, import_core6.throwIfExecutionAborted)(abortSignal);
2327
2327
  assertModelFinish(response);
2328
2328
  if (response.content) args.onTextChunk?.(response.content);
@@ -2353,9 +2353,9 @@ var require_internal = __commonJS({
2353
2353
  endTrace(traceSpan, result);
2354
2354
  return result;
2355
2355
  } catch (error) {
2356
- const failure2 = abortSignal?.aborted ? (0, import_core6.createExecutionCancelledError)() : error;
2357
- failTrace(traceSpan, failure2);
2358
- throw failure2;
2356
+ const failure = abortSignal?.aborted ? (0, import_core6.createExecutionCancelledError)() : error;
2357
+ failTrace(traceSpan, failure);
2358
+ throw failure;
2359
2359
  }
2360
2360
  }
2361
2361
  function runReasonEngine(args) {
@@ -2437,7 +2437,7 @@ var require_dist2 = __commonJS({
2437
2437
  workflowCallFingerprint: () => workflowCallFingerprint
2438
2438
  });
2439
2439
  module2.exports = __toCommonJS2(index_exports2);
2440
- var import_zod12 = require("zod");
2440
+ var import_zod14 = require("zod");
2441
2441
  var import_node_async_hooks2 = require("async_hooks");
2442
2442
  var storage = new import_node_async_hooks2.AsyncLocalStorage();
2443
2443
  var isRecord5 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -2632,7 +2632,7 @@ var require_dist2 = __commonJS({
2632
2632
  var import_node2 = require("@kortyx/usage-telemetry/node");
2633
2633
  var package_default2 = {
2634
2634
  name: "@kortyx/hooks",
2635
- version: "0.34.1",
2635
+ version: "0.34.2",
2636
2636
  private: false,
2637
2637
  description: "Lifecycle hooks and extension points for Kortyx.",
2638
2638
  keywords: [
@@ -2709,9 +2709,9 @@ var require_dist2 = __commonJS({
2709
2709
  measure: (...args) => client2().measure(...args),
2710
2710
  flush: () => client2().flush()
2711
2711
  };
2712
- var optionsSchema = import_zod12.z.object({
2713
- message: import_zod12.z.string().optional(),
2714
- data: import_zod12.z.json().optional()
2712
+ var optionsSchema = import_zod14.z.object({
2713
+ message: import_zod14.z.string().optional(),
2714
+ data: import_zod14.z.json().optional()
2715
2715
  }).strict();
2716
2716
  async function completeResponseInternal(options = {}) {
2717
2717
  const ctx = getHookContext();
@@ -2771,14 +2771,14 @@ var require_dist2 = __commonJS({
2771
2771
  workflowState: args.workflowState
2772
2772
  }
2773
2773
  });
2774
- var import_errors8 = require("@kortyx/core/errors");
2774
+ var import_errors16 = require("@kortyx/core/errors");
2775
2775
  var parseWithSchema = (schema, value, label) => {
2776
2776
  if (!schema) return value;
2777
2777
  const parsed = schema.safeParse(value);
2778
2778
  if (parsed.success) return parsed.data;
2779
2779
  const parsedError = "error" in parsed && parsed.error ? parsed.error : void 0;
2780
2780
  const reason = typeof parsedError?.message === "string" && parsedError.message.length > 0 ? parsedError.message : "invalid payload";
2781
- throw new import_errors8.ValidationError(
2781
+ throw new import_errors16.ValidationError(
2782
2782
  label === "useReason output" ? "MODEL_OUTPUT_SCHEMA" : "SCHEMA_VALIDATION",
2783
2783
  `${label} validation failed: ${reason}`,
2784
2784
  parsedError
@@ -3097,10 +3097,10 @@ var require_dist2 = __commonJS({
3097
3097
  }
3098
3098
  return execution ?? invoke(safeSpan(void 0));
3099
3099
  }
3100
- var import_node_crypto7 = require("crypto");
3100
+ var import_node_crypto8 = require("crypto");
3101
3101
  var createStructuredStreamId = () => {
3102
3102
  try {
3103
- return (0, import_node_crypto7.randomUUID)();
3103
+ return (0, import_node_crypto8.randomUUID)();
3104
3104
  } catch {
3105
3105
  return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
3106
3106
  }
@@ -3888,7 +3888,7 @@ var require_dist2 = __commonJS({
3888
3888
  tools: Boolean(tools2?.length),
3889
3889
  provider: args.model.provider.id
3890
3890
  });
3891
- const messages = args.messages !== void 0 ? args.messages : [
3891
+ const messages2 = args.messages !== void 0 ? args.messages : [
3892
3892
  ...typeof args.system === "string" && args.system.length > 0 ? [{ role: "system", content: args.system }] : [],
3893
3893
  { role: "user", content: String(args.input ?? "") }
3894
3894
  ];
@@ -3915,7 +3915,7 @@ var require_dist2 = __commonJS({
3915
3915
  },
3916
3916
  telemetry: {
3917
3917
  ...args.telemetry ?? {},
3918
- input: args.telemetry?.input ?? messages.map(
3918
+ input: args.telemetry?.input ?? messages2.map(
3919
3919
  ({ continuation: _continuation, raw: _raw, ...message }) => message
3920
3920
  )
3921
3921
  }
@@ -3977,7 +3977,7 @@ var require_dist2 = __commonJS({
3977
3977
  ...commonMeta
3978
3978
  });
3979
3979
  }
3980
- const response2 = await model.stream(messages);
3980
+ const response2 = await model.stream(messages2);
3981
3981
  for await (const chunk of response2) {
3982
3982
  (0, import_core32.throwIfExecutionAborted)(abortSignal);
3983
3983
  switch (chunk.type) {
@@ -4066,7 +4066,7 @@ var require_dist2 = __commonJS({
4066
4066
  endTrace(traceSpan, result2);
4067
4067
  return result2;
4068
4068
  }
4069
- const response = await model.invoke(messages);
4069
+ const response = await model.invoke(messages2);
4070
4070
  (0, import_core32.throwIfExecutionAborted)(abortSignal);
4071
4071
  assertModelFinish(response);
4072
4072
  if (response.content) args.onTextChunk?.(response.content);
@@ -4097,9 +4097,9 @@ var require_dist2 = __commonJS({
4097
4097
  endTrace(traceSpan, result);
4098
4098
  return result;
4099
4099
  } catch (error) {
4100
- const failure2 = abortSignal?.aborted ? (0, import_core32.createExecutionCancelledError)() : error;
4101
- failTrace(traceSpan, failure2);
4102
- throw failure2;
4100
+ const failure = abortSignal?.aborted ? (0, import_core32.createExecutionCancelledError)() : error;
4101
+ failTrace(traceSpan, failure);
4102
+ throw failure;
4103
4103
  }
4104
4104
  }
4105
4105
  function runReasonEngine(args) {
@@ -4940,13 +4940,13 @@ var require_dist2 = __commonJS({
4940
4940
  return parseWithSchema(args.schema, candidate, args.label);
4941
4941
  } catch (error) {
4942
4942
  if (!(error instanceof import_errors52.ValidationError)) throw error;
4943
- const failure2 = args.finishReason?.unified === "length" ? createTruncatedStructuredOutputError(args.label, error) : typeof candidate === "string" && !validJson ? createInvalidStructuredOutputError(args.label, error) : error;
4944
- if (failure2 && typeof failure2 === "object")
4945
- Object.assign(failure2, {
4943
+ const failure = args.finishReason?.unified === "length" ? createTruncatedStructuredOutputError(args.label, error) : typeof candidate === "string" && !validJson ? createInvalidStructuredOutputError(args.label, error) : error;
4944
+ if (failure && typeof failure === "object")
4945
+ Object.assign(failure, {
4946
4946
  ...args.usage ? { usage: args.usage } : {},
4947
4947
  ...args.finishReason ? { finishReason: args.finishReason } : {}
4948
4948
  });
4949
- throw failure2;
4949
+ throw failure;
4950
4950
  }
4951
4951
  };
4952
4952
  var parseInterruptFirstPassResult = (args) => {
@@ -5494,7 +5494,19 @@ ${tryStringify2(args.response)}`
5494
5494
  let finalizing = checkpoint?.finalizing ?? false;
5495
5495
  let completed = false;
5496
5496
  const maxSteps = Math.max(1, useReasonArgs.toolExecution?.maxSteps ?? 3);
5497
- const messages = checkpoint?.messages ?? createInitialMessages({
5497
+ const missingReturnCorrections = useReasonArgs.toolExecution?.missingReturnCorrections ?? 0;
5498
+ if (!Number.isSafeInteger(missingReturnCorrections) || missingReturnCorrections < 0)
5499
+ throw new import_errors62.KortyxError(
5500
+ "INVALID_REASON_CORRECTION_POLICY",
5501
+ "Invalid missing return correction budget.",
5502
+ {
5503
+ category: "configuration",
5504
+ retryable: false,
5505
+ safeMessage: "toolExecution.missingReturnCorrections must be a nonnegative safe integer."
5506
+ }
5507
+ );
5508
+ let missingReturnAttempts = checkpoint?.missingReturnAttempts ?? 0;
5509
+ const messages2 = checkpoint?.messages ?? createInitialMessages({
5498
5510
  messages: useReasonArgs.messages,
5499
5511
  inputOverride: Boolean(useReasonArgs.outputSchema),
5500
5512
  system: useReasonArgs.system,
@@ -5545,13 +5557,17 @@ ${tryStringify2(args.response)}`
5545
5557
  let outputContractCorrections = checkpoint?.outputContractCorrections ?? 0;
5546
5558
  const correctionExhausted = () => {
5547
5559
  const message = `useReason could not complete output-contract correction within toolExecution.maxSteps (${maxSteps}). Select exactly one terminal return contract; multiple emit contracts are allowed. Increase maxSteps to allow correction and output generation.`;
5548
- return new import_errors62.ProviderRequestError(message, {
5549
- code: "REASON_OUTPUT_CONTRACT_CORRECTION_EXHAUSTED",
5550
- operation: "useReason",
5551
- safeMessage: message,
5552
- retryable: false,
5553
- details: { maxSteps, outputContractCorrections }
5554
- });
5560
+ return new import_errors62.KortyxError(
5561
+ "REASON_OUTPUT_CONTRACT_CORRECTION_EXHAUSTED",
5562
+ message,
5563
+ {
5564
+ category: "validation",
5565
+ operation: "useReason",
5566
+ safeMessage: message,
5567
+ retryable: false,
5568
+ details: { maxSteps, outputContractCorrections }
5569
+ }
5570
+ );
5555
5571
  };
5556
5572
  const resolvedInterrupts = checkpoint?.resolvedInterrupts ?? [];
5557
5573
  for (const request of resolvedInterrupts) ctx.node.replayInterrupt?.(request);
@@ -5563,13 +5579,14 @@ ${tryStringify2(args.response)}`
5563
5579
  ctx.currentNodeState.byKey[checkpointKey] = {
5564
5580
  status: "tool_loop",
5565
5581
  opId,
5566
- messages,
5582
+ messages: messages2,
5567
5583
  steps,
5568
5584
  approvedCalls,
5569
5585
  resolvedInterrupts,
5570
5586
  interruptHistory,
5571
5587
  emissions,
5572
5588
  outputContractCorrections,
5589
+ missingReturnAttempts,
5573
5590
  ...returned ? { returned } : {},
5574
5591
  finalizing,
5575
5592
  ...pending ? { pending } : {},
@@ -5605,9 +5622,9 @@ ${tryStringify2(args.response)}`
5605
5622
  const step = pending ?? await reasonEngine(
5606
5623
  {
5607
5624
  ...useReasonArgs,
5608
- tools: finalizing ? [] : toolDefinitions,
5625
+ tools: finalizing ? [] : missingReturnAttempts > 0 ? outputDefinitions : toolDefinitions,
5609
5626
  ...separateOutput && !finalizing ? { responseFormat: { type: "text" } } : {},
5610
- messages,
5627
+ messages: messages2,
5611
5628
  emit: false,
5612
5629
  stream,
5613
5630
  onTextChunk: (delta) => {
@@ -5636,6 +5653,16 @@ ${tryStringify2(args.response)}`
5636
5653
  );
5637
5654
  aggregatedWarnings = mergeWarnings(aggregatedWarnings, step.warnings);
5638
5655
  const toolCalls = step.toolCalls ?? [];
5656
+ if (missingReturnAttempts > 0 && toolCalls.some((call) => !outputByToolName.has(call.name)))
5657
+ throw new import_errors62.KortyxError(
5658
+ "REASON_OUTPUT_CORRECTION_TOOL_DISALLOWED",
5659
+ "A return correction requested a non-output tool.",
5660
+ {
5661
+ category: "validation",
5662
+ retryable: false,
5663
+ safeMessage: "A terminal output correction cannot rerun tools or human-input requests."
5664
+ }
5665
+ );
5639
5666
  const ids = /* @__PURE__ */ new Set();
5640
5667
  for (const call of toolCalls) {
5641
5668
  if (!call.id || ids.has(call.id) || !reused && knownToolCallIds.has(call.id))
@@ -5656,10 +5683,32 @@ ${tryStringify2(args.response)}`
5656
5683
  });
5657
5684
  if (!reused) for (const call of toolCalls) knownToolCallIds.add(call.id);
5658
5685
  if (toolCalls.length === 0) {
5659
- if (Object.keys(useReasonArgs.outputs?.return ?? {}).length > 0 && !returned)
5660
- throw new Error(
5661
- "useReason outputs.return requires one terminal output contract call."
5686
+ if (Object.keys(useReasonArgs.outputs?.return ?? {}).length > 0 && !returned) {
5687
+ if (missingReturnAttempts < missingReturnCorrections) {
5688
+ messages2.push({ role: "assistant", content: step.text });
5689
+ messages2.push({
5690
+ role: "user",
5691
+ content: "MISSING_TERMINAL_OUTPUT: No terminal output was published. Select exactly one configured return contract using the completed tool and human-input results. Do not repeat completed calls."
5692
+ });
5693
+ missingReturnAttempts += 1;
5694
+ outputContractCorrections += 1;
5695
+ pending = void 0;
5696
+ pendingStepIndex = void 0;
5697
+ save();
5698
+ continue;
5699
+ }
5700
+ throw new import_errors62.KortyxError(
5701
+ "REASON_TERMINAL_OUTPUT_MISSING",
5702
+ "useReason outputs.return requires one terminal output contract call.",
5703
+ {
5704
+ category: "validation",
5705
+ operation: "useReason",
5706
+ retryable: false,
5707
+ safeMessage: "useReason outputs.return requires one terminal output contract call.",
5708
+ details: { missingReturnAttempts }
5709
+ }
5662
5710
  );
5711
+ }
5663
5712
  if (interruptConfig?.mode === "required" && interruptHistory.length === 0)
5664
5713
  throw new Error(
5665
5714
  "useReason interrupts.mode is required, but the model returned a final answer without requesting human input."
@@ -5686,12 +5735,12 @@ ${tryStringify2(args.response)}`
5686
5735
  } catch {
5687
5736
  }
5688
5737
  }
5689
- messages.push({
5738
+ messages2.push({
5690
5739
  role: "assistant",
5691
5740
  content: step.text,
5692
5741
  ...step.continuation ? { continuation: step.continuation } : {}
5693
5742
  });
5694
- messages.push({
5743
+ messages2.push({
5695
5744
  role: "user",
5696
5745
  content: "Return the final answer using the requested output schema and the tool results above."
5697
5746
  });
@@ -5714,7 +5763,7 @@ ${tryStringify2(args.response)}`
5714
5763
  (call) => !interruptByToolName.has(call.name) && !outputByToolName.has(call.name)
5715
5764
  )
5716
5765
  );
5717
- messages.push({
5766
+ messages2.push({
5718
5767
  role: "assistant",
5719
5768
  content: step.text,
5720
5769
  toolCalls,
@@ -5742,7 +5791,7 @@ ${tryStringify2(args.response)}`
5742
5791
  content: "MULTIPLE_TERMINAL_OUTPUTS: No terminal output was published. Select exactly one return contract using the tool and human-input results. Do not repeat completed calls. Multiple emit contracts are allowed."
5743
5792
  };
5744
5793
  toolResults.push(result2);
5745
- messages.push({ role: "tool", ...result2 });
5794
+ messages2.push({ role: "tool", ...result2 });
5746
5795
  corrected = true;
5747
5796
  }
5748
5797
  if (corrected) outputContractCorrections += 1;
@@ -5827,7 +5876,7 @@ ${tryStringify2(args.response)}`
5827
5876
  tools: [],
5828
5877
  ...inferred.responseFormat ? { responseFormat: inferred.responseFormat } : {},
5829
5878
  messages: [
5830
- ...messages,
5879
+ ...messages2,
5831
5880
  ...toolCalls.filter(
5832
5881
  (pendingCall) => !toolResults.some(
5833
5882
  (result3) => result3.toolCallId === pendingCall.id
@@ -5946,7 +5995,7 @@ ${tryStringify2(args.response)}`
5946
5995
  });
5947
5996
  const result2 = normalizeToolResult(call, { emitted: true, data });
5948
5997
  toolResults.push(result2);
5949
- messages.push({
5998
+ messages2.push({
5950
5999
  role: "tool",
5951
6000
  content: result2.content,
5952
6001
  toolCallId: result2.toolCallId,
@@ -6003,7 +6052,7 @@ ${tryStringify2(args.response)}`
6003
6052
  });
6004
6053
  const result2 = normalizeToolResult(toolCall, response);
6005
6054
  toolResults.push(result2);
6006
- messages.push({
6055
+ messages2.push({
6007
6056
  role: "tool",
6008
6057
  content: result2.content,
6009
6058
  toolCallId: result2.toolCallId,
@@ -6117,7 +6166,7 @@ ${tryStringify2(args.response)}`
6117
6166
  isError: true
6118
6167
  });
6119
6168
  }
6120
- messages.push({
6169
+ messages2.push({
6121
6170
  role: "tool",
6122
6171
  content: denied.content,
6123
6172
  toolCallId: denied.toolCallId,
@@ -6174,17 +6223,21 @@ ${tryStringify2(args.response)}`
6174
6223
  toolResults.push(result2);
6175
6224
  allToolResults.push(result2);
6176
6225
  if (shouldEmitTool) {
6226
+ const diagnosticId = steps[stepIndex]?.toolObservations?.slice().reverse().find(
6227
+ (observation) => observation.toolCallId === `${opId}:${toolCall.id}`
6228
+ )?.diagnosticId;
6177
6229
  emitToolEvent("tool-call-error", {
6178
6230
  tool: tool.name,
6179
6231
  toolCallId: toolCall.id,
6180
6232
  message: result2.content,
6181
- failure: result2.failure
6233
+ failure: result2.failure,
6234
+ ...diagnosticId ? { diagnosticId } : {}
6182
6235
  });
6183
6236
  }
6184
6237
  }
6185
6238
  const completedToolResult = toolResults.at(-1);
6186
6239
  if (completedToolResult)
6187
- messages.push({
6240
+ messages2.push({
6188
6241
  role: "tool",
6189
6242
  content: completedToolResult.content,
6190
6243
  toolCallId: completedToolResult.toolCallId,
@@ -6967,9 +7020,9 @@ ${tryStringify2(args.response)}`
6967
7020
  var import_core8 = require("@kortyx/core");
6968
7021
  var import_errors82 = require("@kortyx/core/errors");
6969
7022
  var WorkflowCallError = class extends import_errors82.KortyxError {
6970
- constructor(workflow, message, cause, failure2) {
7023
+ constructor(workflow, message, cause, failure) {
6971
7024
  const detail = (0, import_errors82.serializeFailure)(
6972
- failure2 ?? cause ?? new import_errors82.WorkflowContractError(message)
7025
+ failure ?? cause ?? new import_errors82.WorkflowContractError(message)
6973
7026
  );
6974
7027
  super(detail.code, `Workflow '${workflow}': ${message}`, {
6975
7028
  ...detail,
@@ -6986,7 +7039,7 @@ ${tryStringify2(args.response)}`
6986
7039
  };
6987
7040
  function workflowCallFingerprint(value) {
6988
7041
  const seen = /* @__PURE__ */ new Set();
6989
- const canonical2 = (v) => {
7042
+ const canonical3 = (v) => {
6990
7043
  if (v === null || typeof v === "string" || typeof v === "boolean") return v;
6991
7044
  if (typeof v === "number" && Number.isFinite(v)) return v;
6992
7045
  if (typeof v !== "object" || !v || seen.has(v)) {
@@ -7000,16 +7053,16 @@ ${tryStringify2(args.response)}`
7000
7053
  );
7001
7054
  }
7002
7055
  seen.add(v);
7003
- const result = Array.isArray(v) ? v.map(canonical2) : Object.fromEntries(
7056
+ const result = Array.isArray(v) ? v.map(canonical3) : Object.fromEntries(
7004
7057
  Object.keys(v).sort().map((key) => [
7005
7058
  key,
7006
- canonical2(v[key])
7059
+ canonical3(v[key])
7007
7060
  ])
7008
7061
  );
7009
7062
  seen.delete(v);
7010
7063
  return result;
7011
7064
  };
7012
- return JSON.stringify(canonical2(value));
7065
+ return JSON.stringify(canonical3(value));
7013
7066
  }
7014
7067
  function createWorkflowHooks(workflows) {
7015
7068
  return {
@@ -7239,6 +7292,7 @@ __export(index_exports, {
7239
7292
  ChatLifecycleHookError: () => ChatLifecycleHookError,
7240
7293
  EvalConfigurationError: () => EvalConfigurationError,
7241
7294
  EvalEvidencePolicySchema: () => EvalEvidencePolicySchema,
7295
+ EvalIssueSchema: () => EvalIssueSchema,
7242
7296
  EvalJudgeIdentitySchema: () => EvalJudgeIdentitySchema,
7243
7297
  EvalJudgeUsageSchema: () => EvalJudgeUsageSchema,
7244
7298
  EvalManifestSchema: () => EvalManifestSchema,
@@ -7260,6 +7314,7 @@ __export(index_exports, {
7260
7314
  createAgent: () => createAgent,
7261
7315
  createChatRouteHandler: () => createChatRouteHandler,
7262
7316
  createCheckpointRouteHandler: () => createCheckpointRouteHandler,
7317
+ createEvalIssue: () => createEvalIssue,
7263
7318
  createEvalJudge: () => createEvalJudge,
7264
7319
  createEvalRouteHandler: () => createEvalRouteHandler,
7265
7320
  createEvals: () => createEvals,
@@ -7288,7 +7343,7 @@ module.exports = __toCommonJS(index_exports);
7288
7343
  // src/adapters/http.ts
7289
7344
  var import_errors5 = require("@kortyx/core/errors");
7290
7345
  var import_stream2 = require("@kortyx/stream");
7291
- var import_zod2 = require("zod");
7346
+ var import_zod3 = require("zod");
7292
7347
 
7293
7348
  // src/chat/lifecycle.ts
7294
7349
  var import_errors = require("@kortyx/core/errors");
@@ -7336,6 +7391,7 @@ var import_internal = __toESM(require_internal());
7336
7391
  var import_runtime = require("@kortyx/runtime");
7337
7392
  var import_stream = require("@kortyx/stream");
7338
7393
  var import_langgraph = require("@langchain/langgraph");
7394
+ var import_zod2 = require("zod");
7339
7395
 
7340
7396
  // src/execution/contracts.ts
7341
7397
  var import_errors3 = require("@kortyx/core/errors");
@@ -7397,12 +7453,12 @@ async function validateExecutionOutput(state, select) {
7397
7453
  if (terminal.outputSchema || root.outputSchema) import_zod.z.json().parse(data);
7398
7454
  } catch (error) {
7399
7455
  if (!(error instanceof import_zod.z.ZodError)) throw error;
7400
- const failure2 = new import_errors3.ValidationError(
7456
+ const failure = new import_errors3.ValidationError(
7401
7457
  "INVALID_OUTPUT",
7402
7458
  `Workflow output validation failed: ${error.message}`,
7403
7459
  error
7404
7460
  );
7405
- throw failure2;
7461
+ throw failure;
7406
7462
  }
7407
7463
  return { ...state, data };
7408
7464
  }
@@ -7792,7 +7848,7 @@ var import_node = require("@kortyx/usage-telemetry/node");
7792
7848
  // package.json
7793
7849
  var package_default = {
7794
7850
  name: "@kortyx/agent",
7795
- version: "0.37.1",
7851
+ version: "0.38.0",
7796
7852
  private: false,
7797
7853
  description: "Agent composition utilities for Kortyx.",
7798
7854
  keywords: [
@@ -8056,6 +8112,24 @@ async function orchestrateGraphStream({
8056
8112
  isRecord3(config.context) ? { userId: config.context.userId, tenantId: config.context.tenantId } : {}
8057
8113
  );
8058
8114
  const telemetryConfig = isRecord3(config.telemetry) ? config.telemetry : {};
8115
+ const errorChunk = (error, existingDiagnosticId) => {
8116
+ const failure = (0, import_errors4.serializeFailure)(error);
8117
+ let diagnosticId = existingDiagnosticId;
8118
+ if (!diagnosticId) {
8119
+ try {
8120
+ diagnosticId = traceAdapter?.reportError?.(error, {
8121
+ correlation: { runId, ...sessionId ? { sessionId } : {} }
8122
+ });
8123
+ } catch {
8124
+ }
8125
+ }
8126
+ return {
8127
+ type: "error",
8128
+ message: failure.message,
8129
+ failure,
8130
+ ...typeof diagnosticId === "string" && import_zod2.z.uuid().safeParse(diagnosticId).success ? { diagnosticId } : {}
8131
+ };
8132
+ };
8059
8133
  const emitResumeFailure = (resumeError) => {
8060
8134
  const interruptId = typeof config.telemetryInterruptId === "string" ? config.telemetryInterruptId : void 0;
8061
8135
  if (!interruptId) return;
@@ -8322,11 +8396,12 @@ async function orchestrateGraphStream({
8322
8396
  );
8323
8397
  const supplied = payload?.failure;
8324
8398
  outcomeError = (0, import_errors4.isFailureDescriptor)(supplied) ? (0, import_errors4.errorFromFailure)(supplied) : new Error(msg);
8325
- write({
8326
- type: "error",
8327
- message: (0, import_errors4.serializeFailure)(outcomeError).message,
8328
- failure: (0, import_errors4.serializeFailure)(outcomeError)
8329
- });
8399
+ write(
8400
+ errorChunk(
8401
+ outcomeError,
8402
+ payload?.diagnosticId
8403
+ )
8404
+ );
8330
8405
  write({ type: "done" });
8331
8406
  finished = true;
8332
8407
  out.end();
@@ -8695,11 +8770,7 @@ async function orchestrateGraphStream({
8695
8770
  runTraceSpan.addEvent?.("kortyx.transition.error", {
8696
8771
  transitionTo
8697
8772
  });
8698
- write({
8699
- type: "error",
8700
- message: (0, import_errors4.serializeFailure)(err).message,
8701
- failure: (0, import_errors4.serializeFailure)(err)
8702
- });
8773
+ write(errorChunk(err));
8703
8774
  write({ type: "done" });
8704
8775
  out.end();
8705
8776
  return;
@@ -9083,11 +9154,7 @@ async function orchestrateGraphStream({
9083
9154
  fallbackRunSpan?.fail?.(err);
9084
9155
  emitResumeFailure(err);
9085
9156
  console.error("[error:orchestrateGraphStream]", (0, import_errors4.serializeFailure)(err));
9086
- write({
9087
- type: "error",
9088
- message: (0, import_errors4.serializeFailure)(err).message,
9089
- failure: (0, import_errors4.serializeFailure)(err)
9090
- });
9157
+ write(errorChunk(err));
9091
9158
  write({ type: "done" });
9092
9159
  finished = true;
9093
9160
  out.end();
@@ -9432,38 +9499,38 @@ var reportLifecycleError = async (callback, event) => {
9432
9499
  console.error("[chat:onLifecycleError]", (0, import_errors5.serializeFailure)(error));
9433
9500
  }
9434
9501
  };
9435
- var chatMessageSchema = import_zod2.z.object({
9436
- role: import_zod2.z.enum(["user", "assistant", "system"]),
9437
- content: import_zod2.z.string(),
9438
- metadata: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
9439
- id: import_zod2.z.string().optional(),
9440
- timestamp: import_zod2.z.number().refine(Number.isFinite).optional()
9502
+ var chatMessageSchema = import_zod3.z.object({
9503
+ role: import_zod3.z.enum(["user", "assistant", "system"]),
9504
+ content: import_zod3.z.string(),
9505
+ metadata: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional(),
9506
+ id: import_zod3.z.string().optional(),
9507
+ timestamp: import_zod3.z.number().refine(Number.isFinite).optional()
9441
9508
  }).strict();
9442
- var chatRequestBodySchema = import_zod2.z.looseObject({
9443
- sessionId: import_zod2.z.string().optional(),
9444
- clientTurnId: import_zod2.z.string().max(128).optional(),
9445
- workflowId: import_zod2.z.string().optional(),
9446
- stream: import_zod2.z.boolean().optional(),
9447
- context: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
9448
- messages: import_zod2.z.array(chatMessageSchema)
9509
+ var chatRequestBodySchema = import_zod3.z.looseObject({
9510
+ sessionId: import_zod3.z.string().optional(),
9511
+ clientTurnId: import_zod3.z.string().max(128).optional(),
9512
+ workflowId: import_zod3.z.string().optional(),
9513
+ stream: import_zod3.z.boolean().optional(),
9514
+ context: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional(),
9515
+ messages: import_zod3.z.array(chatMessageSchema)
9449
9516
  });
9450
- var checkpointRequestBodySchema = import_zod2.z.discriminatedUnion("action", [
9451
- import_zod2.z.object({
9452
- action: import_zod2.z.literal("list"),
9453
- sessionId: import_zod2.z.string().min(1)
9517
+ var checkpointRequestBodySchema = import_zod3.z.discriminatedUnion("action", [
9518
+ import_zod3.z.object({
9519
+ action: import_zod3.z.literal("list"),
9520
+ sessionId: import_zod3.z.string().min(1)
9454
9521
  }).strict(),
9455
- import_zod2.z.object({
9456
- action: import_zod2.z.literal("get"),
9457
- checkpointId: import_zod2.z.string().min(1)
9522
+ import_zod3.z.object({
9523
+ action: import_zod3.z.literal("get"),
9524
+ checkpointId: import_zod3.z.string().min(1)
9458
9525
  }).strict(),
9459
- import_zod2.z.object({
9460
- action: import_zod2.z.literal("rollback"),
9461
- checkpointId: import_zod2.z.string().min(1)
9526
+ import_zod3.z.object({
9527
+ action: import_zod3.z.literal("rollback"),
9528
+ checkpointId: import_zod3.z.string().min(1)
9462
9529
  }).strict(),
9463
- import_zod2.z.object({
9464
- action: import_zod2.z.literal("fork"),
9465
- checkpointId: import_zod2.z.string().min(1),
9466
- newSessionId: import_zod2.z.string().min(1).optional()
9530
+ import_zod3.z.object({
9531
+ action: import_zod3.z.literal("fork"),
9532
+ checkpointId: import_zod3.z.string().min(1),
9533
+ newSessionId: import_zod3.z.string().min(1).optional()
9467
9534
  }).strict()
9468
9535
  ]);
9469
9536
  async function readRequestJson(request) {
@@ -9486,10 +9553,10 @@ async function readRequestJson(request) {
9486
9553
  }
9487
9554
  }
9488
9555
  function createFailureResponse(error, status2) {
9489
- const failure2 = (0, import_errors5.serializeFailure)(error);
9556
+ const failure = (0, import_errors5.serializeFailure)(error);
9490
9557
  return Response.json(
9491
- { error: failure2.message, failure: failure2 },
9492
- { status: status2 ?? (0, import_errors5.failureHttpStatus)(failure2) }
9558
+ { error: failure.message, failure },
9559
+ { status: status2 ?? (0, import_errors5.failureHttpStatus)(failure) }
9493
9560
  );
9494
9561
  }
9495
9562
  function parseChatRequestBody(value) {
@@ -9723,7 +9790,7 @@ var import_node_path = require("path");
9723
9790
  var import_core5 = require("@kortyx/core");
9724
9791
  var import_providers = require("@kortyx/providers");
9725
9792
  var import_runtime5 = require("@kortyx/runtime");
9726
- var import_zod5 = require("zod");
9793
+ var import_zod6 = require("zod");
9727
9794
 
9728
9795
  // src/evals/prompt-context.ts
9729
9796
  var import_node_async_hooks = require("async_hooks");
@@ -9733,21 +9800,21 @@ var promptEvaluationContext = new import_node_async_hooks.AsyncLocalStorage();
9733
9800
  var import_core4 = require("@kortyx/core");
9734
9801
  var import_errors6 = require("@kortyx/core/errors");
9735
9802
  var import_runtime3 = require("@kortyx/runtime");
9736
- var import_zod3 = require("zod");
9737
- var handleSchema = import_zod3.z.object({
9738
- token: import_zod3.z.string().min(1),
9739
- requestId: import_zod3.z.string().min(1),
9740
- sessionId: import_zod3.z.string().min(1),
9741
- runId: import_zod3.z.string().min(1)
9803
+ var import_zod4 = require("zod");
9804
+ var handleSchema = import_zod4.z.object({
9805
+ token: import_zod4.z.string().min(1),
9806
+ requestId: import_zod4.z.string().min(1),
9807
+ sessionId: import_zod4.z.string().min(1),
9808
+ runId: import_zod4.z.string().min(1)
9742
9809
  }).strict();
9743
- var responseSchema = import_zod3.z.discriminatedUnion("type", [
9744
- import_zod3.z.object({ type: import_zod3.z.literal("text"), text: import_zod3.z.string().min(1) }).strict(),
9745
- import_zod3.z.object({
9746
- type: import_zod3.z.literal("select"),
9747
- ids: import_zod3.z.array(import_zod3.z.string().min(1)).min(1)
9810
+ var responseSchema = import_zod4.z.discriminatedUnion("type", [
9811
+ import_zod4.z.object({ type: import_zod4.z.literal("text"), text: import_zod4.z.string().min(1) }).strict(),
9812
+ import_zod4.z.object({
9813
+ type: import_zod4.z.literal("select"),
9814
+ ids: import_zod4.z.array(import_zod4.z.string().min(1)).min(1)
9748
9815
  }).strict(),
9749
- import_zod3.z.object({ type: import_zod3.z.literal("value"), value: import_zod3.z.unknown() }).strict(),
9750
- import_zod3.z.object({ type: import_zod3.z.literal("cancel") }).strict()
9816
+ import_zod4.z.object({ type: import_zod4.z.literal("value"), value: import_zod4.z.unknown() }).strict(),
9817
+ import_zod4.z.object({ type: import_zod4.z.literal("cancel") }).strict()
9751
9818
  ]);
9752
9819
  function resultFromOutcome(outcome, runId, sessionId) {
9753
9820
  const usage2 = outcome.pending?.schema.meta?.__kortyxResumeStatePatch?.tokenUsage ?? outcome.error?.__kortyxHookStatePatch?.tokenUsage ?? outcome.state.runtime?.tokenUsage;
@@ -9872,7 +9939,7 @@ async function executeWorkflow(services, args) {
9872
9939
  });
9873
9940
  }
9874
9941
  async function resumeWorkflow(services, args) {
9875
- const parsed = import_zod3.z.object({ resume: handleSchema, response: responseSchema }).safeParse(args);
9942
+ const parsed = import_zod4.z.object({ resume: handleSchema, response: responseSchema }).safeParse(args);
9876
9943
  if (!parsed.success)
9877
9944
  throw new ExecutionRequestError("INVALID_RESUME", parsed.error.message);
9878
9945
  const { resume: handle, response } = parsed.data;
@@ -9957,13 +10024,13 @@ async function resumeWorkflow(services, args) {
9957
10024
  }
9958
10025
 
9959
10026
  // src/interrupt/discovery.ts
9960
- var import_zod4 = require("zod");
9961
- var scopeSchema = import_zod4.z.object({
9962
- sessionId: import_zod4.z.string().min(1).optional(),
9963
- runId: import_zod4.z.string().min(1).optional(),
9964
- context: import_zod4.z.record(
9965
- import_zod4.z.string(),
9966
- import_zod4.z.union([import_zod4.z.string(), import_zod4.z.number(), import_zod4.z.boolean(), import_zod4.z.null()])
10027
+ var import_zod5 = require("zod");
10028
+ var scopeSchema = import_zod5.z.object({
10029
+ sessionId: import_zod5.z.string().min(1).optional(),
10030
+ runId: import_zod5.z.string().min(1).optional(),
10031
+ context: import_zod5.z.record(
10032
+ import_zod5.z.string(),
10033
+ import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number(), import_zod5.z.boolean(), import_zod5.z.null()])
9967
10034
  ).optional()
9968
10035
  }).strict().refine(
9969
10036
  (scope) => Boolean(
@@ -10011,15 +10078,15 @@ function createInterruptDiscovery(store) {
10011
10078
  status: _status,
10012
10079
  afterResponseCompleted,
10013
10080
  ...scope
10014
- } = import_zod4.z.object({
10015
- sessionId: import_zod4.z.string().optional(),
10016
- runId: import_zod4.z.string().optional(),
10017
- context: import_zod4.z.record(
10018
- import_zod4.z.string(),
10019
- import_zod4.z.union([import_zod4.z.string(), import_zod4.z.number(), import_zod4.z.boolean(), import_zod4.z.null()])
10081
+ } = import_zod5.z.object({
10082
+ sessionId: import_zod5.z.string().optional(),
10083
+ runId: import_zod5.z.string().optional(),
10084
+ context: import_zod5.z.record(
10085
+ import_zod5.z.string(),
10086
+ import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number(), import_zod5.z.boolean(), import_zod5.z.null()])
10020
10087
  ).optional(),
10021
- status: import_zod4.z.literal("pending").optional(),
10022
- afterResponseCompleted: import_zod4.z.boolean().optional()
10088
+ status: import_zod5.z.literal("pending").optional(),
10089
+ afterResponseCompleted: import_zod5.z.boolean().optional()
10023
10090
  }).strict().parse(options);
10024
10091
  scopeSchema.parse(scope);
10025
10092
  return (await records()).filter(
@@ -10029,7 +10096,7 @@ function createInterruptDiscovery(store) {
10029
10096
  ).map(summary);
10030
10097
  },
10031
10098
  async getInterrupt(id3, scope) {
10032
- import_zod4.z.string().min(1).parse(id3);
10099
+ import_zod5.z.string().min(1).parse(id3);
10033
10100
  scopeSchema.parse(scope);
10034
10101
  const record = (await records()).find(
10035
10102
  (record2) => record2.requestId === id3 && matches(record2, scope)
@@ -10153,10 +10220,10 @@ var import_errors7 = require("@kortyx/core/errors");
10153
10220
  var import_runtime4 = require("@kortyx/runtime");
10154
10221
 
10155
10222
  // src/utils/extract-latest-message.ts
10156
- function extractLatestUserMessage(messages) {
10157
- if (!messages || messages.length === 0) return "";
10158
- for (let i = messages.length - 1; i >= 0; i -= 1) {
10159
- const msg = messages[i];
10223
+ function extractLatestUserMessage(messages2) {
10224
+ if (!messages2 || messages2.length === 0) return "";
10225
+ for (let i = messages2.length - 1; i >= 0; i -= 1) {
10226
+ const msg = messages2[i];
10160
10227
  if (msg?.role === "user" && msg?.content?.trim()) {
10161
10228
  return msg.content.trim();
10162
10229
  }
@@ -10166,7 +10233,7 @@ function extractLatestUserMessage(messages) {
10166
10233
 
10167
10234
  // src/chat/process-chat.ts
10168
10235
  async function streamChat({
10169
- messages,
10236
+ messages: messages2,
10170
10237
  abortSignal,
10171
10238
  executionSignal,
10172
10239
  onExecution,
@@ -10211,9 +10278,9 @@ async function streamChat({
10211
10278
  runtimeConfig2.selectWorkflow = workflowSelector;
10212
10279
  const fallbackSessionId = options?.sessionId;
10213
10280
  const resolvedSessionId = sessionId || fallbackSessionId || "anonymous-session";
10214
- const last = messages[messages.length - 1];
10215
- const input = extractLatestUserMessage(messages);
10216
- const previousMessages = messages.slice(0, -1);
10281
+ const last = messages2[messages2.length - 1];
10282
+ const input = extractLatestUserMessage(messages2);
10283
+ const previousMessages = messages2.slice(0, -1);
10217
10284
  const runtime = {
10218
10285
  ...previousMessages.length > 0 ? { priorMessages: previousMessages } : {}
10219
10286
  };
@@ -10326,30 +10393,30 @@ async function streamChat({
10326
10393
  }
10327
10394
 
10328
10395
  // src/chat/create-agent.ts
10329
- var agentProcessOptionsSchema = import_zod5.z.object({
10330
- executionSignal: import_zod5.z.custom((value) => value instanceof AbortSignal).optional(),
10331
- onExecution: import_zod5.z.custom(
10396
+ var agentProcessOptionsSchema = import_zod6.z.object({
10397
+ executionSignal: import_zod6.z.custom((value) => value instanceof AbortSignal).optional(),
10398
+ onExecution: import_zod6.z.custom(
10332
10399
  (value) => typeof value === "function"
10333
10400
  ).optional(),
10334
- clientTurnId: import_zod5.z.string().min(1).max(128).optional(),
10335
- continueOnDisconnect: import_zod5.z.boolean().optional(),
10336
- onResponseFinalized: import_zod5.z.custom((value) => typeof value === "function").optional(),
10401
+ clientTurnId: import_zod6.z.string().min(1).max(128).optional(),
10402
+ continueOnDisconnect: import_zod6.z.boolean().optional(),
10403
+ onResponseFinalized: import_zod6.z.custom((value) => typeof value === "function").optional(),
10337
10404
  limits: import_core5.ExecutionLimitsSchema.optional(),
10338
- abortSignal: import_zod5.z.custom((value) => value instanceof AbortSignal).optional(),
10339
- sessionId: import_zod5.z.string().optional(),
10340
- workflowId: import_zod5.z.string().optional(),
10341
- context: import_zod5.z.record(import_zod5.z.string(), import_zod5.z.unknown()).optional()
10405
+ abortSignal: import_zod6.z.custom((value) => value instanceof AbortSignal).optional(),
10406
+ sessionId: import_zod6.z.string().optional(),
10407
+ workflowId: import_zod6.z.string().optional(),
10408
+ context: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.unknown()).optional()
10342
10409
  }).strict();
10343
- var createAgentArgsBaseSchema = import_zod5.z.object({
10410
+ var createAgentArgsBaseSchema = import_zod6.z.object({
10344
10411
  limits: import_core5.ExecutionLimitsSchema.optional(),
10345
- getProvider: import_zod5.z.unknown().optional(),
10346
- workflows: import_zod5.z.array(import_zod5.z.unknown()).optional(),
10347
- workflowsDir: import_zod5.z.string().optional(),
10348
- workflowRegistry: import_zod5.z.unknown().optional(),
10349
- defaultWorkflowId: import_zod5.z.string().optional(),
10350
- frameworkAdapter: import_zod5.z.unknown().optional(),
10351
- telemetry: import_zod5.z.unknown().optional(),
10352
- prompts: import_zod5.z.unknown().optional()
10412
+ getProvider: import_zod6.z.unknown().optional(),
10413
+ workflows: import_zod6.z.array(import_zod6.z.unknown()).optional(),
10414
+ workflowsDir: import_zod6.z.string().optional(),
10415
+ workflowRegistry: import_zod6.z.unknown().optional(),
10416
+ defaultWorkflowId: import_zod6.z.string().optional(),
10417
+ frameworkAdapter: import_zod6.z.unknown().optional(),
10418
+ telemetry: import_zod6.z.unknown().optional(),
10419
+ prompts: import_zod6.z.unknown().optional()
10353
10420
  }).strict();
10354
10421
  var createAgentArgsSchema = createAgentArgsBaseSchema.superRefine(
10355
10422
  (value, ctx) => {
@@ -10451,7 +10518,22 @@ function createAgentInternal(args) {
10451
10518
  (registry) => registry?.list?.()
10452
10519
  );
10453
10520
  void registeredWorkflowsPromise.then(
10454
- () => registryUsage.end(),
10521
+ (registered) => {
10522
+ try {
10523
+ registryUsage.end(
10524
+ "success",
10525
+ registered ? {
10526
+ data_reducers: registered.some(
10527
+ (workflow) => Object.values(workflow.reduce ?? {}).some(
10528
+ (callback) => typeof callback === "function"
10529
+ )
10530
+ )
10531
+ } : {}
10532
+ );
10533
+ } catch {
10534
+ registryUsage.end();
10535
+ }
10536
+ },
10455
10537
  (error) => registryUsage.fail(error)
10456
10538
  );
10457
10539
  const projectTopology = async (options) => {
@@ -10467,7 +10549,7 @@ function createAgentInternal(args) {
10467
10549
  })
10468
10550
  );
10469
10551
  };
10470
- const streamChatInternal = async (messages, options) => {
10552
+ const streamChatInternal = async (messages2, options) => {
10471
10553
  const parsedOptions = parseAgentProcessOptions(options);
10472
10554
  const promptEvaluation = promptEvaluationContext.getStore();
10473
10555
  if (promptEvaluation && !prompts)
@@ -10486,7 +10568,7 @@ function createAgentInternal(args) {
10486
10568
  );
10487
10569
  return streamChat({
10488
10570
  ...resolvedDefaultWorkflowId ? { defaultWorkflowId: resolvedDefaultWorkflowId } : {},
10489
- messages,
10571
+ messages: messages2,
10490
10572
  abortSignal: parsedOptions?.abortSignal,
10491
10573
  executionSignal: parsedOptions?.executionSignal,
10492
10574
  onExecution: parsedOptions?.onExecution,
@@ -10524,9 +10606,9 @@ function createAgentInternal(args) {
10524
10606
  })
10525
10607
  });
10526
10608
  };
10527
- const streamChat2 = (messages, options) => usage.measure(
10609
+ const streamChat2 = (messages2, options) => usage.measure(
10528
10610
  "sdk.chat.admission",
10529
- () => streamChatInternal(messages, options),
10611
+ () => streamChatInternal(messages2, options),
10530
10612
  {
10531
10613
  phase: "admission",
10532
10614
  continue_on_disconnect: options?.continueOnDisconnect === true
@@ -10682,6 +10764,12 @@ function createAgentInternal(args) {
10682
10764
  ));
10683
10765
  return {
10684
10766
  ...createInterruptDiscovery(resolvedFrameworkAdapter.pendingRequests),
10767
+ reportError: (error, options) => {
10768
+ try {
10769
+ return telemetry?.trace?.reportError?.(error, options);
10770
+ } catch {
10771
+ }
10772
+ },
10685
10773
  execute,
10686
10774
  resume,
10687
10775
  projectTopology,
@@ -10689,8 +10777,8 @@ function createAgentInternal(args) {
10689
10777
  describePromptContracts: () => (prompts?.definitions ?? []).map((ref) => ({
10690
10778
  id: ref.id,
10691
10779
  format: ref.format,
10692
- variablesSchema: import_zod5.z.toJSONSchema(ref.variables, { io: "input" }),
10693
- configSchema: import_zod5.z.toJSONSchema(ref.config, { io: "input" })
10780
+ variablesSchema: import_zod6.z.toJSONSchema(ref.variables, { io: "input" }),
10781
+ configSchema: import_zod6.z.toJSONSchema(ref.config, { io: "input" })
10694
10782
  })),
10695
10783
  listCheckpoints,
10696
10784
  getCheckpoint,
@@ -10720,11 +10808,12 @@ function createAgent(args) {
10720
10808
  }
10721
10809
 
10722
10810
  // src/evals/contracts.ts
10811
+ var import_errors8 = require("@kortyx/core/errors");
10723
10812
  var import_browser2 = require("@kortyx/prompts/browser");
10724
- var import_zod7 = require("zod");
10813
+ var import_zod8 = require("zod");
10725
10814
 
10726
10815
  // src/evals/evidence-policy.ts
10727
- var import_zod6 = require("zod");
10816
+ var import_zod7 = require("zod");
10728
10817
  var EVAL_EVIDENCE_EVENT_TYPES = [
10729
10818
  "tool-call-start",
10730
10819
  "tool-call-result",
@@ -10737,19 +10826,19 @@ var EVAL_EVIDENCE_EVENT_TYPES = [
10737
10826
  "cancelled",
10738
10827
  "limit-reached"
10739
10828
  ];
10740
- var id = import_zod6.z.string().trim().min(1).max(256);
10741
- var filter = import_zod6.z.object({ using: id, params: import_zod6.z.json().optional() }).strict();
10742
- var EvalEvidencePolicySchema = import_zod6.z.object({
10743
- history: import_zod6.z.boolean().optional(),
10744
- events: import_zod6.z.union([
10745
- import_zod6.z.literal(false),
10746
- import_zod6.z.array(import_zod6.z.enum(EVAL_EVIDENCE_EVENT_TYPES)),
10829
+ var id = import_zod7.z.string().trim().min(1).max(256);
10830
+ var filter = import_zod7.z.object({ using: id, params: import_zod7.z.json().optional() }).strict();
10831
+ var EvalEvidencePolicySchema = import_zod7.z.object({
10832
+ history: import_zod7.z.boolean().optional(),
10833
+ events: import_zod7.z.union([
10834
+ import_zod7.z.literal(false),
10835
+ import_zod7.z.array(import_zod7.z.enum(EVAL_EVIDENCE_EVENT_TYPES)),
10747
10836
  filter
10748
10837
  ]).optional(),
10749
- outputs: import_zod6.z.union([
10750
- import_zod6.z.literal(false),
10751
- import_zod6.z.array(
10752
- import_zod6.z.object({
10838
+ outputs: import_zod7.z.union([
10839
+ import_zod7.z.literal(false),
10840
+ import_zod7.z.array(
10841
+ import_zod7.z.object({
10753
10842
  dataType: id.optional(),
10754
10843
  schemaId: id.optional(),
10755
10844
  schemaVersion: id.optional()
@@ -10762,26 +10851,29 @@ var EvalEvidencePolicySchema = import_zod6.z.object({
10762
10851
  }).strict();
10763
10852
 
10764
10853
  // src/evals/contracts.ts
10765
- var id2 = import_zod7.z.string().trim().min(1).max(256);
10766
- var handler = import_zod7.z.object({ using: id2, params: import_zod7.z.json().optional() }).strict();
10767
- var EvalResumeResponseSchema = import_zod7.z.discriminatedUnion("type", [
10768
- import_zod7.z.object({ type: import_zod7.z.literal("text"), text: import_zod7.z.string() }).strict(),
10769
- import_zod7.z.object({ type: import_zod7.z.literal("select"), ids: import_zod7.z.array(import_zod7.z.string()) }).strict(),
10770
- import_zod7.z.object({ type: import_zod7.z.literal("value"), value: import_zod7.z.json() }).strict(),
10771
- import_zod7.z.object({ type: import_zod7.z.literal("cancel") }).strict()
10854
+ var id2 = import_zod8.z.string().trim().min(1).max(256);
10855
+ var failureDescriptor = import_zod8.z.custom(import_errors8.isFailureDescriptor).transform(
10856
+ (value) => JSON.parse(JSON.stringify((0, import_errors8.serializeFailure)(value)))
10857
+ );
10858
+ var handler = import_zod8.z.object({ using: id2, params: import_zod8.z.json().optional() }).strict();
10859
+ var EvalResumeResponseSchema = import_zod8.z.discriminatedUnion("type", [
10860
+ import_zod8.z.object({ type: import_zod8.z.literal("text"), text: import_zod8.z.string() }).strict(),
10861
+ import_zod8.z.object({ type: import_zod8.z.literal("select"), ids: import_zod8.z.array(import_zod8.z.string()) }).strict(),
10862
+ import_zod8.z.object({ type: import_zod8.z.literal("value"), value: import_zod8.z.json() }).strict(),
10863
+ import_zod8.z.object({ type: import_zod8.z.literal("cancel") }).strict()
10772
10864
  ]);
10773
- var expectation = import_zod7.z.object({
10774
- type: import_zod7.z.enum(["answer", "interrupt"]),
10865
+ var expectation = import_zod8.z.object({
10866
+ type: import_zod8.z.enum(["answer", "interrupt"]),
10775
10867
  schemaId: id2.optional(),
10776
10868
  schemaVersion: id2.optional(),
10777
- outputs: import_zod7.z.array(import_zod7.z.object({ schemaId: id2, schemaVersion: id2.optional() }).strict()).optional(),
10778
- criteria: import_zod7.z.array(
10779
- import_zod7.z.union([
10780
- import_zod7.z.string().trim().min(1),
10781
- import_zod7.z.object({ id: id2, text: import_zod7.z.string().trim().min(1) }).strict()
10869
+ outputs: import_zod8.z.array(import_zod8.z.object({ schemaId: id2, schemaVersion: id2.optional() }).strict()).optional(),
10870
+ criteria: import_zod8.z.array(
10871
+ import_zod8.z.union([
10872
+ import_zod8.z.string().trim().min(1),
10873
+ import_zod8.z.object({ id: id2, text: import_zod8.z.string().trim().min(1) }).strict()
10782
10874
  ])
10783
10875
  ).optional(),
10784
- reference: import_zod7.z.json().optional()
10876
+ reference: import_zod8.z.json().optional()
10785
10877
  }).strict().superRefine((value, ctx) => {
10786
10878
  if (value.type === "answer" && (value.schemaId || value.schemaVersion))
10787
10879
  ctx.addIssue({
@@ -10797,21 +10889,21 @@ var expectation = import_zod7.z.object({
10797
10889
  message: "Criterion IDs must be unique within a step."
10798
10890
  });
10799
10891
  });
10800
- var EvalSuiteSchema = import_zod7.z.object({
10892
+ var EvalSuiteSchema = import_zod8.z.object({
10801
10893
  evidence: EvalEvidencePolicySchema.optional(),
10802
10894
  id: id2,
10803
- name: import_zod7.z.string().optional(),
10804
- cases: import_zod7.z.array(
10805
- import_zod7.z.object({
10895
+ name: import_zod8.z.string().optional(),
10896
+ cases: import_zod8.z.array(
10897
+ import_zod8.z.object({
10806
10898
  id: id2,
10807
- name: import_zod7.z.string().optional(),
10808
- params: import_zod7.z.json().optional(),
10899
+ name: import_zod8.z.string().optional(),
10900
+ params: import_zod8.z.json().optional(),
10809
10901
  workflowId: id2.optional(),
10810
- steps: import_zod7.z.array(
10811
- import_zod7.z.union([
10812
- import_zod7.z.object({ message: import_zod7.z.string().min(1), expect: expectation }).strict(),
10813
- import_zod7.z.object({
10814
- resume: import_zod7.z.union([EvalResumeResponseSchema, handler]),
10902
+ steps: import_zod8.z.array(
10903
+ import_zod8.z.union([
10904
+ import_zod8.z.object({ message: import_zod8.z.string().min(1), expect: expectation }).strict(),
10905
+ import_zod8.z.object({
10906
+ resume: import_zod8.z.union([EvalResumeResponseSchema, handler]),
10815
10907
  expect: expectation
10816
10908
  }).strict()
10817
10909
  ])
@@ -10819,42 +10911,44 @@ var EvalSuiteSchema = import_zod7.z.object({
10819
10911
  }).strict()
10820
10912
  ).min(1)
10821
10913
  }).strict();
10822
- var EvalVerdictSchema = import_zod7.z.object({
10823
- passed: import_zod7.z.boolean(),
10824
- reason: import_zod7.z.string().trim().min(1),
10825
- evidence: import_zod7.z.array(import_zod7.z.string().min(1))
10914
+ var EvalVerdictSchema = import_zod8.z.object({
10915
+ passed: import_zod8.z.boolean(),
10916
+ reason: import_zod8.z.string().trim().min(1),
10917
+ evidence: import_zod8.z.array(import_zod8.z.string().min(1))
10826
10918
  }).strict();
10827
- var EvalObservationSchema = import_zod7.z.object({
10828
- promptUsage: import_zod7.z.array(
10829
- import_zod7.z.object({
10830
- id: import_zod7.z.string(),
10831
- version: import_zod7.z.number().int().positive(),
10832
- hash: import_zod7.z.string().regex(/^[a-f0-9]{64}$/),
10833
- environment: import_zod7.z.string(),
10834
- snapshotRevision: import_zod7.z.string(),
10835
- model: import_zod7.z.string().optional()
10919
+ var EvalObservationSchema = import_zod8.z.object({
10920
+ failure: failureDescriptor.optional(),
10921
+ diagnosticId: import_zod8.z.uuid().optional(),
10922
+ promptUsage: import_zod8.z.array(
10923
+ import_zod8.z.object({
10924
+ id: import_zod8.z.string(),
10925
+ version: import_zod8.z.number().int().positive(),
10926
+ hash: import_zod8.z.string().regex(/^[a-f0-9]{64}$/),
10927
+ environment: import_zod8.z.string(),
10928
+ snapshotRevision: import_zod8.z.string(),
10929
+ model: import_zod8.z.string().optional()
10836
10930
  }).strict()
10837
10931
  ).optional(),
10838
- type: import_zod7.z.enum(["answer", "interrupt", "error", "cancelled"]),
10839
- text: import_zod7.z.string(),
10840
- structured: import_zod7.z.array(import_zod7.z.json()),
10841
- events: import_zod7.z.array(import_zod7.z.json()).optional(),
10842
- runId: import_zod7.z.string().optional(),
10843
- checkpointId: import_zod7.z.string().optional(),
10844
- interrupt: import_zod7.z.object({
10845
- requestId: import_zod7.z.string(),
10846
- kind: import_zod7.z.enum(["text", "choice", "multi-choice", "custom"]),
10847
- question: import_zod7.z.string().optional(),
10848
- schemaId: import_zod7.z.string().optional(),
10849
- schemaVersion: import_zod7.z.string().optional(),
10850
- options: import_zod7.z.array(
10851
- import_zod7.z.object({
10852
- id: import_zod7.z.string(),
10853
- label: import_zod7.z.string(),
10854
- description: import_zod7.z.string().optional()
10932
+ type: import_zod8.z.enum(["answer", "interrupt", "error", "cancelled"]),
10933
+ text: import_zod8.z.string(),
10934
+ structured: import_zod8.z.array(import_zod8.z.json()),
10935
+ events: import_zod8.z.array(import_zod8.z.json()).optional(),
10936
+ runId: import_zod8.z.string().optional(),
10937
+ checkpointId: import_zod8.z.string().optional(),
10938
+ interrupt: import_zod8.z.object({
10939
+ requestId: import_zod8.z.string(),
10940
+ kind: import_zod8.z.enum(["text", "choice", "multi-choice", "custom"]),
10941
+ question: import_zod8.z.string().optional(),
10942
+ schemaId: import_zod8.z.string().optional(),
10943
+ schemaVersion: import_zod8.z.string().optional(),
10944
+ options: import_zod8.z.array(
10945
+ import_zod8.z.object({
10946
+ id: import_zod8.z.string(),
10947
+ label: import_zod8.z.string(),
10948
+ description: import_zod8.z.string().optional()
10855
10949
  }).strict()
10856
10950
  ),
10857
- request: import_zod7.z.json().optional()
10951
+ request: import_zod8.z.json().optional()
10858
10952
  }).strict().optional()
10859
10953
  }).strict().superRefine((value, ctx) => {
10860
10954
  if (value.type === "interrupt" !== Boolean(value.interrupt))
@@ -10863,195 +10957,211 @@ var EvalObservationSchema = import_zod7.z.object({
10863
10957
  message: "Interrupt observations require exactly one interrupt."
10864
10958
  });
10865
10959
  });
10866
- var status = import_zod7.z.enum(["passed", "failed", "error", "cancelled", "ungraded"]);
10867
- var issue = import_zod7.z.object({
10868
- phase: import_zod7.z.enum([
10960
+ var status = import_zod8.z.enum(["passed", "failed", "error", "cancelled", "ungraded"]);
10961
+ var EvalIssueSchema = import_zod8.z.object({
10962
+ failure: failureDescriptor.optional(),
10963
+ diagnosticId: import_zod8.z.uuid().optional(),
10964
+ phase: import_zod8.z.enum([
10869
10965
  "params",
10870
10966
  "setup",
10871
10967
  "execute",
10872
10968
  "responder",
10873
10969
  "reference",
10874
10970
  "grading",
10971
+ "verification",
10875
10972
  "cleanup",
10876
10973
  "reporting"
10877
10974
  ]),
10878
- code: import_zod7.z.string(),
10879
- message: import_zod7.z.string()
10975
+ code: import_zod8.z.string(),
10976
+ message: import_zod8.z.string()
10880
10977
  }).strict();
10881
- var EvalJudgeUsageSchema = import_zod7.z.object({
10882
- provider: import_zod7.z.string().min(1),
10883
- model: import_zod7.z.string().min(1),
10884
- occurredAt: import_zod7.z.iso.datetime(),
10885
- usage: import_zod7.z.object({
10886
- input: import_zod7.z.number().finite().nonnegative().optional(),
10887
- output: import_zod7.z.number().finite().nonnegative().optional(),
10888
- total: import_zod7.z.number().finite().nonnegative().optional(),
10889
- reasoning: import_zod7.z.number().finite().nonnegative().optional(),
10890
- cacheRead: import_zod7.z.number().finite().nonnegative().optional(),
10891
- cacheWrite: import_zod7.z.number().finite().nonnegative().optional(),
10892
- cacheWrite1h: import_zod7.z.number().finite().nonnegative().optional(),
10893
- outputIncludesReasoning: import_zod7.z.boolean().optional(),
10894
- inputIncludesCacheRead: import_zod7.z.boolean().optional(),
10895
- inputIncludesCacheWrite: import_zod7.z.boolean().optional()
10978
+ var issue = EvalIssueSchema;
10979
+ var EvalJudgeUsageSchema = import_zod8.z.object({
10980
+ provider: import_zod8.z.string().min(1),
10981
+ model: import_zod8.z.string().min(1),
10982
+ occurredAt: import_zod8.z.iso.datetime(),
10983
+ usage: import_zod8.z.object({
10984
+ input: import_zod8.z.number().finite().nonnegative().optional(),
10985
+ output: import_zod8.z.number().finite().nonnegative().optional(),
10986
+ total: import_zod8.z.number().finite().nonnegative().optional(),
10987
+ reasoning: import_zod8.z.number().finite().nonnegative().optional(),
10988
+ cacheRead: import_zod8.z.number().finite().nonnegative().optional(),
10989
+ cacheWrite: import_zod8.z.number().finite().nonnegative().optional(),
10990
+ cacheWrite1h: import_zod8.z.number().finite().nonnegative().optional(),
10991
+ outputIncludesReasoning: import_zod8.z.boolean().optional(),
10992
+ inputIncludesCacheRead: import_zod8.z.boolean().optional(),
10993
+ inputIncludesCacheWrite: import_zod8.z.boolean().optional()
10896
10994
  }).strict().optional(),
10897
- pricingContext: import_zod7.z.object({
10898
- serviceTier: import_zod7.z.string().min(1).max(100).optional(),
10899
- inferenceGeo: import_zod7.z.string().min(1).max(100).optional(),
10900
- speed: import_zod7.z.string().min(1).max(100).optional()
10995
+ pricingContext: import_zod8.z.object({
10996
+ serviceTier: import_zod8.z.string().min(1).max(100).optional(),
10997
+ inferenceGeo: import_zod8.z.string().min(1).max(100).optional(),
10998
+ speed: import_zod8.z.string().min(1).max(100).optional()
10901
10999
  }).strict().optional(),
10902
- pricing: import_zod7.z.object({
10903
- source: import_zod7.z.literal("provider"),
10904
- currency: import_zod7.z.literal("USD"),
10905
- actualCostMicros: import_zod7.z.number().int().nonnegative().safe()
11000
+ pricing: import_zod8.z.object({
11001
+ source: import_zod8.z.literal("provider"),
11002
+ currency: import_zod8.z.literal("USD"),
11003
+ actualCostMicros: import_zod8.z.number().int().nonnegative().safe()
10906
11004
  }).strict().optional()
10907
11005
  }).strict();
10908
- var EvalStepResultSchema = import_zod7.z.object({
10909
- evidence: import_zod7.z.object({
10910
- version: import_zod7.z.literal("compact-v1"),
10911
- history: import_zod7.z.boolean(),
11006
+ var EvalStepResultSchema = import_zod8.z.object({
11007
+ evidence: import_zod8.z.object({
11008
+ version: import_zod8.z.literal("compact-v1"),
11009
+ history: import_zod8.z.boolean(),
10912
11010
  observation: EvalObservationSchema
10913
11011
  }).strict().optional(),
10914
- index: import_zod7.z.number().int().nonnegative(),
10915
- input: import_zod7.z.union([
10916
- import_zod7.z.object({ message: import_zod7.z.string() }).strict(),
10917
- import_zod7.z.object({ resume: EvalResumeResponseSchema }).strict()
11012
+ index: import_zod8.z.number().int().nonnegative(),
11013
+ input: import_zod8.z.union([
11014
+ import_zod8.z.object({ message: import_zod8.z.string() }).strict(),
11015
+ import_zod8.z.object({ resume: EvalResumeResponseSchema }).strict()
10918
11016
  ]),
10919
11017
  expectation,
10920
11018
  observation: EvalObservationSchema,
10921
- reference: import_zod7.z.json().optional(),
11019
+ reference: import_zod8.z.json().optional(),
10922
11020
  status,
10923
- reason: import_zod7.z.string().optional(),
10924
- judgeCalls: import_zod7.z.number().int().nonnegative().optional(),
10925
- judgeUsage: import_zod7.z.array(EvalJudgeUsageSchema).optional(),
10926
- criteria: import_zod7.z.array(
10927
- EvalVerdictSchema.extend({ id: import_zod7.z.string(), text: import_zod7.z.string() })
11021
+ reason: import_zod8.z.string().optional(),
11022
+ judgeCalls: import_zod8.z.number().int().nonnegative().optional(),
11023
+ judgeUsage: import_zod8.z.array(EvalJudgeUsageSchema).optional(),
11024
+ criteria: import_zod8.z.array(
11025
+ EvalVerdictSchema.extend({ id: import_zod8.z.string(), text: import_zod8.z.string() })
10928
11026
  )
10929
11027
  }).strict();
10930
- var runtimeExecution = import_zod7.z.object({ sessionId: import_zod7.z.string().min(1), runId: import_zod7.z.string().min(1) }).strict();
10931
- var EvalCaseResultSchema = import_zod7.z.object({
11028
+ var runtimeExecution = import_zod8.z.object({ sessionId: import_zod8.z.string().min(1), runId: import_zod8.z.string().min(1) }).strict();
11029
+ var EvalCaseResultSchema = import_zod8.z.object({
11030
+ verification: EvalVerdictSchema.optional(),
11031
+ phaseDurationsMs: import_zod8.z.partialRecord(issue.shape.phase, import_zod8.z.number().finite().nonnegative()).optional(),
10932
11032
  caseId: id2,
10933
- repetition: import_zod7.z.number().int().positive(),
10934
- attemptId: import_zod7.z.uuid().optional(),
10935
- runtimeExecutions: import_zod7.z.array(runtimeExecution).optional(),
10936
- sessionId: import_zod7.z.string(),
11033
+ repetition: import_zod8.z.number().int().positive(),
11034
+ attemptId: import_zod8.z.uuid().optional(),
11035
+ runtimeExecutions: import_zod8.z.array(runtimeExecution).optional(),
11036
+ sessionId: import_zod8.z.string(),
10937
11037
  status,
10938
- durationMs: import_zod7.z.number().nonnegative(),
10939
- steps: import_zod7.z.array(EvalStepResultSchema),
10940
- errors: import_zod7.z.array(issue)
11038
+ durationMs: import_zod8.z.number().nonnegative(),
11039
+ steps: import_zod8.z.array(EvalStepResultSchema),
11040
+ errors: import_zod8.z.array(issue)
10941
11041
  }).strict();
10942
- var EvalJudgeIdentitySchema = import_zod7.z.object({
11042
+ var EvalJudgeIdentitySchema = import_zod8.z.object({
10943
11043
  id: id2,
10944
11044
  version: id2,
10945
- location: import_zod7.z.enum(["app", "studio"]).optional()
11045
+ location: import_zod8.z.enum(["app", "studio"]).optional()
10946
11046
  }).strict();
10947
11047
  var judge = EvalJudgeIdentitySchema;
10948
- var StudioEvalJudgeRequestSchema = import_zod7.z.object({
11048
+ var StudioEvalJudgeRequestSchema = import_zod8.z.object({
10949
11049
  environment: id2,
10950
11050
  judge: EvalJudgeIdentitySchema,
10951
- criterion: import_zod7.z.object({ id: id2, text: import_zod7.z.string().trim().min(1).max(16384) }).strict(),
11051
+ criterion: import_zod8.z.object({ id: id2, text: import_zod8.z.string().trim().min(1).max(16384) }).strict(),
10952
11052
  input: EvalStepResultSchema.shape.input,
10953
11053
  observation: EvalObservationSchema,
10954
- reference: import_zod7.z.json().optional(),
10955
- conversation: import_zod7.z.array(EvalStepResultSchema).max(100)
11054
+ reference: import_zod8.z.json().optional(),
11055
+ conversation: import_zod8.z.array(EvalStepResultSchema).max(100)
10956
11056
  }).strict();
10957
- var StudioEvalJudgeResponseSchema = import_zod7.z.object({
11057
+ var StudioEvalJudgeResponseSchema = import_zod8.z.object({
10958
11058
  judge: EvalJudgeIdentitySchema,
10959
11059
  verdict: EvalVerdictSchema,
10960
- usage: import_zod7.z.array(EvalJudgeUsageSchema).optional()
11060
+ usage: import_zod8.z.array(EvalJudgeUsageSchema).optional()
10961
11061
  }).strict();
10962
- var EvalRunResultSchema = import_zod7.z.object({
10963
- id: import_zod7.z.uuid(),
11062
+ var EvalRunResultSchema = import_zod8.z.object({
11063
+ id: import_zod8.z.uuid(),
10964
11064
  suiteId: id2,
10965
- suiteRevision: import_zod7.z.string().regex(/^[a-f0-9]{64}$/),
11065
+ suiteRevision: import_zod8.z.string().regex(/^[a-f0-9]{64}$/),
10966
11066
  suite: EvalSuiteSchema,
10967
11067
  judge: judge.optional(),
10968
- startedAt: import_zod7.z.iso.datetime(),
10969
- durationMs: import_zod7.z.number().nonnegative(),
11068
+ startedAt: import_zod8.z.iso.datetime(),
11069
+ durationMs: import_zod8.z.number().nonnegative(),
10970
11070
  status,
10971
- counts: import_zod7.z.object({
10972
- passed: import_zod7.z.number().int().nonnegative(),
10973
- failed: import_zod7.z.number().int().nonnegative(),
10974
- error: import_zod7.z.number().int().nonnegative(),
10975
- cancelled: import_zod7.z.number().int().nonnegative(),
10976
- ungraded: import_zod7.z.number().int().nonnegative().optional()
11071
+ counts: import_zod8.z.object({
11072
+ passed: import_zod8.z.number().int().nonnegative(),
11073
+ failed: import_zod8.z.number().int().nonnegative(),
11074
+ error: import_zod8.z.number().int().nonnegative(),
11075
+ cancelled: import_zod8.z.number().int().nonnegative(),
11076
+ ungraded: import_zod8.z.number().int().nonnegative().optional()
10977
11077
  }).strict(),
10978
- cases: import_zod7.z.array(EvalCaseResultSchema),
10979
- errors: import_zod7.z.array(issue)
11078
+ cases: import_zod8.z.array(EvalCaseResultSchema),
11079
+ errors: import_zod8.z.array(issue)
10980
11080
  }).strict();
10981
- var EvalManifestSchema = import_zod7.z.object({
10982
- schemaVersion: import_zod7.z.literal(1),
10983
- studioJudging: import_zod7.z.literal(true).optional(),
10984
- promptContracts: import_zod7.z.array(
10985
- import_zod7.z.object({
10986
- id: import_zod7.z.string(),
10987
- format: import_zod7.z.enum(["system-user", "chat"]),
10988
- variablesSchema: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.unknown()),
10989
- configSchema: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.unknown())
11081
+ var EvalManifestSchema = import_zod8.z.object({
11082
+ schemaVersion: import_zod8.z.literal(1),
11083
+ studioJudging: import_zod8.z.literal(true).optional(),
11084
+ promptContracts: import_zod8.z.array(
11085
+ import_zod8.z.object({
11086
+ id: import_zod8.z.string(),
11087
+ format: import_zod8.z.enum(["system-user", "chat"]),
11088
+ variablesSchema: import_zod8.z.record(import_zod8.z.string(), import_zod8.z.unknown()),
11089
+ configSchema: import_zod8.z.record(import_zod8.z.string(), import_zod8.z.unknown())
10990
11090
  }).strict()
10991
11091
  ).optional(),
10992
- attemptScheduling: import_zod7.z.literal(true).optional(),
10993
- suites: import_zod7.z.array(EvalSuiteSchema),
10994
- responders: import_zod7.z.array(
10995
- import_zod7.z.object({
11092
+ attemptScheduling: import_zod8.z.literal(true).optional(),
11093
+ suites: import_zod8.z.array(EvalSuiteSchema),
11094
+ responders: import_zod8.z.array(
11095
+ import_zod8.z.object({
10996
11096
  name: id2,
10997
11097
  schemaId: id2.optional(),
10998
11098
  schemaVersion: id2.optional()
10999
11099
  }).strict()
11000
11100
  ),
11001
- references: import_zod7.z.array(id2),
11002
- paramsSchema: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.unknown()).optional(),
11101
+ references: import_zod8.z.array(id2),
11102
+ paramsSchema: import_zod8.z.record(import_zod8.z.string(), import_zod8.z.unknown()).optional(),
11003
11103
  judge: judge.optional()
11004
11104
  }).strict();
11005
- var EvalProgressSchema = import_zod7.z.discriminatedUnion("type", [
11006
- import_zod7.z.object({
11007
- type: import_zod7.z.literal("case-runtime-associated"),
11105
+ var EvalProgressSchema = import_zod8.z.discriminatedUnion("type", [
11106
+ import_zod8.z.object({
11107
+ type: import_zod8.z.literal("case-dispatch"),
11008
11108
  caseId: id2,
11009
- repetition: import_zod7.z.number().int().positive(),
11010
- attemptId: import_zod7.z.uuid(),
11109
+ repetition: import_zod8.z.number().int().positive(),
11110
+ status: import_zod8.z.enum(["queued", "retrying", "reconnecting"]),
11111
+ retryAt: import_zod8.z.iso.datetime().optional(),
11112
+ httpStatus: import_zod8.z.number().int().min(100).max(599).optional(),
11113
+ executionId: import_zod8.z.uuid().optional(),
11114
+ generation: import_zod8.z.uuid().optional()
11115
+ }).strict(),
11116
+ import_zod8.z.object({
11117
+ type: import_zod8.z.literal("case-runtime-associated"),
11118
+ caseId: id2,
11119
+ repetition: import_zod8.z.number().int().positive(),
11120
+ attemptId: import_zod8.z.uuid(),
11011
11121
  execution: runtimeExecution
11012
11122
  }).strict(),
11013
- import_zod7.z.object({
11014
- type: import_zod7.z.literal("run-started"),
11015
- caseIds: import_zod7.z.array(id2).min(1),
11016
- repetitions: import_zod7.z.number().int().positive(),
11017
- concurrency: import_zod7.z.number().int().positive()
11123
+ import_zod8.z.object({
11124
+ type: import_zod8.z.literal("run-started"),
11125
+ caseIds: import_zod8.z.array(id2).min(1),
11126
+ repetitions: import_zod8.z.number().int().positive(),
11127
+ concurrency: import_zod8.z.number().int().positive()
11018
11128
  }).strict(),
11019
- import_zod7.z.object({
11020
- type: import_zod7.z.literal("case-progress"),
11129
+ import_zod8.z.object({
11130
+ type: import_zod8.z.literal("case-progress"),
11021
11131
  caseId: id2,
11022
- repetition: import_zod7.z.number().int().positive(),
11132
+ repetition: import_zod8.z.number().int().positive(),
11023
11133
  phase: issue.shape.phase,
11024
- stepIndex: import_zod7.z.number().int().nonnegative().optional()
11134
+ stepIndex: import_zod8.z.number().int().nonnegative().optional()
11025
11135
  }).strict(),
11026
- import_zod7.z.object({
11027
- type: import_zod7.z.literal("case-started"),
11028
- attemptId: import_zod7.z.uuid().optional(),
11136
+ import_zod8.z.object({
11137
+ type: import_zod8.z.literal("case-started"),
11138
+ attemptId: import_zod8.z.uuid().optional(),
11029
11139
  caseId: id2,
11030
- repetition: import_zod7.z.number().int().positive(),
11031
- sessionId: import_zod7.z.string()
11140
+ repetition: import_zod8.z.number().int().positive(),
11141
+ sessionId: import_zod8.z.string()
11032
11142
  }).strict(),
11033
- import_zod7.z.object({
11034
- type: import_zod7.z.literal("step-completed"),
11143
+ import_zod8.z.object({
11144
+ type: import_zod8.z.literal("step-completed"),
11035
11145
  caseId: id2,
11036
- repetition: import_zod7.z.number().int().positive(),
11146
+ repetition: import_zod8.z.number().int().positive(),
11037
11147
  step: EvalStepResultSchema
11038
11148
  }).strict(),
11039
- import_zod7.z.object({ type: import_zod7.z.literal("case-completed"), result: EvalCaseResultSchema }).strict()
11149
+ import_zod8.z.object({ type: import_zod8.z.literal("case-completed"), result: EvalCaseResultSchema }).strict()
11040
11150
  ]);
11041
- var EvalRemoteRunRequestSchema = import_zod7.z.object({
11151
+ var EvalRemoteRunRequestSchema = import_zod8.z.object({
11042
11152
  promptSnapshot: import_browser2.PromptSnapshotSchema.optional(),
11043
- promptGroupName: import_zod7.z.string().optional(),
11153
+ promptGroupName: import_zod8.z.string().optional(),
11044
11154
  suiteId: id2,
11045
- suiteRevision: import_zod7.z.string().regex(/^[a-f0-9]{64}$/),
11046
- grading: import_zod7.z.enum(["app", "studio"]).optional(),
11155
+ suiteRevision: import_zod8.z.string().regex(/^[a-f0-9]{64}$/),
11156
+ grading: import_zod8.z.enum(["app", "studio"]).optional(),
11047
11157
  judge: EvalJudgeIdentitySchema.optional(),
11048
- caseIds: import_zod7.z.array(id2).min(1).max(100).optional(),
11049
- repetitions: import_zod7.z.number().int().min(1).max(20).default(1),
11050
- concurrency: import_zod7.z.number().int().min(1).max(20).default(1),
11051
- attempt: import_zod7.z.object({
11158
+ caseIds: import_zod8.z.array(id2).min(1).max(100).optional(),
11159
+ repetitions: import_zod8.z.number().int().min(1).max(20).default(1),
11160
+ concurrency: import_zod8.z.number().int().min(1).max(20).default(1),
11161
+ attempt: import_zod8.z.object({
11052
11162
  caseId: id2,
11053
- repetition: import_zod7.z.number().int().min(1).max(20),
11054
- evaluationId: import_zod7.z.uuid()
11163
+ repetition: import_zod8.z.number().int().min(1).max(20),
11164
+ evaluationId: import_zod8.z.uuid()
11055
11165
  }).strict().optional()
11056
11166
  }).strict();
11057
11167
  var StudioEvalStartRequestSchema = EvalRemoteRunRequestSchema.omit({
@@ -11061,22 +11171,40 @@ var StudioEvalStartRequestSchema = EvalRemoteRunRequestSchema.omit({
11061
11171
  promptGroupName: true,
11062
11172
  attempt: true
11063
11173
  }).extend({
11064
- promptSelection: import_zod7.z.discriminatedUnion("type", [
11065
- import_zod7.z.object({ type: import_zod7.z.literal("live") }).strict(),
11066
- import_zod7.z.object({
11067
- type: import_zod7.z.literal("single"),
11068
- id: import_zod7.z.string(),
11069
- version: import_zod7.z.number().int().positive()
11174
+ promptSelection: import_zod8.z.discriminatedUnion("type", [
11175
+ import_zod8.z.object({ type: import_zod8.z.literal("live") }).strict(),
11176
+ import_zod8.z.object({
11177
+ type: import_zod8.z.literal("single"),
11178
+ id: import_zod8.z.string(),
11179
+ version: import_zod8.z.number().int().positive()
11070
11180
  }).strict(),
11071
- import_zod7.z.object({ type: import_zod7.z.literal("group"), groupId: import_zod7.z.uuid() }).strict()
11181
+ import_zod8.z.object({ type: import_zod8.z.literal("group"), groupId: import_zod8.z.uuid() }).strict()
11072
11182
  ]).optional(),
11073
- targetId: import_zod7.z.string().min(1).max(128),
11074
- judge: import_zod7.z.enum(["studio", "app"]).default("studio")
11183
+ targetId: import_zod8.z.string().min(1).max(128),
11184
+ judge: import_zod8.z.enum(["studio", "app"]).default("studio")
11075
11185
  });
11076
- var EvalWireEventSchema = import_zod7.z.discriminatedUnion("type", [
11077
- import_zod7.z.object({ type: import_zod7.z.literal("progress"), event: EvalProgressSchema }).strict(),
11078
- import_zod7.z.object({ type: import_zod7.z.literal("result"), result: EvalRunResultSchema }).strict(),
11079
- import_zod7.z.object({ type: import_zod7.z.literal("error"), message: import_zod7.z.string() }).strict()
11186
+ var EvalWireEventSchema = import_zod8.z.discriminatedUnion("type", [
11187
+ import_zod8.z.object({
11188
+ type: import_zod8.z.literal("execution-status"),
11189
+ state: import_zod8.z.enum(["queued", "running", "completed", "cancelled", "unknown"])
11190
+ }).strict(),
11191
+ import_zod8.z.object({
11192
+ type: import_zod8.z.literal("progress"),
11193
+ event: EvalProgressSchema,
11194
+ sequence: import_zod8.z.number().int().positive().optional()
11195
+ }).strict(),
11196
+ import_zod8.z.object({
11197
+ type: import_zod8.z.literal("result"),
11198
+ result: EvalRunResultSchema,
11199
+ sequence: import_zod8.z.number().int().positive().optional()
11200
+ }).strict(),
11201
+ import_zod8.z.object({
11202
+ type: import_zod8.z.literal("error"),
11203
+ message: import_zod8.z.string(),
11204
+ failure: failureDescriptor.optional(),
11205
+ diagnosticId: import_zod8.z.uuid().optional(),
11206
+ sequence: import_zod8.z.number().int().positive().optional()
11207
+ }).strict()
11080
11208
  ]);
11081
11209
  var EvalConfigurationError = class extends Error {
11082
11210
  name = "EvalConfigurationError";
@@ -11107,7 +11235,41 @@ function parseEvalSuite(value) {
11107
11235
  var import_node_crypto5 = require("crypto");
11108
11236
  var import_eval_attribution2 = require("@kortyx/core/eval-attribution");
11109
11237
  var import_usage_telemetry = require("@kortyx/usage-telemetry");
11110
- var import_zod8 = require("zod");
11238
+ var import_zod10 = require("zod");
11239
+
11240
+ // src/evals/errors.ts
11241
+ var import_errors9 = require("@kortyx/core/errors");
11242
+ var import_zod9 = require("zod");
11243
+ var messages = {
11244
+ params: "Case parameters failed validation.",
11245
+ setup: "Case setup failed.",
11246
+ execute: "Agent execution failed or returned an invalid observation.",
11247
+ responder: "Interrupt response failed or was incompatible with the waiting contract.",
11248
+ reference: "Reference resolution failed or returned non-JSON data.",
11249
+ grading: "Grading failed or returned an invalid verdict.",
11250
+ verification: "Case verification failed or returned an invalid verdict.",
11251
+ cleanup: "Case cleanup failed.",
11252
+ reporting: "Progress reporting failed."
11253
+ };
11254
+ function createEvalIssue(phase, error, options = {}) {
11255
+ const control = (0, import_errors9.isControlFlowError)(error);
11256
+ const declared = !control && ((0, import_errors9.isFailureDescriptor)(error) || (0, import_errors9.isFailureDescriptor)((0, import_errors9.errorProperty)(error, "failure")));
11257
+ const failure = (0, import_errors9.serializeFailure)(control ? void 0 : error);
11258
+ let diagnosticId = options.diagnosticId ?? (0, import_errors9.errorProperty)(error, "diagnosticId");
11259
+ if (!control && !diagnosticId && options.reportError) {
11260
+ try {
11261
+ diagnosticId = options.reportError(error, options.correlation);
11262
+ } catch {
11263
+ }
11264
+ }
11265
+ return {
11266
+ phase,
11267
+ code: declared ? failure.code : options.code ?? "EVAL_HOOK_FAILED",
11268
+ message: declared ? failure.message : messages[phase],
11269
+ failure,
11270
+ ...typeof diagnosticId === "string" && import_zod9.z.uuid().safeParse(diagnosticId).success ? { diagnosticId } : {}
11271
+ };
11272
+ }
11111
11273
 
11112
11274
  // src/evals/evidence.ts
11113
11275
  var object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
@@ -11234,10 +11396,12 @@ function canonical(value) {
11234
11396
  var getEvalSuiteRevision = (suite) => (0, import_node_crypto4.createHash)("sha256").update(canonical(suite)).digest("hex");
11235
11397
 
11236
11398
  // src/evals/stream.ts
11399
+ var import_errors11 = require("@kortyx/core/errors");
11237
11400
  var import_prompts = require("@kortyx/prompts");
11238
11401
  var import_stream3 = require("@kortyx/stream");
11239
11402
 
11240
11403
  // src/evals/stream-evidence.ts
11404
+ var import_errors10 = require("@kortyx/core/errors");
11241
11405
  function toEvalJson(value) {
11242
11406
  return JSON.parse(JSON.stringify(value));
11243
11407
  }
@@ -11272,7 +11436,9 @@ function captureEvalEvent(chunk) {
11272
11436
  ...source,
11273
11437
  tool: chunk.tool,
11274
11438
  toolCallId: chunk.toolCallId,
11275
- message: chunk.message
11439
+ message: chunk.message,
11440
+ ...chunk.failure ? { failure: (0, import_errors10.serializeFailure)(chunk.failure) } : {},
11441
+ ...chunk.diagnosticId ? { diagnosticId: chunk.diagnosticId } : {}
11276
11442
  });
11277
11443
  case "tool-result":
11278
11444
  return toEvalJson({
@@ -11348,7 +11514,12 @@ function captureEvalEvent(chunk) {
11348
11514
  case "transition":
11349
11515
  return { type: chunk.type, transitionTo: chunk.transitionTo };
11350
11516
  case "error":
11351
- return { type: chunk.type, message: chunk.message };
11517
+ return toEvalJson({
11518
+ type: chunk.type,
11519
+ message: chunk.failure ? (0, import_errors10.serializeFailure)(chunk.failure).message : chunk.message,
11520
+ ...chunk.failure ? { failure: (0, import_errors10.serializeFailure)(chunk.failure) } : {},
11521
+ ...chunk.diagnosticId ? { diagnosticId: chunk.diagnosticId } : {}
11522
+ });
11352
11523
  case "cancelled":
11353
11524
  return toEvalJson({
11354
11525
  type: chunk.type,
@@ -11402,14 +11573,14 @@ async function executeEvalChat(args) {
11402
11573
  return { observation: { type: "cancelled", text: "", structured: [] } };
11403
11574
  }
11404
11575
  const pending = waiting?.[0];
11405
- const messages = [...args.messages ?? args.history];
11576
+ const messages2 = [...args.messages ?? args.history];
11406
11577
  if (args.command.type === "message")
11407
- messages.push({ role: "user", content: args.command.message });
11578
+ messages2.push({ role: "user", content: args.command.message });
11408
11579
  else {
11409
11580
  if (!pending?.resumeToken || !pending.requestId)
11410
11581
  throw new Error("No waiting interrupt to resume.");
11411
11582
  const response = args.command.type === "cancel" ? { type: "cancel" } : args.command.response;
11412
- messages.push({
11583
+ messages2.push({
11413
11584
  role: "user",
11414
11585
  content: response.type === "text" ? response.text : response.type === "select" ? response.ids.join(", ") : response.type === "value" ? JSON.stringify(response.value) : "",
11415
11586
  metadata: {
@@ -11431,6 +11602,7 @@ async function executeEvalChat(args) {
11431
11602
  const events = [];
11432
11603
  let previousChunk;
11433
11604
  let error = false;
11605
+ let terminalFailure;
11434
11606
  let cancelled = false;
11435
11607
  let sawDone = false;
11436
11608
  let completedWithData = false;
@@ -11452,7 +11624,7 @@ async function executeEvalChat(args) {
11452
11624
  ...args.context ? { context: args.context } : {}
11453
11625
  };
11454
11626
  try {
11455
- for await (const chunk of await args.agent.streamChat(messages, options)) {
11627
+ for await (const chunk of await args.agent.streamChat(messages2, options)) {
11456
11628
  accumulator.apply(chunk);
11457
11629
  const event = captureEvalEvent(chunk);
11458
11630
  if (event !== void 0) {
@@ -11466,7 +11638,13 @@ async function executeEvalChat(args) {
11466
11638
  }
11467
11639
  previousChunk = chunk;
11468
11640
  if (chunk.type === "interrupt") interrupts.set(chunk.requestId, chunk);
11469
- if (chunk.type === "error") error = true;
11641
+ if (chunk.type === "error") {
11642
+ error = true;
11643
+ terminalFailure = {
11644
+ ...chunk.failure ? { failure: (0, import_errors11.serializeFailure)(chunk.failure) } : {},
11645
+ ...chunk.diagnosticId ? { diagnosticId: chunk.diagnosticId } : {}
11646
+ };
11647
+ }
11470
11648
  if (chunk.type === "cancelled") cancelled = true;
11471
11649
  if (chunk.type === "trace") runId = chunk.runId;
11472
11650
  if (chunk.type === "done") {
@@ -11486,6 +11664,7 @@ async function executeEvalChat(args) {
11486
11664
  const observedRunId = finalized?.runId ?? runId;
11487
11665
  const type = error || finalized?.status === "failed" || interrupts.size > 1 ? "error" : cancelled || finalized?.status === "cancelled" ? "cancelled" : interrupts.size ? "interrupt" : "answer";
11488
11666
  const observation = {
11667
+ ...terminalFailure,
11489
11668
  type,
11490
11669
  text: message.content,
11491
11670
  structured: message.contentPieces.filter((item) => item.type === "structured").map((item) => toEvalJson(item.data)),
@@ -11527,21 +11706,6 @@ var positive = (value, label) => {
11527
11706
  return value;
11528
11707
  };
11529
11708
  var handlerRef = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && typeof value.using === "string" && Object.keys(value).every((key) => key === "using" || key === "params");
11530
- var phases = {
11531
- params: "Case parameters failed validation.",
11532
- setup: "Case setup failed.",
11533
- execute: "Agent execution failed or returned an invalid observation.",
11534
- responder: "Interrupt response failed or was incompatible with the waiting contract.",
11535
- reference: "Reference resolution failed or returned non-JSON data.",
11536
- grading: "Grading failed or returned an invalid verdict.",
11537
- cleanup: "Case cleanup failed.",
11538
- reporting: "Progress reporting failed."
11539
- };
11540
- var failure = (phase, code = "EVAL_HOOK_FAILED") => ({
11541
- phase,
11542
- code,
11543
- message: phases[phase]
11544
- });
11545
11709
  var statusFor = (counts, errors) => errors.length || counts.error ? "error" : counts.cancelled ? "cancelled" : counts.failed ? "failed" : counts.ungraded ? "ungraded" : "passed";
11546
11710
  function createEvals(options) {
11547
11711
  const defaultEvidence = EvalEvidencePolicySchema.parse(
@@ -11591,11 +11755,25 @@ function createEvals(options) {
11591
11755
  options.defaults?.caseTimeoutMs ?? 6e4,
11592
11756
  "caseTimeoutMs"
11593
11757
  ),
11758
+ setupTimeoutMs: positive(
11759
+ options.defaults?.setupTimeoutMs ?? options.defaults?.caseTimeoutMs ?? 6e4,
11760
+ "setupTimeoutMs"
11761
+ ),
11762
+ verificationTimeoutMs: positive(
11763
+ options.defaults?.verificationTimeoutMs ?? options.defaults?.caseTimeoutMs ?? 6e4,
11764
+ "verificationTimeoutMs"
11765
+ ),
11594
11766
  cleanupTimeoutMs: positive(
11595
11767
  options.defaults?.cleanupTimeoutMs ?? 1e4,
11596
11768
  "cleanupTimeoutMs"
11597
11769
  )
11598
11770
  };
11771
+ const reportError = options.reportError ?? options.agent.reportError?.bind(options.agent);
11772
+ const issueFor = (phase, error, correlation, code) => createEvalIssue(phase, error, {
11773
+ reportError,
11774
+ correlation,
11775
+ ...code ? { code } : {}
11776
+ });
11599
11777
  return {
11600
11778
  listSuites() {
11601
11779
  return clone(suites);
@@ -11616,7 +11794,7 @@ function createEvals(options) {
11616
11794
  })),
11617
11795
  references: Object.keys(references),
11618
11796
  ...options.paramsSchema ? {
11619
- paramsSchema: import_zod8.z.toJSONSchema(options.paramsSchema, {
11797
+ paramsSchema: import_zod10.z.toJSONSchema(options.paramsSchema, {
11620
11798
  io: "input"
11621
11799
  })
11622
11800
  } : {},
@@ -11695,19 +11873,24 @@ function createEvals(options) {
11695
11873
  void 0,
11696
11874
  () => args.onProgress(clone(event))
11697
11875
  );
11698
- } catch {
11876
+ } catch (error) {
11699
11877
  reporting = false;
11700
- result.errors.push(failure("reporting"));
11878
+ result.errors.push(issueFor("reporting", error));
11701
11879
  }
11702
11880
  };
11703
11881
  const attempt = async (item, repetition) => {
11704
11882
  const started = Date.now();
11705
11883
  const controller = new AbortController();
11706
11884
  let timedOut = false;
11707
- const timer = setTimeout(() => {
11708
- timedOut = true;
11709
- controller.abort();
11710
- }, defaults.caseTimeoutMs);
11885
+ let timer;
11886
+ const deadline = (milliseconds) => {
11887
+ clearTimeout(timer);
11888
+ timer = setTimeout(() => {
11889
+ timedOut = true;
11890
+ controller.abort();
11891
+ }, milliseconds);
11892
+ };
11893
+ deadline(defaults.setupTimeoutMs);
11711
11894
  const signal = args.signal ? AbortSignal.any([args.signal, controller.signal]) : controller.signal;
11712
11895
  const attemptId = (0, import_node_crypto5.randomUUID)();
11713
11896
  const runtimeExecutions = [];
@@ -11720,14 +11903,31 @@ function createEvals(options) {
11720
11903
  status: "passed",
11721
11904
  durationMs: 0,
11722
11905
  steps: [],
11723
- errors: []
11906
+ errors: [],
11907
+ phaseDurationsMs: {}
11724
11908
  };
11725
11909
  let associationProgress = Promise.resolve();
11726
11910
  let acceptingExecutions = true;
11727
11911
  const executeAttempt = async () => {
11728
11912
  let phase = "params";
11913
+ let phaseStarted = Date.now();
11914
+ const recordPhase = () => {
11915
+ const now = Date.now();
11916
+ const durations = attemptResult.phaseDurationsMs;
11917
+ durations[phase] = (durations[phase] ?? 0) + now - phaseStarted;
11918
+ phaseStarted = now;
11919
+ };
11920
+ const phaseIssue = (error, code) => issueFor(
11921
+ phase,
11922
+ error,
11923
+ {
11924
+ correlation: { sessionId: attemptResult.sessionId, attemptId }
11925
+ },
11926
+ code
11927
+ );
11729
11928
  let stepIndex;
11730
11929
  const reportPhase = async (next) => {
11930
+ recordPhase();
11731
11931
  phase = next;
11732
11932
  if (args.includeActivity)
11733
11933
  await emit({
@@ -11800,6 +12000,7 @@ function createEvals(options) {
11800
12000
  const prepared = options.setup ? await options.setup(base) : void 0;
11801
12001
  context = { ...base, prepared };
11802
12002
  signal.throwIfAborted();
12003
+ deadline(defaults.caseTimeoutMs);
11803
12004
  for (const [index, step] of item.steps.entries()) {
11804
12005
  stepIndex = index;
11805
12006
  activeStep = void 0;
@@ -11846,8 +12047,22 @@ function createEvals(options) {
11846
12047
  attemptResult.steps.push(evaluated);
11847
12048
  activeStep = evaluated;
11848
12049
  signal.throwIfAborted();
11849
- if (observation.type === "error")
11850
- throw new Error("Agent failed.");
12050
+ if (observation.type === "error") {
12051
+ const issue2 = createEvalIssue("execute", observation.failure, {
12052
+ ...observation.diagnosticId ? { diagnosticId: observation.diagnosticId } : {}
12053
+ });
12054
+ attemptResult.errors.push(issue2);
12055
+ attemptResult.status = evaluated.status = "error";
12056
+ evaluated.reason = issue2.message;
12057
+ await emit({
12058
+ type: "step-completed",
12059
+ caseId: item.id,
12060
+ repetition,
12061
+ step: evaluated
12062
+ });
12063
+ activeStepReported = true;
12064
+ break;
12065
+ }
11851
12066
  if (observation.type === "cancelled") {
11852
12067
  evaluated.status = "cancelled";
11853
12068
  attemptResult.status = "cancelled";
@@ -11875,7 +12090,7 @@ function createEvals(options) {
11875
12090
  const reference = step.expect.reference;
11876
12091
  if (reference !== void 0) {
11877
12092
  await reportPhase("reference");
11878
- evaluated.reference = handlerRef(reference) ? import_zod8.z.json().parse(
12093
+ evaluated.reference = handlerRef(reference) ? import_zod10.z.json().parse(
11879
12094
  await references[reference.using]({
11880
12095
  ...context,
11881
12096
  observation: clone(observation),
@@ -11943,18 +12158,32 @@ function createEvals(options) {
11943
12158
  { role: "assistant", content: observation.text }
11944
12159
  );
11945
12160
  }
11946
- } catch {
12161
+ if (options.verify && attemptResult.status !== "cancelled" && attemptResult.status !== "error") {
12162
+ stepIndex = void 0;
12163
+ deadline(defaults.verificationTimeoutMs);
12164
+ await reportPhase("verification");
12165
+ const verification = EvalVerdictSchema.parse(
12166
+ await options.verify({
12167
+ ...context,
12168
+ result: clone(attemptResult)
12169
+ })
12170
+ );
12171
+ signal.throwIfAborted();
12172
+ attemptResult.verification = verification;
12173
+ if (!verification.passed) attemptResult.status = "failed";
12174
+ }
12175
+ } catch (error) {
11947
12176
  if (signal.aborted) {
11948
12177
  attemptResult.status = timedOut ? "error" : "cancelled";
11949
12178
  if (timedOut)
11950
12179
  attemptResult.errors.push({
11951
- phase,
11952
- code: "EVAL_TIMEOUT",
11953
- message: "Case exceeded its configured time limit."
12180
+ ...phaseIssue(error),
12181
+ code: phase === "params" || phase === "setup" ? "EVAL_SETUP_TIMEOUT" : phase === "verification" ? "EVAL_VERIFICATION_TIMEOUT" : "EVAL_TIMEOUT",
12182
+ message: phase === "params" || phase === "setup" ? "Case setup exceeded its configured time limit." : phase === "verification" ? "Case verification exceeded its configured time limit." : "Case execution exceeded its configured time limit."
11954
12183
  });
11955
12184
  } else {
11956
12185
  attemptResult.status = "error";
11957
- attemptResult.errors.push(failure(phase));
12186
+ attemptResult.errors.push(phaseIssue(error));
11958
12187
  }
11959
12188
  if (activeStep && !activeStepReported) {
11960
12189
  activeStep.status = attemptResult.status;
@@ -11985,12 +12214,21 @@ function createEvals(options) {
11985
12214
  );
11986
12215
  if (cancelled.observation.type === "error" || cancelled.continuation !== void 0)
11987
12216
  attemptResult.errors.push(
11988
- failure("cleanup", "EVAL_INTERRUPT_CLEANUP_FAILED")
12217
+ createEvalIssue(
12218
+ "cleanup",
12219
+ cancelled.observation.failure,
12220
+ {
12221
+ code: "EVAL_INTERRUPT_CLEANUP_FAILED",
12222
+ ...cancelled.observation.diagnosticId ? {
12223
+ diagnosticId: cancelled.observation.diagnosticId
12224
+ } : {}
12225
+ }
12226
+ )
11989
12227
  );
11990
12228
  cleanup.signal.throwIfAborted();
11991
- } catch {
12229
+ } catch (error) {
11992
12230
  attemptResult.errors.push(
11993
- failure("cleanup", "EVAL_INTERRUPT_CLEANUP_FAILED")
12231
+ phaseIssue(error, "EVAL_INTERRUPT_CLEANUP_FAILED")
11994
12232
  );
11995
12233
  }
11996
12234
  }
@@ -12001,8 +12239,8 @@ function createEvals(options) {
12001
12239
  result: clone(attemptResult)
12002
12240
  });
12003
12241
  cleanup.signal.throwIfAborted();
12004
- } catch {
12005
- attemptResult.errors.push(failure("cleanup"));
12242
+ } catch (error) {
12243
+ attemptResult.errors.push(phaseIssue(error));
12006
12244
  }
12007
12245
  } finally {
12008
12246
  clearTimeout(cleanupTimer);
@@ -12010,6 +12248,7 @@ function createEvals(options) {
12010
12248
  if (attemptResult.errors.some((error) => error.phase === "cleanup"))
12011
12249
  attemptResult.status = "error";
12012
12250
  }
12251
+ recordPhase();
12013
12252
  attemptResult.durationMs = Date.now() - started;
12014
12253
  }
12015
12254
  acceptingExecutions = false;
@@ -12081,23 +12320,23 @@ function defineSuite(suite) {
12081
12320
  }
12082
12321
 
12083
12322
  // src/evals/evaluation-contracts.ts
12084
- var import_zod10 = require("zod");
12323
+ var import_zod12 = require("zod");
12085
12324
 
12086
12325
  // src/evals/studio-contracts.ts
12087
12326
  var import_browser3 = require("@kortyx/prompts/browser");
12088
- var import_zod9 = require("zod");
12089
- var StudioEvalTargetsResponseSchema = import_zod9.z.object({
12090
- canRun: import_zod9.z.boolean(),
12327
+ var import_zod11 = require("zod");
12328
+ var StudioEvalTargetsResponseSchema = import_zod11.z.object({
12329
+ canRun: import_zod11.z.boolean(),
12091
12330
  studioJudge: EvalJudgeIdentitySchema.nullable().optional(),
12092
- targets: import_zod9.z.array(
12093
- import_zod9.z.object({
12094
- id: import_zod9.z.string(),
12095
- name: import_zod9.z.string(),
12096
- environment: import_zod9.z.string(),
12097
- error: import_zod9.z.string().nullable(),
12331
+ targets: import_zod11.z.array(
12332
+ import_zod11.z.object({
12333
+ id: import_zod11.z.string(),
12334
+ name: import_zod11.z.string(),
12335
+ environment: import_zod11.z.string(),
12336
+ error: import_zod11.z.string().nullable(),
12098
12337
  // Safe discovery diagnostics; optional for compatibility with older APIs.
12099
- diagnostic: import_zod9.z.object({
12100
- code: import_zod9.z.enum([
12338
+ diagnostic: import_zod11.z.object({
12339
+ code: import_zod11.z.enum([
12101
12340
  "environment_forbidden",
12102
12341
  "environment_unavailable",
12103
12342
  "endpoint_not_found",
@@ -12106,44 +12345,44 @@ var StudioEvalTargetsResponseSchema = import_zod9.z.object({
12106
12345
  "endpoint_unreachable",
12107
12346
  "manifest_invalid"
12108
12347
  ]),
12109
- httpStatus: import_zod9.z.number().int().min(100).max(599).optional()
12348
+ httpStatus: import_zod11.z.number().int().min(100).max(599).optional()
12110
12349
  }).nullable().optional(),
12111
12350
  manifest: EvalManifestSchema.nullable(),
12112
- revisions: import_zod9.z.record(import_zod9.z.string(), import_zod9.z.string())
12351
+ revisions: import_zod11.z.record(import_zod11.z.string(), import_zod11.z.string())
12113
12352
  })
12114
12353
  )
12115
12354
  });
12116
- var EvalCostAmountSchema = import_zod9.z.object({
12117
- costSummary: import_zod9.z.object({
12118
- amounts: import_zod9.z.array(
12119
- import_zod9.z.object({
12120
- amount: import_zod9.z.number().finite().nonnegative(),
12121
- currency: import_zod9.z.string().nullable()
12355
+ var EvalCostAmountSchema = import_zod11.z.object({
12356
+ costSummary: import_zod11.z.object({
12357
+ amounts: import_zod11.z.array(
12358
+ import_zod11.z.object({
12359
+ amount: import_zod11.z.number().finite().nonnegative(),
12360
+ currency: import_zod11.z.string().nullable()
12122
12361
  })
12123
12362
  ),
12124
- complete: import_zod9.z.boolean()
12363
+ complete: import_zod11.z.boolean()
12125
12364
  }).optional(),
12126
- amount: import_zod9.z.number().finite().nonnegative().nullable(),
12127
- currency: import_zod9.z.string().nullable(),
12128
- status: import_zod9.z.enum(["complete", "partial", "unavailable"]),
12129
- calls: import_zod9.z.number().int().nonnegative(),
12130
- unpricedCalls: import_zod9.z.number().int().nonnegative(),
12131
- estimated: import_zod9.z.boolean()
12365
+ amount: import_zod11.z.number().finite().nonnegative().nullable(),
12366
+ currency: import_zod11.z.string().nullable(),
12367
+ status: import_zod11.z.enum(["complete", "partial", "unavailable"]),
12368
+ calls: import_zod11.z.number().int().nonnegative(),
12369
+ unpricedCalls: import_zod11.z.number().int().nonnegative(),
12370
+ estimated: import_zod11.z.boolean()
12132
12371
  });
12133
- var EvalCostsSchema = import_zod9.z.object({
12372
+ var EvalCostsSchema = import_zod11.z.object({
12134
12373
  workflow: EvalCostAmountSchema,
12135
12374
  judge: EvalCostAmountSchema,
12136
12375
  total: EvalCostAmountSchema
12137
12376
  });
12138
- var StudioEvalRunSummarySchema = import_zod9.z.object({
12139
- id: import_zod9.z.uuid(),
12140
- evaluationId: import_zod9.z.uuid().nullable().optional(),
12141
- targetId: import_zod9.z.string(),
12142
- targetName: import_zod9.z.string(),
12143
- environment: import_zod9.z.string(),
12144
- suiteId: import_zod9.z.string(),
12145
- suiteRevision: import_zod9.z.string(),
12146
- status: import_zod9.z.enum([
12377
+ var StudioEvalRunSummarySchema = import_zod11.z.object({
12378
+ id: import_zod11.z.uuid(),
12379
+ evaluationId: import_zod11.z.uuid().nullable().optional(),
12380
+ targetId: import_zod11.z.string(),
12381
+ targetName: import_zod11.z.string(),
12382
+ environment: import_zod11.z.string(),
12383
+ suiteId: import_zod11.z.string(),
12384
+ suiteRevision: import_zod11.z.string(),
12385
+ status: import_zod11.z.enum([
12147
12386
  "queued",
12148
12387
  "running",
12149
12388
  "passed",
@@ -12151,49 +12390,49 @@ var StudioEvalRunSummarySchema = import_zod9.z.object({
12151
12390
  "error",
12152
12391
  "cancelled"
12153
12392
  ]),
12154
- createdAt: import_zod9.z.string(),
12155
- startedAt: import_zod9.z.string().nullable(),
12156
- endedAt: import_zod9.z.string().nullable(),
12157
- error: import_zod9.z.string().nullable(),
12158
- cancelRequestedAt: import_zod9.z.string().nullable(),
12393
+ createdAt: import_zod11.z.string(),
12394
+ startedAt: import_zod11.z.string().nullable(),
12395
+ endedAt: import_zod11.z.string().nullable(),
12396
+ error: import_zod11.z.string().nullable(),
12397
+ cancelRequestedAt: import_zod11.z.string().nullable(),
12159
12398
  costs: EvalCostsSchema.optional(),
12160
- counts: import_zod9.z.object({
12161
- passed: import_zod9.z.number(),
12162
- failed: import_zod9.z.number(),
12163
- error: import_zod9.z.number(),
12164
- cancelled: import_zod9.z.number()
12399
+ counts: import_zod11.z.object({
12400
+ passed: import_zod11.z.number(),
12401
+ failed: import_zod11.z.number(),
12402
+ error: import_zod11.z.number(),
12403
+ cancelled: import_zod11.z.number()
12165
12404
  }).nullable().optional(),
12166
- suiteName: import_zod9.z.string().nullable().optional(),
12167
- totalAttempts: import_zod9.z.number().int().nonnegative().optional(),
12168
- completedAttempts: import_zod9.z.number().int().nonnegative().optional(),
12169
- phase: import_zod9.z.string().optional()
12405
+ suiteName: import_zod11.z.string().nullable().optional(),
12406
+ totalAttempts: import_zod11.z.number().int().nonnegative().optional(),
12407
+ completedAttempts: import_zod11.z.number().int().nonnegative().optional(),
12408
+ phase: import_zod11.z.string().optional()
12170
12409
  });
12171
- var StudioEvalHistorySchema = import_zod9.z.object({
12172
- runs: import_zod9.z.array(StudioEvalRunSummarySchema)
12410
+ var StudioEvalHistorySchema = import_zod11.z.object({
12411
+ runs: import_zod11.z.array(StudioEvalRunSummarySchema)
12173
12412
  });
12174
- var StudioEvalDetailSchema = import_zod9.z.object({
12413
+ var StudioEvalDetailSchema = import_zod11.z.object({
12175
12414
  run: StudioEvalRunSummarySchema.extend({
12176
- caseCosts: import_zod9.z.record(import_zod9.z.string(), EvalCostsSchema).optional(),
12177
- request: import_zod9.z.object({
12178
- caseIds: import_zod9.z.array(import_zod9.z.string()).optional(),
12179
- grading: import_zod9.z.enum(["app", "studio"]).optional(),
12415
+ caseCosts: import_zod11.z.record(import_zod11.z.string(), EvalCostsSchema).optional(),
12416
+ request: import_zod11.z.object({
12417
+ caseIds: import_zod11.z.array(import_zod11.z.string()).optional(),
12418
+ grading: import_zod11.z.enum(["app", "studio"]).optional(),
12180
12419
  judge: EvalJudgeIdentitySchema.optional(),
12181
- repetitions: import_zod9.z.number().int().positive(),
12182
- concurrency: import_zod9.z.number().optional(),
12420
+ repetitions: import_zod11.z.number().int().positive(),
12421
+ concurrency: import_zod11.z.number().optional(),
12183
12422
  promptSnapshot: import_browser3.PromptSnapshotSchema.optional(),
12184
- promptGroupName: import_zod9.z.string().optional()
12423
+ promptGroupName: import_zod11.z.string().optional()
12185
12424
  }).optional(),
12186
12425
  suite: EvalSuiteSchema,
12187
12426
  result: EvalRunResultSchema.nullable(),
12188
- events: import_zod9.z.array(import_zod9.z.object({ id: import_zod9.z.number(), event: EvalProgressSchema }))
12427
+ events: import_zod11.z.array(import_zod11.z.object({ id: import_zod11.z.number(), event: EvalProgressSchema }))
12189
12428
  })
12190
12429
  });
12191
12430
 
12192
12431
  // src/evals/evaluation-contracts.ts
12193
- var EvaluationMetadataSchema = import_zod10.z.object({
12194
- source: import_zod10.z.enum(["manual", "deployment", "schedule", "ci"]).default("manual"),
12195
- commit: import_zod10.z.string().trim().min(1).max(100).optional(),
12196
- deploymentUrl: import_zod10.z.url().refine((value) => {
12432
+ var EvaluationMetadataSchema = import_zod12.z.object({
12433
+ source: import_zod12.z.enum(["manual", "deployment", "schedule", "ci"]).default("manual"),
12434
+ commit: import_zod12.z.string().trim().min(1).max(100).optional(),
12435
+ deploymentUrl: import_zod12.z.url().refine((value) => {
12197
12436
  try {
12198
12437
  const url = new URL(value);
12199
12438
  return ["https:", "http:"].includes(url.protocol) && !url.username && !url.password;
@@ -12202,67 +12441,67 @@ var EvaluationMetadataSchema = import_zod10.z.object({
12202
12441
  }
12203
12442
  }, "Expected an HTTP(S) URL without credentials").optional()
12204
12443
  }).strict();
12205
- var StudioEvaluationStartRequestSchema = import_zod10.z.object({
12206
- targetId: import_zod10.z.string().trim().min(1),
12207
- name: import_zod10.z.string().trim().min(1).max(200).optional(),
12444
+ var StudioEvaluationStartRequestSchema = import_zod12.z.object({
12445
+ targetId: import_zod12.z.string().trim().min(1),
12446
+ name: import_zod12.z.string().trim().min(1).max(200).optional(),
12208
12447
  promptSelection: StudioEvalStartRequestSchema.shape.promptSelection,
12209
- selection: import_zod10.z.enum(["all", "selected"]),
12210
- suites: import_zod10.z.array(
12211
- import_zod10.z.object({
12212
- suiteId: import_zod10.z.string().min(1),
12213
- suiteRevision: import_zod10.z.string().regex(/^[a-f0-9]{64}$/),
12214
- caseIds: import_zod10.z.array(import_zod10.z.string().min(1)).min(1).max(100).optional()
12448
+ selection: import_zod12.z.enum(["all", "selected"]),
12449
+ suites: import_zod12.z.array(
12450
+ import_zod12.z.object({
12451
+ suiteId: import_zod12.z.string().min(1),
12452
+ suiteRevision: import_zod12.z.string().regex(/^[a-f0-9]{64}$/),
12453
+ caseIds: import_zod12.z.array(import_zod12.z.string().min(1)).min(1).max(100).optional()
12215
12454
  }).strict()
12216
12455
  ).min(1).max(100),
12217
- judge: import_zod10.z.enum(["studio", "app"]).default("studio"),
12218
- repetitions: import_zod10.z.number().int().min(1).max(20).default(1),
12219
- concurrency: import_zod10.z.number().int().min(1).max(20).default(1),
12456
+ judge: import_zod12.z.enum(["studio", "app"]).default("studio"),
12457
+ repetitions: import_zod12.z.number().int().min(1).max(20).default(1),
12458
+ concurrency: import_zod12.z.number().int().min(1).max(20).default(1),
12220
12459
  metadata: EvaluationMetadataSchema.default({ source: "manual" }),
12221
- idempotencyKey: import_zod10.z.string().trim().min(1).max(200).optional()
12460
+ idempotencyKey: import_zod12.z.string().trim().min(1).max(200).optional()
12222
12461
  }).strict();
12223
- var StudioEvaluationSummarySchema = import_zod10.z.object({
12224
- id: import_zod10.z.uuid(),
12225
- name: import_zod10.z.string(),
12226
- targetId: import_zod10.z.string(),
12227
- targetName: import_zod10.z.string(),
12228
- environment: import_zod10.z.string(),
12229
- selection: import_zod10.z.enum(["all", "selected"]),
12462
+ var StudioEvaluationSummarySchema = import_zod12.z.object({
12463
+ id: import_zod12.z.uuid(),
12464
+ name: import_zod12.z.string(),
12465
+ targetId: import_zod12.z.string(),
12466
+ targetName: import_zod12.z.string(),
12467
+ environment: import_zod12.z.string(),
12468
+ selection: import_zod12.z.enum(["all", "selected"]),
12230
12469
  metadata: EvaluationMetadataSchema,
12231
12470
  judge: EvalJudgeIdentitySchema.optional(),
12232
12471
  status: StudioEvalRunSummarySchema.shape.status,
12233
- createdAt: import_zod10.z.string(),
12234
- startedAt: import_zod10.z.string().nullable(),
12235
- endedAt: import_zod10.z.string().nullable(),
12236
- cancelRequestedAt: import_zod10.z.string().nullable(),
12237
- suiteCount: import_zod10.z.number().int().nonnegative(),
12238
- completedSuites: import_zod10.z.number().int().nonnegative(),
12239
- totalAttempts: import_zod10.z.number().int().nonnegative(),
12240
- completedAttempts: import_zod10.z.number().int().nonnegative(),
12241
- counts: import_zod10.z.object({
12242
- passed: import_zod10.z.number(),
12243
- failed: import_zod10.z.number(),
12244
- error: import_zod10.z.number(),
12245
- cancelled: import_zod10.z.number()
12472
+ createdAt: import_zod12.z.string(),
12473
+ startedAt: import_zod12.z.string().nullable(),
12474
+ endedAt: import_zod12.z.string().nullable(),
12475
+ cancelRequestedAt: import_zod12.z.string().nullable(),
12476
+ suiteCount: import_zod12.z.number().int().nonnegative(),
12477
+ completedSuites: import_zod12.z.number().int().nonnegative(),
12478
+ totalAttempts: import_zod12.z.number().int().nonnegative(),
12479
+ completedAttempts: import_zod12.z.number().int().nonnegative(),
12480
+ counts: import_zod12.z.object({
12481
+ passed: import_zod12.z.number(),
12482
+ failed: import_zod12.z.number(),
12483
+ error: import_zod12.z.number(),
12484
+ cancelled: import_zod12.z.number()
12246
12485
  }),
12247
12486
  costs: EvalCostsSchema.optional(),
12248
- legacy: import_zod10.z.boolean().optional()
12487
+ legacy: import_zod12.z.boolean().optional()
12249
12488
  });
12250
- var StudioEvaluationHistorySchema = import_zod10.z.object({
12251
- runs: import_zod10.z.array(StudioEvaluationSummarySchema)
12489
+ var StudioEvaluationHistorySchema = import_zod12.z.object({
12490
+ runs: import_zod12.z.array(StudioEvaluationSummarySchema)
12252
12491
  });
12253
- var StudioEvaluationDetailSchema = import_zod10.z.object({
12492
+ var StudioEvaluationDetailSchema = import_zod12.z.object({
12254
12493
  run: StudioEvaluationSummarySchema.extend({
12255
- suites: import_zod10.z.array(StudioEvalRunSummarySchema)
12494
+ suites: import_zod12.z.array(StudioEvalRunSummarySchema)
12256
12495
  })
12257
12496
  });
12258
- var StudioEvaluationResultsSchema = import_zod10.z.object({
12497
+ var StudioEvaluationResultsSchema = import_zod12.z.object({
12259
12498
  run: StudioEvaluationSummarySchema.extend({
12260
- suites: import_zod10.z.array(StudioEvalDetailSchema.shape.run)
12499
+ suites: import_zod12.z.array(StudioEvalDetailSchema.shape.run)
12261
12500
  })
12262
12501
  });
12263
12502
 
12264
12503
  // src/evals/judge.ts
12265
- var import_zod11 = require("zod");
12504
+ var import_zod13 = require("zod");
12266
12505
  function createEvalJudge({
12267
12506
  model,
12268
12507
  id: id3 = `${model.provider.id}/${model.modelId}`,
@@ -12289,7 +12528,7 @@ function createEvalJudge({
12289
12528
  responseFormat: {
12290
12529
  type: "json",
12291
12530
  name: "eval_verdict",
12292
- schema: import_zod11.z.toJSONSchema(EvalVerdictSchema)
12531
+ schema: import_zod13.z.toJSONSchema(EvalVerdictSchema)
12293
12532
  }
12294
12533
  });
12295
12534
  const result = await judge2.invoke([
@@ -12366,28 +12605,423 @@ function createEvalJudge({
12366
12605
  }
12367
12606
 
12368
12607
  // src/evals/route-handler.ts
12369
- var import_node_crypto6 = require("crypto");
12608
+ var import_node_crypto7 = require("crypto");
12370
12609
  var import_prompts2 = require("@kortyx/prompts");
12610
+ var import_runtime6 = require("@kortyx/runtime");
12611
+
12612
+ // src/evals/route-executions.ts
12613
+ var import_node_crypto6 = require("crypto");
12614
+ var import_errors13 = require("@kortyx/core/errors");
12615
+ var protocol = "jobs-v1";
12616
+ var uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i;
12617
+ var wait = (ms, signal) => new Promise((resolve2, reject) => {
12618
+ if (signal.aborted) {
12619
+ reject(signal.reason);
12620
+ return;
12621
+ }
12622
+ const abort = () => {
12623
+ clearTimeout(timer);
12624
+ reject(signal.reason);
12625
+ };
12626
+ const timer = setTimeout(() => {
12627
+ signal.removeEventListener("abort", abort);
12628
+ resolve2();
12629
+ }, ms);
12630
+ signal.addEventListener("abort", abort, { once: true });
12631
+ });
12632
+ var canonical2 = (value) => {
12633
+ if (Array.isArray(value)) return `[${value.map(canonical2).join(",")}]`;
12634
+ if (value && typeof value === "object")
12635
+ return `{${Object.entries(value).sort(([a], [b]) => a < b ? -1 : 1).map(([key, child]) => `${JSON.stringify(key)}:${canonical2(child)}`).join(",")}}`;
12636
+ return JSON.stringify(value);
12637
+ };
12638
+ function createEvalExecutionTransport({
12639
+ evals,
12640
+ store,
12641
+ scope,
12642
+ limits,
12643
+ onExecution
12644
+ }) {
12645
+ const owner = (0, import_node_crypto6.randomUUID)();
12646
+ const active = /* @__PURE__ */ new Map();
12647
+ let ticking = false;
12648
+ let stopped = false;
12649
+ const key = (id3) => (0, import_node_crypto6.createHash)("sha256").update(`${scope}\0${id3}`).digest("hex");
12650
+ const fail = async (job, error) => {
12651
+ const issue2 = createEvalIssue("reporting", error);
12652
+ await store.append(job.id, owner, {
12653
+ type: "error",
12654
+ message: issue2.message,
12655
+ failure: issue2.failure,
12656
+ ...issue2.diagnosticId ? { diagnosticId: issue2.diagnosticId } : {}
12657
+ });
12658
+ };
12659
+ const run = async (job, controller) => {
12660
+ let renewing = false;
12661
+ const timer2 = setInterval(() => {
12662
+ if (renewing) return;
12663
+ renewing = true;
12664
+ void store.heartbeat(job.id, owner).then(
12665
+ (current) => {
12666
+ if (!current) controller.abort("lease-lost");
12667
+ else if (current.cancelRequested)
12668
+ controller.abort("user-cancelled");
12669
+ },
12670
+ () => controller.abort("lease-lost")
12671
+ ).finally(() => {
12672
+ renewing = false;
12673
+ });
12674
+ }, store.heartbeatIntervalMs);
12675
+ const deadline = setTimeout(
12676
+ () => controller.abort("execution-timeout"),
12677
+ 30 * 6e4
12678
+ );
12679
+ try {
12680
+ const body = EvalRemoteRunRequestSchema.parse(job.payload);
12681
+ const current = evals.describe().suites.find((suite) => suite.id === body.suiteId);
12682
+ if (!current || getEvalSuiteRevision(current) !== body.suiteRevision)
12683
+ throw new import_errors13.KortyxError(
12684
+ "EVAL_CONTRACT_CHANGED",
12685
+ "The queued suite changed before execution.",
12686
+ {
12687
+ category: "configuration",
12688
+ retryable: false,
12689
+ safeMessage: "The queued suite changed before execution."
12690
+ }
12691
+ );
12692
+ const result = await evals.run({
12693
+ suiteId: body.suiteId,
12694
+ repetitions: body.repetitions,
12695
+ concurrency: body.concurrency,
12696
+ signal: controller.signal,
12697
+ ...body.attempt ? { attempt: body.attempt } : {},
12698
+ ...body.caseIds ? { caseIds: body.caseIds } : {},
12699
+ ...body.grading ? { grading: body.grading } : {},
12700
+ ...body.judge ? { judgeIdentity: body.judge } : {},
12701
+ ...body.promptSnapshot ? { promptSnapshot: body.promptSnapshot } : {},
12702
+ onProgress: (event) => store.append(job.id, owner, { type: "progress", event })
12703
+ });
12704
+ await store.append(job.id, owner, { type: "result", result });
12705
+ await store.finish(
12706
+ job.id,
12707
+ owner,
12708
+ result.status === "cancelled" ? "cancelled" : "completed"
12709
+ );
12710
+ } catch (error) {
12711
+ try {
12712
+ if (controller.signal.reason === "user-cancelled" && (0, import_errors13.isControlFlowError)(error))
12713
+ error = new import_errors13.KortyxError(
12714
+ "EVAL_EXECUTION_CANCELLED",
12715
+ "Evaluation execution was cancelled.",
12716
+ {
12717
+ category: "request",
12718
+ status: 409,
12719
+ retryable: false,
12720
+ safeMessage: "Evaluation execution was cancelled."
12721
+ }
12722
+ );
12723
+ await fail(job, error);
12724
+ await store.finish(
12725
+ job.id,
12726
+ owner,
12727
+ controller.signal.reason === "user-cancelled" ? "cancelled" : "completed"
12728
+ );
12729
+ } catch {
12730
+ }
12731
+ } finally {
12732
+ clearInterval(timer2);
12733
+ clearTimeout(deadline);
12734
+ active.delete(job.id);
12735
+ }
12736
+ };
12737
+ const tick = async () => {
12738
+ if (stopped || ticking) return;
12739
+ ticking = true;
12740
+ try {
12741
+ while (!stopped) {
12742
+ const job = await store.claim(owner, scope, limits);
12743
+ if (!job) break;
12744
+ const controller = new AbortController();
12745
+ const completion = run(job, controller);
12746
+ active.set(job.id, { controller, completion });
12747
+ try {
12748
+ onExecution?.(completion);
12749
+ } catch {
12750
+ }
12751
+ }
12752
+ } catch {
12753
+ } finally {
12754
+ ticking = false;
12755
+ }
12756
+ };
12757
+ const timer = setInterval(() => {
12758
+ void tick();
12759
+ }, 250);
12760
+ timer.unref?.();
12761
+ void tick();
12762
+ const headers = async (id3) => ({
12763
+ "content-type": "application/x-ndjson",
12764
+ "cache-control": "no-store",
12765
+ "x-accel-buffering": "no",
12766
+ "x-kortyx-eval-protocol": protocol,
12767
+ "x-kortyx-eval-execution-id": id3,
12768
+ "x-kortyx-eval-generation": await store.generation()
12769
+ });
12770
+ const problem = (error, negotiated) => {
12771
+ const failure = (0, import_errors13.serializeFailure)(error);
12772
+ const busy = failure.code === "EVAL_EXECUTOR_BUSY";
12773
+ return Response.json(
12774
+ { error: failure.message, failure, ...busy ? { accepted: false } : {} },
12775
+ {
12776
+ status: busy ? negotiated ? 503 : 429 : !negotiated && failure.code === "EVAL_CONCURRENCY_CHANGED" ? 429 : failure.status ?? 503,
12777
+ headers: {
12778
+ ...negotiated ? { "x-kortyx-eval-protocol": protocol } : {},
12779
+ ...busy ? { "retry-after": "2" } : {}
12780
+ }
12781
+ }
12782
+ );
12783
+ };
12784
+ const observe = async (request, id3, after = 0, negotiated = true) => {
12785
+ const backend = key(id3);
12786
+ const job = await store.status(backend);
12787
+ if (!job)
12788
+ return Response.json(
12789
+ {
12790
+ error: "Evaluation execution is unavailable; do not replay it.",
12791
+ code: "EVAL_EXECUTION_UNKNOWN"
12792
+ },
12793
+ { status: 410 }
12794
+ );
12795
+ if (after > job.sequence)
12796
+ return Response.json(
12797
+ { error: "Invalid execution event cursor." },
12798
+ { status: 409 }
12799
+ );
12800
+ const controller = new AbortController();
12801
+ const disconnect = () => {
12802
+ controller.abort();
12803
+ if (!negotiated) {
12804
+ active.get(backend)?.controller.abort("user-cancelled");
12805
+ void store.cancel(backend).catch(() => {
12806
+ });
12807
+ }
12808
+ };
12809
+ request.signal.addEventListener("abort", disconnect, { once: true });
12810
+ if (request.signal.aborted) disconnect();
12811
+ const encoder = new TextEncoder();
12812
+ const stream = new ReadableStream({
12813
+ start(output) {
12814
+ void (async () => {
12815
+ let cursor = after;
12816
+ let state;
12817
+ try {
12818
+ while (!controller.signal.aborted) {
12819
+ const record = await store.status(backend);
12820
+ if (!record) throw new Error("Execution record expired.");
12821
+ if (negotiated && state !== record.state) {
12822
+ state = record.state;
12823
+ output.enqueue(
12824
+ encoder.encode(
12825
+ `${JSON.stringify({ type: "execution-status", state })}
12826
+ `
12827
+ )
12828
+ );
12829
+ }
12830
+ for (const item of await store.events(backend, cursor)) {
12831
+ if (controller.signal.aborted) break;
12832
+ output.enqueue(
12833
+ encoder.encode(
12834
+ `${JSON.stringify({ ...item.event, ...negotiated ? { sequence: item.sequence } : {} })}
12835
+ `
12836
+ )
12837
+ );
12838
+ cursor = item.sequence;
12839
+ }
12840
+ if (record.state !== "queued" && record.state !== "running" && cursor >= record.sequence)
12841
+ break;
12842
+ await wait(100, controller.signal);
12843
+ }
12844
+ if (!controller.signal.aborted) output.close();
12845
+ } catch (error) {
12846
+ if (!controller.signal.aborted) output.error(error);
12847
+ } finally {
12848
+ if (controller.signal.aborted) {
12849
+ try {
12850
+ output.close();
12851
+ } catch {
12852
+ }
12853
+ }
12854
+ request.signal.removeEventListener("abort", disconnect);
12855
+ }
12856
+ })();
12857
+ },
12858
+ cancel() {
12859
+ disconnect();
12860
+ }
12861
+ });
12862
+ return new Response(stream, { headers: await headers(id3) });
12863
+ };
12864
+ return {
12865
+ async existing(request) {
12866
+ const url = new URL(request.url);
12867
+ const id3 = url.searchParams.get("executionId");
12868
+ if (!id3) return void 0;
12869
+ if (!uuid.test(id3))
12870
+ return Response.json(
12871
+ { error: "Invalid execution identity." },
12872
+ { status: 400 }
12873
+ );
12874
+ try {
12875
+ const generation = request.headers.get("x-kortyx-eval-generation");
12876
+ if (generation && generation !== await store.generation())
12877
+ return Response.json(
12878
+ {
12879
+ error: "Execution storage changed; execution status is unknown.",
12880
+ code: "EVAL_EXECUTION_STORE_CHANGED"
12881
+ },
12882
+ { status: 409 }
12883
+ );
12884
+ if (request.method === "DELETE") {
12885
+ if (!await store.status(key(id3)))
12886
+ return Response.json(
12887
+ { error: "Unknown execution." },
12888
+ { status: 404 }
12889
+ );
12890
+ await store.cancel(key(id3));
12891
+ active.get(key(id3))?.controller.abort("user-cancelled");
12892
+ return Response.json({ cancelRequested: true });
12893
+ }
12894
+ if (request.method !== "GET")
12895
+ return Response.json(
12896
+ { error: "Unsupported observation method." },
12897
+ { status: 405 }
12898
+ );
12899
+ const raw = url.searchParams.get("after") ?? "0";
12900
+ if (!/^\d{1,8}$/.test(raw))
12901
+ return Response.json(
12902
+ { error: "Invalid execution event cursor." },
12903
+ { status: 400 }
12904
+ );
12905
+ return await observe(request, id3, Number(raw));
12906
+ } catch (error) {
12907
+ return problem(error, true);
12908
+ }
12909
+ },
12910
+ async submit(request, body) {
12911
+ const negotiated = request.headers.get("x-kortyx-eval-protocol") === protocol;
12912
+ if (stopped)
12913
+ return problem(
12914
+ new import_errors13.KortyxError(
12915
+ "EVAL_EXECUTOR_BUSY",
12916
+ "Eval executor is draining; execution was not accepted.",
12917
+ {
12918
+ category: "request",
12919
+ status: 503,
12920
+ retryable: true,
12921
+ safeMessage: "Eval executor is draining; execution was not accepted."
12922
+ }
12923
+ ),
12924
+ negotiated
12925
+ );
12926
+ const id3 = negotiated ? request.headers.get("idempotency-key") : (0, import_node_crypto6.randomUUID)();
12927
+ if (!id3 || !uuid.test(id3))
12928
+ return Response.json(
12929
+ { error: "A UUID execution identity is required." },
12930
+ { status: 400 }
12931
+ );
12932
+ const submitted = request.headers.get("x-kortyx-eval-submitted-at");
12933
+ if (negotiated && (!submitted || !Number.isFinite(Date.parse(submitted)) || Date.parse(submitted) < Date.now() - 864e5 || Date.parse(submitted) > Date.now() + 3e5))
12934
+ return Response.json(
12935
+ {
12936
+ error: "Execution submission window expired; inspect before starting another execution."
12937
+ },
12938
+ { status: 410 }
12939
+ );
12940
+ try {
12941
+ if (negotiated && request.headers.get("x-kortyx-eval-generation") !== await store.generation())
12942
+ return Response.json(
12943
+ {
12944
+ error: "Execution storage changed; execution status is unknown.",
12945
+ code: "EVAL_EXECUTION_STORE_CHANGED"
12946
+ },
12947
+ { status: 409 }
12948
+ );
12949
+ await store.submit(
12950
+ {
12951
+ id: key(id3),
12952
+ scope,
12953
+ fingerprint: (0, import_node_crypto6.createHash)("sha256").update(canonical2(body)).digest("hex"),
12954
+ group: key(body.attempt?.evaluationId ?? id3),
12955
+ concurrency: body.concurrency,
12956
+ weight: body.attempt ? 1 : body.concurrency,
12957
+ payload: body,
12958
+ queued: negotiated
12959
+ },
12960
+ limits
12961
+ );
12962
+ await tick();
12963
+ if (!negotiated) {
12964
+ while ((await store.status(key(id3)))?.state === "queued") {
12965
+ request.signal.throwIfAborted();
12966
+ await wait(10, request.signal);
12967
+ await tick();
12968
+ }
12969
+ }
12970
+ return await observe(request, id3, 0, negotiated);
12971
+ } catch (error) {
12972
+ if (!negotiated && request.signal.aborted) {
12973
+ active.get(key(id3))?.controller.abort("user-cancelled");
12974
+ await store.cancel(key(id3)).catch(() => {
12975
+ });
12976
+ }
12977
+ return problem(error, negotiated);
12978
+ }
12979
+ },
12980
+ async capabilityHeaders() {
12981
+ return {
12982
+ "x-kortyx-eval-protocol": protocol,
12983
+ "x-kortyx-eval-generation": await store.generation()
12984
+ };
12985
+ },
12986
+ async close() {
12987
+ stopped = true;
12988
+ clearInterval(timer);
12989
+ for (const job of active.values()) job.controller.abort("host-stopped");
12990
+ await Promise.all([...active.values()].map((job) => job.completion));
12991
+ }
12992
+ };
12993
+ }
12994
+
12995
+ // src/evals/route-handler.ts
12371
12996
  function createEvalRouteHandler({
12372
12997
  evals,
12373
12998
  serviceKey,
12374
12999
  maxCases = 100,
12375
- maxActiveRuns = 1
13000
+ maxActiveRuns = 1,
13001
+ maxActiveAttempts = 20,
13002
+ maxQueuedExecutions = 1e3,
13003
+ executionStore = (0, import_runtime6.createInMemoryEvalExecutionStore)(),
13004
+ onExecution
12376
13005
  }) {
12377
13006
  if (serviceKey.length < 32)
12378
13007
  throw new EvalConfigurationError(
12379
13008
  "Eval service keys must have at least 32 characters."
12380
13009
  );
12381
- if (!Number.isSafeInteger(maxCases) || maxCases < 1 || !Number.isSafeInteger(maxActiveRuns) || maxActiveRuns < 1)
13010
+ if (!Number.isSafeInteger(maxCases) || maxCases < 1 || !Number.isSafeInteger(maxActiveRuns) || maxActiveRuns < 1 || !Number.isSafeInteger(maxActiveAttempts) || maxActiveAttempts < 1 || !Number.isSafeInteger(maxQueuedExecutions) || maxQueuedExecutions < 1 || !Number.isSafeInteger(executionStore.heartbeatIntervalMs) || executionStore.heartbeatIntervalMs < 1)
12382
13011
  throw new EvalConfigurationError(
12383
13012
  "Eval endpoint limits must be positive integers."
12384
13013
  );
12385
- const digest = (value) => (0, import_node_crypto6.createHash)("sha256").update(value).digest();
13014
+ const digest = (value) => (0, import_node_crypto7.createHash)("sha256").update(value).digest();
12386
13015
  const expected = digest(`Bearer ${serviceKey}`);
12387
- let active = 0;
12388
- const evaluations = /* @__PURE__ */ new Map();
12389
- return async (request) => {
12390
- if (!(0, import_node_crypto6.timingSafeEqual)(
13016
+ const execution = createEvalExecutionTransport({
13017
+ evals,
13018
+ store: executionStore,
13019
+ scope: expected.toString("hex"),
13020
+ limits: { maxActiveRuns, maxActiveAttempts, maxQueuedExecutions },
13021
+ ...onExecution ? { onExecution } : {}
13022
+ });
13023
+ const handler3 = async (request) => {
13024
+ if (!(0, import_node_crypto7.timingSafeEqual)(
12391
13025
  expected,
12392
13026
  digest(request.headers.get("authorization") ?? "")
12393
13027
  ))
@@ -12395,10 +13029,15 @@ function createEvalRouteHandler({
12395
13029
  { error: "Unauthorized eval request." },
12396
13030
  { status: 401 }
12397
13031
  );
13032
+ const observed = await execution.existing(request);
13033
+ if (observed) return observed;
12398
13034
  const manifest = evals.describe();
12399
13035
  if (request.method === "GET")
12400
13036
  return Response.json(manifest, {
12401
- headers: { "cache-control": "no-store" }
13037
+ headers: {
13038
+ "cache-control": "no-store",
13039
+ ...await execution.capabilityHeaders()
13040
+ }
12402
13041
  });
12403
13042
  if (request.method !== "POST")
12404
13043
  return Response.json({ error: "Unsupported method." }, { status: 405 });
@@ -12469,80 +13108,11 @@ function createEvalRouteHandler({
12469
13108
  { error: "Unsupported or invalid scheduled attempt." },
12470
13109
  { status: 409 }
12471
13110
  );
12472
- const group = body.attempt && evaluations.get(body.attempt.evaluationId);
12473
- if (group && (group.concurrency !== body.concurrency || group.active >= group.concurrency))
12474
- return Response.json(
12475
- { error: "Evaluation concurrency exhausted or changed." },
12476
- { status: 429 }
12477
- );
12478
- if (!group && active >= maxActiveRuns)
12479
- return Response.json(
12480
- { error: "Eval executor is busy." },
12481
- { status: 429 }
12482
- );
12483
13111
  if (request.signal.aborted)
12484
13112
  return Response.json({ error: "Request cancelled." }, { status: 409 });
12485
- if (body.attempt) {
12486
- const state = group ?? { active: 0, concurrency: body.concurrency };
12487
- if (!group) {
12488
- active++;
12489
- evaluations.set(body.attempt.evaluationId, state);
12490
- }
12491
- state.active++;
12492
- } else active++;
12493
- const controller = new AbortController();
12494
- const requestSignal = request.signal;
12495
- const abortRequest = () => controller.abort();
12496
- requestSignal.addEventListener("abort", abortRequest, { once: true });
12497
- const signal = controller.signal;
12498
- const encoder = new TextEncoder();
12499
- const stream = new ReadableStream({
12500
- start(output) {
12501
- const send = (event) => {
12502
- if (!signal.aborted)
12503
- output.enqueue(encoder.encode(`${JSON.stringify(event)}
12504
- `));
12505
- };
12506
- void evals.run({
12507
- suiteId: body.suiteId,
12508
- ...body.promptSnapshot ? { promptSnapshot: body.promptSnapshot } : {},
12509
- ...body.attempt ? { attempt: body.attempt } : {},
12510
- ...body.grading ? { grading: body.grading } : {},
12511
- ...body.judge ? { judgeIdentity: body.judge } : {},
12512
- repetitions: body.repetitions,
12513
- concurrency: body.concurrency,
12514
- signal,
12515
- ...body.caseIds ? { caseIds: body.caseIds } : {},
12516
- onProgress: (event) => send({ type: "progress", event })
12517
- }).then(
12518
- (result) => send({ type: "result", result }),
12519
- () => send({ type: "error", message: "Eval runner failed." })
12520
- ).finally(() => {
12521
- requestSignal.removeEventListener("abort", abortRequest);
12522
- if (body.attempt) {
12523
- const state = evaluations.get(body.attempt.evaluationId);
12524
- state.active--;
12525
- if (!state.active) {
12526
- evaluations.delete(body.attempt.evaluationId);
12527
- active--;
12528
- }
12529
- } else active--;
12530
- if (!controller.signal.aborted) output.close();
12531
- });
12532
- },
12533
- cancel() {
12534
- request.signal.removeEventListener("abort", abortRequest);
12535
- controller.abort();
12536
- }
12537
- });
12538
- return new Response(stream, {
12539
- headers: {
12540
- "content-type": "application/x-ndjson",
12541
- "cache-control": "no-store",
12542
- "x-accel-buffering": "no"
12543
- }
12544
- });
13113
+ return execution.submit(request, body);
12545
13114
  };
13115
+ return Object.assign(handler3, { close: execution.close });
12546
13116
  }
12547
13117
 
12548
13118
  // src/evals/studio-judge.ts
@@ -12656,6 +13226,7 @@ async function createStudioEvalJudge(options) {
12656
13226
  ChatLifecycleHookError,
12657
13227
  EvalConfigurationError,
12658
13228
  EvalEvidencePolicySchema,
13229
+ EvalIssueSchema,
12659
13230
  EvalJudgeIdentitySchema,
12660
13231
  EvalJudgeUsageSchema,
12661
13232
  EvalManifestSchema,
@@ -12677,6 +13248,7 @@ async function createStudioEvalJudge(options) {
12677
13248
  createAgent,
12678
13249
  createChatRouteHandler,
12679
13250
  createCheckpointRouteHandler,
13251
+ createEvalIssue,
12680
13252
  createEvalJudge,
12681
13253
  createEvalRouteHandler,
12682
13254
  createEvals,