@kortyx/agent 0.37.1 → 0.38.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.3",
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.3",
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) => {
@@ -5292,6 +5292,36 @@ ${tryStringify2(args.response)}`
5292
5292
  var import_core52 = require("@kortyx/core");
5293
5293
  var import_errors62 = require("@kortyx/core/errors");
5294
5294
  var import_zod52 = require("zod");
5295
+ var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
5296
+ function schemaPath(schema, path) {
5297
+ let current = schema;
5298
+ let label = "";
5299
+ for (const part of path.slice(0, 8)) {
5300
+ if (!record(current)) break;
5301
+ if (typeof part === "number" && Number.isSafeInteger(part) && part >= 0) {
5302
+ if (!record(current.items)) break;
5303
+ current = current.items;
5304
+ label += `[${part}]`;
5305
+ } else if (typeof part === "string" && record(current.properties) && Object.hasOwn(current.properties, part)) {
5306
+ current = current.properties[part];
5307
+ label += `${label ? "." : ""}${part.slice(0, 64)}`;
5308
+ } else break;
5309
+ }
5310
+ return label || "input";
5311
+ }
5312
+ function interruptInputFeedback(error, schema, name, required) {
5313
+ const issues = Array.isArray(error.issues) ? error.issues : [];
5314
+ const problems = issues.slice(0, 5).map((issue2) => {
5315
+ const path = record(issue2) && Array.isArray(issue2.path) ? issue2.path : [];
5316
+ return `- ${schemaPath(schema, path)} must satisfy its declared input schema.`;
5317
+ });
5318
+ return [
5319
+ `Invalid input for ${name}:`,
5320
+ ...problems,
5321
+ ...issues.length > 5 ? ["- Additional input fields are invalid."] : [],
5322
+ required ? "Correct the input and call the tool again. Human input is required before finishing." : "Correct the input and call the tool again, or finish without requesting human input when none is needed."
5323
+ ].join("\n");
5324
+ }
5295
5325
  var toToolDefinitions = (tools2) => tools2.map((tool) => ({
5296
5326
  name: tool.name,
5297
5327
  ...tool.title ? { title: tool.title } : {},
@@ -5494,7 +5524,19 @@ ${tryStringify2(args.response)}`
5494
5524
  let finalizing = checkpoint?.finalizing ?? false;
5495
5525
  let completed = false;
5496
5526
  const maxSteps = Math.max(1, useReasonArgs.toolExecution?.maxSteps ?? 3);
5497
- const messages = checkpoint?.messages ?? createInitialMessages({
5527
+ const missingReturnCorrections = useReasonArgs.toolExecution?.missingReturnCorrections ?? 0;
5528
+ if (!Number.isSafeInteger(missingReturnCorrections) || missingReturnCorrections < 0)
5529
+ throw new import_errors62.KortyxError(
5530
+ "INVALID_REASON_CORRECTION_POLICY",
5531
+ "Invalid missing return correction budget.",
5532
+ {
5533
+ category: "configuration",
5534
+ retryable: false,
5535
+ safeMessage: "toolExecution.missingReturnCorrections must be a nonnegative safe integer."
5536
+ }
5537
+ );
5538
+ let missingReturnAttempts = checkpoint?.missingReturnAttempts ?? 0;
5539
+ const messages2 = checkpoint?.messages ?? createInitialMessages({
5498
5540
  messages: useReasonArgs.messages,
5499
5541
  inputOverride: Boolean(useReasonArgs.outputSchema),
5500
5542
  system: useReasonArgs.system,
@@ -5545,13 +5587,17 @@ ${tryStringify2(args.response)}`
5545
5587
  let outputContractCorrections = checkpoint?.outputContractCorrections ?? 0;
5546
5588
  const correctionExhausted = () => {
5547
5589
  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
- });
5590
+ return new import_errors62.KortyxError(
5591
+ "REASON_OUTPUT_CONTRACT_CORRECTION_EXHAUSTED",
5592
+ message,
5593
+ {
5594
+ category: "validation",
5595
+ operation: "useReason",
5596
+ safeMessage: message,
5597
+ retryable: false,
5598
+ details: { maxSteps, outputContractCorrections }
5599
+ }
5600
+ );
5555
5601
  };
5556
5602
  const resolvedInterrupts = checkpoint?.resolvedInterrupts ?? [];
5557
5603
  for (const request of resolvedInterrupts) ctx.node.replayInterrupt?.(request);
@@ -5563,13 +5609,14 @@ ${tryStringify2(args.response)}`
5563
5609
  ctx.currentNodeState.byKey[checkpointKey] = {
5564
5610
  status: "tool_loop",
5565
5611
  opId,
5566
- messages,
5612
+ messages: messages2,
5567
5613
  steps,
5568
5614
  approvedCalls,
5569
5615
  resolvedInterrupts,
5570
5616
  interruptHistory,
5571
5617
  emissions,
5572
5618
  outputContractCorrections,
5619
+ missingReturnAttempts,
5573
5620
  ...returned ? { returned } : {},
5574
5621
  finalizing,
5575
5622
  ...pending ? { pending } : {},
@@ -5605,9 +5652,9 @@ ${tryStringify2(args.response)}`
5605
5652
  const step = pending ?? await reasonEngine(
5606
5653
  {
5607
5654
  ...useReasonArgs,
5608
- tools: finalizing ? [] : toolDefinitions,
5655
+ tools: finalizing ? [] : missingReturnAttempts > 0 ? outputDefinitions : toolDefinitions,
5609
5656
  ...separateOutput && !finalizing ? { responseFormat: { type: "text" } } : {},
5610
- messages,
5657
+ messages: messages2,
5611
5658
  emit: false,
5612
5659
  stream,
5613
5660
  onTextChunk: (delta) => {
@@ -5636,6 +5683,16 @@ ${tryStringify2(args.response)}`
5636
5683
  );
5637
5684
  aggregatedWarnings = mergeWarnings(aggregatedWarnings, step.warnings);
5638
5685
  const toolCalls = step.toolCalls ?? [];
5686
+ if (missingReturnAttempts > 0 && toolCalls.some((call) => !outputByToolName.has(call.name)))
5687
+ throw new import_errors62.KortyxError(
5688
+ "REASON_OUTPUT_CORRECTION_TOOL_DISALLOWED",
5689
+ "A return correction requested a non-output tool.",
5690
+ {
5691
+ category: "validation",
5692
+ retryable: false,
5693
+ safeMessage: "A terminal output correction cannot rerun tools or human-input requests."
5694
+ }
5695
+ );
5639
5696
  const ids = /* @__PURE__ */ new Set();
5640
5697
  for (const call of toolCalls) {
5641
5698
  if (!call.id || ids.has(call.id) || !reused && knownToolCallIds.has(call.id))
@@ -5656,10 +5713,32 @@ ${tryStringify2(args.response)}`
5656
5713
  });
5657
5714
  if (!reused) for (const call of toolCalls) knownToolCallIds.add(call.id);
5658
5715
  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."
5716
+ if (Object.keys(useReasonArgs.outputs?.return ?? {}).length > 0 && !returned) {
5717
+ if (missingReturnAttempts < missingReturnCorrections) {
5718
+ messages2.push({ role: "assistant", content: step.text });
5719
+ messages2.push({
5720
+ role: "user",
5721
+ 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."
5722
+ });
5723
+ missingReturnAttempts += 1;
5724
+ outputContractCorrections += 1;
5725
+ pending = void 0;
5726
+ pendingStepIndex = void 0;
5727
+ save();
5728
+ continue;
5729
+ }
5730
+ throw new import_errors62.KortyxError(
5731
+ "REASON_TERMINAL_OUTPUT_MISSING",
5732
+ "useReason outputs.return requires one terminal output contract call.",
5733
+ {
5734
+ category: "validation",
5735
+ operation: "useReason",
5736
+ retryable: false,
5737
+ safeMessage: "useReason outputs.return requires one terminal output contract call.",
5738
+ details: { missingReturnAttempts }
5739
+ }
5662
5740
  );
5741
+ }
5663
5742
  if (interruptConfig?.mode === "required" && interruptHistory.length === 0)
5664
5743
  throw new Error(
5665
5744
  "useReason interrupts.mode is required, but the model returned a final answer without requesting human input."
@@ -5686,12 +5765,12 @@ ${tryStringify2(args.response)}`
5686
5765
  } catch {
5687
5766
  }
5688
5767
  }
5689
- messages.push({
5768
+ messages2.push({
5690
5769
  role: "assistant",
5691
5770
  content: step.text,
5692
5771
  ...step.continuation ? { continuation: step.continuation } : {}
5693
5772
  });
5694
- messages.push({
5773
+ messages2.push({
5695
5774
  role: "user",
5696
5775
  content: "Return the final answer using the requested output schema and the tool results above."
5697
5776
  });
@@ -5714,7 +5793,7 @@ ${tryStringify2(args.response)}`
5714
5793
  (call) => !interruptByToolName.has(call.name) && !outputByToolName.has(call.name)
5715
5794
  )
5716
5795
  );
5717
- messages.push({
5796
+ messages2.push({
5718
5797
  role: "assistant",
5719
5798
  content: step.text,
5720
5799
  toolCalls,
@@ -5742,7 +5821,7 @@ ${tryStringify2(args.response)}`
5742
5821
  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
5822
  };
5744
5823
  toolResults.push(result2);
5745
- messages.push({ role: "tool", ...result2 });
5824
+ messages2.push({ role: "tool", ...result2 });
5746
5825
  corrected = true;
5747
5826
  }
5748
5827
  if (corrected) outputContractCorrections += 1;
@@ -5827,7 +5906,7 @@ ${tryStringify2(args.response)}`
5827
5906
  tools: [],
5828
5907
  ...inferred.responseFormat ? { responseFormat: inferred.responseFormat } : {},
5829
5908
  messages: [
5830
- ...messages,
5909
+ ...messages2,
5831
5910
  ...toolCalls.filter(
5832
5911
  (pendingCall) => !toolResults.some(
5833
5912
  (result3) => result3.toolCallId === pendingCall.id
@@ -5946,7 +6025,7 @@ ${tryStringify2(args.response)}`
5946
6025
  });
5947
6026
  const result2 = normalizeToolResult(call, { emitted: true, data });
5948
6027
  toolResults.push(result2);
5949
- messages.push({
6028
+ messages2.push({
5950
6029
  role: "tool",
5951
6030
  content: result2.content,
5952
6031
  toolCallId: result2.toolCallId,
@@ -5969,11 +6048,35 @@ ${tryStringify2(args.response)}`
5969
6048
  throw new Error(
5970
6049
  `useReason reached interrupts.maxRequests (${interruptConfig?.maxRequests ?? 1}).`
5971
6050
  );
5972
- const request = parseWithSchema(
5973
- resolved.contract.requestSchema,
5974
- toolCall.input,
5975
- `useReason interrupt contract "${resolved.name}" request`
5976
- );
6051
+ let request;
6052
+ try {
6053
+ request = parseWithSchema(
6054
+ resolved.contract.requestSchema,
6055
+ toolCall.input,
6056
+ `useReason interrupt contract "${resolved.name}" request`
6057
+ );
6058
+ } catch (error) {
6059
+ if (!(error instanceof import_errors62.ValidationError)) throw error;
6060
+ const result3 = {
6061
+ toolCallId: toolCall.id,
6062
+ name: toolCall.name,
6063
+ isError: true,
6064
+ content: interruptInputFeedback(
6065
+ error,
6066
+ interruptDefinitions.find((tool2) => tool2.name === toolCall.name)?.inputSchema,
6067
+ toolCall.name,
6068
+ interruptConfig?.mode === "required"
6069
+ )
6070
+ };
6071
+ toolResults.push(result3);
6072
+ messages2.push({ role: "tool", ...result3 });
6073
+ traceSpan?.addEvent?.("useReason.interrupt.invalid", {
6074
+ checkpointKey,
6075
+ contract: resolved.name
6076
+ });
6077
+ save();
6078
+ continue;
6079
+ }
5977
6080
  traceSpan?.addEvent?.("useReason.interrupt.requested", {
5978
6081
  checkpointKey,
5979
6082
  contract: resolved.name,
@@ -6003,7 +6106,7 @@ ${tryStringify2(args.response)}`
6003
6106
  });
6004
6107
  const result2 = normalizeToolResult(toolCall, response);
6005
6108
  toolResults.push(result2);
6006
- messages.push({
6109
+ messages2.push({
6007
6110
  role: "tool",
6008
6111
  content: result2.content,
6009
6112
  toolCallId: result2.toolCallId,
@@ -6117,7 +6220,7 @@ ${tryStringify2(args.response)}`
6117
6220
  isError: true
6118
6221
  });
6119
6222
  }
6120
- messages.push({
6223
+ messages2.push({
6121
6224
  role: "tool",
6122
6225
  content: denied.content,
6123
6226
  toolCallId: denied.toolCallId,
@@ -6174,17 +6277,21 @@ ${tryStringify2(args.response)}`
6174
6277
  toolResults.push(result2);
6175
6278
  allToolResults.push(result2);
6176
6279
  if (shouldEmitTool) {
6280
+ const diagnosticId = steps[stepIndex]?.toolObservations?.slice().reverse().find(
6281
+ (observation) => observation.toolCallId === `${opId}:${toolCall.id}`
6282
+ )?.diagnosticId;
6177
6283
  emitToolEvent("tool-call-error", {
6178
6284
  tool: tool.name,
6179
6285
  toolCallId: toolCall.id,
6180
6286
  message: result2.content,
6181
- failure: result2.failure
6287
+ failure: result2.failure,
6288
+ ...diagnosticId ? { diagnosticId } : {}
6182
6289
  });
6183
6290
  }
6184
6291
  }
6185
6292
  const completedToolResult = toolResults.at(-1);
6186
6293
  if (completedToolResult)
6187
- messages.push({
6294
+ messages2.push({
6188
6295
  role: "tool",
6189
6296
  content: completedToolResult.content,
6190
6297
  toolCallId: completedToolResult.toolCallId,
@@ -6903,10 +7010,10 @@ ${tryStringify2(args.response)}`
6903
7010
  throw new Error("Parallel call membership changed during replay.");
6904
7011
  }
6905
7012
  for (const callId of group.record.calls) {
6906
- const record = callRecord(callId);
6907
- if (record?.status !== "interrupted") continue;
6908
- const index = record.interrupts.length - 1;
6909
- if (record.interrupts[index]?.response !== void 0) continue;
7013
+ const record2 = callRecord(callId);
7014
+ if (record2?.status !== "interrupted") continue;
7015
+ const index = record2.interrupts.length - 1;
7016
+ if (record2.interrupts[index]?.response !== void 0) continue;
6910
7017
  group.record.interrupts.push({ callId, index });
6911
7018
  await bridge(callId, index);
6912
7019
  throw new Error(
@@ -6967,9 +7074,9 @@ ${tryStringify2(args.response)}`
6967
7074
  var import_core8 = require("@kortyx/core");
6968
7075
  var import_errors82 = require("@kortyx/core/errors");
6969
7076
  var WorkflowCallError = class extends import_errors82.KortyxError {
6970
- constructor(workflow, message, cause, failure2) {
7077
+ constructor(workflow, message, cause, failure) {
6971
7078
  const detail = (0, import_errors82.serializeFailure)(
6972
- failure2 ?? cause ?? new import_errors82.WorkflowContractError(message)
7079
+ failure ?? cause ?? new import_errors82.WorkflowContractError(message)
6973
7080
  );
6974
7081
  super(detail.code, `Workflow '${workflow}': ${message}`, {
6975
7082
  ...detail,
@@ -6986,7 +7093,7 @@ ${tryStringify2(args.response)}`
6986
7093
  };
6987
7094
  function workflowCallFingerprint(value) {
6988
7095
  const seen = /* @__PURE__ */ new Set();
6989
- const canonical2 = (v) => {
7096
+ const canonical3 = (v) => {
6990
7097
  if (v === null || typeof v === "string" || typeof v === "boolean") return v;
6991
7098
  if (typeof v === "number" && Number.isFinite(v)) return v;
6992
7099
  if (typeof v !== "object" || !v || seen.has(v)) {
@@ -7000,16 +7107,16 @@ ${tryStringify2(args.response)}`
7000
7107
  );
7001
7108
  }
7002
7109
  seen.add(v);
7003
- const result = Array.isArray(v) ? v.map(canonical2) : Object.fromEntries(
7110
+ const result = Array.isArray(v) ? v.map(canonical3) : Object.fromEntries(
7004
7111
  Object.keys(v).sort().map((key) => [
7005
7112
  key,
7006
- canonical2(v[key])
7113
+ canonical3(v[key])
7007
7114
  ])
7008
7115
  );
7009
7116
  seen.delete(v);
7010
7117
  return result;
7011
7118
  };
7012
- return JSON.stringify(canonical2(value));
7119
+ return JSON.stringify(canonical3(value));
7013
7120
  }
7014
7121
  function createWorkflowHooks(workflows) {
7015
7122
  return {
@@ -7071,26 +7178,26 @@ ${tryStringify2(args.response)}`
7071
7178
  version: definition?.version ?? null
7072
7179
  });
7073
7180
  const key = `__useWorkflow:${args.id}`;
7074
- let record = ctx.currentNodeState.byKey[key];
7075
- if (record && record.parallelKey !== task.group?.key)
7181
+ let record2 = ctx.currentNodeState.byKey[key];
7182
+ if (record2 && record2.parallelKey !== task.group?.key)
7076
7183
  throw new WorkflowCallError(
7077
7184
  workflow,
7078
7185
  "parallel call membership changed during replay"
7079
7186
  );
7080
- if (record && record.fingerprint !== fingerprint)
7187
+ if (record2 && record2.fingerprint !== fingerprint)
7081
7188
  throw new WorkflowCallError(
7082
7189
  workflow,
7083
7190
  "call input or target changed during replay"
7084
7191
  );
7085
- if (!record) ctx.node.consumeExecution?.("maxChildInvocations");
7086
- record ??= {
7192
+ if (!record2) ctx.node.consumeExecution?.("maxChildInvocations");
7193
+ record2 ??= {
7087
7194
  fingerprint,
7088
7195
  invocationId: (0, import_node_crypto62.randomUUID)(),
7089
7196
  status: "running",
7090
7197
  interrupts: [],
7091
7198
  ...task.group ? { parallelKey: task.group.key } : {}
7092
7199
  };
7093
- ctx.currentNodeState.byKey[key] = record;
7200
+ ctx.currentNodeState.byKey[key] = record2;
7094
7201
  ctx.stateDirty = true;
7095
7202
  if (!task.group) ctx.workflowCallActive = true;
7096
7203
  const telemetry = ctx.node.workflowCallTelemetry;
@@ -7098,7 +7205,7 @@ ${tryStringify2(args.response)}`
7098
7205
  ctx.currentNodeState.byKey[activationKey] ??= (0, import_node_crypto62.randomUUID)();
7099
7206
  const callerNodeExecutionId = ctx.currentNodeState.byKey[activationKey];
7100
7207
  const metadata2 = {
7101
- invocationId: record.invocationId,
7208
+ invocationId: record2.invocationId,
7102
7209
  parentInvocationId: telemetry?.correlation?.invocationId ?? null,
7103
7210
  branchId: telemetry?.correlation?.branchId ?? telemetry?.correlation?.runId ?? "unknown",
7104
7211
  callId: args.id,
@@ -7108,46 +7215,49 @@ ${tryStringify2(args.response)}`
7108
7215
  targetWorkflowId: workflow,
7109
7216
  targetVersion: definition?.version ?? null
7110
7217
  };
7111
- record.telemetry = metadata2;
7218
+ record2.telemetry = metadata2;
7112
7219
  const report = (status2, content = {}) => {
7113
- record.sequence = (record.sequence ?? 0) + 1;
7220
+ record2.sequence = (record2.sequence ?? 0) + 1;
7114
7221
  emitWorkflowCall2(telemetry, `workflow.call.${status2}`, {
7115
7222
  ...metadata2,
7116
- sequence: record.sequence,
7223
+ sequence: record2.sequence,
7117
7224
  ...content
7118
7225
  });
7119
7226
  };
7120
7227
  const recordUsage = (usage22) => {
7121
7228
  if (!usage22) return;
7122
7229
  accumulateTokenUsage({
7123
- input: usage22.input - (record.usage?.input ?? 0),
7124
- output: usage22.output - (record.usage?.output ?? 0),
7125
- total: usage22.total - (record.usage?.total ?? 0)
7230
+ input: usage22.input - (record2.usage?.input ?? 0),
7231
+ output: usage22.output - (record2.usage?.output ?? 0),
7232
+ total: usage22.total - (record2.usage?.total ?? 0)
7126
7233
  });
7127
- record.usage = usage22;
7234
+ record2.usage = usage22;
7128
7235
  };
7129
- const cached = record.status === "completed";
7236
+ const cached = record2.status === "completed";
7130
7237
  try {
7131
- for (const interruption of task.group ? [] : record.interrupts) {
7238
+ for (const interruption of task.group ? [] : record2.interrupts) {
7132
7239
  interruption.response = await awaitInterruptInternal({
7133
7240
  request: interruption.request,
7134
7241
  ...interruption.request.meta ? { meta: interruption.request.meta } : {}
7135
7242
  });
7136
7243
  }
7137
- if (record.status === "failed")
7244
+ if (record2.status === "failed")
7138
7245
  throw new WorkflowCallError(
7139
7246
  workflow,
7140
- record.error ?? "child failed",
7247
+ record2.error ?? "child failed",
7141
7248
  void 0,
7142
- record.failure ?? (0, import_errors82.serializeFailure)(void 0)
7249
+ record2.failure ?? (0, import_errors82.serializeFailure)(void 0)
7143
7250
  );
7144
- if (task.group && record.status === "interrupted" && record.interrupts.at(-1)?.response === void 0)
7251
+ if (task.group && record2.status === "interrupted" && record2.interrupts.at(-1)?.response === void 0)
7145
7252
  throw new ParallelChildWaiting();
7146
- while (record.status !== "completed") {
7253
+ while (record2.status !== "completed") {
7147
7254
  let outcome;
7148
7255
  try {
7256
+ if (Array.isArray(record2.snapshot) && record2.snapshot.length !== 1)
7257
+ throw new import_errors82.WorkflowContractError("Invalid child workflow snapshot.");
7258
+ const snapshot = Array.isArray(record2.snapshot) ? record2.snapshot[0] : record2.snapshot;
7149
7259
  report(
7150
- record.snapshot ? "resumed" : "started",
7260
+ snapshot ? "resumed" : "started",
7151
7261
  workflowCallContent(telemetry, "input", input)
7152
7262
  );
7153
7263
  outcome = await service({
@@ -7156,9 +7266,9 @@ ${tryStringify2(args.response)}`
7156
7266
  workflow,
7157
7267
  input,
7158
7268
  definition,
7159
- invocationId: record.invocationId,
7160
- ...record.snapshot ? { snapshot: record.snapshot } : {},
7161
- ...record.interrupts.length ? { response: record.interrupts.at(-1)?.response } : {}
7269
+ invocationId: record2.invocationId,
7270
+ ...snapshot ? { snapshot } : {},
7271
+ ...record2.interrupts.length ? { response: record2.interrupts.at(-1)?.response } : {}
7162
7272
  });
7163
7273
  } catch (error) {
7164
7274
  const child = error;
@@ -7167,48 +7277,48 @@ ${tryStringify2(args.response)}`
7167
7277
  if ((0, import_core8.isExecutionCancelled)(error)) throw error;
7168
7278
  if ((0, import_core8.isExecutionLimitReached)(error)) {
7169
7279
  if (child?.__kortyxChildSnapshot)
7170
- record.snapshot = child.__kortyxChildSnapshot;
7280
+ record2.snapshot = child.__kortyxChildSnapshot;
7171
7281
  report("suspended", {
7172
7282
  reason: "limit_reached",
7173
7283
  limit: error.limitReached
7174
7284
  });
7175
7285
  throw error;
7176
7286
  }
7177
- record.status = "failed";
7178
- record.failure = (0, import_errors82.serializeFailure)(error);
7179
- record.error = record.failure.message;
7287
+ record2.status = "failed";
7288
+ record2.failure = (0, import_errors82.serializeFailure)(error);
7289
+ record2.error = record2.failure.message;
7180
7290
  report("failed", { error: "Child workflow failed" });
7181
7291
  throw new WorkflowCallError(
7182
7292
  workflow,
7183
- record.error,
7293
+ record2.error,
7184
7294
  error,
7185
- record.failure
7295
+ record2.failure
7186
7296
  );
7187
7297
  }
7188
7298
  (0, import_core8.throwIfExecutionAborted)(ctx.node.abortSignal);
7189
7299
  recordUsage(outcome.usage);
7190
7300
  if (outcome.status === "completed") {
7191
- record.data = outcome.data;
7192
- workflowCallFingerprint(record.data);
7193
- record.status = "completed";
7194
- record.toolObservations = outcome.toolObservations ?? [];
7195
- for (const observation of record.toolObservations)
7301
+ record2.data = outcome.data;
7302
+ workflowCallFingerprint(record2.data);
7303
+ record2.status = "completed";
7304
+ record2.toolObservations = outcome.toolObservations ?? [];
7305
+ for (const observation of record2.toolObservations)
7196
7306
  rememberToolObservation(observation);
7197
- delete record.snapshot;
7307
+ delete record2.snapshot;
7198
7308
  report(
7199
7309
  "completed",
7200
- workflowCallContent(telemetry, "output", record.data)
7310
+ workflowCallContent(telemetry, "output", record2.data)
7201
7311
  );
7202
7312
  } else {
7203
- record.status = "interrupted";
7204
- record.snapshot = outcome.snapshot;
7313
+ record2.status = "interrupted";
7314
+ record2.snapshot = outcome.snapshot;
7205
7315
  report("suspended", {
7206
7316
  leaf: outcome.request.meta?.workflowCall ?? null
7207
7317
  });
7208
7318
  const interruption = {
7209
7319
  request: outcome.request
7210
7320
  };
7211
- record.interrupts.push(interruption);
7321
+ record2.interrupts.push(interruption);
7212
7322
  if (task.group) throw new ParallelChildWaiting();
7213
7323
  interruption.response = await awaitInterruptInternal({
7214
7324
  request: interruption.request,
@@ -7217,12 +7327,12 @@ ${tryStringify2(args.response)}`
7217
7327
  }
7218
7328
  }
7219
7329
  if (cached) {
7220
- report("reused", workflowCallContent(telemetry, "output", record.data));
7221
- if (record.restoredToolBranch !== telemetry?.correlation?.branchId)
7222
- await replayToolObservations(record.toolObservations ?? [], true);
7223
- delete record.restoredToolBranch;
7330
+ report("reused", workflowCallContent(telemetry, "output", record2.data));
7331
+ if (record2.restoredToolBranch !== telemetry?.correlation?.branchId)
7332
+ await replayToolObservations(record2.toolObservations ?? [], true);
7333
+ delete record2.restoredToolBranch;
7224
7334
  }
7225
- const data = record.data ?? {};
7335
+ const data = record2.data ?? {};
7226
7336
  return {
7227
7337
  data: JSON.parse(JSON.stringify(data))
7228
7338
  };
@@ -7239,6 +7349,7 @@ __export(index_exports, {
7239
7349
  ChatLifecycleHookError: () => ChatLifecycleHookError,
7240
7350
  EvalConfigurationError: () => EvalConfigurationError,
7241
7351
  EvalEvidencePolicySchema: () => EvalEvidencePolicySchema,
7352
+ EvalIssueSchema: () => EvalIssueSchema,
7242
7353
  EvalJudgeIdentitySchema: () => EvalJudgeIdentitySchema,
7243
7354
  EvalJudgeUsageSchema: () => EvalJudgeUsageSchema,
7244
7355
  EvalManifestSchema: () => EvalManifestSchema,
@@ -7260,6 +7371,7 @@ __export(index_exports, {
7260
7371
  createAgent: () => createAgent,
7261
7372
  createChatRouteHandler: () => createChatRouteHandler,
7262
7373
  createCheckpointRouteHandler: () => createCheckpointRouteHandler,
7374
+ createEvalIssue: () => createEvalIssue,
7263
7375
  createEvalJudge: () => createEvalJudge,
7264
7376
  createEvalRouteHandler: () => createEvalRouteHandler,
7265
7377
  createEvals: () => createEvals,
@@ -7288,7 +7400,7 @@ module.exports = __toCommonJS(index_exports);
7288
7400
  // src/adapters/http.ts
7289
7401
  var import_errors5 = require("@kortyx/core/errors");
7290
7402
  var import_stream2 = require("@kortyx/stream");
7291
- var import_zod2 = require("zod");
7403
+ var import_zod3 = require("zod");
7292
7404
 
7293
7405
  // src/chat/lifecycle.ts
7294
7406
  var import_errors = require("@kortyx/core/errors");
@@ -7313,6 +7425,7 @@ var ChatLifecycleHookError = class extends import_errors.KortyxError {
7313
7425
  // src/interrupt/resume-handler.ts
7314
7426
  var import_core3 = require("@kortyx/core");
7315
7427
  var import_runtime2 = require("@kortyx/runtime");
7428
+ var import_utils = require("@kortyx/utils");
7316
7429
 
7317
7430
  // src/execution/types.ts
7318
7431
  var import_errors2 = require("@kortyx/core/errors");
@@ -7336,6 +7449,7 @@ var import_internal = __toESM(require_internal());
7336
7449
  var import_runtime = require("@kortyx/runtime");
7337
7450
  var import_stream = require("@kortyx/stream");
7338
7451
  var import_langgraph = require("@langchain/langgraph");
7452
+ var import_zod2 = require("zod");
7339
7453
 
7340
7454
  // src/execution/contracts.ts
7341
7455
  var import_errors3 = require("@kortyx/core/errors");
@@ -7397,12 +7511,12 @@ async function validateExecutionOutput(state, select) {
7397
7511
  if (terminal.outputSchema || root.outputSchema) import_zod.z.json().parse(data);
7398
7512
  } catch (error) {
7399
7513
  if (!(error instanceof import_zod.z.ZodError)) throw error;
7400
- const failure2 = new import_errors3.ValidationError(
7514
+ const failure = new import_errors3.ValidationError(
7401
7515
  "INVALID_OUTPUT",
7402
7516
  `Workflow output validation failed: ${error.message}`,
7403
7517
  error
7404
7518
  );
7405
- throw failure2;
7519
+ throw failure;
7406
7520
  }
7407
7521
  return { ...state, data };
7408
7522
  }
@@ -7792,7 +7906,7 @@ var import_node = require("@kortyx/usage-telemetry/node");
7792
7906
  // package.json
7793
7907
  var package_default = {
7794
7908
  name: "@kortyx/agent",
7795
- version: "0.37.1",
7909
+ version: "0.38.1",
7796
7910
  private: false,
7797
7911
  description: "Agent composition utilities for Kortyx.",
7798
7912
  keywords: [
@@ -8056,6 +8170,24 @@ async function orchestrateGraphStream({
8056
8170
  isRecord3(config.context) ? { userId: config.context.userId, tenantId: config.context.tenantId } : {}
8057
8171
  );
8058
8172
  const telemetryConfig = isRecord3(config.telemetry) ? config.telemetry : {};
8173
+ const errorChunk = (error, existingDiagnosticId) => {
8174
+ const failure = (0, import_errors4.serializeFailure)(error);
8175
+ let diagnosticId = existingDiagnosticId;
8176
+ if (!diagnosticId) {
8177
+ try {
8178
+ diagnosticId = traceAdapter?.reportError?.(error, {
8179
+ correlation: { runId, ...sessionId ? { sessionId } : {} }
8180
+ });
8181
+ } catch {
8182
+ }
8183
+ }
8184
+ return {
8185
+ type: "error",
8186
+ message: failure.message,
8187
+ failure,
8188
+ ...typeof diagnosticId === "string" && import_zod2.z.uuid().safeParse(diagnosticId).success ? { diagnosticId } : {}
8189
+ };
8190
+ };
8059
8191
  const emitResumeFailure = (resumeError) => {
8060
8192
  const interruptId = typeof config.telemetryInterruptId === "string" ? config.telemetryInterruptId : void 0;
8061
8193
  if (!interruptId) return;
@@ -8322,11 +8454,12 @@ async function orchestrateGraphStream({
8322
8454
  );
8323
8455
  const supplied = payload?.failure;
8324
8456
  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
- });
8457
+ write(
8458
+ errorChunk(
8459
+ outcomeError,
8460
+ payload?.diagnosticId
8461
+ )
8462
+ );
8330
8463
  write({ type: "done" });
8331
8464
  finished = true;
8332
8465
  out.end();
@@ -8695,11 +8828,7 @@ async function orchestrateGraphStream({
8695
8828
  runTraceSpan.addEvent?.("kortyx.transition.error", {
8696
8829
  transitionTo
8697
8830
  });
8698
- write({
8699
- type: "error",
8700
- message: (0, import_errors4.serializeFailure)(err).message,
8701
- failure: (0, import_errors4.serializeFailure)(err)
8702
- });
8831
+ write(errorChunk(err));
8703
8832
  write({ type: "done" });
8704
8833
  out.end();
8705
8834
  return;
@@ -8969,7 +9098,15 @@ async function orchestrateGraphStream({
8969
9098
  if ((0, import_core2.isExecutionLimitReached)(err)) {
8970
9099
  usageLimitReached = true;
8971
9100
  try {
8972
- const snapshot = frameworkAdapter && await (0, import_runtime.captureGraphSnapshot)(frameworkAdapter.checkpointer, runId);
9101
+ const snapshot = frameworkAdapter && await (0, import_runtime.captureGraphSnapshot)(
9102
+ frameworkAdapter.checkpointer,
9103
+ runId,
9104
+ void 0,
9105
+ {
9106
+ runtimePatch,
9107
+ response: currentGraph.execution?.resumeDelivery
9108
+ }
9109
+ );
8973
9110
  (0, import_core2.throwIfExecutionAborted)(abortSignal);
8974
9111
  if (!snapshot)
8975
9112
  throw new Error(
@@ -9083,11 +9220,7 @@ async function orchestrateGraphStream({
9083
9220
  fallbackRunSpan?.fail?.(err);
9084
9221
  emitResumeFailure(err);
9085
9222
  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
- });
9223
+ write(errorChunk(err));
9091
9224
  write({ type: "done" });
9092
9225
  finished = true;
9093
9226
  out.end();
@@ -9300,12 +9433,13 @@ async function tryPrepareResumeStream({
9300
9433
  }
9301
9434
  } : {};
9302
9435
  if (isLimitPause && pending.graphSnapshot) {
9436
+ pending.graphSnapshot = (0, import_runtime2.prepareSuspensionSnapshot)(pending.graphSnapshot);
9303
9437
  pending.graphSnapshot.checkpoint.channel_values.config = telemetryConfig;
9304
9438
  if (resumeStatePatch)
9305
- pending.graphSnapshot.checkpoint.channel_values.runtime = {
9306
- ...pending.graphSnapshot.checkpoint.channel_values.runtime,
9307
- ...resumeStatePatch
9308
- };
9439
+ pending.graphSnapshot.checkpoint.channel_values.runtime = (0, import_utils.mergeRuntimeState)(
9440
+ pending.graphSnapshot.checkpoint.channel_values.runtime,
9441
+ resumeStatePatch
9442
+ );
9309
9443
  }
9310
9444
  leaseAbort.signal.throwIfAborted();
9311
9445
  if (pending.graphSnapshot && frameworkAdapter)
@@ -9324,8 +9458,17 @@ async function tryPrepareResumeStream({
9324
9458
  resumeUpdate.runtime = resumeStatePatch;
9325
9459
  }
9326
9460
  const hasResumeUpdate = !isLimitPause && Object.keys(resumeUpdate).length > 0;
9327
- const resumeValue = isLimitPause ? void 0 : meta.hasValue && pending.schema.kind === "custom" ? meta.value : meta.selected?.length && pending.schema.kind === "multi-choice" ? meta.selected.map((x) => String(x)) : meta.selected?.length ? String(meta.selected[0]) : void 0;
9461
+ const outstandingResponse = isLimitPause ? pending.graphSnapshot?.suspension?.response : void 0;
9462
+ const humanValue = isLimitPause ? outstandingResponse?.value : meta.hasValue && pending.schema.kind === "custom" ? meta.value : meta.selected?.length && pending.schema.kind === "multi-choice" ? meta.selected.map((x) => String(x)) : meta.selected?.length ? String(meta.selected[0]) : void 0;
9328
9463
  const resumeCheckpointId = typeof pending.graphCheckpointId === "string" && pending.graphCheckpointId.length > 0 ? pending.graphCheckpointId : void 0;
9464
+ const resumeDelivery = isLimitPause ? outstandingResponse : humanValue !== void 0 ? (0, import_runtime2.createResumeDelivery)(
9465
+ pending.requestId,
9466
+ pending.node,
9467
+ pending.schema,
9468
+ humanValue,
9469
+ pending.graphSnapshot
9470
+ ) : void 0;
9471
+ const resumeValue = resumeDelivery ? (0, import_runtime2.resumeDeliveryInput)(resumeDelivery) : humanValue;
9329
9472
  const resumedGraph = await (0, import_runtime2.createExecutionGraph)(wf, {
9330
9473
  ...telemetryConfig,
9331
9474
  resume: true,
@@ -9333,6 +9476,8 @@ async function tryPrepareResumeStream({
9333
9476
  ...resumeCheckpointId ? { resumeCheckpointId } : {},
9334
9477
  ...hasResumeUpdate ? { resumeUpdate } : {}
9335
9478
  });
9479
+ resumedGraph.execution ??= {};
9480
+ resumedGraph.execution.resumeDelivery = resumeDelivery;
9336
9481
  await store.delete(pending.token);
9337
9482
  const response = meta.hasValue ? JSON.stringify(meta.value) : responseFromSelection(meta.selected);
9338
9483
  const telemetry = isRecord4(telemetryConfig.telemetry) ? telemetryConfig.telemetry : {};
@@ -9432,38 +9577,38 @@ var reportLifecycleError = async (callback, event) => {
9432
9577
  console.error("[chat:onLifecycleError]", (0, import_errors5.serializeFailure)(error));
9433
9578
  }
9434
9579
  };
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()
9580
+ var chatMessageSchema = import_zod3.z.object({
9581
+ role: import_zod3.z.enum(["user", "assistant", "system"]),
9582
+ content: import_zod3.z.string(),
9583
+ metadata: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional(),
9584
+ id: import_zod3.z.string().optional(),
9585
+ timestamp: import_zod3.z.number().refine(Number.isFinite).optional()
9441
9586
  }).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)
9587
+ var chatRequestBodySchema = import_zod3.z.looseObject({
9588
+ sessionId: import_zod3.z.string().optional(),
9589
+ clientTurnId: import_zod3.z.string().max(128).optional(),
9590
+ workflowId: import_zod3.z.string().optional(),
9591
+ stream: import_zod3.z.boolean().optional(),
9592
+ context: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional(),
9593
+ messages: import_zod3.z.array(chatMessageSchema)
9449
9594
  });
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)
9595
+ var checkpointRequestBodySchema = import_zod3.z.discriminatedUnion("action", [
9596
+ import_zod3.z.object({
9597
+ action: import_zod3.z.literal("list"),
9598
+ sessionId: import_zod3.z.string().min(1)
9454
9599
  }).strict(),
9455
- import_zod2.z.object({
9456
- action: import_zod2.z.literal("get"),
9457
- checkpointId: import_zod2.z.string().min(1)
9600
+ import_zod3.z.object({
9601
+ action: import_zod3.z.literal("get"),
9602
+ checkpointId: import_zod3.z.string().min(1)
9458
9603
  }).strict(),
9459
- import_zod2.z.object({
9460
- action: import_zod2.z.literal("rollback"),
9461
- checkpointId: import_zod2.z.string().min(1)
9604
+ import_zod3.z.object({
9605
+ action: import_zod3.z.literal("rollback"),
9606
+ checkpointId: import_zod3.z.string().min(1)
9462
9607
  }).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()
9608
+ import_zod3.z.object({
9609
+ action: import_zod3.z.literal("fork"),
9610
+ checkpointId: import_zod3.z.string().min(1),
9611
+ newSessionId: import_zod3.z.string().min(1).optional()
9467
9612
  }).strict()
9468
9613
  ]);
9469
9614
  async function readRequestJson(request) {
@@ -9486,10 +9631,10 @@ async function readRequestJson(request) {
9486
9631
  }
9487
9632
  }
9488
9633
  function createFailureResponse(error, status2) {
9489
- const failure2 = (0, import_errors5.serializeFailure)(error);
9634
+ const failure = (0, import_errors5.serializeFailure)(error);
9490
9635
  return Response.json(
9491
- { error: failure2.message, failure: failure2 },
9492
- { status: status2 ?? (0, import_errors5.failureHttpStatus)(failure2) }
9636
+ { error: failure.message, failure },
9637
+ { status: status2 ?? (0, import_errors5.failureHttpStatus)(failure) }
9493
9638
  );
9494
9639
  }
9495
9640
  function parseChatRequestBody(value) {
@@ -9723,7 +9868,7 @@ var import_node_path = require("path");
9723
9868
  var import_core5 = require("@kortyx/core");
9724
9869
  var import_providers = require("@kortyx/providers");
9725
9870
  var import_runtime5 = require("@kortyx/runtime");
9726
- var import_zod5 = require("zod");
9871
+ var import_zod6 = require("zod");
9727
9872
 
9728
9873
  // src/evals/prompt-context.ts
9729
9874
  var import_node_async_hooks = require("async_hooks");
@@ -9733,21 +9878,21 @@ var promptEvaluationContext = new import_node_async_hooks.AsyncLocalStorage();
9733
9878
  var import_core4 = require("@kortyx/core");
9734
9879
  var import_errors6 = require("@kortyx/core/errors");
9735
9880
  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)
9881
+ var import_zod4 = require("zod");
9882
+ var handleSchema = import_zod4.z.object({
9883
+ token: import_zod4.z.string().min(1),
9884
+ requestId: import_zod4.z.string().min(1),
9885
+ sessionId: import_zod4.z.string().min(1),
9886
+ runId: import_zod4.z.string().min(1)
9742
9887
  }).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)
9888
+ var responseSchema = import_zod4.z.discriminatedUnion("type", [
9889
+ import_zod4.z.object({ type: import_zod4.z.literal("text"), text: import_zod4.z.string().min(1) }).strict(),
9890
+ import_zod4.z.object({
9891
+ type: import_zod4.z.literal("select"),
9892
+ ids: import_zod4.z.array(import_zod4.z.string().min(1)).min(1)
9748
9893
  }).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()
9894
+ import_zod4.z.object({ type: import_zod4.z.literal("value"), value: import_zod4.z.unknown() }).strict(),
9895
+ import_zod4.z.object({ type: import_zod4.z.literal("cancel") }).strict()
9751
9896
  ]);
9752
9897
  function resultFromOutcome(outcome, runId, sessionId) {
9753
9898
  const usage2 = outcome.pending?.schema.meta?.__kortyxResumeStatePatch?.tokenUsage ?? outcome.error?.__kortyxHookStatePatch?.tokenUsage ?? outcome.state.runtime?.tokenUsage;
@@ -9872,7 +10017,7 @@ async function executeWorkflow(services, args) {
9872
10017
  });
9873
10018
  }
9874
10019
  async function resumeWorkflow(services, args) {
9875
- const parsed = import_zod3.z.object({ resume: handleSchema, response: responseSchema }).safeParse(args);
10020
+ const parsed = import_zod4.z.object({ resume: handleSchema, response: responseSchema }).safeParse(args);
9876
10021
  if (!parsed.success)
9877
10022
  throw new ExecutionRequestError("INVALID_RESUME", parsed.error.message);
9878
10023
  const { resume: handle, response } = parsed.data;
@@ -9957,13 +10102,13 @@ async function resumeWorkflow(services, args) {
9957
10102
  }
9958
10103
 
9959
10104
  // 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()])
10105
+ var import_zod5 = require("zod");
10106
+ var scopeSchema = import_zod5.z.object({
10107
+ sessionId: import_zod5.z.string().min(1).optional(),
10108
+ runId: import_zod5.z.string().min(1).optional(),
10109
+ context: import_zod5.z.record(
10110
+ import_zod5.z.string(),
10111
+ import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number(), import_zod5.z.boolean(), import_zod5.z.null()])
9967
10112
  ).optional()
9968
10113
  }).strict().refine(
9969
10114
  (scope) => Boolean(
@@ -10011,15 +10156,15 @@ function createInterruptDiscovery(store) {
10011
10156
  status: _status,
10012
10157
  afterResponseCompleted,
10013
10158
  ...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()])
10159
+ } = import_zod5.z.object({
10160
+ sessionId: import_zod5.z.string().optional(),
10161
+ runId: import_zod5.z.string().optional(),
10162
+ context: import_zod5.z.record(
10163
+ import_zod5.z.string(),
10164
+ import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number(), import_zod5.z.boolean(), import_zod5.z.null()])
10020
10165
  ).optional(),
10021
- status: import_zod4.z.literal("pending").optional(),
10022
- afterResponseCompleted: import_zod4.z.boolean().optional()
10166
+ status: import_zod5.z.literal("pending").optional(),
10167
+ afterResponseCompleted: import_zod5.z.boolean().optional()
10023
10168
  }).strict().parse(options);
10024
10169
  scopeSchema.parse(scope);
10025
10170
  return (await records()).filter(
@@ -10029,7 +10174,7 @@ function createInterruptDiscovery(store) {
10029
10174
  ).map(summary);
10030
10175
  },
10031
10176
  async getInterrupt(id3, scope) {
10032
- import_zod4.z.string().min(1).parse(id3);
10177
+ import_zod5.z.string().min(1).parse(id3);
10033
10178
  scopeSchema.parse(scope);
10034
10179
  const record = (await records()).find(
10035
10180
  (record2) => record2.requestId === id3 && matches(record2, scope)
@@ -10153,10 +10298,10 @@ var import_errors7 = require("@kortyx/core/errors");
10153
10298
  var import_runtime4 = require("@kortyx/runtime");
10154
10299
 
10155
10300
  // 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];
10301
+ function extractLatestUserMessage(messages2) {
10302
+ if (!messages2 || messages2.length === 0) return "";
10303
+ for (let i = messages2.length - 1; i >= 0; i -= 1) {
10304
+ const msg = messages2[i];
10160
10305
  if (msg?.role === "user" && msg?.content?.trim()) {
10161
10306
  return msg.content.trim();
10162
10307
  }
@@ -10166,7 +10311,7 @@ function extractLatestUserMessage(messages) {
10166
10311
 
10167
10312
  // src/chat/process-chat.ts
10168
10313
  async function streamChat({
10169
- messages,
10314
+ messages: messages2,
10170
10315
  abortSignal,
10171
10316
  executionSignal,
10172
10317
  onExecution,
@@ -10211,9 +10356,9 @@ async function streamChat({
10211
10356
  runtimeConfig2.selectWorkflow = workflowSelector;
10212
10357
  const fallbackSessionId = options?.sessionId;
10213
10358
  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);
10359
+ const last = messages2[messages2.length - 1];
10360
+ const input = extractLatestUserMessage(messages2);
10361
+ const previousMessages = messages2.slice(0, -1);
10217
10362
  const runtime = {
10218
10363
  ...previousMessages.length > 0 ? { priorMessages: previousMessages } : {}
10219
10364
  };
@@ -10326,30 +10471,30 @@ async function streamChat({
10326
10471
  }
10327
10472
 
10328
10473
  // 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(
10474
+ var agentProcessOptionsSchema = import_zod6.z.object({
10475
+ executionSignal: import_zod6.z.custom((value) => value instanceof AbortSignal).optional(),
10476
+ onExecution: import_zod6.z.custom(
10332
10477
  (value) => typeof value === "function"
10333
10478
  ).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(),
10479
+ clientTurnId: import_zod6.z.string().min(1).max(128).optional(),
10480
+ continueOnDisconnect: import_zod6.z.boolean().optional(),
10481
+ onResponseFinalized: import_zod6.z.custom((value) => typeof value === "function").optional(),
10337
10482
  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()
10483
+ abortSignal: import_zod6.z.custom((value) => value instanceof AbortSignal).optional(),
10484
+ sessionId: import_zod6.z.string().optional(),
10485
+ workflowId: import_zod6.z.string().optional(),
10486
+ context: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.unknown()).optional()
10342
10487
  }).strict();
10343
- var createAgentArgsBaseSchema = import_zod5.z.object({
10488
+ var createAgentArgsBaseSchema = import_zod6.z.object({
10344
10489
  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()
10490
+ getProvider: import_zod6.z.unknown().optional(),
10491
+ workflows: import_zod6.z.array(import_zod6.z.unknown()).optional(),
10492
+ workflowsDir: import_zod6.z.string().optional(),
10493
+ workflowRegistry: import_zod6.z.unknown().optional(),
10494
+ defaultWorkflowId: import_zod6.z.string().optional(),
10495
+ frameworkAdapter: import_zod6.z.unknown().optional(),
10496
+ telemetry: import_zod6.z.unknown().optional(),
10497
+ prompts: import_zod6.z.unknown().optional()
10353
10498
  }).strict();
10354
10499
  var createAgentArgsSchema = createAgentArgsBaseSchema.superRefine(
10355
10500
  (value, ctx) => {
@@ -10451,7 +10596,22 @@ function createAgentInternal(args) {
10451
10596
  (registry) => registry?.list?.()
10452
10597
  );
10453
10598
  void registeredWorkflowsPromise.then(
10454
- () => registryUsage.end(),
10599
+ (registered) => {
10600
+ try {
10601
+ registryUsage.end(
10602
+ "success",
10603
+ registered ? {
10604
+ data_reducers: registered.some(
10605
+ (workflow) => Object.values(workflow.reduce ?? {}).some(
10606
+ (callback) => typeof callback === "function"
10607
+ )
10608
+ )
10609
+ } : {}
10610
+ );
10611
+ } catch {
10612
+ registryUsage.end();
10613
+ }
10614
+ },
10455
10615
  (error) => registryUsage.fail(error)
10456
10616
  );
10457
10617
  const projectTopology = async (options) => {
@@ -10467,7 +10627,7 @@ function createAgentInternal(args) {
10467
10627
  })
10468
10628
  );
10469
10629
  };
10470
- const streamChatInternal = async (messages, options) => {
10630
+ const streamChatInternal = async (messages2, options) => {
10471
10631
  const parsedOptions = parseAgentProcessOptions(options);
10472
10632
  const promptEvaluation = promptEvaluationContext.getStore();
10473
10633
  if (promptEvaluation && !prompts)
@@ -10486,7 +10646,7 @@ function createAgentInternal(args) {
10486
10646
  );
10487
10647
  return streamChat({
10488
10648
  ...resolvedDefaultWorkflowId ? { defaultWorkflowId: resolvedDefaultWorkflowId } : {},
10489
- messages,
10649
+ messages: messages2,
10490
10650
  abortSignal: parsedOptions?.abortSignal,
10491
10651
  executionSignal: parsedOptions?.executionSignal,
10492
10652
  onExecution: parsedOptions?.onExecution,
@@ -10524,9 +10684,9 @@ function createAgentInternal(args) {
10524
10684
  })
10525
10685
  });
10526
10686
  };
10527
- const streamChat2 = (messages, options) => usage.measure(
10687
+ const streamChat2 = (messages2, options) => usage.measure(
10528
10688
  "sdk.chat.admission",
10529
- () => streamChatInternal(messages, options),
10689
+ () => streamChatInternal(messages2, options),
10530
10690
  {
10531
10691
  phase: "admission",
10532
10692
  continue_on_disconnect: options?.continueOnDisconnect === true
@@ -10682,6 +10842,12 @@ function createAgentInternal(args) {
10682
10842
  ));
10683
10843
  return {
10684
10844
  ...createInterruptDiscovery(resolvedFrameworkAdapter.pendingRequests),
10845
+ reportError: (error, options) => {
10846
+ try {
10847
+ return telemetry?.trace?.reportError?.(error, options);
10848
+ } catch {
10849
+ }
10850
+ },
10685
10851
  execute,
10686
10852
  resume,
10687
10853
  projectTopology,
@@ -10689,8 +10855,8 @@ function createAgentInternal(args) {
10689
10855
  describePromptContracts: () => (prompts?.definitions ?? []).map((ref) => ({
10690
10856
  id: ref.id,
10691
10857
  format: ref.format,
10692
- variablesSchema: import_zod5.z.toJSONSchema(ref.variables, { io: "input" }),
10693
- configSchema: import_zod5.z.toJSONSchema(ref.config, { io: "input" })
10858
+ variablesSchema: import_zod6.z.toJSONSchema(ref.variables, { io: "input" }),
10859
+ configSchema: import_zod6.z.toJSONSchema(ref.config, { io: "input" })
10694
10860
  })),
10695
10861
  listCheckpoints,
10696
10862
  getCheckpoint,
@@ -10720,11 +10886,12 @@ function createAgent(args) {
10720
10886
  }
10721
10887
 
10722
10888
  // src/evals/contracts.ts
10889
+ var import_errors8 = require("@kortyx/core/errors");
10723
10890
  var import_browser2 = require("@kortyx/prompts/browser");
10724
- var import_zod7 = require("zod");
10891
+ var import_zod8 = require("zod");
10725
10892
 
10726
10893
  // src/evals/evidence-policy.ts
10727
- var import_zod6 = require("zod");
10894
+ var import_zod7 = require("zod");
10728
10895
  var EVAL_EVIDENCE_EVENT_TYPES = [
10729
10896
  "tool-call-start",
10730
10897
  "tool-call-result",
@@ -10737,19 +10904,19 @@ var EVAL_EVIDENCE_EVENT_TYPES = [
10737
10904
  "cancelled",
10738
10905
  "limit-reached"
10739
10906
  ];
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)),
10907
+ var id = import_zod7.z.string().trim().min(1).max(256);
10908
+ var filter = import_zod7.z.object({ using: id, params: import_zod7.z.json().optional() }).strict();
10909
+ var EvalEvidencePolicySchema = import_zod7.z.object({
10910
+ history: import_zod7.z.boolean().optional(),
10911
+ events: import_zod7.z.union([
10912
+ import_zod7.z.literal(false),
10913
+ import_zod7.z.array(import_zod7.z.enum(EVAL_EVIDENCE_EVENT_TYPES)),
10747
10914
  filter
10748
10915
  ]).optional(),
10749
- outputs: import_zod6.z.union([
10750
- import_zod6.z.literal(false),
10751
- import_zod6.z.array(
10752
- import_zod6.z.object({
10916
+ outputs: import_zod7.z.union([
10917
+ import_zod7.z.literal(false),
10918
+ import_zod7.z.array(
10919
+ import_zod7.z.object({
10753
10920
  dataType: id.optional(),
10754
10921
  schemaId: id.optional(),
10755
10922
  schemaVersion: id.optional()
@@ -10762,26 +10929,29 @@ var EvalEvidencePolicySchema = import_zod6.z.object({
10762
10929
  }).strict();
10763
10930
 
10764
10931
  // 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()
10932
+ var id2 = import_zod8.z.string().trim().min(1).max(256);
10933
+ var failureDescriptor = import_zod8.z.custom(import_errors8.isFailureDescriptor).transform(
10934
+ (value) => JSON.parse(JSON.stringify((0, import_errors8.serializeFailure)(value)))
10935
+ );
10936
+ var handler = import_zod8.z.object({ using: id2, params: import_zod8.z.json().optional() }).strict();
10937
+ var EvalResumeResponseSchema = import_zod8.z.discriminatedUnion("type", [
10938
+ import_zod8.z.object({ type: import_zod8.z.literal("text"), text: import_zod8.z.string() }).strict(),
10939
+ import_zod8.z.object({ type: import_zod8.z.literal("select"), ids: import_zod8.z.array(import_zod8.z.string()) }).strict(),
10940
+ import_zod8.z.object({ type: import_zod8.z.literal("value"), value: import_zod8.z.json() }).strict(),
10941
+ import_zod8.z.object({ type: import_zod8.z.literal("cancel") }).strict()
10772
10942
  ]);
10773
- var expectation = import_zod7.z.object({
10774
- type: import_zod7.z.enum(["answer", "interrupt"]),
10943
+ var expectation = import_zod8.z.object({
10944
+ type: import_zod8.z.enum(["answer", "interrupt"]),
10775
10945
  schemaId: id2.optional(),
10776
10946
  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()
10947
+ outputs: import_zod8.z.array(import_zod8.z.object({ schemaId: id2, schemaVersion: id2.optional() }).strict()).optional(),
10948
+ criteria: import_zod8.z.array(
10949
+ import_zod8.z.union([
10950
+ import_zod8.z.string().trim().min(1),
10951
+ import_zod8.z.object({ id: id2, text: import_zod8.z.string().trim().min(1) }).strict()
10782
10952
  ])
10783
10953
  ).optional(),
10784
- reference: import_zod7.z.json().optional()
10954
+ reference: import_zod8.z.json().optional()
10785
10955
  }).strict().superRefine((value, ctx) => {
10786
10956
  if (value.type === "answer" && (value.schemaId || value.schemaVersion))
10787
10957
  ctx.addIssue({
@@ -10797,21 +10967,21 @@ var expectation = import_zod7.z.object({
10797
10967
  message: "Criterion IDs must be unique within a step."
10798
10968
  });
10799
10969
  });
10800
- var EvalSuiteSchema = import_zod7.z.object({
10970
+ var EvalSuiteSchema = import_zod8.z.object({
10801
10971
  evidence: EvalEvidencePolicySchema.optional(),
10802
10972
  id: id2,
10803
- name: import_zod7.z.string().optional(),
10804
- cases: import_zod7.z.array(
10805
- import_zod7.z.object({
10973
+ name: import_zod8.z.string().optional(),
10974
+ cases: import_zod8.z.array(
10975
+ import_zod8.z.object({
10806
10976
  id: id2,
10807
- name: import_zod7.z.string().optional(),
10808
- params: import_zod7.z.json().optional(),
10977
+ name: import_zod8.z.string().optional(),
10978
+ params: import_zod8.z.json().optional(),
10809
10979
  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]),
10980
+ steps: import_zod8.z.array(
10981
+ import_zod8.z.union([
10982
+ import_zod8.z.object({ message: import_zod8.z.string().min(1), expect: expectation }).strict(),
10983
+ import_zod8.z.object({
10984
+ resume: import_zod8.z.union([EvalResumeResponseSchema, handler]),
10815
10985
  expect: expectation
10816
10986
  }).strict()
10817
10987
  ])
@@ -10819,42 +10989,44 @@ var EvalSuiteSchema = import_zod7.z.object({
10819
10989
  }).strict()
10820
10990
  ).min(1)
10821
10991
  }).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))
10992
+ var EvalVerdictSchema = import_zod8.z.object({
10993
+ passed: import_zod8.z.boolean(),
10994
+ reason: import_zod8.z.string().trim().min(1),
10995
+ evidence: import_zod8.z.array(import_zod8.z.string().min(1))
10826
10996
  }).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()
10997
+ var EvalObservationSchema = import_zod8.z.object({
10998
+ failure: failureDescriptor.optional(),
10999
+ diagnosticId: import_zod8.z.uuid().optional(),
11000
+ promptUsage: import_zod8.z.array(
11001
+ import_zod8.z.object({
11002
+ id: import_zod8.z.string(),
11003
+ version: import_zod8.z.number().int().positive(),
11004
+ hash: import_zod8.z.string().regex(/^[a-f0-9]{64}$/),
11005
+ environment: import_zod8.z.string(),
11006
+ snapshotRevision: import_zod8.z.string(),
11007
+ model: import_zod8.z.string().optional()
10836
11008
  }).strict()
10837
11009
  ).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()
11010
+ type: import_zod8.z.enum(["answer", "interrupt", "error", "cancelled"]),
11011
+ text: import_zod8.z.string(),
11012
+ structured: import_zod8.z.array(import_zod8.z.json()),
11013
+ events: import_zod8.z.array(import_zod8.z.json()).optional(),
11014
+ runId: import_zod8.z.string().optional(),
11015
+ checkpointId: import_zod8.z.string().optional(),
11016
+ interrupt: import_zod8.z.object({
11017
+ requestId: import_zod8.z.string(),
11018
+ kind: import_zod8.z.enum(["text", "choice", "multi-choice", "custom"]),
11019
+ question: import_zod8.z.string().optional(),
11020
+ schemaId: import_zod8.z.string().optional(),
11021
+ schemaVersion: import_zod8.z.string().optional(),
11022
+ options: import_zod8.z.array(
11023
+ import_zod8.z.object({
11024
+ id: import_zod8.z.string(),
11025
+ label: import_zod8.z.string(),
11026
+ description: import_zod8.z.string().optional()
10855
11027
  }).strict()
10856
11028
  ),
10857
- request: import_zod7.z.json().optional()
11029
+ request: import_zod8.z.json().optional()
10858
11030
  }).strict().optional()
10859
11031
  }).strict().superRefine((value, ctx) => {
10860
11032
  if (value.type === "interrupt" !== Boolean(value.interrupt))
@@ -10863,195 +11035,211 @@ var EvalObservationSchema = import_zod7.z.object({
10863
11035
  message: "Interrupt observations require exactly one interrupt."
10864
11036
  });
10865
11037
  });
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([
11038
+ var status = import_zod8.z.enum(["passed", "failed", "error", "cancelled", "ungraded"]);
11039
+ var EvalIssueSchema = import_zod8.z.object({
11040
+ failure: failureDescriptor.optional(),
11041
+ diagnosticId: import_zod8.z.uuid().optional(),
11042
+ phase: import_zod8.z.enum([
10869
11043
  "params",
10870
11044
  "setup",
10871
11045
  "execute",
10872
11046
  "responder",
10873
11047
  "reference",
10874
11048
  "grading",
11049
+ "verification",
10875
11050
  "cleanup",
10876
11051
  "reporting"
10877
11052
  ]),
10878
- code: import_zod7.z.string(),
10879
- message: import_zod7.z.string()
11053
+ code: import_zod8.z.string(),
11054
+ message: import_zod8.z.string()
10880
11055
  }).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()
11056
+ var issue = EvalIssueSchema;
11057
+ var EvalJudgeUsageSchema = import_zod8.z.object({
11058
+ provider: import_zod8.z.string().min(1),
11059
+ model: import_zod8.z.string().min(1),
11060
+ occurredAt: import_zod8.z.iso.datetime(),
11061
+ usage: import_zod8.z.object({
11062
+ input: import_zod8.z.number().finite().nonnegative().optional(),
11063
+ output: import_zod8.z.number().finite().nonnegative().optional(),
11064
+ total: import_zod8.z.number().finite().nonnegative().optional(),
11065
+ reasoning: import_zod8.z.number().finite().nonnegative().optional(),
11066
+ cacheRead: import_zod8.z.number().finite().nonnegative().optional(),
11067
+ cacheWrite: import_zod8.z.number().finite().nonnegative().optional(),
11068
+ cacheWrite1h: import_zod8.z.number().finite().nonnegative().optional(),
11069
+ outputIncludesReasoning: import_zod8.z.boolean().optional(),
11070
+ inputIncludesCacheRead: import_zod8.z.boolean().optional(),
11071
+ inputIncludesCacheWrite: import_zod8.z.boolean().optional()
10896
11072
  }).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()
11073
+ pricingContext: import_zod8.z.object({
11074
+ serviceTier: import_zod8.z.string().min(1).max(100).optional(),
11075
+ inferenceGeo: import_zod8.z.string().min(1).max(100).optional(),
11076
+ speed: import_zod8.z.string().min(1).max(100).optional()
10901
11077
  }).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()
11078
+ pricing: import_zod8.z.object({
11079
+ source: import_zod8.z.literal("provider"),
11080
+ currency: import_zod8.z.literal("USD"),
11081
+ actualCostMicros: import_zod8.z.number().int().nonnegative().safe()
10906
11082
  }).strict().optional()
10907
11083
  }).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(),
11084
+ var EvalStepResultSchema = import_zod8.z.object({
11085
+ evidence: import_zod8.z.object({
11086
+ version: import_zod8.z.literal("compact-v1"),
11087
+ history: import_zod8.z.boolean(),
10912
11088
  observation: EvalObservationSchema
10913
11089
  }).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()
11090
+ index: import_zod8.z.number().int().nonnegative(),
11091
+ input: import_zod8.z.union([
11092
+ import_zod8.z.object({ message: import_zod8.z.string() }).strict(),
11093
+ import_zod8.z.object({ resume: EvalResumeResponseSchema }).strict()
10918
11094
  ]),
10919
11095
  expectation,
10920
11096
  observation: EvalObservationSchema,
10921
- reference: import_zod7.z.json().optional(),
11097
+ reference: import_zod8.z.json().optional(),
10922
11098
  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() })
11099
+ reason: import_zod8.z.string().optional(),
11100
+ judgeCalls: import_zod8.z.number().int().nonnegative().optional(),
11101
+ judgeUsage: import_zod8.z.array(EvalJudgeUsageSchema).optional(),
11102
+ criteria: import_zod8.z.array(
11103
+ EvalVerdictSchema.extend({ id: import_zod8.z.string(), text: import_zod8.z.string() })
10928
11104
  )
10929
11105
  }).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({
11106
+ var runtimeExecution = import_zod8.z.object({ sessionId: import_zod8.z.string().min(1), runId: import_zod8.z.string().min(1) }).strict();
11107
+ var EvalCaseResultSchema = import_zod8.z.object({
11108
+ verification: EvalVerdictSchema.optional(),
11109
+ phaseDurationsMs: import_zod8.z.partialRecord(issue.shape.phase, import_zod8.z.number().finite().nonnegative()).optional(),
10932
11110
  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(),
11111
+ repetition: import_zod8.z.number().int().positive(),
11112
+ attemptId: import_zod8.z.uuid().optional(),
11113
+ runtimeExecutions: import_zod8.z.array(runtimeExecution).optional(),
11114
+ sessionId: import_zod8.z.string(),
10937
11115
  status,
10938
- durationMs: import_zod7.z.number().nonnegative(),
10939
- steps: import_zod7.z.array(EvalStepResultSchema),
10940
- errors: import_zod7.z.array(issue)
11116
+ durationMs: import_zod8.z.number().nonnegative(),
11117
+ steps: import_zod8.z.array(EvalStepResultSchema),
11118
+ errors: import_zod8.z.array(issue)
10941
11119
  }).strict();
10942
- var EvalJudgeIdentitySchema = import_zod7.z.object({
11120
+ var EvalJudgeIdentitySchema = import_zod8.z.object({
10943
11121
  id: id2,
10944
11122
  version: id2,
10945
- location: import_zod7.z.enum(["app", "studio"]).optional()
11123
+ location: import_zod8.z.enum(["app", "studio"]).optional()
10946
11124
  }).strict();
10947
11125
  var judge = EvalJudgeIdentitySchema;
10948
- var StudioEvalJudgeRequestSchema = import_zod7.z.object({
11126
+ var StudioEvalJudgeRequestSchema = import_zod8.z.object({
10949
11127
  environment: id2,
10950
11128
  judge: EvalJudgeIdentitySchema,
10951
- criterion: import_zod7.z.object({ id: id2, text: import_zod7.z.string().trim().min(1).max(16384) }).strict(),
11129
+ criterion: import_zod8.z.object({ id: id2, text: import_zod8.z.string().trim().min(1).max(16384) }).strict(),
10952
11130
  input: EvalStepResultSchema.shape.input,
10953
11131
  observation: EvalObservationSchema,
10954
- reference: import_zod7.z.json().optional(),
10955
- conversation: import_zod7.z.array(EvalStepResultSchema).max(100)
11132
+ reference: import_zod8.z.json().optional(),
11133
+ conversation: import_zod8.z.array(EvalStepResultSchema).max(100)
10956
11134
  }).strict();
10957
- var StudioEvalJudgeResponseSchema = import_zod7.z.object({
11135
+ var StudioEvalJudgeResponseSchema = import_zod8.z.object({
10958
11136
  judge: EvalJudgeIdentitySchema,
10959
11137
  verdict: EvalVerdictSchema,
10960
- usage: import_zod7.z.array(EvalJudgeUsageSchema).optional()
11138
+ usage: import_zod8.z.array(EvalJudgeUsageSchema).optional()
10961
11139
  }).strict();
10962
- var EvalRunResultSchema = import_zod7.z.object({
10963
- id: import_zod7.z.uuid(),
11140
+ var EvalRunResultSchema = import_zod8.z.object({
11141
+ id: import_zod8.z.uuid(),
10964
11142
  suiteId: id2,
10965
- suiteRevision: import_zod7.z.string().regex(/^[a-f0-9]{64}$/),
11143
+ suiteRevision: import_zod8.z.string().regex(/^[a-f0-9]{64}$/),
10966
11144
  suite: EvalSuiteSchema,
10967
11145
  judge: judge.optional(),
10968
- startedAt: import_zod7.z.iso.datetime(),
10969
- durationMs: import_zod7.z.number().nonnegative(),
11146
+ startedAt: import_zod8.z.iso.datetime(),
11147
+ durationMs: import_zod8.z.number().nonnegative(),
10970
11148
  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()
11149
+ counts: import_zod8.z.object({
11150
+ passed: import_zod8.z.number().int().nonnegative(),
11151
+ failed: import_zod8.z.number().int().nonnegative(),
11152
+ error: import_zod8.z.number().int().nonnegative(),
11153
+ cancelled: import_zod8.z.number().int().nonnegative(),
11154
+ ungraded: import_zod8.z.number().int().nonnegative().optional()
10977
11155
  }).strict(),
10978
- cases: import_zod7.z.array(EvalCaseResultSchema),
10979
- errors: import_zod7.z.array(issue)
11156
+ cases: import_zod8.z.array(EvalCaseResultSchema),
11157
+ errors: import_zod8.z.array(issue)
10980
11158
  }).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())
11159
+ var EvalManifestSchema = import_zod8.z.object({
11160
+ schemaVersion: import_zod8.z.literal(1),
11161
+ studioJudging: import_zod8.z.literal(true).optional(),
11162
+ promptContracts: import_zod8.z.array(
11163
+ import_zod8.z.object({
11164
+ id: import_zod8.z.string(),
11165
+ format: import_zod8.z.enum(["system-user", "chat"]),
11166
+ variablesSchema: import_zod8.z.record(import_zod8.z.string(), import_zod8.z.unknown()),
11167
+ configSchema: import_zod8.z.record(import_zod8.z.string(), import_zod8.z.unknown())
10990
11168
  }).strict()
10991
11169
  ).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({
11170
+ attemptScheduling: import_zod8.z.literal(true).optional(),
11171
+ suites: import_zod8.z.array(EvalSuiteSchema),
11172
+ responders: import_zod8.z.array(
11173
+ import_zod8.z.object({
10996
11174
  name: id2,
10997
11175
  schemaId: id2.optional(),
10998
11176
  schemaVersion: id2.optional()
10999
11177
  }).strict()
11000
11178
  ),
11001
- references: import_zod7.z.array(id2),
11002
- paramsSchema: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.unknown()).optional(),
11179
+ references: import_zod8.z.array(id2),
11180
+ paramsSchema: import_zod8.z.record(import_zod8.z.string(), import_zod8.z.unknown()).optional(),
11003
11181
  judge: judge.optional()
11004
11182
  }).strict();
11005
- var EvalProgressSchema = import_zod7.z.discriminatedUnion("type", [
11006
- import_zod7.z.object({
11007
- type: import_zod7.z.literal("case-runtime-associated"),
11183
+ var EvalProgressSchema = import_zod8.z.discriminatedUnion("type", [
11184
+ import_zod8.z.object({
11185
+ type: import_zod8.z.literal("case-dispatch"),
11186
+ caseId: id2,
11187
+ repetition: import_zod8.z.number().int().positive(),
11188
+ status: import_zod8.z.enum(["queued", "retrying", "reconnecting"]),
11189
+ retryAt: import_zod8.z.iso.datetime().optional(),
11190
+ httpStatus: import_zod8.z.number().int().min(100).max(599).optional(),
11191
+ executionId: import_zod8.z.uuid().optional(),
11192
+ generation: import_zod8.z.uuid().optional()
11193
+ }).strict(),
11194
+ import_zod8.z.object({
11195
+ type: import_zod8.z.literal("case-runtime-associated"),
11008
11196
  caseId: id2,
11009
- repetition: import_zod7.z.number().int().positive(),
11010
- attemptId: import_zod7.z.uuid(),
11197
+ repetition: import_zod8.z.number().int().positive(),
11198
+ attemptId: import_zod8.z.uuid(),
11011
11199
  execution: runtimeExecution
11012
11200
  }).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()
11201
+ import_zod8.z.object({
11202
+ type: import_zod8.z.literal("run-started"),
11203
+ caseIds: import_zod8.z.array(id2).min(1),
11204
+ repetitions: import_zod8.z.number().int().positive(),
11205
+ concurrency: import_zod8.z.number().int().positive()
11018
11206
  }).strict(),
11019
- import_zod7.z.object({
11020
- type: import_zod7.z.literal("case-progress"),
11207
+ import_zod8.z.object({
11208
+ type: import_zod8.z.literal("case-progress"),
11021
11209
  caseId: id2,
11022
- repetition: import_zod7.z.number().int().positive(),
11210
+ repetition: import_zod8.z.number().int().positive(),
11023
11211
  phase: issue.shape.phase,
11024
- stepIndex: import_zod7.z.number().int().nonnegative().optional()
11212
+ stepIndex: import_zod8.z.number().int().nonnegative().optional()
11025
11213
  }).strict(),
11026
- import_zod7.z.object({
11027
- type: import_zod7.z.literal("case-started"),
11028
- attemptId: import_zod7.z.uuid().optional(),
11214
+ import_zod8.z.object({
11215
+ type: import_zod8.z.literal("case-started"),
11216
+ attemptId: import_zod8.z.uuid().optional(),
11029
11217
  caseId: id2,
11030
- repetition: import_zod7.z.number().int().positive(),
11031
- sessionId: import_zod7.z.string()
11218
+ repetition: import_zod8.z.number().int().positive(),
11219
+ sessionId: import_zod8.z.string()
11032
11220
  }).strict(),
11033
- import_zod7.z.object({
11034
- type: import_zod7.z.literal("step-completed"),
11221
+ import_zod8.z.object({
11222
+ type: import_zod8.z.literal("step-completed"),
11035
11223
  caseId: id2,
11036
- repetition: import_zod7.z.number().int().positive(),
11224
+ repetition: import_zod8.z.number().int().positive(),
11037
11225
  step: EvalStepResultSchema
11038
11226
  }).strict(),
11039
- import_zod7.z.object({ type: import_zod7.z.literal("case-completed"), result: EvalCaseResultSchema }).strict()
11227
+ import_zod8.z.object({ type: import_zod8.z.literal("case-completed"), result: EvalCaseResultSchema }).strict()
11040
11228
  ]);
11041
- var EvalRemoteRunRequestSchema = import_zod7.z.object({
11229
+ var EvalRemoteRunRequestSchema = import_zod8.z.object({
11042
11230
  promptSnapshot: import_browser2.PromptSnapshotSchema.optional(),
11043
- promptGroupName: import_zod7.z.string().optional(),
11231
+ promptGroupName: import_zod8.z.string().optional(),
11044
11232
  suiteId: id2,
11045
- suiteRevision: import_zod7.z.string().regex(/^[a-f0-9]{64}$/),
11046
- grading: import_zod7.z.enum(["app", "studio"]).optional(),
11233
+ suiteRevision: import_zod8.z.string().regex(/^[a-f0-9]{64}$/),
11234
+ grading: import_zod8.z.enum(["app", "studio"]).optional(),
11047
11235
  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({
11236
+ caseIds: import_zod8.z.array(id2).min(1).max(100).optional(),
11237
+ repetitions: import_zod8.z.number().int().min(1).max(20).default(1),
11238
+ concurrency: import_zod8.z.number().int().min(1).max(20).default(1),
11239
+ attempt: import_zod8.z.object({
11052
11240
  caseId: id2,
11053
- repetition: import_zod7.z.number().int().min(1).max(20),
11054
- evaluationId: import_zod7.z.uuid()
11241
+ repetition: import_zod8.z.number().int().min(1).max(20),
11242
+ evaluationId: import_zod8.z.uuid()
11055
11243
  }).strict().optional()
11056
11244
  }).strict();
11057
11245
  var StudioEvalStartRequestSchema = EvalRemoteRunRequestSchema.omit({
@@ -11061,22 +11249,40 @@ var StudioEvalStartRequestSchema = EvalRemoteRunRequestSchema.omit({
11061
11249
  promptGroupName: true,
11062
11250
  attempt: true
11063
11251
  }).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()
11252
+ promptSelection: import_zod8.z.discriminatedUnion("type", [
11253
+ import_zod8.z.object({ type: import_zod8.z.literal("live") }).strict(),
11254
+ import_zod8.z.object({
11255
+ type: import_zod8.z.literal("single"),
11256
+ id: import_zod8.z.string(),
11257
+ version: import_zod8.z.number().int().positive()
11070
11258
  }).strict(),
11071
- import_zod7.z.object({ type: import_zod7.z.literal("group"), groupId: import_zod7.z.uuid() }).strict()
11259
+ import_zod8.z.object({ type: import_zod8.z.literal("group"), groupId: import_zod8.z.uuid() }).strict()
11072
11260
  ]).optional(),
11073
- targetId: import_zod7.z.string().min(1).max(128),
11074
- judge: import_zod7.z.enum(["studio", "app"]).default("studio")
11261
+ targetId: import_zod8.z.string().min(1).max(128),
11262
+ judge: import_zod8.z.enum(["studio", "app"]).default("studio")
11075
11263
  });
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()
11264
+ var EvalWireEventSchema = import_zod8.z.discriminatedUnion("type", [
11265
+ import_zod8.z.object({
11266
+ type: import_zod8.z.literal("execution-status"),
11267
+ state: import_zod8.z.enum(["queued", "running", "completed", "cancelled", "unknown"])
11268
+ }).strict(),
11269
+ import_zod8.z.object({
11270
+ type: import_zod8.z.literal("progress"),
11271
+ event: EvalProgressSchema,
11272
+ sequence: import_zod8.z.number().int().positive().optional()
11273
+ }).strict(),
11274
+ import_zod8.z.object({
11275
+ type: import_zod8.z.literal("result"),
11276
+ result: EvalRunResultSchema,
11277
+ sequence: import_zod8.z.number().int().positive().optional()
11278
+ }).strict(),
11279
+ import_zod8.z.object({
11280
+ type: import_zod8.z.literal("error"),
11281
+ message: import_zod8.z.string(),
11282
+ failure: failureDescriptor.optional(),
11283
+ diagnosticId: import_zod8.z.uuid().optional(),
11284
+ sequence: import_zod8.z.number().int().positive().optional()
11285
+ }).strict()
11080
11286
  ]);
11081
11287
  var EvalConfigurationError = class extends Error {
11082
11288
  name = "EvalConfigurationError";
@@ -11107,7 +11313,41 @@ function parseEvalSuite(value) {
11107
11313
  var import_node_crypto5 = require("crypto");
11108
11314
  var import_eval_attribution2 = require("@kortyx/core/eval-attribution");
11109
11315
  var import_usage_telemetry = require("@kortyx/usage-telemetry");
11110
- var import_zod8 = require("zod");
11316
+ var import_zod10 = require("zod");
11317
+
11318
+ // src/evals/errors.ts
11319
+ var import_errors9 = require("@kortyx/core/errors");
11320
+ var import_zod9 = require("zod");
11321
+ var messages = {
11322
+ params: "Case parameters failed validation.",
11323
+ setup: "Case setup failed.",
11324
+ execute: "Agent execution failed or returned an invalid observation.",
11325
+ responder: "Interrupt response failed or was incompatible with the waiting contract.",
11326
+ reference: "Reference resolution failed or returned non-JSON data.",
11327
+ grading: "Grading failed or returned an invalid verdict.",
11328
+ verification: "Case verification failed or returned an invalid verdict.",
11329
+ cleanup: "Case cleanup failed.",
11330
+ reporting: "Progress reporting failed."
11331
+ };
11332
+ function createEvalIssue(phase, error, options = {}) {
11333
+ const control = (0, import_errors9.isControlFlowError)(error);
11334
+ const declared = !control && ((0, import_errors9.isFailureDescriptor)(error) || (0, import_errors9.isFailureDescriptor)((0, import_errors9.errorProperty)(error, "failure")));
11335
+ const failure = (0, import_errors9.serializeFailure)(control ? void 0 : error);
11336
+ let diagnosticId = options.diagnosticId ?? (0, import_errors9.errorProperty)(error, "diagnosticId");
11337
+ if (!control && !diagnosticId && options.reportError) {
11338
+ try {
11339
+ diagnosticId = options.reportError(error, options.correlation);
11340
+ } catch {
11341
+ }
11342
+ }
11343
+ return {
11344
+ phase,
11345
+ code: declared ? failure.code : options.code ?? "EVAL_HOOK_FAILED",
11346
+ message: declared ? failure.message : messages[phase],
11347
+ failure,
11348
+ ...typeof diagnosticId === "string" && import_zod9.z.uuid().safeParse(diagnosticId).success ? { diagnosticId } : {}
11349
+ };
11350
+ }
11111
11351
 
11112
11352
  // src/evals/evidence.ts
11113
11353
  var object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
@@ -11234,10 +11474,12 @@ function canonical(value) {
11234
11474
  var getEvalSuiteRevision = (suite) => (0, import_node_crypto4.createHash)("sha256").update(canonical(suite)).digest("hex");
11235
11475
 
11236
11476
  // src/evals/stream.ts
11477
+ var import_errors11 = require("@kortyx/core/errors");
11237
11478
  var import_prompts = require("@kortyx/prompts");
11238
11479
  var import_stream3 = require("@kortyx/stream");
11239
11480
 
11240
11481
  // src/evals/stream-evidence.ts
11482
+ var import_errors10 = require("@kortyx/core/errors");
11241
11483
  function toEvalJson(value) {
11242
11484
  return JSON.parse(JSON.stringify(value));
11243
11485
  }
@@ -11272,7 +11514,9 @@ function captureEvalEvent(chunk) {
11272
11514
  ...source,
11273
11515
  tool: chunk.tool,
11274
11516
  toolCallId: chunk.toolCallId,
11275
- message: chunk.message
11517
+ message: chunk.message,
11518
+ ...chunk.failure ? { failure: (0, import_errors10.serializeFailure)(chunk.failure) } : {},
11519
+ ...chunk.diagnosticId ? { diagnosticId: chunk.diagnosticId } : {}
11276
11520
  });
11277
11521
  case "tool-result":
11278
11522
  return toEvalJson({
@@ -11348,7 +11592,12 @@ function captureEvalEvent(chunk) {
11348
11592
  case "transition":
11349
11593
  return { type: chunk.type, transitionTo: chunk.transitionTo };
11350
11594
  case "error":
11351
- return { type: chunk.type, message: chunk.message };
11595
+ return toEvalJson({
11596
+ type: chunk.type,
11597
+ message: chunk.failure ? (0, import_errors10.serializeFailure)(chunk.failure).message : chunk.message,
11598
+ ...chunk.failure ? { failure: (0, import_errors10.serializeFailure)(chunk.failure) } : {},
11599
+ ...chunk.diagnosticId ? { diagnosticId: chunk.diagnosticId } : {}
11600
+ });
11352
11601
  case "cancelled":
11353
11602
  return toEvalJson({
11354
11603
  type: chunk.type,
@@ -11402,14 +11651,14 @@ async function executeEvalChat(args) {
11402
11651
  return { observation: { type: "cancelled", text: "", structured: [] } };
11403
11652
  }
11404
11653
  const pending = waiting?.[0];
11405
- const messages = [...args.messages ?? args.history];
11654
+ const messages2 = [...args.messages ?? args.history];
11406
11655
  if (args.command.type === "message")
11407
- messages.push({ role: "user", content: args.command.message });
11656
+ messages2.push({ role: "user", content: args.command.message });
11408
11657
  else {
11409
11658
  if (!pending?.resumeToken || !pending.requestId)
11410
11659
  throw new Error("No waiting interrupt to resume.");
11411
11660
  const response = args.command.type === "cancel" ? { type: "cancel" } : args.command.response;
11412
- messages.push({
11661
+ messages2.push({
11413
11662
  role: "user",
11414
11663
  content: response.type === "text" ? response.text : response.type === "select" ? response.ids.join(", ") : response.type === "value" ? JSON.stringify(response.value) : "",
11415
11664
  metadata: {
@@ -11431,6 +11680,7 @@ async function executeEvalChat(args) {
11431
11680
  const events = [];
11432
11681
  let previousChunk;
11433
11682
  let error = false;
11683
+ let terminalFailure;
11434
11684
  let cancelled = false;
11435
11685
  let sawDone = false;
11436
11686
  let completedWithData = false;
@@ -11452,7 +11702,7 @@ async function executeEvalChat(args) {
11452
11702
  ...args.context ? { context: args.context } : {}
11453
11703
  };
11454
11704
  try {
11455
- for await (const chunk of await args.agent.streamChat(messages, options)) {
11705
+ for await (const chunk of await args.agent.streamChat(messages2, options)) {
11456
11706
  accumulator.apply(chunk);
11457
11707
  const event = captureEvalEvent(chunk);
11458
11708
  if (event !== void 0) {
@@ -11466,7 +11716,13 @@ async function executeEvalChat(args) {
11466
11716
  }
11467
11717
  previousChunk = chunk;
11468
11718
  if (chunk.type === "interrupt") interrupts.set(chunk.requestId, chunk);
11469
- if (chunk.type === "error") error = true;
11719
+ if (chunk.type === "error") {
11720
+ error = true;
11721
+ terminalFailure = {
11722
+ ...chunk.failure ? { failure: (0, import_errors11.serializeFailure)(chunk.failure) } : {},
11723
+ ...chunk.diagnosticId ? { diagnosticId: chunk.diagnosticId } : {}
11724
+ };
11725
+ }
11470
11726
  if (chunk.type === "cancelled") cancelled = true;
11471
11727
  if (chunk.type === "trace") runId = chunk.runId;
11472
11728
  if (chunk.type === "done") {
@@ -11486,6 +11742,7 @@ async function executeEvalChat(args) {
11486
11742
  const observedRunId = finalized?.runId ?? runId;
11487
11743
  const type = error || finalized?.status === "failed" || interrupts.size > 1 ? "error" : cancelled || finalized?.status === "cancelled" ? "cancelled" : interrupts.size ? "interrupt" : "answer";
11488
11744
  const observation = {
11745
+ ...terminalFailure,
11489
11746
  type,
11490
11747
  text: message.content,
11491
11748
  structured: message.contentPieces.filter((item) => item.type === "structured").map((item) => toEvalJson(item.data)),
@@ -11527,21 +11784,6 @@ var positive = (value, label) => {
11527
11784
  return value;
11528
11785
  };
11529
11786
  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
11787
  var statusFor = (counts, errors) => errors.length || counts.error ? "error" : counts.cancelled ? "cancelled" : counts.failed ? "failed" : counts.ungraded ? "ungraded" : "passed";
11546
11788
  function createEvals(options) {
11547
11789
  const defaultEvidence = EvalEvidencePolicySchema.parse(
@@ -11591,11 +11833,25 @@ function createEvals(options) {
11591
11833
  options.defaults?.caseTimeoutMs ?? 6e4,
11592
11834
  "caseTimeoutMs"
11593
11835
  ),
11836
+ setupTimeoutMs: positive(
11837
+ options.defaults?.setupTimeoutMs ?? options.defaults?.caseTimeoutMs ?? 6e4,
11838
+ "setupTimeoutMs"
11839
+ ),
11840
+ verificationTimeoutMs: positive(
11841
+ options.defaults?.verificationTimeoutMs ?? options.defaults?.caseTimeoutMs ?? 6e4,
11842
+ "verificationTimeoutMs"
11843
+ ),
11594
11844
  cleanupTimeoutMs: positive(
11595
11845
  options.defaults?.cleanupTimeoutMs ?? 1e4,
11596
11846
  "cleanupTimeoutMs"
11597
11847
  )
11598
11848
  };
11849
+ const reportError = options.reportError ?? options.agent.reportError?.bind(options.agent);
11850
+ const issueFor = (phase, error, correlation, code) => createEvalIssue(phase, error, {
11851
+ reportError,
11852
+ correlation,
11853
+ ...code ? { code } : {}
11854
+ });
11599
11855
  return {
11600
11856
  listSuites() {
11601
11857
  return clone(suites);
@@ -11616,7 +11872,7 @@ function createEvals(options) {
11616
11872
  })),
11617
11873
  references: Object.keys(references),
11618
11874
  ...options.paramsSchema ? {
11619
- paramsSchema: import_zod8.z.toJSONSchema(options.paramsSchema, {
11875
+ paramsSchema: import_zod10.z.toJSONSchema(options.paramsSchema, {
11620
11876
  io: "input"
11621
11877
  })
11622
11878
  } : {},
@@ -11695,19 +11951,24 @@ function createEvals(options) {
11695
11951
  void 0,
11696
11952
  () => args.onProgress(clone(event))
11697
11953
  );
11698
- } catch {
11954
+ } catch (error) {
11699
11955
  reporting = false;
11700
- result.errors.push(failure("reporting"));
11956
+ result.errors.push(issueFor("reporting", error));
11701
11957
  }
11702
11958
  };
11703
11959
  const attempt = async (item, repetition) => {
11704
11960
  const started = Date.now();
11705
11961
  const controller = new AbortController();
11706
11962
  let timedOut = false;
11707
- const timer = setTimeout(() => {
11708
- timedOut = true;
11709
- controller.abort();
11710
- }, defaults.caseTimeoutMs);
11963
+ let timer;
11964
+ const deadline = (milliseconds) => {
11965
+ clearTimeout(timer);
11966
+ timer = setTimeout(() => {
11967
+ timedOut = true;
11968
+ controller.abort();
11969
+ }, milliseconds);
11970
+ };
11971
+ deadline(defaults.setupTimeoutMs);
11711
11972
  const signal = args.signal ? AbortSignal.any([args.signal, controller.signal]) : controller.signal;
11712
11973
  const attemptId = (0, import_node_crypto5.randomUUID)();
11713
11974
  const runtimeExecutions = [];
@@ -11720,14 +11981,31 @@ function createEvals(options) {
11720
11981
  status: "passed",
11721
11982
  durationMs: 0,
11722
11983
  steps: [],
11723
- errors: []
11984
+ errors: [],
11985
+ phaseDurationsMs: {}
11724
11986
  };
11725
11987
  let associationProgress = Promise.resolve();
11726
11988
  let acceptingExecutions = true;
11727
11989
  const executeAttempt = async () => {
11728
11990
  let phase = "params";
11991
+ let phaseStarted = Date.now();
11992
+ const recordPhase = () => {
11993
+ const now = Date.now();
11994
+ const durations = attemptResult.phaseDurationsMs;
11995
+ durations[phase] = (durations[phase] ?? 0) + now - phaseStarted;
11996
+ phaseStarted = now;
11997
+ };
11998
+ const phaseIssue = (error, code) => issueFor(
11999
+ phase,
12000
+ error,
12001
+ {
12002
+ correlation: { sessionId: attemptResult.sessionId, attemptId }
12003
+ },
12004
+ code
12005
+ );
11729
12006
  let stepIndex;
11730
12007
  const reportPhase = async (next) => {
12008
+ recordPhase();
11731
12009
  phase = next;
11732
12010
  if (args.includeActivity)
11733
12011
  await emit({
@@ -11800,6 +12078,7 @@ function createEvals(options) {
11800
12078
  const prepared = options.setup ? await options.setup(base) : void 0;
11801
12079
  context = { ...base, prepared };
11802
12080
  signal.throwIfAborted();
12081
+ deadline(defaults.caseTimeoutMs);
11803
12082
  for (const [index, step] of item.steps.entries()) {
11804
12083
  stepIndex = index;
11805
12084
  activeStep = void 0;
@@ -11846,8 +12125,22 @@ function createEvals(options) {
11846
12125
  attemptResult.steps.push(evaluated);
11847
12126
  activeStep = evaluated;
11848
12127
  signal.throwIfAborted();
11849
- if (observation.type === "error")
11850
- throw new Error("Agent failed.");
12128
+ if (observation.type === "error") {
12129
+ const issue2 = createEvalIssue("execute", observation.failure, {
12130
+ ...observation.diagnosticId ? { diagnosticId: observation.diagnosticId } : {}
12131
+ });
12132
+ attemptResult.errors.push(issue2);
12133
+ attemptResult.status = evaluated.status = "error";
12134
+ evaluated.reason = issue2.message;
12135
+ await emit({
12136
+ type: "step-completed",
12137
+ caseId: item.id,
12138
+ repetition,
12139
+ step: evaluated
12140
+ });
12141
+ activeStepReported = true;
12142
+ break;
12143
+ }
11851
12144
  if (observation.type === "cancelled") {
11852
12145
  evaluated.status = "cancelled";
11853
12146
  attemptResult.status = "cancelled";
@@ -11875,7 +12168,7 @@ function createEvals(options) {
11875
12168
  const reference = step.expect.reference;
11876
12169
  if (reference !== void 0) {
11877
12170
  await reportPhase("reference");
11878
- evaluated.reference = handlerRef(reference) ? import_zod8.z.json().parse(
12171
+ evaluated.reference = handlerRef(reference) ? import_zod10.z.json().parse(
11879
12172
  await references[reference.using]({
11880
12173
  ...context,
11881
12174
  observation: clone(observation),
@@ -11943,18 +12236,32 @@ function createEvals(options) {
11943
12236
  { role: "assistant", content: observation.text }
11944
12237
  );
11945
12238
  }
11946
- } catch {
12239
+ if (options.verify && attemptResult.status !== "cancelled" && attemptResult.status !== "error") {
12240
+ stepIndex = void 0;
12241
+ deadline(defaults.verificationTimeoutMs);
12242
+ await reportPhase("verification");
12243
+ const verification = EvalVerdictSchema.parse(
12244
+ await options.verify({
12245
+ ...context,
12246
+ result: clone(attemptResult)
12247
+ })
12248
+ );
12249
+ signal.throwIfAborted();
12250
+ attemptResult.verification = verification;
12251
+ if (!verification.passed) attemptResult.status = "failed";
12252
+ }
12253
+ } catch (error) {
11947
12254
  if (signal.aborted) {
11948
12255
  attemptResult.status = timedOut ? "error" : "cancelled";
11949
12256
  if (timedOut)
11950
12257
  attemptResult.errors.push({
11951
- phase,
11952
- code: "EVAL_TIMEOUT",
11953
- message: "Case exceeded its configured time limit."
12258
+ ...phaseIssue(error),
12259
+ code: phase === "params" || phase === "setup" ? "EVAL_SETUP_TIMEOUT" : phase === "verification" ? "EVAL_VERIFICATION_TIMEOUT" : "EVAL_TIMEOUT",
12260
+ 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
12261
  });
11955
12262
  } else {
11956
12263
  attemptResult.status = "error";
11957
- attemptResult.errors.push(failure(phase));
12264
+ attemptResult.errors.push(phaseIssue(error));
11958
12265
  }
11959
12266
  if (activeStep && !activeStepReported) {
11960
12267
  activeStep.status = attemptResult.status;
@@ -11985,12 +12292,21 @@ function createEvals(options) {
11985
12292
  );
11986
12293
  if (cancelled.observation.type === "error" || cancelled.continuation !== void 0)
11987
12294
  attemptResult.errors.push(
11988
- failure("cleanup", "EVAL_INTERRUPT_CLEANUP_FAILED")
12295
+ createEvalIssue(
12296
+ "cleanup",
12297
+ cancelled.observation.failure,
12298
+ {
12299
+ code: "EVAL_INTERRUPT_CLEANUP_FAILED",
12300
+ ...cancelled.observation.diagnosticId ? {
12301
+ diagnosticId: cancelled.observation.diagnosticId
12302
+ } : {}
12303
+ }
12304
+ )
11989
12305
  );
11990
12306
  cleanup.signal.throwIfAborted();
11991
- } catch {
12307
+ } catch (error) {
11992
12308
  attemptResult.errors.push(
11993
- failure("cleanup", "EVAL_INTERRUPT_CLEANUP_FAILED")
12309
+ phaseIssue(error, "EVAL_INTERRUPT_CLEANUP_FAILED")
11994
12310
  );
11995
12311
  }
11996
12312
  }
@@ -12001,8 +12317,8 @@ function createEvals(options) {
12001
12317
  result: clone(attemptResult)
12002
12318
  });
12003
12319
  cleanup.signal.throwIfAborted();
12004
- } catch {
12005
- attemptResult.errors.push(failure("cleanup"));
12320
+ } catch (error) {
12321
+ attemptResult.errors.push(phaseIssue(error));
12006
12322
  }
12007
12323
  } finally {
12008
12324
  clearTimeout(cleanupTimer);
@@ -12010,6 +12326,7 @@ function createEvals(options) {
12010
12326
  if (attemptResult.errors.some((error) => error.phase === "cleanup"))
12011
12327
  attemptResult.status = "error";
12012
12328
  }
12329
+ recordPhase();
12013
12330
  attemptResult.durationMs = Date.now() - started;
12014
12331
  }
12015
12332
  acceptingExecutions = false;
@@ -12081,23 +12398,23 @@ function defineSuite(suite) {
12081
12398
  }
12082
12399
 
12083
12400
  // src/evals/evaluation-contracts.ts
12084
- var import_zod10 = require("zod");
12401
+ var import_zod12 = require("zod");
12085
12402
 
12086
12403
  // src/evals/studio-contracts.ts
12087
12404
  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(),
12405
+ var import_zod11 = require("zod");
12406
+ var StudioEvalTargetsResponseSchema = import_zod11.z.object({
12407
+ canRun: import_zod11.z.boolean(),
12091
12408
  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(),
12409
+ targets: import_zod11.z.array(
12410
+ import_zod11.z.object({
12411
+ id: import_zod11.z.string(),
12412
+ name: import_zod11.z.string(),
12413
+ environment: import_zod11.z.string(),
12414
+ error: import_zod11.z.string().nullable(),
12098
12415
  // Safe discovery diagnostics; optional for compatibility with older APIs.
12099
- diagnostic: import_zod9.z.object({
12100
- code: import_zod9.z.enum([
12416
+ diagnostic: import_zod11.z.object({
12417
+ code: import_zod11.z.enum([
12101
12418
  "environment_forbidden",
12102
12419
  "environment_unavailable",
12103
12420
  "endpoint_not_found",
@@ -12106,44 +12423,44 @@ var StudioEvalTargetsResponseSchema = import_zod9.z.object({
12106
12423
  "endpoint_unreachable",
12107
12424
  "manifest_invalid"
12108
12425
  ]),
12109
- httpStatus: import_zod9.z.number().int().min(100).max(599).optional()
12426
+ httpStatus: import_zod11.z.number().int().min(100).max(599).optional()
12110
12427
  }).nullable().optional(),
12111
12428
  manifest: EvalManifestSchema.nullable(),
12112
- revisions: import_zod9.z.record(import_zod9.z.string(), import_zod9.z.string())
12429
+ revisions: import_zod11.z.record(import_zod11.z.string(), import_zod11.z.string())
12113
12430
  })
12114
12431
  )
12115
12432
  });
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()
12433
+ var EvalCostAmountSchema = import_zod11.z.object({
12434
+ costSummary: import_zod11.z.object({
12435
+ amounts: import_zod11.z.array(
12436
+ import_zod11.z.object({
12437
+ amount: import_zod11.z.number().finite().nonnegative(),
12438
+ currency: import_zod11.z.string().nullable()
12122
12439
  })
12123
12440
  ),
12124
- complete: import_zod9.z.boolean()
12441
+ complete: import_zod11.z.boolean()
12125
12442
  }).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()
12443
+ amount: import_zod11.z.number().finite().nonnegative().nullable(),
12444
+ currency: import_zod11.z.string().nullable(),
12445
+ status: import_zod11.z.enum(["complete", "partial", "unavailable"]),
12446
+ calls: import_zod11.z.number().int().nonnegative(),
12447
+ unpricedCalls: import_zod11.z.number().int().nonnegative(),
12448
+ estimated: import_zod11.z.boolean()
12132
12449
  });
12133
- var EvalCostsSchema = import_zod9.z.object({
12450
+ var EvalCostsSchema = import_zod11.z.object({
12134
12451
  workflow: EvalCostAmountSchema,
12135
12452
  judge: EvalCostAmountSchema,
12136
12453
  total: EvalCostAmountSchema
12137
12454
  });
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([
12455
+ var StudioEvalRunSummarySchema = import_zod11.z.object({
12456
+ id: import_zod11.z.uuid(),
12457
+ evaluationId: import_zod11.z.uuid().nullable().optional(),
12458
+ targetId: import_zod11.z.string(),
12459
+ targetName: import_zod11.z.string(),
12460
+ environment: import_zod11.z.string(),
12461
+ suiteId: import_zod11.z.string(),
12462
+ suiteRevision: import_zod11.z.string(),
12463
+ status: import_zod11.z.enum([
12147
12464
  "queued",
12148
12465
  "running",
12149
12466
  "passed",
@@ -12151,49 +12468,49 @@ var StudioEvalRunSummarySchema = import_zod9.z.object({
12151
12468
  "error",
12152
12469
  "cancelled"
12153
12470
  ]),
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(),
12471
+ createdAt: import_zod11.z.string(),
12472
+ startedAt: import_zod11.z.string().nullable(),
12473
+ endedAt: import_zod11.z.string().nullable(),
12474
+ error: import_zod11.z.string().nullable(),
12475
+ cancelRequestedAt: import_zod11.z.string().nullable(),
12159
12476
  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()
12477
+ counts: import_zod11.z.object({
12478
+ passed: import_zod11.z.number(),
12479
+ failed: import_zod11.z.number(),
12480
+ error: import_zod11.z.number(),
12481
+ cancelled: import_zod11.z.number()
12165
12482
  }).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()
12483
+ suiteName: import_zod11.z.string().nullable().optional(),
12484
+ totalAttempts: import_zod11.z.number().int().nonnegative().optional(),
12485
+ completedAttempts: import_zod11.z.number().int().nonnegative().optional(),
12486
+ phase: import_zod11.z.string().optional()
12170
12487
  });
12171
- var StudioEvalHistorySchema = import_zod9.z.object({
12172
- runs: import_zod9.z.array(StudioEvalRunSummarySchema)
12488
+ var StudioEvalHistorySchema = import_zod11.z.object({
12489
+ runs: import_zod11.z.array(StudioEvalRunSummarySchema)
12173
12490
  });
12174
- var StudioEvalDetailSchema = import_zod9.z.object({
12491
+ var StudioEvalDetailSchema = import_zod11.z.object({
12175
12492
  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(),
12493
+ caseCosts: import_zod11.z.record(import_zod11.z.string(), EvalCostsSchema).optional(),
12494
+ request: import_zod11.z.object({
12495
+ caseIds: import_zod11.z.array(import_zod11.z.string()).optional(),
12496
+ grading: import_zod11.z.enum(["app", "studio"]).optional(),
12180
12497
  judge: EvalJudgeIdentitySchema.optional(),
12181
- repetitions: import_zod9.z.number().int().positive(),
12182
- concurrency: import_zod9.z.number().optional(),
12498
+ repetitions: import_zod11.z.number().int().positive(),
12499
+ concurrency: import_zod11.z.number().optional(),
12183
12500
  promptSnapshot: import_browser3.PromptSnapshotSchema.optional(),
12184
- promptGroupName: import_zod9.z.string().optional()
12501
+ promptGroupName: import_zod11.z.string().optional()
12185
12502
  }).optional(),
12186
12503
  suite: EvalSuiteSchema,
12187
12504
  result: EvalRunResultSchema.nullable(),
12188
- events: import_zod9.z.array(import_zod9.z.object({ id: import_zod9.z.number(), event: EvalProgressSchema }))
12505
+ events: import_zod11.z.array(import_zod11.z.object({ id: import_zod11.z.number(), event: EvalProgressSchema }))
12189
12506
  })
12190
12507
  });
12191
12508
 
12192
12509
  // 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) => {
12510
+ var EvaluationMetadataSchema = import_zod12.z.object({
12511
+ source: import_zod12.z.enum(["manual", "deployment", "schedule", "ci"]).default("manual"),
12512
+ commit: import_zod12.z.string().trim().min(1).max(100).optional(),
12513
+ deploymentUrl: import_zod12.z.url().refine((value) => {
12197
12514
  try {
12198
12515
  const url = new URL(value);
12199
12516
  return ["https:", "http:"].includes(url.protocol) && !url.username && !url.password;
@@ -12202,67 +12519,67 @@ var EvaluationMetadataSchema = import_zod10.z.object({
12202
12519
  }
12203
12520
  }, "Expected an HTTP(S) URL without credentials").optional()
12204
12521
  }).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(),
12522
+ var StudioEvaluationStartRequestSchema = import_zod12.z.object({
12523
+ targetId: import_zod12.z.string().trim().min(1),
12524
+ name: import_zod12.z.string().trim().min(1).max(200).optional(),
12208
12525
  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()
12526
+ selection: import_zod12.z.enum(["all", "selected"]),
12527
+ suites: import_zod12.z.array(
12528
+ import_zod12.z.object({
12529
+ suiteId: import_zod12.z.string().min(1),
12530
+ suiteRevision: import_zod12.z.string().regex(/^[a-f0-9]{64}$/),
12531
+ caseIds: import_zod12.z.array(import_zod12.z.string().min(1)).min(1).max(100).optional()
12215
12532
  }).strict()
12216
12533
  ).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),
12534
+ judge: import_zod12.z.enum(["studio", "app"]).default("studio"),
12535
+ repetitions: import_zod12.z.number().int().min(1).max(20).default(1),
12536
+ concurrency: import_zod12.z.number().int().min(1).max(20).default(1),
12220
12537
  metadata: EvaluationMetadataSchema.default({ source: "manual" }),
12221
- idempotencyKey: import_zod10.z.string().trim().min(1).max(200).optional()
12538
+ idempotencyKey: import_zod12.z.string().trim().min(1).max(200).optional()
12222
12539
  }).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"]),
12540
+ var StudioEvaluationSummarySchema = import_zod12.z.object({
12541
+ id: import_zod12.z.uuid(),
12542
+ name: import_zod12.z.string(),
12543
+ targetId: import_zod12.z.string(),
12544
+ targetName: import_zod12.z.string(),
12545
+ environment: import_zod12.z.string(),
12546
+ selection: import_zod12.z.enum(["all", "selected"]),
12230
12547
  metadata: EvaluationMetadataSchema,
12231
12548
  judge: EvalJudgeIdentitySchema.optional(),
12232
12549
  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()
12550
+ createdAt: import_zod12.z.string(),
12551
+ startedAt: import_zod12.z.string().nullable(),
12552
+ endedAt: import_zod12.z.string().nullable(),
12553
+ cancelRequestedAt: import_zod12.z.string().nullable(),
12554
+ suiteCount: import_zod12.z.number().int().nonnegative(),
12555
+ completedSuites: import_zod12.z.number().int().nonnegative(),
12556
+ totalAttempts: import_zod12.z.number().int().nonnegative(),
12557
+ completedAttempts: import_zod12.z.number().int().nonnegative(),
12558
+ counts: import_zod12.z.object({
12559
+ passed: import_zod12.z.number(),
12560
+ failed: import_zod12.z.number(),
12561
+ error: import_zod12.z.number(),
12562
+ cancelled: import_zod12.z.number()
12246
12563
  }),
12247
12564
  costs: EvalCostsSchema.optional(),
12248
- legacy: import_zod10.z.boolean().optional()
12565
+ legacy: import_zod12.z.boolean().optional()
12249
12566
  });
12250
- var StudioEvaluationHistorySchema = import_zod10.z.object({
12251
- runs: import_zod10.z.array(StudioEvaluationSummarySchema)
12567
+ var StudioEvaluationHistorySchema = import_zod12.z.object({
12568
+ runs: import_zod12.z.array(StudioEvaluationSummarySchema)
12252
12569
  });
12253
- var StudioEvaluationDetailSchema = import_zod10.z.object({
12570
+ var StudioEvaluationDetailSchema = import_zod12.z.object({
12254
12571
  run: StudioEvaluationSummarySchema.extend({
12255
- suites: import_zod10.z.array(StudioEvalRunSummarySchema)
12572
+ suites: import_zod12.z.array(StudioEvalRunSummarySchema)
12256
12573
  })
12257
12574
  });
12258
- var StudioEvaluationResultsSchema = import_zod10.z.object({
12575
+ var StudioEvaluationResultsSchema = import_zod12.z.object({
12259
12576
  run: StudioEvaluationSummarySchema.extend({
12260
- suites: import_zod10.z.array(StudioEvalDetailSchema.shape.run)
12577
+ suites: import_zod12.z.array(StudioEvalDetailSchema.shape.run)
12261
12578
  })
12262
12579
  });
12263
12580
 
12264
12581
  // src/evals/judge.ts
12265
- var import_zod11 = require("zod");
12582
+ var import_zod13 = require("zod");
12266
12583
  function createEvalJudge({
12267
12584
  model,
12268
12585
  id: id3 = `${model.provider.id}/${model.modelId}`,
@@ -12289,7 +12606,7 @@ function createEvalJudge({
12289
12606
  responseFormat: {
12290
12607
  type: "json",
12291
12608
  name: "eval_verdict",
12292
- schema: import_zod11.z.toJSONSchema(EvalVerdictSchema)
12609
+ schema: import_zod13.z.toJSONSchema(EvalVerdictSchema)
12293
12610
  }
12294
12611
  });
12295
12612
  const result = await judge2.invoke([
@@ -12366,28 +12683,423 @@ function createEvalJudge({
12366
12683
  }
12367
12684
 
12368
12685
  // src/evals/route-handler.ts
12369
- var import_node_crypto6 = require("crypto");
12686
+ var import_node_crypto7 = require("crypto");
12370
12687
  var import_prompts2 = require("@kortyx/prompts");
12688
+ var import_runtime6 = require("@kortyx/runtime");
12689
+
12690
+ // src/evals/route-executions.ts
12691
+ var import_node_crypto6 = require("crypto");
12692
+ var import_errors13 = require("@kortyx/core/errors");
12693
+ var protocol = "jobs-v1";
12694
+ var uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i;
12695
+ var wait = (ms, signal) => new Promise((resolve2, reject) => {
12696
+ if (signal.aborted) {
12697
+ reject(signal.reason);
12698
+ return;
12699
+ }
12700
+ const abort = () => {
12701
+ clearTimeout(timer);
12702
+ reject(signal.reason);
12703
+ };
12704
+ const timer = setTimeout(() => {
12705
+ signal.removeEventListener("abort", abort);
12706
+ resolve2();
12707
+ }, ms);
12708
+ signal.addEventListener("abort", abort, { once: true });
12709
+ });
12710
+ var canonical2 = (value) => {
12711
+ if (Array.isArray(value)) return `[${value.map(canonical2).join(",")}]`;
12712
+ if (value && typeof value === "object")
12713
+ return `{${Object.entries(value).sort(([a], [b]) => a < b ? -1 : 1).map(([key, child]) => `${JSON.stringify(key)}:${canonical2(child)}`).join(",")}}`;
12714
+ return JSON.stringify(value);
12715
+ };
12716
+ function createEvalExecutionTransport({
12717
+ evals,
12718
+ store,
12719
+ scope,
12720
+ limits,
12721
+ onExecution
12722
+ }) {
12723
+ const owner = (0, import_node_crypto6.randomUUID)();
12724
+ const active = /* @__PURE__ */ new Map();
12725
+ let ticking = false;
12726
+ let stopped = false;
12727
+ const key = (id3) => (0, import_node_crypto6.createHash)("sha256").update(`${scope}\0${id3}`).digest("hex");
12728
+ const fail = async (job, error) => {
12729
+ const issue2 = createEvalIssue("reporting", error);
12730
+ await store.append(job.id, owner, {
12731
+ type: "error",
12732
+ message: issue2.message,
12733
+ failure: issue2.failure,
12734
+ ...issue2.diagnosticId ? { diagnosticId: issue2.diagnosticId } : {}
12735
+ });
12736
+ };
12737
+ const run = async (job, controller) => {
12738
+ let renewing = false;
12739
+ const timer2 = setInterval(() => {
12740
+ if (renewing) return;
12741
+ renewing = true;
12742
+ void store.heartbeat(job.id, owner).then(
12743
+ (current) => {
12744
+ if (!current) controller.abort("lease-lost");
12745
+ else if (current.cancelRequested)
12746
+ controller.abort("user-cancelled");
12747
+ },
12748
+ () => controller.abort("lease-lost")
12749
+ ).finally(() => {
12750
+ renewing = false;
12751
+ });
12752
+ }, store.heartbeatIntervalMs);
12753
+ const deadline = setTimeout(
12754
+ () => controller.abort("execution-timeout"),
12755
+ 30 * 6e4
12756
+ );
12757
+ try {
12758
+ const body = EvalRemoteRunRequestSchema.parse(job.payload);
12759
+ const current = evals.describe().suites.find((suite) => suite.id === body.suiteId);
12760
+ if (!current || getEvalSuiteRevision(current) !== body.suiteRevision)
12761
+ throw new import_errors13.KortyxError(
12762
+ "EVAL_CONTRACT_CHANGED",
12763
+ "The queued suite changed before execution.",
12764
+ {
12765
+ category: "configuration",
12766
+ retryable: false,
12767
+ safeMessage: "The queued suite changed before execution."
12768
+ }
12769
+ );
12770
+ const result = await evals.run({
12771
+ suiteId: body.suiteId,
12772
+ repetitions: body.repetitions,
12773
+ concurrency: body.concurrency,
12774
+ signal: controller.signal,
12775
+ ...body.attempt ? { attempt: body.attempt } : {},
12776
+ ...body.caseIds ? { caseIds: body.caseIds } : {},
12777
+ ...body.grading ? { grading: body.grading } : {},
12778
+ ...body.judge ? { judgeIdentity: body.judge } : {},
12779
+ ...body.promptSnapshot ? { promptSnapshot: body.promptSnapshot } : {},
12780
+ onProgress: (event) => store.append(job.id, owner, { type: "progress", event })
12781
+ });
12782
+ await store.append(job.id, owner, { type: "result", result });
12783
+ await store.finish(
12784
+ job.id,
12785
+ owner,
12786
+ result.status === "cancelled" ? "cancelled" : "completed"
12787
+ );
12788
+ } catch (error) {
12789
+ try {
12790
+ if (controller.signal.reason === "user-cancelled" && (0, import_errors13.isControlFlowError)(error))
12791
+ error = new import_errors13.KortyxError(
12792
+ "EVAL_EXECUTION_CANCELLED",
12793
+ "Evaluation execution was cancelled.",
12794
+ {
12795
+ category: "request",
12796
+ status: 409,
12797
+ retryable: false,
12798
+ safeMessage: "Evaluation execution was cancelled."
12799
+ }
12800
+ );
12801
+ await fail(job, error);
12802
+ await store.finish(
12803
+ job.id,
12804
+ owner,
12805
+ controller.signal.reason === "user-cancelled" ? "cancelled" : "completed"
12806
+ );
12807
+ } catch {
12808
+ }
12809
+ } finally {
12810
+ clearInterval(timer2);
12811
+ clearTimeout(deadline);
12812
+ active.delete(job.id);
12813
+ }
12814
+ };
12815
+ const tick = async () => {
12816
+ if (stopped || ticking) return;
12817
+ ticking = true;
12818
+ try {
12819
+ while (!stopped) {
12820
+ const job = await store.claim(owner, scope, limits);
12821
+ if (!job) break;
12822
+ const controller = new AbortController();
12823
+ const completion = run(job, controller);
12824
+ active.set(job.id, { controller, completion });
12825
+ try {
12826
+ onExecution?.(completion);
12827
+ } catch {
12828
+ }
12829
+ }
12830
+ } catch {
12831
+ } finally {
12832
+ ticking = false;
12833
+ }
12834
+ };
12835
+ const timer = setInterval(() => {
12836
+ void tick();
12837
+ }, 250);
12838
+ timer.unref?.();
12839
+ void tick();
12840
+ const headers = async (id3) => ({
12841
+ "content-type": "application/x-ndjson",
12842
+ "cache-control": "no-store",
12843
+ "x-accel-buffering": "no",
12844
+ "x-kortyx-eval-protocol": protocol,
12845
+ "x-kortyx-eval-execution-id": id3,
12846
+ "x-kortyx-eval-generation": await store.generation()
12847
+ });
12848
+ const problem = (error, negotiated) => {
12849
+ const failure = (0, import_errors13.serializeFailure)(error);
12850
+ const busy = failure.code === "EVAL_EXECUTOR_BUSY";
12851
+ return Response.json(
12852
+ { error: failure.message, failure, ...busy ? { accepted: false } : {} },
12853
+ {
12854
+ status: busy ? negotiated ? 503 : 429 : !negotiated && failure.code === "EVAL_CONCURRENCY_CHANGED" ? 429 : failure.status ?? 503,
12855
+ headers: {
12856
+ ...negotiated ? { "x-kortyx-eval-protocol": protocol } : {},
12857
+ ...busy ? { "retry-after": "2" } : {}
12858
+ }
12859
+ }
12860
+ );
12861
+ };
12862
+ const observe = async (request, id3, after = 0, negotiated = true) => {
12863
+ const backend = key(id3);
12864
+ const job = await store.status(backend);
12865
+ if (!job)
12866
+ return Response.json(
12867
+ {
12868
+ error: "Evaluation execution is unavailable; do not replay it.",
12869
+ code: "EVAL_EXECUTION_UNKNOWN"
12870
+ },
12871
+ { status: 410 }
12872
+ );
12873
+ if (after > job.sequence)
12874
+ return Response.json(
12875
+ { error: "Invalid execution event cursor." },
12876
+ { status: 409 }
12877
+ );
12878
+ const controller = new AbortController();
12879
+ const disconnect = () => {
12880
+ controller.abort();
12881
+ if (!negotiated) {
12882
+ active.get(backend)?.controller.abort("user-cancelled");
12883
+ void store.cancel(backend).catch(() => {
12884
+ });
12885
+ }
12886
+ };
12887
+ request.signal.addEventListener("abort", disconnect, { once: true });
12888
+ if (request.signal.aborted) disconnect();
12889
+ const encoder = new TextEncoder();
12890
+ const stream = new ReadableStream({
12891
+ start(output) {
12892
+ void (async () => {
12893
+ let cursor = after;
12894
+ let state;
12895
+ try {
12896
+ while (!controller.signal.aborted) {
12897
+ const record = await store.status(backend);
12898
+ if (!record) throw new Error("Execution record expired.");
12899
+ if (negotiated && state !== record.state) {
12900
+ state = record.state;
12901
+ output.enqueue(
12902
+ encoder.encode(
12903
+ `${JSON.stringify({ type: "execution-status", state })}
12904
+ `
12905
+ )
12906
+ );
12907
+ }
12908
+ for (const item of await store.events(backend, cursor)) {
12909
+ if (controller.signal.aborted) break;
12910
+ output.enqueue(
12911
+ encoder.encode(
12912
+ `${JSON.stringify({ ...item.event, ...negotiated ? { sequence: item.sequence } : {} })}
12913
+ `
12914
+ )
12915
+ );
12916
+ cursor = item.sequence;
12917
+ }
12918
+ if (record.state !== "queued" && record.state !== "running" && cursor >= record.sequence)
12919
+ break;
12920
+ await wait(100, controller.signal);
12921
+ }
12922
+ if (!controller.signal.aborted) output.close();
12923
+ } catch (error) {
12924
+ if (!controller.signal.aborted) output.error(error);
12925
+ } finally {
12926
+ if (controller.signal.aborted) {
12927
+ try {
12928
+ output.close();
12929
+ } catch {
12930
+ }
12931
+ }
12932
+ request.signal.removeEventListener("abort", disconnect);
12933
+ }
12934
+ })();
12935
+ },
12936
+ cancel() {
12937
+ disconnect();
12938
+ }
12939
+ });
12940
+ return new Response(stream, { headers: await headers(id3) });
12941
+ };
12942
+ return {
12943
+ async existing(request) {
12944
+ const url = new URL(request.url);
12945
+ const id3 = url.searchParams.get("executionId");
12946
+ if (!id3) return void 0;
12947
+ if (!uuid.test(id3))
12948
+ return Response.json(
12949
+ { error: "Invalid execution identity." },
12950
+ { status: 400 }
12951
+ );
12952
+ try {
12953
+ const generation = request.headers.get("x-kortyx-eval-generation");
12954
+ if (generation && generation !== await store.generation())
12955
+ return Response.json(
12956
+ {
12957
+ error: "Execution storage changed; execution status is unknown.",
12958
+ code: "EVAL_EXECUTION_STORE_CHANGED"
12959
+ },
12960
+ { status: 409 }
12961
+ );
12962
+ if (request.method === "DELETE") {
12963
+ if (!await store.status(key(id3)))
12964
+ return Response.json(
12965
+ { error: "Unknown execution." },
12966
+ { status: 404 }
12967
+ );
12968
+ await store.cancel(key(id3));
12969
+ active.get(key(id3))?.controller.abort("user-cancelled");
12970
+ return Response.json({ cancelRequested: true });
12971
+ }
12972
+ if (request.method !== "GET")
12973
+ return Response.json(
12974
+ { error: "Unsupported observation method." },
12975
+ { status: 405 }
12976
+ );
12977
+ const raw = url.searchParams.get("after") ?? "0";
12978
+ if (!/^\d{1,8}$/.test(raw))
12979
+ return Response.json(
12980
+ { error: "Invalid execution event cursor." },
12981
+ { status: 400 }
12982
+ );
12983
+ return await observe(request, id3, Number(raw));
12984
+ } catch (error) {
12985
+ return problem(error, true);
12986
+ }
12987
+ },
12988
+ async submit(request, body) {
12989
+ const negotiated = request.headers.get("x-kortyx-eval-protocol") === protocol;
12990
+ if (stopped)
12991
+ return problem(
12992
+ new import_errors13.KortyxError(
12993
+ "EVAL_EXECUTOR_BUSY",
12994
+ "Eval executor is draining; execution was not accepted.",
12995
+ {
12996
+ category: "request",
12997
+ status: 503,
12998
+ retryable: true,
12999
+ safeMessage: "Eval executor is draining; execution was not accepted."
13000
+ }
13001
+ ),
13002
+ negotiated
13003
+ );
13004
+ const id3 = negotiated ? request.headers.get("idempotency-key") : (0, import_node_crypto6.randomUUID)();
13005
+ if (!id3 || !uuid.test(id3))
13006
+ return Response.json(
13007
+ { error: "A UUID execution identity is required." },
13008
+ { status: 400 }
13009
+ );
13010
+ const submitted = request.headers.get("x-kortyx-eval-submitted-at");
13011
+ if (negotiated && (!submitted || !Number.isFinite(Date.parse(submitted)) || Date.parse(submitted) < Date.now() - 864e5 || Date.parse(submitted) > Date.now() + 3e5))
13012
+ return Response.json(
13013
+ {
13014
+ error: "Execution submission window expired; inspect before starting another execution."
13015
+ },
13016
+ { status: 410 }
13017
+ );
13018
+ try {
13019
+ if (negotiated && request.headers.get("x-kortyx-eval-generation") !== await store.generation())
13020
+ return Response.json(
13021
+ {
13022
+ error: "Execution storage changed; execution status is unknown.",
13023
+ code: "EVAL_EXECUTION_STORE_CHANGED"
13024
+ },
13025
+ { status: 409 }
13026
+ );
13027
+ await store.submit(
13028
+ {
13029
+ id: key(id3),
13030
+ scope,
13031
+ fingerprint: (0, import_node_crypto6.createHash)("sha256").update(canonical2(body)).digest("hex"),
13032
+ group: key(body.attempt?.evaluationId ?? id3),
13033
+ concurrency: body.concurrency,
13034
+ weight: body.attempt ? 1 : body.concurrency,
13035
+ payload: body,
13036
+ queued: negotiated
13037
+ },
13038
+ limits
13039
+ );
13040
+ await tick();
13041
+ if (!negotiated) {
13042
+ while ((await store.status(key(id3)))?.state === "queued") {
13043
+ request.signal.throwIfAborted();
13044
+ await wait(10, request.signal);
13045
+ await tick();
13046
+ }
13047
+ }
13048
+ return await observe(request, id3, 0, negotiated);
13049
+ } catch (error) {
13050
+ if (!negotiated && request.signal.aborted) {
13051
+ active.get(key(id3))?.controller.abort("user-cancelled");
13052
+ await store.cancel(key(id3)).catch(() => {
13053
+ });
13054
+ }
13055
+ return problem(error, negotiated);
13056
+ }
13057
+ },
13058
+ async capabilityHeaders() {
13059
+ return {
13060
+ "x-kortyx-eval-protocol": protocol,
13061
+ "x-kortyx-eval-generation": await store.generation()
13062
+ };
13063
+ },
13064
+ async close() {
13065
+ stopped = true;
13066
+ clearInterval(timer);
13067
+ for (const job of active.values()) job.controller.abort("host-stopped");
13068
+ await Promise.all([...active.values()].map((job) => job.completion));
13069
+ }
13070
+ };
13071
+ }
13072
+
13073
+ // src/evals/route-handler.ts
12371
13074
  function createEvalRouteHandler({
12372
13075
  evals,
12373
13076
  serviceKey,
12374
13077
  maxCases = 100,
12375
- maxActiveRuns = 1
13078
+ maxActiveRuns = 1,
13079
+ maxActiveAttempts = 20,
13080
+ maxQueuedExecutions = 1e3,
13081
+ executionStore = (0, import_runtime6.createInMemoryEvalExecutionStore)(),
13082
+ onExecution
12376
13083
  }) {
12377
13084
  if (serviceKey.length < 32)
12378
13085
  throw new EvalConfigurationError(
12379
13086
  "Eval service keys must have at least 32 characters."
12380
13087
  );
12381
- if (!Number.isSafeInteger(maxCases) || maxCases < 1 || !Number.isSafeInteger(maxActiveRuns) || maxActiveRuns < 1)
13088
+ 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
13089
  throw new EvalConfigurationError(
12383
13090
  "Eval endpoint limits must be positive integers."
12384
13091
  );
12385
- const digest = (value) => (0, import_node_crypto6.createHash)("sha256").update(value).digest();
13092
+ const digest = (value) => (0, import_node_crypto7.createHash)("sha256").update(value).digest();
12386
13093
  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)(
13094
+ const execution = createEvalExecutionTransport({
13095
+ evals,
13096
+ store: executionStore,
13097
+ scope: expected.toString("hex"),
13098
+ limits: { maxActiveRuns, maxActiveAttempts, maxQueuedExecutions },
13099
+ ...onExecution ? { onExecution } : {}
13100
+ });
13101
+ const handler3 = async (request) => {
13102
+ if (!(0, import_node_crypto7.timingSafeEqual)(
12391
13103
  expected,
12392
13104
  digest(request.headers.get("authorization") ?? "")
12393
13105
  ))
@@ -12395,10 +13107,15 @@ function createEvalRouteHandler({
12395
13107
  { error: "Unauthorized eval request." },
12396
13108
  { status: 401 }
12397
13109
  );
13110
+ const observed = await execution.existing(request);
13111
+ if (observed) return observed;
12398
13112
  const manifest = evals.describe();
12399
13113
  if (request.method === "GET")
12400
13114
  return Response.json(manifest, {
12401
- headers: { "cache-control": "no-store" }
13115
+ headers: {
13116
+ "cache-control": "no-store",
13117
+ ...await execution.capabilityHeaders()
13118
+ }
12402
13119
  });
12403
13120
  if (request.method !== "POST")
12404
13121
  return Response.json({ error: "Unsupported method." }, { status: 405 });
@@ -12469,80 +13186,11 @@ function createEvalRouteHandler({
12469
13186
  { error: "Unsupported or invalid scheduled attempt." },
12470
13187
  { status: 409 }
12471
13188
  );
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
13189
  if (request.signal.aborted)
12484
13190
  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
- });
13191
+ return execution.submit(request, body);
12545
13192
  };
13193
+ return Object.assign(handler3, { close: execution.close });
12546
13194
  }
12547
13195
 
12548
13196
  // src/evals/studio-judge.ts
@@ -12656,6 +13304,7 @@ async function createStudioEvalJudge(options) {
12656
13304
  ChatLifecycleHookError,
12657
13305
  EvalConfigurationError,
12658
13306
  EvalEvidencePolicySchema,
13307
+ EvalIssueSchema,
12659
13308
  EvalJudgeIdentitySchema,
12660
13309
  EvalJudgeUsageSchema,
12661
13310
  EvalManifestSchema,
@@ -12677,6 +13326,7 @@ async function createStudioEvalJudge(options) {
12677
13326
  createAgent,
12678
13327
  createChatRouteHandler,
12679
13328
  createCheckpointRouteHandler,
13329
+ createEvalIssue,
12680
13330
  createEvalJudge,
12681
13331
  createEvalRouteHandler,
12682
13332
  createEvals,