@kortyx/hooks 0.34.3 → 0.35.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/CHANGELOG.md +29 -0
- package/dist/index.js +44 -279
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +2 -6
- package/dist/internal.js +5 -240
- package/dist/internal.js.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,35 @@
|
|
|
5
5
|
- Return recoverable, bounded model feedback for invalid named interrupt requests. Preserve strict human responses, request quotas, approval gates, and tool-loop limits.
|
|
6
6
|
- Replace child execution snapshots natively while reading legacy object and single-element array snapshots.
|
|
7
7
|
|
|
8
|
+
## [0.35.1](https://github.com/kortyx-io/kortyx/compare/hooks-v0.35.0...hooks-v0.35.1) (2026-10-18)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @kortyx/telemetry-contracts bumped to 0.19.0
|
|
16
|
+
* @kortyx/prompts bumped to 0.2.3
|
|
17
|
+
* @kortyx/usage-telemetry bumped to 0.5.0
|
|
18
|
+
|
|
19
|
+
## [0.35.0](https://github.com/kortyx-io/kortyx/compare/hooks-v0.34.3...hooks-v0.35.0) (2026-10-16)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* **evals:** configurable deadlines and original error visibility ([#354](https://github.com/kortyx-io/kortyx/issues/354)) ([7dde173](https://github.com/kortyx-io/kortyx/commit/7dde173b54eb37a2d28ff28ac342a3333e5ed902))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Dependencies
|
|
28
|
+
|
|
29
|
+
* The following workspace dependencies were updated
|
|
30
|
+
* dependencies
|
|
31
|
+
* @kortyx/core bumped to 0.15.0
|
|
32
|
+
* @kortyx/providers bumped to 0.9.4
|
|
33
|
+
* @kortyx/telemetry-contracts bumped to 0.18.0
|
|
34
|
+
* @kortyx/prompts bumped to 0.2.2
|
|
35
|
+
* @kortyx/usage-telemetry bumped to 0.4.0
|
|
36
|
+
|
|
8
37
|
## [0.34.3](https://github.com/kortyx-io/kortyx/compare/hooks-v0.34.2...hooks-v0.34.3) (2026-10-14)
|
|
9
38
|
|
|
10
39
|
|
package/dist/index.js
CHANGED
|
@@ -245,7 +245,7 @@ var import_node = require("@kortyx/usage-telemetry/node");
|
|
|
245
245
|
// package.json
|
|
246
246
|
var package_default = {
|
|
247
247
|
name: "@kortyx/hooks",
|
|
248
|
-
version: "0.
|
|
248
|
+
version: "0.35.1",
|
|
249
249
|
private: false,
|
|
250
250
|
description: "Lifecycle hooks and extension points for Kortyx.",
|
|
251
251
|
keywords: [
|
|
@@ -822,252 +822,17 @@ var emitStructuredData = (args) => {
|
|
|
822
822
|
var import_node_async_hooks2 = require("async_hooks");
|
|
823
823
|
var import_node_crypto3 = require("crypto");
|
|
824
824
|
var import_core2 = require("@kortyx/core");
|
|
825
|
-
var
|
|
825
|
+
var import_errors2 = require("@kortyx/core/errors");
|
|
826
826
|
|
|
827
827
|
// src/error-diagnostics.ts
|
|
828
828
|
var import_telemetry_contracts2 = require("@kortyx/telemetry-contracts");
|
|
829
829
|
|
|
830
830
|
// src/diagnostic-capture.ts
|
|
831
|
-
var import_errors2 = require("@kortyx/core/errors");
|
|
832
831
|
var import_telemetry_contracts = require("@kortyx/telemetry-contracts");
|
|
833
|
-
var encoder = new TextEncoder();
|
|
834
|
-
var nativeStackGetter = Object.getOwnPropertyDescriptor(
|
|
835
|
-
new Error(),
|
|
836
|
-
"stack"
|
|
837
|
-
)?.get;
|
|
838
|
-
function nativeStack(object, getter) {
|
|
839
|
-
if (!getter || getter !== nativeStackGetter)
|
|
840
|
-
throw new Error("Custom stack accessor");
|
|
841
|
-
for (const key of ["name", "message"]) {
|
|
842
|
-
let cursor = object;
|
|
843
|
-
while (cursor) {
|
|
844
|
-
const descriptor = Object.getOwnPropertyDescriptor(cursor, key);
|
|
845
|
-
if (descriptor) {
|
|
846
|
-
if (!("value" in descriptor) || typeof descriptor.value !== "string")
|
|
847
|
-
throw new Error("Custom error formatting");
|
|
848
|
-
break;
|
|
849
|
-
}
|
|
850
|
-
cursor = Object.getPrototypeOf(cursor);
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
const formatter = Object.getOwnPropertyDescriptor(Error, "prepareStackTrace");
|
|
854
|
-
if (formatter && (!("value" in formatter) || !formatter.writable))
|
|
855
|
-
throw new Error("Custom stack formatter");
|
|
856
|
-
Object.defineProperty(Error, "prepareStackTrace", {
|
|
857
|
-
...formatter ?? { configurable: true, writable: true },
|
|
858
|
-
value: void 0
|
|
859
|
-
});
|
|
860
|
-
try {
|
|
861
|
-
return getter.call(object);
|
|
862
|
-
} finally {
|
|
863
|
-
if (formatter) Object.defineProperty(Error, "prepareStackTrace", formatter);
|
|
864
|
-
else Reflect.deleteProperty(Error, "prepareStackTrace");
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
var pointer = (key) => key.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
868
|
-
function captureDiagnosticContent(error, project) {
|
|
869
|
-
const omissions = [];
|
|
870
|
-
const redactions = [];
|
|
871
|
-
const seen = /* @__PURE__ */ new WeakMap();
|
|
872
|
-
let nodes = 0;
|
|
873
|
-
let remaining = import_telemetry_contracts.DIAGNOSTIC_LIMITS.bytes - 64 * 1024;
|
|
874
|
-
const omit = (path, reason, extra = {}) => {
|
|
875
|
-
if (omissions.length < 1e3)
|
|
876
|
-
omissions.push({ path: path.slice(0, 4096), reason, ...extra });
|
|
877
|
-
return { $omitted: reason };
|
|
878
|
-
};
|
|
879
|
-
const visit = (value, path, depth) => {
|
|
880
|
-
if (++nodes > import_telemetry_contracts.DIAGNOSTIC_LIMITS.nodes) return omit(path, "node_limit");
|
|
881
|
-
if (depth > import_telemetry_contracts.DIAGNOSTIC_LIMITS.depth) return omit(path, "depth_limit");
|
|
882
|
-
if (typeof value === "string") {
|
|
883
|
-
const clean = (0, import_telemetry_contracts.redactDiagnosticText)(value);
|
|
884
|
-
if (clean !== value && redactions.length < 1e3)
|
|
885
|
-
redactions.push({
|
|
886
|
-
path: path.slice(0, 4096),
|
|
887
|
-
reason: "credential_text"
|
|
888
|
-
});
|
|
889
|
-
const bytes = encoder.encode(JSON.stringify(clean)).length;
|
|
890
|
-
if (bytes > remaining)
|
|
891
|
-
return omit(path, "byte_limit", {
|
|
892
|
-
originalBytes: encoder.encode(value).length
|
|
893
|
-
});
|
|
894
|
-
remaining -= bytes;
|
|
895
|
-
return clean;
|
|
896
|
-
}
|
|
897
|
-
if (value === null || typeof value === "boolean") return value;
|
|
898
|
-
if (typeof value === "number")
|
|
899
|
-
return Number.isFinite(value) ? value : { $type: "number", value: String(value) };
|
|
900
|
-
if (typeof value === "bigint")
|
|
901
|
-
return { $type: "bigint", value: value.toString() };
|
|
902
|
-
if (typeof value === "undefined") return { $type: "undefined" };
|
|
903
|
-
if (typeof value === "function" || typeof value === "symbol")
|
|
904
|
-
return omit(path, `unsupported_${typeof value}`);
|
|
905
|
-
const object = value;
|
|
906
|
-
const reference = seen.get(object);
|
|
907
|
-
if (reference) return { $ref: reference };
|
|
908
|
-
seen.set(object, path);
|
|
909
|
-
remaining -= 32;
|
|
910
|
-
if (remaining < 0) return omit(path, "byte_limit");
|
|
911
|
-
try {
|
|
912
|
-
if (value instanceof Date)
|
|
913
|
-
return { $type: "Date", value: Date.prototype.toISOString.call(value) };
|
|
914
|
-
if (value instanceof Map || value instanceof Set) {
|
|
915
|
-
const isMap = value instanceof Map;
|
|
916
|
-
const iterator = isMap ? Map.prototype.entries.call(value) : Set.prototype.values.call(value);
|
|
917
|
-
const count = Object.getOwnPropertyDescriptor(
|
|
918
|
-
isMap ? Map.prototype : Set.prototype,
|
|
919
|
-
"size"
|
|
920
|
-
)?.get?.call(value);
|
|
921
|
-
const entries = [];
|
|
922
|
-
for (let index = 0; index < Math.min(count, import_telemetry_contracts.DIAGNOSTIC_LIMITS.properties); index++)
|
|
923
|
-
entries.push(iterator.next().value);
|
|
924
|
-
if (count > entries.length)
|
|
925
|
-
omissions.push({
|
|
926
|
-
path,
|
|
927
|
-
reason: "collection_limit",
|
|
928
|
-
originalCount: count
|
|
929
|
-
});
|
|
930
|
-
return isMap ? {
|
|
931
|
-
$type: "Map",
|
|
932
|
-
entries: visit(entries, `${path}/entries`, depth + 1)
|
|
933
|
-
} : {
|
|
934
|
-
$type: "Set",
|
|
935
|
-
values: visit(entries, `${path}/values`, depth + 1)
|
|
936
|
-
};
|
|
937
|
-
}
|
|
938
|
-
if (Array.isArray(value)) {
|
|
939
|
-
const count = Math.min(value.length, import_telemetry_contracts.DIAGNOSTIC_LIMITS.properties);
|
|
940
|
-
const items = Array.from(
|
|
941
|
-
{ length: count },
|
|
942
|
-
(_, index) => read(value, String(index), `${path}/${index}`, depth)
|
|
943
|
-
);
|
|
944
|
-
if (count < value.length)
|
|
945
|
-
items.push(
|
|
946
|
-
omit(path, "collection_limit", { originalCount: value.length })
|
|
947
|
-
);
|
|
948
|
-
return items;
|
|
949
|
-
}
|
|
950
|
-
const keys = Object.getOwnPropertyNames(object);
|
|
951
|
-
const result = /* @__PURE__ */ Object.create(null);
|
|
952
|
-
if (value instanceof Error) {
|
|
953
|
-
const ownName = Object.getOwnPropertyDescriptor(object, "name");
|
|
954
|
-
let type = ownName && "value" in ownName ? ownName.value : void 0;
|
|
955
|
-
if (typeof type !== "string") {
|
|
956
|
-
const name = Object.getOwnPropertyDescriptor(
|
|
957
|
-
Object.getPrototypeOf(value),
|
|
958
|
-
"name"
|
|
959
|
-
);
|
|
960
|
-
type = name && "value" in name ? name.value : "Error";
|
|
961
|
-
}
|
|
962
|
-
result.type = visit(
|
|
963
|
-
typeof type === "string" ? type : "Error",
|
|
964
|
-
`${path}/type`,
|
|
965
|
-
depth + 1
|
|
966
|
-
);
|
|
967
|
-
}
|
|
968
|
-
for (const key of keys.slice(0, import_telemetry_contracts.DIAGNOSTIC_LIMITS.properties)) {
|
|
969
|
-
if (["__proto__", "constructor", "prototype"].includes(key)) {
|
|
970
|
-
result[key] = omit(`${path}/${pointer(key)}`, "unsafe_key");
|
|
971
|
-
continue;
|
|
972
|
-
}
|
|
973
|
-
remaining -= encoder.encode(key).length + 4;
|
|
974
|
-
result[key] = read(object, key, `${path}/${pointer(key)}`, depth);
|
|
975
|
-
}
|
|
976
|
-
if (keys.length > import_telemetry_contracts.DIAGNOSTIC_LIMITS.properties)
|
|
977
|
-
result.$omittedProperties = omit(path, "property_limit", {
|
|
978
|
-
originalCount: keys.length
|
|
979
|
-
});
|
|
980
|
-
return result;
|
|
981
|
-
} catch {
|
|
982
|
-
return omit(path, "unreadable_object");
|
|
983
|
-
}
|
|
984
|
-
};
|
|
985
|
-
const read = (object, key, path, depth) => {
|
|
986
|
-
if ((0, import_telemetry_contracts.isPrivateDiagnosticField)(key)) {
|
|
987
|
-
if (redactions.length < 1e3)
|
|
988
|
-
redactions.push({
|
|
989
|
-
path: path.slice(0, 4096),
|
|
990
|
-
reason: "credential_field"
|
|
991
|
-
});
|
|
992
|
-
return "[REDACTED]";
|
|
993
|
-
}
|
|
994
|
-
try {
|
|
995
|
-
const property = Object.getOwnPropertyDescriptor(object, key);
|
|
996
|
-
if (property && "value" in property)
|
|
997
|
-
return visit(property.value, path, depth + 1);
|
|
998
|
-
if (key === "stack" && object instanceof Error && property?.get && property.get === nativeStackGetter)
|
|
999
|
-
return visit(nativeStack(object, property.get), path, depth + 1);
|
|
1000
|
-
return omit(
|
|
1001
|
-
path,
|
|
1002
|
-
property ? "accessor_not_evaluated" : "unavailable_property"
|
|
1003
|
-
);
|
|
1004
|
-
} catch {
|
|
1005
|
-
return omit(path, "unreadable_property");
|
|
1006
|
-
}
|
|
1007
|
-
};
|
|
1008
|
-
try {
|
|
1009
|
-
const original = project ? project(error) : error;
|
|
1010
|
-
if (project && original === null) return null;
|
|
1011
|
-
const captured = visit(original, "#/data", 0);
|
|
1012
|
-
const upstreamOmissions = (0, import_errors2.errorProperty)(original, "diagnosticOmissions");
|
|
1013
|
-
if (Array.isArray(upstreamOmissions))
|
|
1014
|
-
for (const note of upstreamOmissions.slice(0, 1e3)) {
|
|
1015
|
-
const path = (0, import_errors2.errorProperty)(note, "path");
|
|
1016
|
-
const reason = (0, import_errors2.errorProperty)(note, "reason");
|
|
1017
|
-
if (typeof path === "string" && typeof reason === "string")
|
|
1018
|
-
omissions.push({
|
|
1019
|
-
path: (0, import_telemetry_contracts.redactDiagnosticText)(path).slice(0, 4096),
|
|
1020
|
-
reason: (0, import_telemetry_contracts.redactDiagnosticText)(reason).slice(0, 128)
|
|
1021
|
-
});
|
|
1022
|
-
}
|
|
1023
|
-
const data = captured && typeof captured === "object" && !Array.isArray(captured) ? captured : {
|
|
1024
|
-
type: "Error",
|
|
1025
|
-
message: typeof captured === "string" ? captured : "Execution reported a fault.",
|
|
1026
|
-
value: captured
|
|
1027
|
-
};
|
|
1028
|
-
if (typeof data.message !== "string" && !("message" in data))
|
|
1029
|
-
data.message = "Execution reported a fault.";
|
|
1030
|
-
if (!("type" in data))
|
|
1031
|
-
data.type = typeof data.name === "string" ? data.name : "Error";
|
|
1032
|
-
const content = {
|
|
1033
|
-
schemaVersion: 1,
|
|
1034
|
-
data,
|
|
1035
|
-
capture: {
|
|
1036
|
-
status: omissions.length ? "partial" : "complete",
|
|
1037
|
-
omissions,
|
|
1038
|
-
redactions
|
|
1039
|
-
}
|
|
1040
|
-
};
|
|
1041
|
-
if (encoder.encode(JSON.stringify(content)).length > import_telemetry_contracts.DIAGNOSTIC_LIMITS.bytes)
|
|
1042
|
-
return {
|
|
1043
|
-
schemaVersion: 1,
|
|
1044
|
-
data: {
|
|
1045
|
-
type: "Error",
|
|
1046
|
-
message: "Diagnostic exceeded the capture budget."
|
|
1047
|
-
},
|
|
1048
|
-
capture: {
|
|
1049
|
-
status: "partial",
|
|
1050
|
-
redactions: [],
|
|
1051
|
-
omissions: [{ path: "#/data", reason: "serialized_byte_limit" }]
|
|
1052
|
-
}
|
|
1053
|
-
};
|
|
1054
|
-
return content;
|
|
1055
|
-
} catch {
|
|
1056
|
-
return {
|
|
1057
|
-
schemaVersion: 1,
|
|
1058
|
-
data: { type: "Error", message: "Diagnostic capture failed." },
|
|
1059
|
-
capture: {
|
|
1060
|
-
status: "failed",
|
|
1061
|
-
redactions: [],
|
|
1062
|
-
omissions: [{ path: "#/data", reason: "projection_or_capture_failed" }]
|
|
1063
|
-
}
|
|
1064
|
-
};
|
|
1065
|
-
}
|
|
1066
|
-
}
|
|
1067
832
|
|
|
1068
833
|
// src/error-diagnostics.ts
|
|
1069
834
|
function exceptionDiagnostics(error, project) {
|
|
1070
|
-
const content = captureDiagnosticContent(error, project);
|
|
835
|
+
const content = (0, import_telemetry_contracts.captureDiagnosticContent)(error, project);
|
|
1071
836
|
return !content || content.capture.status === "failed" ? null : content.data;
|
|
1072
837
|
}
|
|
1073
838
|
function errorDiagnostics(error, project) {
|
|
@@ -1332,7 +1097,7 @@ async function executeObservedTool(args) {
|
|
|
1332
1097
|
return result;
|
|
1333
1098
|
} catch (error) {
|
|
1334
1099
|
if (args.abortSignal?.aborted) observation.outcome = "cancelled";
|
|
1335
|
-
else if (!(0,
|
|
1100
|
+
else if (!(0, import_errors2.isControlFlowError)(error)) {
|
|
1336
1101
|
const outcome = classification(
|
|
1337
1102
|
args.tool,
|
|
1338
1103
|
error,
|
|
@@ -1471,11 +1236,11 @@ var import_prompts = require("@kortyx/prompts");
|
|
|
1471
1236
|
// src/reason-engine.ts
|
|
1472
1237
|
var import_node_crypto4 = require("crypto");
|
|
1473
1238
|
var import_core3 = require("@kortyx/core");
|
|
1474
|
-
var
|
|
1239
|
+
var import_errors3 = require("@kortyx/core/errors");
|
|
1475
1240
|
function assertModelFinish(result) {
|
|
1476
1241
|
if (result.finishReason?.unified !== "content-filter") return;
|
|
1477
1242
|
throw Object.assign(
|
|
1478
|
-
new
|
|
1243
|
+
new import_errors3.KortyxError("PROVIDER_REFUSAL", "The provider refused the request.", {
|
|
1479
1244
|
category: "provider",
|
|
1480
1245
|
retryable: false,
|
|
1481
1246
|
safeMessage: "The provider refused the request."
|
|
@@ -2549,7 +2314,7 @@ function createStructuredOutputStreamer(args, id, opId) {
|
|
|
2549
2314
|
}
|
|
2550
2315
|
|
|
2551
2316
|
// src/reason/parsing.ts
|
|
2552
|
-
var
|
|
2317
|
+
var import_errors4 = require("@kortyx/core/errors");
|
|
2553
2318
|
var tryJsonParse = (value) => {
|
|
2554
2319
|
try {
|
|
2555
2320
|
return { ok: true, value: JSON.parse(value) };
|
|
@@ -2587,12 +2352,12 @@ var resolveOutputCandidate = (text) => {
|
|
|
2587
2352
|
}
|
|
2588
2353
|
return text;
|
|
2589
2354
|
};
|
|
2590
|
-
var createTruncatedStructuredOutputError = (label, cause) => new
|
|
2355
|
+
var createTruncatedStructuredOutputError = (label, cause) => new import_errors4.ValidationError(
|
|
2591
2356
|
"OUTPUT_TRUNCATED",
|
|
2592
2357
|
`${label} was truncated before producing valid structured output. The model stopped due to output length. Increase maxOutputTokens or simplify the requested output.`,
|
|
2593
2358
|
cause
|
|
2594
2359
|
);
|
|
2595
|
-
var createInvalidStructuredOutputError = (label, cause) => new
|
|
2360
|
+
var createInvalidStructuredOutputError = (label, cause) => new import_errors4.ValidationError(
|
|
2596
2361
|
"INVALID_MODEL_JSON",
|
|
2597
2362
|
`${label} did not produce valid structured output. The model returned text instead of the expected JSON payload. Check the output contract or outputSchema and provider structured-output settings.`,
|
|
2598
2363
|
cause
|
|
@@ -2604,7 +2369,7 @@ var parseReasonOutputWithSchema = (args) => {
|
|
|
2604
2369
|
try {
|
|
2605
2370
|
return parseWithSchema(args.schema, candidate, args.label);
|
|
2606
2371
|
} catch (error) {
|
|
2607
|
-
if (!(error instanceof
|
|
2372
|
+
if (!(error instanceof import_errors4.ValidationError)) throw error;
|
|
2608
2373
|
const failure = args.finishReason?.unified === "length" ? createTruncatedStructuredOutputError(args.label, error) : typeof candidate === "string" && !validJson ? createInvalidStructuredOutputError(args.label, error) : error;
|
|
2609
2374
|
if (failure && typeof failure === "object")
|
|
2610
2375
|
Object.assign(failure, {
|
|
@@ -2624,7 +2389,7 @@ var parseInterruptFirstPassResult = (args) => {
|
|
|
2624
2389
|
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
2625
2390
|
throw createInvalidStructuredOutputError("useReason output");
|
|
2626
2391
|
}
|
|
2627
|
-
throw new
|
|
2392
|
+
throw new import_errors4.ValidationError(
|
|
2628
2393
|
"MODEL_OUTPUT_SCHEMA",
|
|
2629
2394
|
"useReason first pass with interrupt must return a JSON object."
|
|
2630
2395
|
);
|
|
@@ -2633,7 +2398,7 @@ var parseInterruptFirstPassResult = (args) => {
|
|
|
2633
2398
|
let interruptRequired = true;
|
|
2634
2399
|
if (mode === "optional") {
|
|
2635
2400
|
if (candidate.decision !== "continue" && candidate.decision !== "interrupt") {
|
|
2636
|
-
throw new
|
|
2401
|
+
throw new import_errors4.ValidationError(
|
|
2637
2402
|
"MODEL_OUTPUT_SCHEMA",
|
|
2638
2403
|
'useReason optional interrupt first pass must include decision "continue" or "interrupt".'
|
|
2639
2404
|
);
|
|
@@ -2646,7 +2411,7 @@ var parseInterruptFirstPassResult = (args) => {
|
|
|
2646
2411
|
candidate.interrupt
|
|
2647
2412
|
].some((value) => value !== null && value !== void 0);
|
|
2648
2413
|
if (hasUnexpectedRequest) {
|
|
2649
|
-
throw new
|
|
2414
|
+
throw new import_errors4.ValidationError(
|
|
2650
2415
|
"MODEL_OUTPUT_SCHEMA",
|
|
2651
2416
|
'useReason optional interrupt first pass with decision "continue" must not include an interrupt request.'
|
|
2652
2417
|
);
|
|
@@ -2680,7 +2445,7 @@ var parseInterruptFirstPassResult = (args) => {
|
|
|
2680
2445
|
"useReason output"
|
|
2681
2446
|
);
|
|
2682
2447
|
} catch (error) {
|
|
2683
|
-
if (!(error instanceof
|
|
2448
|
+
if (!(error instanceof import_errors4.ValidationError)) throw error;
|
|
2684
2449
|
if (args.finishReason?.unified === "length") {
|
|
2685
2450
|
throw createTruncatedStructuredOutputError("useReason output", error);
|
|
2686
2451
|
}
|
|
@@ -2689,7 +2454,7 @@ var parseInterruptFirstPassResult = (args) => {
|
|
|
2689
2454
|
}
|
|
2690
2455
|
const explicitDraft = typeof candidate.draftText === "string" && candidate.draftText.length > 0 ? candidate.draftText : typeof candidate.text === "string" && candidate.text.length > 0 ? candidate.text : void 0;
|
|
2691
2456
|
if (!args.outputSchema && !explicitDraft) {
|
|
2692
|
-
throw new
|
|
2457
|
+
throw new import_errors4.ValidationError(
|
|
2693
2458
|
"MODEL_OUTPUT_SCHEMA",
|
|
2694
2459
|
"useReason first pass with interrupt requires `draftText` when outputSchema is not provided."
|
|
2695
2460
|
);
|
|
@@ -2963,7 +2728,7 @@ var emitReasonStructuredOutput = (args) => {
|
|
|
2963
2728
|
|
|
2964
2729
|
// src/reason/tools.ts
|
|
2965
2730
|
var import_core5 = require("@kortyx/core");
|
|
2966
|
-
var
|
|
2731
|
+
var import_errors5 = require("@kortyx/core/errors");
|
|
2967
2732
|
var import_zod5 = require("zod");
|
|
2968
2733
|
|
|
2969
2734
|
// src/reason/input-feedback.ts
|
|
@@ -3203,7 +2968,7 @@ var runReasonToolLoop = async (args) => {
|
|
|
3203
2968
|
const maxSteps = Math.max(1, useReasonArgs.toolExecution?.maxSteps ?? 3);
|
|
3204
2969
|
const missingReturnCorrections = useReasonArgs.toolExecution?.missingReturnCorrections ?? 0;
|
|
3205
2970
|
if (!Number.isSafeInteger(missingReturnCorrections) || missingReturnCorrections < 0)
|
|
3206
|
-
throw new
|
|
2971
|
+
throw new import_errors5.KortyxError(
|
|
3207
2972
|
"INVALID_REASON_CORRECTION_POLICY",
|
|
3208
2973
|
"Invalid missing return correction budget.",
|
|
3209
2974
|
{
|
|
@@ -3264,7 +3029,7 @@ var runReasonToolLoop = async (args) => {
|
|
|
3264
3029
|
let outputContractCorrections = checkpoint?.outputContractCorrections ?? 0;
|
|
3265
3030
|
const correctionExhausted = () => {
|
|
3266
3031
|
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.`;
|
|
3267
|
-
return new
|
|
3032
|
+
return new import_errors5.KortyxError(
|
|
3268
3033
|
"REASON_OUTPUT_CONTRACT_CORRECTION_EXHAUSTED",
|
|
3269
3034
|
message,
|
|
3270
3035
|
{
|
|
@@ -3361,7 +3126,7 @@ var runReasonToolLoop = async (args) => {
|
|
|
3361
3126
|
aggregatedWarnings = mergeWarnings(aggregatedWarnings, step.warnings);
|
|
3362
3127
|
const toolCalls = step.toolCalls ?? [];
|
|
3363
3128
|
if (missingReturnAttempts > 0 && toolCalls.some((call) => !outputByToolName.has(call.name)))
|
|
3364
|
-
throw new
|
|
3129
|
+
throw new import_errors5.KortyxError(
|
|
3365
3130
|
"REASON_OUTPUT_CORRECTION_TOOL_DISALLOWED",
|
|
3366
3131
|
"A return correction requested a non-output tool.",
|
|
3367
3132
|
{
|
|
@@ -3404,7 +3169,7 @@ var runReasonToolLoop = async (args) => {
|
|
|
3404
3169
|
save();
|
|
3405
3170
|
continue;
|
|
3406
3171
|
}
|
|
3407
|
-
throw new
|
|
3172
|
+
throw new import_errors5.KortyxError(
|
|
3408
3173
|
"REASON_TERMINAL_OUTPUT_MISSING",
|
|
3409
3174
|
"useReason outputs.return requires one terminal output contract call.",
|
|
3410
3175
|
{
|
|
@@ -3538,7 +3303,7 @@ var runReasonToolLoop = async (args) => {
|
|
|
3538
3303
|
);
|
|
3539
3304
|
if (steps.length >= maxSteps) {
|
|
3540
3305
|
const message = `useReason output generation requires another model pass within toolExecution.maxSteps (${maxSteps}). Increase maxSteps to allow outputs to use completed tool and interrupt results.`;
|
|
3541
|
-
throw new
|
|
3306
|
+
throw new import_errors5.ProviderRequestError(message, {
|
|
3542
3307
|
code: "REASON_OUTPUT_BUDGET_EXHAUSTED",
|
|
3543
3308
|
operation: "useReason",
|
|
3544
3309
|
safeMessage: message,
|
|
@@ -3733,7 +3498,7 @@ var runReasonToolLoop = async (args) => {
|
|
|
3733
3498
|
`useReason interrupt contract "${resolved.name}" request`
|
|
3734
3499
|
);
|
|
3735
3500
|
} catch (error) {
|
|
3736
|
-
if (!(error instanceof
|
|
3501
|
+
if (!(error instanceof import_errors5.ValidationError)) throw error;
|
|
3737
3502
|
const result3 = {
|
|
3738
3503
|
toolCallId: toolCall.id,
|
|
3739
3504
|
name: toolCall.name,
|
|
@@ -3943,12 +3708,12 @@ var runReasonToolLoop = async (args) => {
|
|
|
3943
3708
|
}
|
|
3944
3709
|
} catch (error) {
|
|
3945
3710
|
(0, import_core5.throwIfExecutionAborted)(abortSignal);
|
|
3946
|
-
if ((0,
|
|
3711
|
+
if ((0, import_errors5.isControlFlowError)(error)) throw error;
|
|
3947
3712
|
const result2 = {
|
|
3948
3713
|
toolCallId: toolCall.id,
|
|
3949
3714
|
name: tool.name,
|
|
3950
|
-
content: (0,
|
|
3951
|
-
failure: (0,
|
|
3715
|
+
content: (0, import_errors5.serializeFailure)(error).message,
|
|
3716
|
+
failure: (0, import_errors5.serializeFailure)(error),
|
|
3952
3717
|
isError: true
|
|
3953
3718
|
};
|
|
3954
3719
|
toolResults.push(result2);
|
|
@@ -4551,7 +4316,7 @@ function useWorkflowState(key, ...rest) {
|
|
|
4551
4316
|
|
|
4552
4317
|
// src/parallel.ts
|
|
4553
4318
|
var import_core7 = require("@kortyx/core");
|
|
4554
|
-
var
|
|
4319
|
+
var import_errors6 = require("@kortyx/core/errors");
|
|
4555
4320
|
var ParallelChildWaiting = class extends Error {
|
|
4556
4321
|
name = "ParallelChildWaiting";
|
|
4557
4322
|
};
|
|
@@ -4565,14 +4330,14 @@ var ParallelError = class extends AggregateError {
|
|
|
4565
4330
|
);
|
|
4566
4331
|
this.results = results;
|
|
4567
4332
|
this.name = "ParallelError";
|
|
4568
|
-
this.failure = (0,
|
|
4333
|
+
this.failure = (0, import_errors6.serializeFailure)({
|
|
4569
4334
|
version: 1,
|
|
4570
4335
|
code: this.code,
|
|
4571
4336
|
category: "workflow",
|
|
4572
4337
|
message: this.message,
|
|
4573
4338
|
retryable: null,
|
|
4574
4339
|
results: results.map(
|
|
4575
|
-
(result) => result.status === "fulfilled" ? { status: "fulfilled" } : { status: "rejected", failure: (0,
|
|
4340
|
+
(result) => result.status === "fulfilled" ? { status: "fulfilled" } : { status: "rejected", failure: (0, import_errors6.serializeFailure)(result.reason) }
|
|
4576
4341
|
)
|
|
4577
4342
|
});
|
|
4578
4343
|
}
|
|
@@ -4580,7 +4345,7 @@ var ParallelError = class extends AggregateError {
|
|
|
4580
4345
|
code = "PARALLEL_FAILED";
|
|
4581
4346
|
failure;
|
|
4582
4347
|
toJSON() {
|
|
4583
|
-
return (0,
|
|
4348
|
+
return (0, import_errors6.serializeFailure)(this);
|
|
4584
4349
|
}
|
|
4585
4350
|
};
|
|
4586
4351
|
function registerWorkflowTask(id) {
|
|
@@ -4761,11 +4526,11 @@ async function usePrompt(reference, options) {
|
|
|
4761
4526
|
// src/workflow.ts
|
|
4762
4527
|
var import_node_crypto6 = require("crypto");
|
|
4763
4528
|
var import_core8 = require("@kortyx/core");
|
|
4764
|
-
var
|
|
4765
|
-
var WorkflowCallError = class extends
|
|
4529
|
+
var import_errors7 = require("@kortyx/core/errors");
|
|
4530
|
+
var WorkflowCallError = class extends import_errors7.KortyxError {
|
|
4766
4531
|
constructor(workflow, message, cause, failure) {
|
|
4767
|
-
const detail = (0,
|
|
4768
|
-
failure ?? cause ?? new
|
|
4532
|
+
const detail = (0, import_errors7.serializeFailure)(
|
|
4533
|
+
failure ?? cause ?? new import_errors7.WorkflowContractError(message)
|
|
4769
4534
|
);
|
|
4770
4535
|
super(detail.code, `Workflow '${workflow}': ${message}`, {
|
|
4771
4536
|
...detail,
|
|
@@ -4786,12 +4551,12 @@ function workflowCallFingerprint(value) {
|
|
|
4786
4551
|
if (v === null || typeof v === "string" || typeof v === "boolean") return v;
|
|
4787
4552
|
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
4788
4553
|
if (typeof v !== "object" || !v || seen.has(v)) {
|
|
4789
|
-
throw new
|
|
4554
|
+
throw new import_errors7.WorkflowContractError(
|
|
4790
4555
|
"Workflow input and output must be JSON serializable."
|
|
4791
4556
|
);
|
|
4792
4557
|
}
|
|
4793
4558
|
if (!Array.isArray(v) && Object.getPrototypeOf(v) !== Object.prototype) {
|
|
4794
|
-
throw new
|
|
4559
|
+
throw new import_errors7.WorkflowContractError(
|
|
4795
4560
|
"Workflow input and output must contain plain JSON objects."
|
|
4796
4561
|
);
|
|
4797
4562
|
}
|
|
@@ -4812,7 +4577,7 @@ function createWorkflowHooks(workflows) {
|
|
|
4812
4577
|
useWorkflow: (args) => {
|
|
4813
4578
|
const workflow = workflows[args.workflow];
|
|
4814
4579
|
if (!workflow || workflow.id !== args.workflow)
|
|
4815
|
-
throw new
|
|
4580
|
+
throw new import_errors7.WorkflowContractError(
|
|
4816
4581
|
"Workflow registry keys must match definition ids."
|
|
4817
4582
|
);
|
|
4818
4583
|
return useWorkflow({ ...args, workflow });
|
|
@@ -4838,23 +4603,23 @@ async function runWorkflowCall(args, task) {
|
|
|
4838
4603
|
(0, import_core8.throwIfExecutionAborted)(ctx.node.abortSignal);
|
|
4839
4604
|
const service = ctx.node.callWorkflow;
|
|
4840
4605
|
if (!service)
|
|
4841
|
-
throw new
|
|
4606
|
+
throw new import_errors7.WorkflowContractError(
|
|
4842
4607
|
"useWorkflow requires an agent workflow registry."
|
|
4843
4608
|
);
|
|
4844
4609
|
if (!args.id.trim())
|
|
4845
|
-
throw new
|
|
4610
|
+
throw new import_errors7.WorkflowContractError(
|
|
4846
4611
|
"useWorkflow requires a stable, nonempty id."
|
|
4847
4612
|
);
|
|
4848
4613
|
if (ctx.workflowCallActive && !task.group)
|
|
4849
|
-
throw new
|
|
4614
|
+
throw new import_errors7.WorkflowContractError(
|
|
4850
4615
|
"Concurrent workflow calls require parallel([...]); otherwise await each call."
|
|
4851
4616
|
);
|
|
4852
4617
|
if (ctx.workflowCallIds.has(args.id))
|
|
4853
|
-
throw new
|
|
4618
|
+
throw new import_errors7.WorkflowContractError(
|
|
4854
4619
|
`Duplicate workflow call id '${args.id}' in one node activation.`
|
|
4855
4620
|
);
|
|
4856
4621
|
if (ctx.workflowCallIds.size >= 64)
|
|
4857
|
-
throw new
|
|
4622
|
+
throw new import_errors7.WorkflowContractError(
|
|
4858
4623
|
"A node may call at most 64 child workflows per activation."
|
|
4859
4624
|
);
|
|
4860
4625
|
ctx.workflowCallIds.add(args.id);
|
|
@@ -4935,7 +4700,7 @@ async function runWorkflowCall(args, task) {
|
|
|
4935
4700
|
workflow,
|
|
4936
4701
|
record2.error ?? "child failed",
|
|
4937
4702
|
void 0,
|
|
4938
|
-
record2.failure ?? (0,
|
|
4703
|
+
record2.failure ?? (0, import_errors7.serializeFailure)(void 0)
|
|
4939
4704
|
);
|
|
4940
4705
|
if (task.group && record2.status === "interrupted" && record2.interrupts.at(-1)?.response === void 0)
|
|
4941
4706
|
throw new ParallelChildWaiting();
|
|
@@ -4943,7 +4708,7 @@ async function runWorkflowCall(args, task) {
|
|
|
4943
4708
|
let outcome;
|
|
4944
4709
|
try {
|
|
4945
4710
|
if (Array.isArray(record2.snapshot) && record2.snapshot.length !== 1)
|
|
4946
|
-
throw new
|
|
4711
|
+
throw new import_errors7.WorkflowContractError("Invalid child workflow snapshot.");
|
|
4947
4712
|
const snapshot = Array.isArray(record2.snapshot) ? record2.snapshot[0] : record2.snapshot;
|
|
4948
4713
|
report(
|
|
4949
4714
|
snapshot ? "resumed" : "started",
|
|
@@ -4974,7 +4739,7 @@ async function runWorkflowCall(args, task) {
|
|
|
4974
4739
|
throw error;
|
|
4975
4740
|
}
|
|
4976
4741
|
record2.status = "failed";
|
|
4977
|
-
record2.failure = (0,
|
|
4742
|
+
record2.failure = (0, import_errors7.serializeFailure)(error);
|
|
4978
4743
|
record2.error = record2.failure.message;
|
|
4979
4744
|
report("failed", { error: "Child workflow failed" });
|
|
4980
4745
|
throw new WorkflowCallError(
|