agent-inspect 6.31.3 → 6.31.4
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 +8 -0
- package/README.md +1 -1
- package/SECURITY.md +2 -0
- package/docs/GETTING-STARTED.md +2 -0
- package/docs/SAFE-TRACE-SHARING.md +1 -0
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-SJ6FRNOE.mjs → chunk-LKEPABND.mjs} +86 -80
- package/packages/cli/dist/chunk-LKEPABND.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +399 -91
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +307 -14
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-YNEJOPRA.mjs → src-4WYF5RFI.mjs} +3 -3
- package/packages/cli/dist/{src-YNEJOPRA.mjs.map → src-4WYF5RFI.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +97 -30
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.mjs +13 -13
- package/packages/core/dist/checks.cjs +51 -49
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.mjs +5 -5
- package/packages/core/dist/{chunk-PBNBQRXV.mjs → chunk-2KJR6X4V.mjs} +9 -9
- package/packages/core/dist/chunk-2KJR6X4V.mjs.map +1 -0
- package/packages/core/dist/{chunk-26YJSETN.mjs → chunk-7DHSWDKB.mjs} +19 -6
- package/packages/core/dist/chunk-7DHSWDKB.mjs.map +1 -0
- package/packages/core/dist/{chunk-BGF5JDJN.mjs → chunk-INE5IWLN.mjs} +3 -3
- package/packages/core/dist/{chunk-BGF5JDJN.mjs.map → chunk-INE5IWLN.mjs.map} +1 -1
- package/packages/core/dist/{chunk-ZFJ2ICTC.mjs → chunk-MTMTXTJL.mjs} +5 -5
- package/packages/core/dist/{chunk-ZFJ2ICTC.mjs.map → chunk-MTMTXTJL.mjs.map} +1 -1
- package/packages/core/dist/{chunk-KWBO36PH.mjs → chunk-NY4ILMXK.mjs} +4 -4
- package/packages/core/dist/{chunk-KWBO36PH.mjs.map → chunk-NY4ILMXK.mjs.map} +1 -1
- package/packages/core/dist/{chunk-WN5PT4GV.mjs → chunk-OSGNGRHF.mjs} +3 -3
- package/packages/core/dist/{chunk-WN5PT4GV.mjs.map → chunk-OSGNGRHF.mjs.map} +1 -1
- package/packages/core/dist/{chunk-CBPWLHNQ.mjs → chunk-PKDBFBJ7.mjs} +5 -76
- package/packages/core/dist/chunk-PKDBFBJ7.mjs.map +1 -0
- package/packages/core/dist/{chunk-VU6O5QAH.mjs → chunk-VLVCLAPB.mjs} +83 -5
- package/packages/core/dist/chunk-VLVCLAPB.mjs.map +1 -0
- package/packages/core/dist/exporters.cjs +217 -6
- package/packages/core/dist/exporters.cjs.map +1 -1
- package/packages/core/dist/exporters.mjs +118 -9
- package/packages/core/dist/exporters.mjs.map +1 -1
- package/packages/core/dist/index.cjs +97 -8
- package/packages/core/dist/index.cjs.map +1 -1
- package/packages/core/dist/index.mjs +6 -6
- package/packages/core/dist/logs.cjs +80 -2
- package/packages/core/dist/logs.cjs.map +1 -1
- package/packages/core/dist/logs.d.cts +2 -0
- package/packages/core/dist/logs.d.ts +2 -0
- package/packages/core/dist/logs.mjs +2 -2
- package/packages/core/dist/readers.cjs +2 -0
- package/packages/core/dist/readers.cjs.map +1 -1
- package/packages/core/dist/readers.mjs +2 -2
- package/packages/core/dist/writers.cjs +96 -8
- package/packages/core/dist/writers.cjs.map +1 -1
- package/packages/core/dist/writers.mjs +7 -8
- package/packages/core/dist/writers.mjs.map +1 -1
- package/packages/cli/dist/chunk-SJ6FRNOE.mjs.map +0 -1
- package/packages/core/dist/chunk-26YJSETN.mjs.map +0 -1
- package/packages/core/dist/chunk-CBPWLHNQ.mjs.map +0 -1
- package/packages/core/dist/chunk-PBNBQRXV.mjs.map +0 -1
- package/packages/core/dist/chunk-VU6O5QAH.mjs.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { buildRunWhatSummary, renderRunWhat, renderTimeline, buildRunTimeline } from './chunk-
|
|
2
|
-
import { summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml } from './chunk-
|
|
1
|
+
import { buildRunWhatSummary, renderRunWhat, renderTimeline, buildRunTimeline } from './chunk-NY4ILMXK.mjs';
|
|
2
|
+
import { summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml } from './chunk-INE5IWLN.mjs';
|
|
3
3
|
import { escapeHtml, flattenTree, safeString, compactAttributes, stableJson, escapeMarkdown, zeroKinds } from './chunk-CAWPF22J.mjs';
|
|
4
4
|
export { compactAttributes, escapeHtml, escapeMarkdown, flattenTree, safeString, stableJson, summarizeTree } from './chunk-CAWPF22J.mjs';
|
|
5
|
-
import { resolveRedactionProfile, applyProfileMetadataCaps, truncateStringForProfile } from './chunk-
|
|
6
|
-
import { Redactor } from './chunk-
|
|
7
|
-
import './chunk-
|
|
5
|
+
import { resolveRedactionProfile, applyProfileMetadataCaps, truncateStringForProfile, stringContainsHighConfidenceCredential } from './chunk-2KJR6X4V.mjs';
|
|
6
|
+
import { Redactor, DEFAULT_REDACT_KEYS, isCredentialSensitiveKey } from './chunk-VLVCLAPB.mjs';
|
|
7
|
+
import './chunk-7DHSWDKB.mjs';
|
|
8
8
|
import './chunk-EE5Z2GQ3.mjs';
|
|
9
9
|
import './chunk-7TGZLWEE.mjs';
|
|
10
10
|
import crypto from 'crypto';
|
|
@@ -12,6 +12,99 @@ import crypto from 'crypto';
|
|
|
12
12
|
// packages/core/src/exporters/types.ts
|
|
13
13
|
var EXPORT_PAYLOAD_VERSION = "0.1.2";
|
|
14
14
|
|
|
15
|
+
// packages/core/src/safety/url-redaction.ts
|
|
16
|
+
var HTTP_URL = /^https?:\/\/[^\s]+$/i;
|
|
17
|
+
var UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
18
|
+
var HEX_SEGMENT = /^[0-9a-f]{12,}$/i;
|
|
19
|
+
var NUMERIC_SEGMENT = /^\d{5,}$/;
|
|
20
|
+
var OPAQUE_SEGMENT = /^[A-Za-z0-9_-]{20,}$/;
|
|
21
|
+
function looksLikeHttpUrl(value) {
|
|
22
|
+
return HTTP_URL.test(value.trim());
|
|
23
|
+
}
|
|
24
|
+
function parseHttpUrl(value) {
|
|
25
|
+
try {
|
|
26
|
+
const url = new URL(value.trim());
|
|
27
|
+
return url.protocol === "http:" || url.protocol === "https:" ? url : void 0;
|
|
28
|
+
} catch {
|
|
29
|
+
return void 0;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function isIdentifierSegment(segment) {
|
|
33
|
+
if (UUID_SEGMENT.test(segment)) return true;
|
|
34
|
+
if (HEX_SEGMENT.test(segment)) return true;
|
|
35
|
+
if (NUMERIC_SEGMENT.test(segment)) return true;
|
|
36
|
+
return OPAQUE_SEGMENT.test(segment) && /\d/.test(segment) && /[A-Za-z]/.test(segment);
|
|
37
|
+
}
|
|
38
|
+
function decodeParam(value) {
|
|
39
|
+
try {
|
|
40
|
+
return decodeURIComponent(value.replace(/\+/g, " "));
|
|
41
|
+
} catch {
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function redactParams(raw, options, replacement) {
|
|
46
|
+
let redacted = false;
|
|
47
|
+
const parts = raw.split("&").map((part) => {
|
|
48
|
+
if (part.length === 0) return part;
|
|
49
|
+
const separator = part.indexOf("=");
|
|
50
|
+
if (separator < 0) return part;
|
|
51
|
+
const rawKey = part.slice(0, separator);
|
|
52
|
+
const rawValue = part.slice(separator + 1);
|
|
53
|
+
const key = decodeParam(rawKey);
|
|
54
|
+
const value = decodeParam(rawValue);
|
|
55
|
+
if (isCredentialSensitiveKey(key, options.sensitiveKeys) || options.isSensitiveValue(value)) {
|
|
56
|
+
redacted = true;
|
|
57
|
+
return `${rawKey}=${replacement}`;
|
|
58
|
+
}
|
|
59
|
+
return part;
|
|
60
|
+
});
|
|
61
|
+
return { value: parts.join("&"), redacted };
|
|
62
|
+
}
|
|
63
|
+
function redactUrlString(value, options) {
|
|
64
|
+
const unchanged = {
|
|
65
|
+
value,
|
|
66
|
+
credentialRedacted: false,
|
|
67
|
+
identifiersMasked: false
|
|
68
|
+
};
|
|
69
|
+
if (!looksLikeHttpUrl(value)) return unchanged;
|
|
70
|
+
const url = parseHttpUrl(value);
|
|
71
|
+
if (!url) return unchanged;
|
|
72
|
+
const replacement = options.replacement ?? "[REDACTED]";
|
|
73
|
+
const idPlaceholder = options.idPlaceholder ?? "[id]";
|
|
74
|
+
let credentialRedacted = url.username.length > 0 || url.password.length > 0;
|
|
75
|
+
let identifiersMasked = false;
|
|
76
|
+
let pathname = url.pathname;
|
|
77
|
+
if (options.maskPathIds === true) {
|
|
78
|
+
pathname = url.pathname.split("/").map((segment) => {
|
|
79
|
+
if (segment.length === 0 || !isIdentifierSegment(decodeParam(segment))) {
|
|
80
|
+
return segment;
|
|
81
|
+
}
|
|
82
|
+
identifiersMasked = true;
|
|
83
|
+
return idPlaceholder;
|
|
84
|
+
}).join("/");
|
|
85
|
+
}
|
|
86
|
+
let search = "";
|
|
87
|
+
if (url.search.length > 1) {
|
|
88
|
+
const params = redactParams(url.search.slice(1), options, replacement);
|
|
89
|
+
if (params.redacted) credentialRedacted = true;
|
|
90
|
+
search = `?${params.value}`;
|
|
91
|
+
} else if (url.search.length === 1) {
|
|
92
|
+
search = "?";
|
|
93
|
+
}
|
|
94
|
+
let hash = url.hash;
|
|
95
|
+
if (url.hash.includes("=")) {
|
|
96
|
+
const params = redactParams(url.hash.slice(1), options, replacement);
|
|
97
|
+
if (params.redacted) credentialRedacted = true;
|
|
98
|
+
hash = `#${params.value}`;
|
|
99
|
+
}
|
|
100
|
+
if (!credentialRedacted && !identifiersMasked) return unchanged;
|
|
101
|
+
return {
|
|
102
|
+
value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,
|
|
103
|
+
credentialRedacted,
|
|
104
|
+
identifiersMasked
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
15
108
|
// packages/core/src/exporters/redact-export.ts
|
|
16
109
|
function isRecord(value) {
|
|
17
110
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -29,21 +122,34 @@ function deepClone(value) {
|
|
|
29
122
|
}
|
|
30
123
|
return out;
|
|
31
124
|
}
|
|
32
|
-
function boundAttributeValues(record, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
125
|
+
function boundAttributeValues(record, sensitiveKeys, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
33
126
|
if (depth > 32) {
|
|
34
127
|
return { truncated: true, reason: "maxDepth" };
|
|
35
128
|
}
|
|
36
129
|
const out = {};
|
|
37
130
|
for (const [key, value] of Object.entries(record)) {
|
|
38
|
-
out[key] = boundValue(
|
|
131
|
+
out[key] = boundValue(
|
|
132
|
+
value,
|
|
133
|
+
key,
|
|
134
|
+
sensitiveKeys,
|
|
135
|
+
maxMetadataValueLength,
|
|
136
|
+
maxPreviewLength,
|
|
137
|
+
seen,
|
|
138
|
+
depth
|
|
139
|
+
);
|
|
39
140
|
}
|
|
40
141
|
return out;
|
|
41
142
|
}
|
|
42
|
-
function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
143
|
+
function boundValue(value, key, sensitiveKeys, maxMetadataValueLength, maxPreviewLength, seen, depth) {
|
|
43
144
|
if (value === null || typeof value !== "object") {
|
|
44
145
|
if (typeof value === "string") {
|
|
146
|
+
const rewritten = redactUrlString(value, {
|
|
147
|
+
sensitiveKeys,
|
|
148
|
+
isSensitiveValue: stringContainsHighConfidenceCredential,
|
|
149
|
+
maskPathIds: true
|
|
150
|
+
}).value;
|
|
45
151
|
return truncateStringForProfile(
|
|
46
|
-
|
|
152
|
+
stringContainsHighConfidenceCredential(rewritten) ? "[REDACTED]" : rewritten,
|
|
47
153
|
key,
|
|
48
154
|
maxMetadataValueLength,
|
|
49
155
|
maxPreviewLength
|
|
@@ -58,6 +164,7 @@ function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen,
|
|
|
58
164
|
(item, index) => boundValue(
|
|
59
165
|
item,
|
|
60
166
|
String(index),
|
|
167
|
+
sensitiveKeys,
|
|
61
168
|
maxMetadataValueLength,
|
|
62
169
|
maxPreviewLength,
|
|
63
170
|
seen,
|
|
@@ -67,6 +174,7 @@ function boundValue(value, key, maxMetadataValueLength, maxPreviewLength, seen,
|
|
|
67
174
|
}
|
|
68
175
|
return boundAttributeValues(
|
|
69
176
|
value,
|
|
177
|
+
sensitiveKeys,
|
|
70
178
|
maxMetadataValueLength,
|
|
71
179
|
maxPreviewLength,
|
|
72
180
|
seen,
|
|
@@ -81,6 +189,7 @@ function redactEventAttributes(attrs, redactor, maxMetadataValueLength, maxPrevi
|
|
|
81
189
|
const seen = /* @__PURE__ */ new WeakSet();
|
|
82
190
|
const bounded = boundAttributeValues(
|
|
83
191
|
redacted,
|
|
192
|
+
[...DEFAULT_REDACT_KEYS, ...redactor.sensitiveKeys],
|
|
84
193
|
maxMetadataValueLength,
|
|
85
194
|
maxPreviewLength,
|
|
86
195
|
seen,
|