@kortyx/hooks 0.30.1 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +270 -35
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +9 -5
- package/dist/internal.js +243 -35
- package/dist/internal.js.map +1 -1
- package/dist/{tracing-BsxYlgEw.d.ts → tracing-mXE0Euvx.d.ts} +7 -2
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.31.0](https://github.com/kortyx-io/kortyx/compare/hooks-v0.30.2...hooks-v0.31.0) (2026-10-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **telemetry:** preserve complete private error diagnostics ([#290](https://github.com/kortyx-io/kortyx/issues/290)) ([e1c5a88](https://github.com/kortyx-io/kortyx/commit/e1c5a88c494016fd84a1af40579412fcfde31271))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @kortyx/core bumped to 0.12.0
|
|
16
|
+
* @kortyx/providers bumped to 0.9.0
|
|
17
|
+
* @kortyx/telemetry-contracts bumped to 0.15.0
|
|
18
|
+
|
|
19
|
+
## [0.30.2](https://github.com/kortyx-io/kortyx/compare/hooks-v0.30.1...hooks-v0.30.2) (2026-10-07)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Dependencies
|
|
23
|
+
|
|
24
|
+
* The following workspace dependencies were updated
|
|
25
|
+
* dependencies
|
|
26
|
+
* @kortyx/providers bumped to 0.8.4
|
|
27
|
+
* @kortyx/telemetry-contracts bumped to 0.14.0
|
|
28
|
+
|
|
3
29
|
## [0.30.1](https://github.com/kortyx-io/kortyx/compare/hooks-v0.30.0...hooks-v0.30.1) (2026-10-03)
|
|
4
30
|
|
|
5
31
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _kortyx_core from '@kortyx/core';
|
|
2
2
|
import { WorkflowDefinition, TokenUsage, InterruptInput, GraphState, NodeConfig, InterruptResumeValue, InterruptResult } from '@kortyx/core';
|
|
3
|
-
import { K as KortyxTelemetryConfig, R as ReasonTraceAdapter, a as KortyxTraceMetadata, b as ReportErrorOptions, c as KortyxTelemetryEventType } from './tracing-
|
|
4
|
-
export { E as EnsureWorkflowTopologyRequest, d as EnsureWorkflowTopologyResponse, e as KortyxErrorDetails, f as KortyxTelemetryContentCapture, g as KortyxTelemetryCorrelation, h as KortyxTelemetryEvent, i as KortyxTelemetryPrompt, j as KortyxTelemetryReporter, k as KortyxTelemetryService, l as KortyxTraceAdapter, m as KortyxTraceErrorProjection, n as ReasonTraceAttributes, o as ReasonTraceSpan, p as ReasonTraceSpanEndArgs, q as ReasonTraceSpanStartArgs } from './tracing-
|
|
3
|
+
import { K as KortyxTelemetryConfig, R as ReasonTraceAdapter, a as KortyxTraceMetadata, b as ReportErrorOptions, c as KortyxTelemetryEventType } from './tracing-mXE0Euvx.js';
|
|
4
|
+
export { E as EnsureWorkflowTopologyRequest, d as EnsureWorkflowTopologyResponse, e as KortyxErrorDetails, f as KortyxTelemetryContentCapture, g as KortyxTelemetryCorrelation, h as KortyxTelemetryEvent, i as KortyxTelemetryPrompt, j as KortyxTelemetryReporter, k as KortyxTelemetryService, l as KortyxTraceAdapter, m as KortyxTraceErrorProjection, n as ReasonTraceAttributes, o as ReasonTraceSpan, p as ReasonTraceSpanEndArgs, q as ReasonTraceSpanStartArgs } from './tracing-mXE0Euvx.js';
|
|
5
5
|
import { FailureDescriptor, KortyxError } from '@kortyx/core/errors';
|
|
6
6
|
import * as _kortyx_providers from '@kortyx/providers';
|
|
7
7
|
import { ToolObservation, ProviderModelRef, KortyxReasoningOptions, KortyxResponseFormat, KortyxExecutableTool, KortyxUsage, KortyxFinishReason, KortyxProviderMetadata, KortyxWarning, KortyxToolCall, KortyxToolResult } from '@kortyx/providers';
|
package/dist/index.js
CHANGED
|
@@ -717,52 +717,257 @@ var import_core2 = require("@kortyx/core");
|
|
|
717
717
|
var import_errors3 = require("@kortyx/core/errors");
|
|
718
718
|
|
|
719
719
|
// src/error-diagnostics.ts
|
|
720
|
+
var import_telemetry_contracts2 = require("@kortyx/telemetry-contracts");
|
|
721
|
+
|
|
722
|
+
// src/diagnostic-capture.ts
|
|
720
723
|
var import_errors2 = require("@kortyx/core/errors");
|
|
721
|
-
var
|
|
722
|
-
var
|
|
723
|
-
var
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
724
|
+
var import_telemetry_contracts = require("@kortyx/telemetry-contracts");
|
|
725
|
+
var encoder = new TextEncoder();
|
|
726
|
+
var nativeStackGetter = Object.getOwnPropertyDescriptor(
|
|
727
|
+
new Error(),
|
|
728
|
+
"stack"
|
|
729
|
+
)?.get;
|
|
730
|
+
function nativeStack(object, getter) {
|
|
731
|
+
if (!getter || getter !== nativeStackGetter)
|
|
732
|
+
throw new Error("Custom stack accessor");
|
|
733
|
+
for (const key of ["name", "message"]) {
|
|
734
|
+
let cursor = object;
|
|
735
|
+
while (cursor) {
|
|
736
|
+
const descriptor = Object.getOwnPropertyDescriptor(cursor, key);
|
|
737
|
+
if (descriptor) {
|
|
738
|
+
if (!("value" in descriptor) || typeof descriptor.value !== "string")
|
|
739
|
+
throw new Error("Custom error formatting");
|
|
740
|
+
break;
|
|
741
|
+
}
|
|
742
|
+
cursor = Object.getPrototypeOf(cursor);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
const formatter = Object.getOwnPropertyDescriptor(Error, "prepareStackTrace");
|
|
746
|
+
if (formatter && (!("value" in formatter) || !formatter.writable))
|
|
747
|
+
throw new Error("Custom stack formatter");
|
|
748
|
+
Object.defineProperty(Error, "prepareStackTrace", {
|
|
749
|
+
...formatter ?? { configurable: true, writable: true },
|
|
750
|
+
value: void 0
|
|
751
|
+
});
|
|
752
|
+
try {
|
|
753
|
+
return getter.call(object);
|
|
754
|
+
} finally {
|
|
755
|
+
if (formatter) Object.defineProperty(Error, "prepareStackTrace", formatter);
|
|
756
|
+
else Reflect.deleteProperty(Error, "prepareStackTrace");
|
|
729
757
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
758
|
+
}
|
|
759
|
+
var pointer = (key) => key.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
760
|
+
function captureDiagnosticContent(error, project) {
|
|
761
|
+
const omissions = [];
|
|
762
|
+
const redactions = [];
|
|
763
|
+
const seen = /* @__PURE__ */ new WeakMap();
|
|
764
|
+
let nodes = 0;
|
|
765
|
+
let remaining = import_telemetry_contracts.DIAGNOSTIC_LIMITS.bytes - 64 * 1024;
|
|
766
|
+
const omit = (path, reason, extra = {}) => {
|
|
767
|
+
if (omissions.length < 1e3)
|
|
768
|
+
omissions.push({ path: path.slice(0, 4096), reason, ...extra });
|
|
769
|
+
return { $omitted: reason };
|
|
770
|
+
};
|
|
771
|
+
const visit = (value, path, depth) => {
|
|
772
|
+
if (++nodes > import_telemetry_contracts.DIAGNOSTIC_LIMITS.nodes) return omit(path, "node_limit");
|
|
773
|
+
if (depth > import_telemetry_contracts.DIAGNOSTIC_LIMITS.depth) return omit(path, "depth_limit");
|
|
774
|
+
if (typeof value === "string") {
|
|
775
|
+
const clean = (0, import_telemetry_contracts.redactDiagnosticText)(value);
|
|
776
|
+
if (clean !== value && redactions.length < 1e3)
|
|
777
|
+
redactions.push({
|
|
778
|
+
path: path.slice(0, 4096),
|
|
779
|
+
reason: "credential_text"
|
|
780
|
+
});
|
|
781
|
+
const bytes = encoder.encode(JSON.stringify(clean)).length;
|
|
782
|
+
if (bytes > remaining)
|
|
783
|
+
return omit(path, "byte_limit", {
|
|
784
|
+
originalBytes: encoder.encode(value).length
|
|
785
|
+
});
|
|
786
|
+
remaining -= bytes;
|
|
787
|
+
return clean;
|
|
788
|
+
}
|
|
789
|
+
if (value === null || typeof value === "boolean") return value;
|
|
790
|
+
if (typeof value === "number")
|
|
791
|
+
return Number.isFinite(value) ? value : { $type: "number", value: String(value) };
|
|
792
|
+
if (typeof value === "bigint")
|
|
793
|
+
return { $type: "bigint", value: value.toString() };
|
|
794
|
+
if (typeof value === "undefined") return { $type: "undefined" };
|
|
795
|
+
if (typeof value === "function" || typeof value === "symbol")
|
|
796
|
+
return omit(path, `unsupported_${typeof value}`);
|
|
797
|
+
const object = value;
|
|
798
|
+
const reference = seen.get(object);
|
|
799
|
+
if (reference) return { $ref: reference };
|
|
800
|
+
seen.set(object, path);
|
|
801
|
+
remaining -= 32;
|
|
802
|
+
if (remaining < 0) return omit(path, "byte_limit");
|
|
733
803
|
try {
|
|
734
|
-
|
|
804
|
+
if (value instanceof Date)
|
|
805
|
+
return { $type: "Date", value: Date.prototype.toISOString.call(value) };
|
|
806
|
+
if (value instanceof Map || value instanceof Set) {
|
|
807
|
+
const isMap = value instanceof Map;
|
|
808
|
+
const iterator = isMap ? Map.prototype.entries.call(value) : Set.prototype.values.call(value);
|
|
809
|
+
const count = Object.getOwnPropertyDescriptor(
|
|
810
|
+
isMap ? Map.prototype : Set.prototype,
|
|
811
|
+
"size"
|
|
812
|
+
)?.get?.call(value);
|
|
813
|
+
const entries = [];
|
|
814
|
+
for (let index = 0; index < Math.min(count, import_telemetry_contracts.DIAGNOSTIC_LIMITS.properties); index++)
|
|
815
|
+
entries.push(iterator.next().value);
|
|
816
|
+
if (count > entries.length)
|
|
817
|
+
omissions.push({
|
|
818
|
+
path,
|
|
819
|
+
reason: "collection_limit",
|
|
820
|
+
originalCount: count
|
|
821
|
+
});
|
|
822
|
+
return isMap ? {
|
|
823
|
+
$type: "Map",
|
|
824
|
+
entries: visit(entries, `${path}/entries`, depth + 1)
|
|
825
|
+
} : {
|
|
826
|
+
$type: "Set",
|
|
827
|
+
values: visit(entries, `${path}/values`, depth + 1)
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
if (Array.isArray(value)) {
|
|
831
|
+
const count = Math.min(value.length, import_telemetry_contracts.DIAGNOSTIC_LIMITS.properties);
|
|
832
|
+
const items = Array.from(
|
|
833
|
+
{ length: count },
|
|
834
|
+
(_, index) => read(value, String(index), `${path}/${index}`, depth)
|
|
835
|
+
);
|
|
836
|
+
if (count < value.length)
|
|
837
|
+
items.push(
|
|
838
|
+
omit(path, "collection_limit", { originalCount: value.length })
|
|
839
|
+
);
|
|
840
|
+
return items;
|
|
841
|
+
}
|
|
842
|
+
const keys = Object.getOwnPropertyNames(object);
|
|
843
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
844
|
+
if (value instanceof Error) {
|
|
845
|
+
const ownName = Object.getOwnPropertyDescriptor(object, "name");
|
|
846
|
+
let type = ownName && "value" in ownName ? ownName.value : void 0;
|
|
847
|
+
if (typeof type !== "string") {
|
|
848
|
+
const name = Object.getOwnPropertyDescriptor(
|
|
849
|
+
Object.getPrototypeOf(value),
|
|
850
|
+
"name"
|
|
851
|
+
);
|
|
852
|
+
type = name && "value" in name ? name.value : "Error";
|
|
853
|
+
}
|
|
854
|
+
result.type = visit(
|
|
855
|
+
typeof type === "string" ? type : "Error",
|
|
856
|
+
`${path}/type`,
|
|
857
|
+
depth + 1
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
for (const key of keys.slice(0, import_telemetry_contracts.DIAGNOSTIC_LIMITS.properties)) {
|
|
861
|
+
if (["__proto__", "constructor", "prototype"].includes(key)) {
|
|
862
|
+
result[key] = omit(`${path}/${pointer(key)}`, "unsafe_key");
|
|
863
|
+
continue;
|
|
864
|
+
}
|
|
865
|
+
remaining -= encoder.encode(key).length + 4;
|
|
866
|
+
result[key] = read(object, key, `${path}/${pointer(key)}`, depth);
|
|
867
|
+
}
|
|
868
|
+
if (keys.length > import_telemetry_contracts.DIAGNOSTIC_LIMITS.properties)
|
|
869
|
+
result.$omittedProperties = omit(path, "property_limit", {
|
|
870
|
+
originalCount: keys.length
|
|
871
|
+
});
|
|
872
|
+
return result;
|
|
735
873
|
} catch {
|
|
736
|
-
return
|
|
874
|
+
return omit(path, "unreadable_object");
|
|
875
|
+
}
|
|
876
|
+
};
|
|
877
|
+
const read = (object, key, path, depth) => {
|
|
878
|
+
if ((0, import_telemetry_contracts.isPrivateDiagnosticField)(key)) {
|
|
879
|
+
if (redactions.length < 1e3)
|
|
880
|
+
redactions.push({
|
|
881
|
+
path: path.slice(0, 4096),
|
|
882
|
+
reason: "credential_field"
|
|
883
|
+
});
|
|
884
|
+
return "[REDACTED]";
|
|
885
|
+
}
|
|
886
|
+
try {
|
|
887
|
+
const property = Object.getOwnPropertyDescriptor(object, key);
|
|
888
|
+
if (property && "value" in property)
|
|
889
|
+
return visit(property.value, path, depth + 1);
|
|
890
|
+
if (key === "stack" && object instanceof Error && property?.get && property.get === nativeStackGetter)
|
|
891
|
+
return visit(nativeStack(object, property.get), path, depth + 1);
|
|
892
|
+
return omit(
|
|
893
|
+
path,
|
|
894
|
+
property ? "accessor_not_evaluated" : "unavailable_property"
|
|
895
|
+
);
|
|
896
|
+
} catch {
|
|
897
|
+
return omit(path, "unreadable_property");
|
|
737
898
|
}
|
|
738
|
-
})() : void 0);
|
|
739
|
-
const cause = depth < MAX_CAUSE_DEPTH ? (0, import_errors2.errorProperty)(value, "cause") : null;
|
|
740
|
-
return {
|
|
741
|
-
type: typeof name === "string" ? name.slice(0, 256) : "Error",
|
|
742
|
-
message: (typeof value === "string" ? value : typeof message === "string" ? message : "Execution reported a fault.").slice(0, 8192),
|
|
743
|
-
...typeof stack === "string" ? { stack: stack.slice(0, MAX_STACK_LENGTH) } : {},
|
|
744
|
-
...cause !== null && cause !== void 0 ? { cause: projectDetails(cause, depth + 1, seen) } : {}
|
|
745
899
|
};
|
|
746
|
-
};
|
|
747
|
-
var sanitizeProjectedDetails = (details, depth = 0) => ({
|
|
748
|
-
...typeof details.type === "string" ? { type: details.type.slice(0, 256) } : {},
|
|
749
|
-
message: typeof details.message === "string" ? details.message.slice(0, 8192) : "Execution reported a fault.",
|
|
750
|
-
...typeof details.stack === "string" ? { stack: details.stack.slice(0, MAX_STACK_LENGTH) } : {},
|
|
751
|
-
...depth < MAX_CAUSE_DEPTH && details.cause ? { cause: sanitizeProjectedDetails(details.cause, depth + 1) } : {}
|
|
752
|
-
});
|
|
753
|
-
function exceptionDiagnostics(error, project) {
|
|
754
900
|
try {
|
|
755
|
-
const
|
|
756
|
-
|
|
901
|
+
const original = project ? project(error) : error;
|
|
902
|
+
if (project && original === null) return null;
|
|
903
|
+
const captured = visit(original, "#/data", 0);
|
|
904
|
+
const upstreamOmissions = (0, import_errors2.errorProperty)(original, "diagnosticOmissions");
|
|
905
|
+
if (Array.isArray(upstreamOmissions))
|
|
906
|
+
for (const note of upstreamOmissions.slice(0, 1e3)) {
|
|
907
|
+
const path = (0, import_errors2.errorProperty)(note, "path");
|
|
908
|
+
const reason = (0, import_errors2.errorProperty)(note, "reason");
|
|
909
|
+
if (typeof path === "string" && typeof reason === "string")
|
|
910
|
+
omissions.push({
|
|
911
|
+
path: (0, import_telemetry_contracts.redactDiagnosticText)(path).slice(0, 4096),
|
|
912
|
+
reason: (0, import_telemetry_contracts.redactDiagnosticText)(reason).slice(0, 128)
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
const data = captured && typeof captured === "object" && !Array.isArray(captured) ? captured : {
|
|
916
|
+
type: "Error",
|
|
917
|
+
message: typeof captured === "string" ? captured : "Execution reported a fault.",
|
|
918
|
+
value: captured
|
|
919
|
+
};
|
|
920
|
+
if (typeof data.message !== "string" && !("message" in data))
|
|
921
|
+
data.message = "Execution reported a fault.";
|
|
922
|
+
if (!("type" in data))
|
|
923
|
+
data.type = typeof data.name === "string" ? data.name : "Error";
|
|
924
|
+
const content = {
|
|
925
|
+
schemaVersion: 1,
|
|
926
|
+
data,
|
|
927
|
+
capture: {
|
|
928
|
+
status: omissions.length ? "partial" : "complete",
|
|
929
|
+
omissions,
|
|
930
|
+
redactions
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
if (encoder.encode(JSON.stringify(content)).length > import_telemetry_contracts.DIAGNOSTIC_LIMITS.bytes)
|
|
934
|
+
return {
|
|
935
|
+
schemaVersion: 1,
|
|
936
|
+
data: {
|
|
937
|
+
type: "Error",
|
|
938
|
+
message: "Diagnostic exceeded the capture budget."
|
|
939
|
+
},
|
|
940
|
+
capture: {
|
|
941
|
+
status: "partial",
|
|
942
|
+
redactions: [],
|
|
943
|
+
omissions: [{ path: "#/data", reason: "serialized_byte_limit" }]
|
|
944
|
+
}
|
|
945
|
+
};
|
|
946
|
+
return content;
|
|
757
947
|
} catch {
|
|
758
|
-
return
|
|
948
|
+
return {
|
|
949
|
+
schemaVersion: 1,
|
|
950
|
+
data: { type: "Error", message: "Diagnostic capture failed." },
|
|
951
|
+
capture: {
|
|
952
|
+
status: "failed",
|
|
953
|
+
redactions: [],
|
|
954
|
+
omissions: [{ path: "#/data", reason: "projection_or_capture_failed" }]
|
|
955
|
+
}
|
|
956
|
+
};
|
|
759
957
|
}
|
|
760
958
|
}
|
|
959
|
+
|
|
960
|
+
// src/error-diagnostics.ts
|
|
961
|
+
function exceptionDiagnostics(error, project) {
|
|
962
|
+
const content = captureDiagnosticContent(error, project);
|
|
963
|
+
return !content || content.capture.status === "failed" ? null : content.data;
|
|
964
|
+
}
|
|
761
965
|
function errorDiagnostics(error, project) {
|
|
762
|
-
const
|
|
966
|
+
const captured = exceptionDiagnostics(error, project);
|
|
967
|
+
const details = captured ? (0, import_telemetry_contracts2.summarizeDiagnostic)(captured) : null;
|
|
763
968
|
return details ? {
|
|
764
|
-
errorMessage: details.message,
|
|
765
|
-
...details.type ? { errorType: details.type } : {}
|
|
969
|
+
errorMessage: details.message.slice(0, 8192),
|
|
970
|
+
...details.type ? { errorType: details.type.slice(0, 256) } : {}
|
|
766
971
|
} : {};
|
|
767
972
|
}
|
|
768
973
|
|
|
@@ -854,10 +1059,40 @@ async function closeOwnedTools(owned) {
|
|
|
854
1059
|
function captureToolError(observation, error, policy, returned = false) {
|
|
855
1060
|
try {
|
|
856
1061
|
const reported = returned && error && typeof error === "object" && "isError" in error && error.isError === true && "content" in error && typeof error.content === "string" ? { name: "ToolError", message: error.content } : error;
|
|
1062
|
+
let projected = false;
|
|
1063
|
+
let projection;
|
|
1064
|
+
let projectionFailure;
|
|
1065
|
+
let projectionFailed = false;
|
|
1066
|
+
const project = policy?.error ? (original) => {
|
|
1067
|
+
if (!projected) {
|
|
1068
|
+
projected = true;
|
|
1069
|
+
try {
|
|
1070
|
+
projection = policy.error?.(original);
|
|
1071
|
+
} catch (error2) {
|
|
1072
|
+
projectionFailure = error2;
|
|
1073
|
+
projectionFailed = true;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
if (projectionFailed) throw projectionFailure;
|
|
1077
|
+
return projection ?? null;
|
|
1078
|
+
} : void 0;
|
|
857
1079
|
Object.assign(
|
|
858
1080
|
observation,
|
|
859
|
-
errorDiagnostics(policy?.error ? error : reported,
|
|
1081
|
+
errorDiagnostics(policy?.error ? error : reported, project)
|
|
1082
|
+
);
|
|
1083
|
+
const diagnosticId = getHookContext().reasonTrace?.reportError?.(
|
|
1084
|
+
policy?.error ? error : reported,
|
|
1085
|
+
{
|
|
1086
|
+
mechanism: "tool",
|
|
1087
|
+
...project ? { error: project } : {},
|
|
1088
|
+
correlation: {
|
|
1089
|
+
toolCallId: observation.toolCallId,
|
|
1090
|
+
attemptId: observation.attemptId
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
860
1093
|
);
|
|
1094
|
+
if (typeof diagnosticId === "string")
|
|
1095
|
+
observation.diagnosticId = diagnosticId;
|
|
861
1096
|
} catch {
|
|
862
1097
|
}
|
|
863
1098
|
}
|