@agent-inspect/mcp 6.29.1 → 6.29.2
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/README.md +11 -2
- package/dist/index.cjs +3 -1039
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1 -1030
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var crypto = require('crypto');
|
|
5
|
-
var promises = require('fs/promises');
|
|
6
|
-
var path = require('path');
|
|
7
|
-
var os = require('os');
|
|
8
|
-
var nanoid = require('nanoid');
|
|
9
|
-
var chalk = require('chalk');
|
|
10
|
-
|
|
11
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
-
|
|
13
|
-
var crypto__default = /*#__PURE__*/_interopDefault(crypto);
|
|
14
|
-
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
15
|
-
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
16
|
-
var chalk__default = /*#__PURE__*/_interopDefault(chalk);
|
|
3
|
+
var agentInspect = require('agent-inspect');
|
|
17
4
|
|
|
18
5
|
// packages/mcp/src/summarize.ts
|
|
19
6
|
var DEFAULT_MAX_SUMMARY_LENGTH = 240;
|
|
@@ -46,1029 +33,6 @@ function hashServerUrl(url) {
|
|
|
46
33
|
}
|
|
47
34
|
return hash.toString(16).padStart(8, "0");
|
|
48
35
|
}
|
|
49
|
-
var DEFAULT_REDACT_KEYS = [
|
|
50
|
-
"authorization",
|
|
51
|
-
"cookie",
|
|
52
|
-
"token",
|
|
53
|
-
"apiKey",
|
|
54
|
-
"password",
|
|
55
|
-
"secret",
|
|
56
|
-
"email"
|
|
57
|
-
];
|
|
58
|
-
function isRecord(v) {
|
|
59
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
60
|
-
}
|
|
61
|
-
function toKey(s) {
|
|
62
|
-
return s.toLowerCase();
|
|
63
|
-
}
|
|
64
|
-
function stableHash(value) {
|
|
65
|
-
const h = crypto__default.default.createHash("sha256").update(value, "utf8").digest("hex");
|
|
66
|
-
return h.slice(0, 8);
|
|
67
|
-
}
|
|
68
|
-
function compileRules(rules, extraKeys) {
|
|
69
|
-
const out = /* @__PURE__ */ new Map();
|
|
70
|
-
const set = (r) => {
|
|
71
|
-
const k = toKey(r.key);
|
|
72
|
-
out.set(k, { ...r, key: k });
|
|
73
|
-
};
|
|
74
|
-
for (const k of DEFAULT_REDACT_KEYS) {
|
|
75
|
-
set({ key: k, strategy: "full" });
|
|
76
|
-
}
|
|
77
|
-
for (const k of extraKeys ?? []) {
|
|
78
|
-
if (typeof k === "string" && k.length > 0) {
|
|
79
|
-
set({ key: k, strategy: "full" });
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
for (const r of rules ?? []) {
|
|
83
|
-
if (typeof r === "string") {
|
|
84
|
-
set({ key: r, strategy: "full" });
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
const key = r.key;
|
|
88
|
-
if (r.strategy === "full") set({ key, strategy: "full" });
|
|
89
|
-
if (r.strategy === "hash") set({ key, strategy: "hash" });
|
|
90
|
-
if (r.strategy === "prefix") {
|
|
91
|
-
set({ key, strategy: "prefix", keep: typeof r.keep === "number" ? r.keep : 8 });
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return [...out.values()];
|
|
95
|
-
}
|
|
96
|
-
var Redactor = class {
|
|
97
|
-
#rules;
|
|
98
|
-
constructor(options) {
|
|
99
|
-
this.#rules = compileRules(options?.rules, options?.extraKeys);
|
|
100
|
-
}
|
|
101
|
-
redactValue(key, value) {
|
|
102
|
-
const k = toKey(key);
|
|
103
|
-
const rule = this.#rules.find((r) => r.key === k);
|
|
104
|
-
if (!rule) {
|
|
105
|
-
return this.#redactNested(value);
|
|
106
|
-
}
|
|
107
|
-
if (rule.strategy === "full") return "[REDACTED]";
|
|
108
|
-
const asString = typeof value === "string" ? value : typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" ? String(value) : void 0;
|
|
109
|
-
if (rule.strategy === "prefix") {
|
|
110
|
-
if (asString === void 0) return "[REDACTED]";
|
|
111
|
-
const keep = Math.max(0, Math.floor(rule.keep));
|
|
112
|
-
return asString.length <= keep ? `${asString}\u2026` : `${asString.slice(0, keep)}\u2026`;
|
|
113
|
-
}
|
|
114
|
-
if (rule.strategy === "hash") {
|
|
115
|
-
if (asString === void 0) return "[HASH:unknown]";
|
|
116
|
-
return `[HASH:${stableHash(asString)}]`;
|
|
117
|
-
}
|
|
118
|
-
return this.#redactNested(value);
|
|
119
|
-
}
|
|
120
|
-
redactRecord(record) {
|
|
121
|
-
const out = {};
|
|
122
|
-
for (const [k, v] of Object.entries(record)) {
|
|
123
|
-
out[k] = this.redactValue(k, v);
|
|
124
|
-
}
|
|
125
|
-
return out;
|
|
126
|
-
}
|
|
127
|
-
#redactNested(value) {
|
|
128
|
-
if (Array.isArray(value)) {
|
|
129
|
-
return value.map((v) => this.#redactNested(v));
|
|
130
|
-
}
|
|
131
|
-
if (isRecord(value)) {
|
|
132
|
-
const out = {};
|
|
133
|
-
for (const [k, v] of Object.entries(value)) {
|
|
134
|
-
out[k] = this.redactValue(k, v);
|
|
135
|
-
}
|
|
136
|
-
return out;
|
|
137
|
-
}
|
|
138
|
-
return value;
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
// packages/core/src/safety/credential-value-patterns.ts
|
|
143
|
-
var KEY_VALUE_SECRET_PATTERN = /\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=([^\s"'\\]{8,})/i;
|
|
144
|
-
var HIGH_CONFIDENCE_CREDENTIAL_PATTERNS = [
|
|
145
|
-
/^(?:basic|bearer|digest|apikey)\s+[a-z0-9._~+/=-]+$/i,
|
|
146
|
-
/\bbearer\s+[a-z0-9._~+/=-]{12,}\b/i,
|
|
147
|
-
/\b[a-z0-9_.-]+=[^;\s]+(?:;\s*[a-z0-9_.-]+=[^;\s]+)+/i,
|
|
148
|
-
/\beyJ[a-zA-Z0-9_-]{8,}\.[a-zA-Z0-9_-]{8,}\.[a-zA-Z0-9_-]{8,}\b/,
|
|
149
|
-
/\b(?:sk-(?:proj-)?[a-zA-Z0-9_-]{16,}|sk-ant-[a-zA-Z0-9_-]{16,}|AIza[0-9A-Za-z_-]{20,})\b/,
|
|
150
|
-
/\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{20,}\b/,
|
|
151
|
-
/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/,
|
|
152
|
-
/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*-----END [A-Z ]*PRIVATE KEY-----/,
|
|
153
|
-
KEY_VALUE_SECRET_PATTERN
|
|
154
|
-
];
|
|
155
|
-
function stringContainsHighConfidenceCredential(value) {
|
|
156
|
-
for (const pattern of HIGH_CONFIDENCE_CREDENTIAL_PATTERNS) {
|
|
157
|
-
pattern.lastIndex = 0;
|
|
158
|
-
if (pattern.test(value)) {
|
|
159
|
-
pattern.lastIndex = 0;
|
|
160
|
-
return true;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
function redactHighConfidenceCredentialsInString(value, replacement = "[REDACTED]") {
|
|
166
|
-
return stringContainsHighConfidenceCredential(value) ? replacement : value;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// packages/core/src/redaction-profiles.ts
|
|
170
|
-
var SHARE_PROFILE_EXTRA_KEYS = [
|
|
171
|
-
"userEmail",
|
|
172
|
-
"customerEmail",
|
|
173
|
-
"phone",
|
|
174
|
-
"phoneNumber",
|
|
175
|
-
"address",
|
|
176
|
-
"ip",
|
|
177
|
-
"ipAddress",
|
|
178
|
-
"sessionId",
|
|
179
|
-
"requestId",
|
|
180
|
-
"correlationId",
|
|
181
|
-
"decisionId",
|
|
182
|
-
"groupId",
|
|
183
|
-
"customerId",
|
|
184
|
-
"userId",
|
|
185
|
-
"accountId",
|
|
186
|
-
"tenantId",
|
|
187
|
-
"orgId",
|
|
188
|
-
"organizationId",
|
|
189
|
-
"traceId",
|
|
190
|
-
"spanId",
|
|
191
|
-
"parentSpanId"
|
|
192
|
-
];
|
|
193
|
-
var STRICT_PROFILE_EXTRA_KEYS = [
|
|
194
|
-
"prompt",
|
|
195
|
-
"completion",
|
|
196
|
-
"input",
|
|
197
|
-
"output",
|
|
198
|
-
"inputPreview",
|
|
199
|
-
"outputPreview",
|
|
200
|
-
"message",
|
|
201
|
-
"messages",
|
|
202
|
-
"transcript",
|
|
203
|
-
"context",
|
|
204
|
-
"document",
|
|
205
|
-
"documents",
|
|
206
|
-
"chunk",
|
|
207
|
-
"chunks",
|
|
208
|
-
"retrieval",
|
|
209
|
-
"query"
|
|
210
|
-
];
|
|
211
|
-
function resolveRedactionProfile(profile = "local") {
|
|
212
|
-
switch (profile) {
|
|
213
|
-
case "local":
|
|
214
|
-
return { profile: "local", extraKeys: [] };
|
|
215
|
-
case "share":
|
|
216
|
-
return {
|
|
217
|
-
profile: "share",
|
|
218
|
-
extraKeys: SHARE_PROFILE_EXTRA_KEYS,
|
|
219
|
-
maxMetadataValueLengthCap: 500,
|
|
220
|
-
maxPreviewLengthCap: 200
|
|
221
|
-
};
|
|
222
|
-
case "strict":
|
|
223
|
-
return {
|
|
224
|
-
profile: "strict",
|
|
225
|
-
extraKeys: [...SHARE_PROFILE_EXTRA_KEYS, ...STRICT_PROFILE_EXTRA_KEYS],
|
|
226
|
-
maxMetadataValueLengthCap: 200,
|
|
227
|
-
maxPreviewLengthCap: 80
|
|
228
|
-
};
|
|
229
|
-
default:
|
|
230
|
-
return { profile: "local", extraKeys: [] };
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
function applyProfileMetadataCaps(maxMetadataValueLength, maxPreviewLength, resolved) {
|
|
234
|
-
let meta = maxMetadataValueLength;
|
|
235
|
-
let preview = maxPreviewLength;
|
|
236
|
-
if (resolved.maxMetadataValueLengthCap !== void 0) {
|
|
237
|
-
meta = Math.min(meta, resolved.maxMetadataValueLengthCap);
|
|
238
|
-
}
|
|
239
|
-
if (resolved.maxPreviewLengthCap !== void 0) {
|
|
240
|
-
preview = Math.min(preview, resolved.maxPreviewLengthCap);
|
|
241
|
-
}
|
|
242
|
-
return { maxMetadataValueLength: meta, maxPreviewLength: preview };
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// packages/core/src/types.ts
|
|
246
|
-
var STEP_TYPES = [
|
|
247
|
-
"run",
|
|
248
|
-
"llm",
|
|
249
|
-
"tool",
|
|
250
|
-
"decision",
|
|
251
|
-
"logic",
|
|
252
|
-
"state",
|
|
253
|
-
"custom"
|
|
254
|
-
];
|
|
255
|
-
function isStepType(value) {
|
|
256
|
-
return typeof value === "string" && STEP_TYPES.includes(value);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// packages/core/src/utils/duration.ts
|
|
260
|
-
function formatDuration(ms) {
|
|
261
|
-
if (!Number.isFinite(ms)) {
|
|
262
|
-
return "0ms";
|
|
263
|
-
}
|
|
264
|
-
if (ms < 0) {
|
|
265
|
-
throw new Error(`formatDuration: ms must be non-negative (got ${ms})`);
|
|
266
|
-
}
|
|
267
|
-
if (ms < 1e3) {
|
|
268
|
-
return `${Math.floor(ms)}ms`;
|
|
269
|
-
}
|
|
270
|
-
if (ms < 6e4) {
|
|
271
|
-
return `${(ms / 1e3).toFixed(2)}s`;
|
|
272
|
-
}
|
|
273
|
-
if (ms < 36e5) {
|
|
274
|
-
return `${(ms / 6e4).toFixed(1)}m`;
|
|
275
|
-
}
|
|
276
|
-
return `${(ms / 36e5).toFixed(1)}h`;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// packages/core/src/utils.ts
|
|
280
|
-
var DEFAULT_TRACE_DIR_NAME = ".agent-inspect";
|
|
281
|
-
var RUNS_DIR_NAME = "runs";
|
|
282
|
-
var FALLBACK_TRACE_DIR = path__default.default.join(
|
|
283
|
-
os__default.default.tmpdir(),
|
|
284
|
-
"agent-inspect",
|
|
285
|
-
RUNS_DIR_NAME
|
|
286
|
-
);
|
|
287
|
-
var MAX_NAME_LENGTH = 100;
|
|
288
|
-
function createStepId() {
|
|
289
|
-
return `step_${nanoid.nanoid(10)}`;
|
|
290
|
-
}
|
|
291
|
-
function formatDuration2(ms) {
|
|
292
|
-
return formatDuration(ms);
|
|
293
|
-
}
|
|
294
|
-
function getDefaultTraceDir() {
|
|
295
|
-
const envDir = process.env.AGENT_INSPECT_TRACE_DIR;
|
|
296
|
-
if (typeof envDir === "string" && envDir.trim() !== "") {
|
|
297
|
-
return envDir.trim();
|
|
298
|
-
}
|
|
299
|
-
try {
|
|
300
|
-
const home = os__default.default.homedir();
|
|
301
|
-
if (typeof home !== "string" || home.trim() === "") {
|
|
302
|
-
return FALLBACK_TRACE_DIR;
|
|
303
|
-
}
|
|
304
|
-
return path__default.default.join(home, DEFAULT_TRACE_DIR_NAME, RUNS_DIR_NAME);
|
|
305
|
-
} catch {
|
|
306
|
-
return FALLBACK_TRACE_DIR;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
function getTraceFilePath(runId, traceDir) {
|
|
310
|
-
const baseDir = traceDir ?? getDefaultTraceDir();
|
|
311
|
-
let safeId = typeof runId === "string" && runId.trim() !== "" ? runId.trim() : "run_unknown";
|
|
312
|
-
safeId = path__default.default.basename(safeId);
|
|
313
|
-
if (safeId === "" || safeId === "." || safeId === "..") {
|
|
314
|
-
safeId = "run_unknown";
|
|
315
|
-
}
|
|
316
|
-
return path__default.default.join(baseDir, `${safeId}.jsonl`);
|
|
317
|
-
}
|
|
318
|
-
async function ensureTraceDir(traceDir) {
|
|
319
|
-
const primary = path__default.default.resolve(traceDir);
|
|
320
|
-
try {
|
|
321
|
-
await promises.mkdir(primary, { recursive: true });
|
|
322
|
-
return primary;
|
|
323
|
-
} catch {
|
|
324
|
-
warn(`Failed to create trace directory: ${primary}`);
|
|
325
|
-
const fallback = path__default.default.resolve(FALLBACK_TRACE_DIR);
|
|
326
|
-
try {
|
|
327
|
-
await promises.mkdir(fallback, { recursive: true });
|
|
328
|
-
return fallback;
|
|
329
|
-
} catch {
|
|
330
|
-
warn(`Failed to create fallback trace directory: ${fallback}`);
|
|
331
|
-
return primary;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
function formatError(error) {
|
|
336
|
-
if (error instanceof Error) {
|
|
337
|
-
const out = { message: error.message };
|
|
338
|
-
if (typeof error.stack === "string" && error.stack.length > 0) {
|
|
339
|
-
out.stack = error.stack;
|
|
340
|
-
}
|
|
341
|
-
return out;
|
|
342
|
-
}
|
|
343
|
-
if (typeof error === "string") {
|
|
344
|
-
return { message: error };
|
|
345
|
-
}
|
|
346
|
-
if (error === null) {
|
|
347
|
-
return { message: "Unknown error: null" };
|
|
348
|
-
}
|
|
349
|
-
if (error === void 0) {
|
|
350
|
-
return { message: "Unknown error: undefined" };
|
|
351
|
-
}
|
|
352
|
-
if (typeof error === "number" || typeof error === "boolean" || typeof error === "bigint") {
|
|
353
|
-
return { message: String(error) };
|
|
354
|
-
}
|
|
355
|
-
if (typeof error === "object") {
|
|
356
|
-
try {
|
|
357
|
-
return { message: JSON.stringify(error) };
|
|
358
|
-
} catch {
|
|
359
|
-
return { message: "Unknown error" };
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return { message: "Unknown error" };
|
|
363
|
-
}
|
|
364
|
-
function truncateName(name, maxLength = MAX_NAME_LENGTH) {
|
|
365
|
-
if (typeof name !== "string" || name.trim() === "") {
|
|
366
|
-
return "unnamed";
|
|
367
|
-
}
|
|
368
|
-
const trimmed = name.trim();
|
|
369
|
-
if (trimmed.length <= maxLength) {
|
|
370
|
-
return trimmed;
|
|
371
|
-
}
|
|
372
|
-
const ellipsis = "...";
|
|
373
|
-
const head = Math.max(0, maxLength - ellipsis.length);
|
|
374
|
-
return `${trimmed.slice(0, head)}${ellipsis}`;
|
|
375
|
-
}
|
|
376
|
-
function warn(message, error) {
|
|
377
|
-
const base = `[AgentInspect] ${message}`;
|
|
378
|
-
if (error === void 0) {
|
|
379
|
-
console.warn(base);
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
console.warn(`${base}: ${formatError(error).message}`);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
// packages/core/src/storage.ts
|
|
386
|
-
function isRecord2(value) {
|
|
387
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
388
|
-
}
|
|
389
|
-
function nonEmptyString(value) {
|
|
390
|
-
return typeof value === "string" && value.trim() !== "";
|
|
391
|
-
}
|
|
392
|
-
function finiteNumber(value) {
|
|
393
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
394
|
-
}
|
|
395
|
-
function optionalErrorInfo(value) {
|
|
396
|
-
if (value === void 0) return true;
|
|
397
|
-
if (!isRecord2(value)) return false;
|
|
398
|
-
if (typeof value.message !== "string") return false;
|
|
399
|
-
if ("stack" in value && value.stack !== void 0) {
|
|
400
|
-
if (typeof value.stack !== "string") return false;
|
|
401
|
-
}
|
|
402
|
-
return true;
|
|
403
|
-
}
|
|
404
|
-
function validateEvent(event) {
|
|
405
|
-
if (!isRecord2(event)) return false;
|
|
406
|
-
if (event.schemaVersion !== "0.1") return false;
|
|
407
|
-
if (!finiteNumber(event.timestamp)) return false;
|
|
408
|
-
if (typeof event.event !== "string") return false;
|
|
409
|
-
switch (event.event) {
|
|
410
|
-
case "run_started": {
|
|
411
|
-
if (!nonEmptyString(event.runId) || !nonEmptyString(event.name) || !finiteNumber(event.startTime)) {
|
|
412
|
-
return false;
|
|
413
|
-
}
|
|
414
|
-
if (event.metadata !== void 0 && !isRecord2(event.metadata)) {
|
|
415
|
-
return false;
|
|
416
|
-
}
|
|
417
|
-
return true;
|
|
418
|
-
}
|
|
419
|
-
case "run_completed": {
|
|
420
|
-
return nonEmptyString(event.runId) && (event.status === "success" || event.status === "error") && finiteNumber(event.endTime) && finiteNumber(event.durationMs) && optionalErrorInfo(event.error);
|
|
421
|
-
}
|
|
422
|
-
case "step_started": {
|
|
423
|
-
if (!nonEmptyString(event.runId) || !nonEmptyString(event.stepId) || !nonEmptyString(event.name) || !isStepType(event.type) || !finiteNumber(event.startTime)) {
|
|
424
|
-
return false;
|
|
425
|
-
}
|
|
426
|
-
if (event.parentId !== void 0 && typeof event.parentId !== "string") {
|
|
427
|
-
return false;
|
|
428
|
-
}
|
|
429
|
-
if (event.metadata !== void 0 && !isRecord2(event.metadata)) {
|
|
430
|
-
return false;
|
|
431
|
-
}
|
|
432
|
-
return true;
|
|
433
|
-
}
|
|
434
|
-
case "step_completed": {
|
|
435
|
-
return nonEmptyString(event.runId) && nonEmptyString(event.stepId) && (event.status === "success" || event.status === "error") && finiteNumber(event.endTime) && finiteNumber(event.durationMs) && optionalErrorInfo(event.error);
|
|
436
|
-
}
|
|
437
|
-
case "outcome_observed": {
|
|
438
|
-
return nonEmptyString(event.runId) && nonEmptyString(event.outcomeId) && nonEmptyString(event.name) && nonEmptyString(event.expectation) && (event.status === "passed" || event.status === "failed" || event.status === "unknown" || event.status === "skipped") && finiteNumber(event.observedAt);
|
|
439
|
-
}
|
|
440
|
-
default:
|
|
441
|
-
return false;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
function serializeEvent(event) {
|
|
445
|
-
try {
|
|
446
|
-
return JSON.stringify(event);
|
|
447
|
-
} catch {
|
|
448
|
-
return "";
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
function ensureEventWithinBounds(event) {
|
|
452
|
-
const line = serializeEvent(event);
|
|
453
|
-
if (line === "") return event;
|
|
454
|
-
const bytes = Buffer.byteLength(line, "utf8");
|
|
455
|
-
if (bytes <= DEFAULT_MAX_EVENT_BYTES) return event;
|
|
456
|
-
return prepareTraceEventForDisk(event, resolveTraceSafetyOptions());
|
|
457
|
-
}
|
|
458
|
-
async function writeTraceEvent(event, traceDir) {
|
|
459
|
-
const bounded = ensureEventWithinBounds(event);
|
|
460
|
-
if (!validateEvent(bounded)) {
|
|
461
|
-
warn("Skipped invalid trace event (validation failed)");
|
|
462
|
-
return;
|
|
463
|
-
}
|
|
464
|
-
const line = serializeEvent(bounded);
|
|
465
|
-
if (line === "") {
|
|
466
|
-
warn("Skipped trace event (serialization failed)");
|
|
467
|
-
return;
|
|
468
|
-
}
|
|
469
|
-
const payload = `${line}
|
|
470
|
-
`;
|
|
471
|
-
const tryAppend = async (dir) => {
|
|
472
|
-
try {
|
|
473
|
-
const usable = await ensureTraceDir(dir);
|
|
474
|
-
const filePath = getTraceFilePath(event.runId, usable);
|
|
475
|
-
await promises.appendFile(filePath, payload, "utf-8");
|
|
476
|
-
return true;
|
|
477
|
-
} catch {
|
|
478
|
-
return false;
|
|
479
|
-
}
|
|
480
|
-
};
|
|
481
|
-
if (await tryAppend(traceDir)) {
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
484
|
-
warn(`Failed to append trace event for run ${event.runId}`);
|
|
485
|
-
if (await tryAppend(FALLBACK_TRACE_DIR)) {
|
|
486
|
-
return;
|
|
487
|
-
}
|
|
488
|
-
warn("Failed to append trace event to fallback directory");
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// packages/core/src/trace-event-safety.ts
|
|
492
|
-
var DEFAULT_MAX_METADATA_VALUE_LENGTH = 2e3;
|
|
493
|
-
var DEFAULT_MAX_PREVIEW_LENGTH = 500;
|
|
494
|
-
var DEFAULT_MAX_EVENT_BYTES = 65536;
|
|
495
|
-
function isRecord3(value) {
|
|
496
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
497
|
-
}
|
|
498
|
-
function isPreviewKey(key) {
|
|
499
|
-
return key.toLowerCase().includes("preview");
|
|
500
|
-
}
|
|
501
|
-
function truncateString(value, maxLen) {
|
|
502
|
-
if (maxLen <= 0) return "\u2026";
|
|
503
|
-
if (value.length <= maxLen) return value;
|
|
504
|
-
return `${value.slice(0, maxLen)}\u2026`;
|
|
505
|
-
}
|
|
506
|
-
function byteLength(text) {
|
|
507
|
-
return Buffer.byteLength(text, "utf8");
|
|
508
|
-
}
|
|
509
|
-
function resolveTraceSafetyOptions(options) {
|
|
510
|
-
let redactEnabled = true;
|
|
511
|
-
let redactionRules;
|
|
512
|
-
{
|
|
513
|
-
redactEnabled = true;
|
|
514
|
-
}
|
|
515
|
-
const profile = options?.redactionProfile ?? "local";
|
|
516
|
-
const resolvedProfile = resolveRedactionProfile(profile);
|
|
517
|
-
const userMaxMetadata = "undefined" === "number" && Number.isFinite(options.maxMetadataValueLength) && options.maxMetadataValueLength >= 0 ? Math.floor(options.maxMetadataValueLength) : void 0;
|
|
518
|
-
const userMaxPreview = "undefined" === "number" && Number.isFinite(options.maxPreviewLength) && options.maxPreviewLength >= 0 ? Math.floor(options.maxPreviewLength) : void 0;
|
|
519
|
-
let maxMetadataValueLength = userMaxMetadata ?? DEFAULT_MAX_METADATA_VALUE_LENGTH;
|
|
520
|
-
let maxPreviewLength = userMaxPreview ?? DEFAULT_MAX_PREVIEW_LENGTH;
|
|
521
|
-
if (redactEnabled && profile !== "local") {
|
|
522
|
-
const capped = applyProfileMetadataCaps(
|
|
523
|
-
maxMetadataValueLength,
|
|
524
|
-
maxPreviewLength,
|
|
525
|
-
resolvedProfile
|
|
526
|
-
);
|
|
527
|
-
maxMetadataValueLength = capped.maxMetadataValueLength;
|
|
528
|
-
maxPreviewLength = capped.maxPreviewLength;
|
|
529
|
-
}
|
|
530
|
-
return {
|
|
531
|
-
redactEnabled,
|
|
532
|
-
redactionRules,
|
|
533
|
-
redactionProfile: profile,
|
|
534
|
-
profileExtraKeys: redactEnabled ? resolvedProfile.extraKeys : [],
|
|
535
|
-
maxMetadataValueLength,
|
|
536
|
-
maxPreviewLength,
|
|
537
|
-
maxEventBytes: "undefined" === "number" && Number.isFinite(options.maxEventBytes) && options.maxEventBytes > 0 ? Math.floor(options.maxEventBytes) : DEFAULT_MAX_EVENT_BYTES
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
function boundMetadataValue(key, value, opts, seen, depth) {
|
|
541
|
-
if (depth > 32) return "[MaxDepth]";
|
|
542
|
-
if (typeof value === "bigint") {
|
|
543
|
-
return `${value.toString()}n`;
|
|
544
|
-
}
|
|
545
|
-
if (typeof value === "function") {
|
|
546
|
-
return "[Function]";
|
|
547
|
-
}
|
|
548
|
-
if (typeof value === "symbol") {
|
|
549
|
-
return "[Symbol]";
|
|
550
|
-
}
|
|
551
|
-
if (typeof value === "number" && !Number.isFinite(value)) {
|
|
552
|
-
return String(value);
|
|
553
|
-
}
|
|
554
|
-
if (value === void 0) {
|
|
555
|
-
return null;
|
|
556
|
-
}
|
|
557
|
-
if (value === null || typeof value !== "object") {
|
|
558
|
-
if (typeof value === "string") {
|
|
559
|
-
const max = isPreviewKey(key) ? opts.maxPreviewLength : opts.maxMetadataValueLength;
|
|
560
|
-
return truncateString(value, max);
|
|
561
|
-
}
|
|
562
|
-
return value;
|
|
563
|
-
}
|
|
564
|
-
if (seen.has(value)) return "[Circular]";
|
|
565
|
-
seen.add(value);
|
|
566
|
-
if (Array.isArray(value)) {
|
|
567
|
-
const maxItems = 50;
|
|
568
|
-
const out2 = value.slice(0, maxItems).map(
|
|
569
|
-
(item, index) => boundMetadataValue(String(index), item, opts, seen, depth + 1)
|
|
570
|
-
);
|
|
571
|
-
if (value.length > maxItems) {
|
|
572
|
-
out2.push(`\u2026(+${value.length - maxItems} more)`);
|
|
573
|
-
}
|
|
574
|
-
return out2;
|
|
575
|
-
}
|
|
576
|
-
const record = value;
|
|
577
|
-
const out = {};
|
|
578
|
-
try {
|
|
579
|
-
for (const [k, v] of Object.entries(record)) {
|
|
580
|
-
out[k] = boundMetadataValue(k, v, opts, seen, depth + 1);
|
|
581
|
-
}
|
|
582
|
-
} catch {
|
|
583
|
-
return { truncated: true, reason: "metadataEnumerationFailed" };
|
|
584
|
-
}
|
|
585
|
-
return out;
|
|
586
|
-
}
|
|
587
|
-
function redactMetadata(metadata, opts) {
|
|
588
|
-
if (!opts.redactEnabled) return { ...metadata };
|
|
589
|
-
const redactor = new Redactor({
|
|
590
|
-
rules: opts.redactionRules,
|
|
591
|
-
extraKeys: opts.profileExtraKeys
|
|
592
|
-
});
|
|
593
|
-
return redactor.redactRecord(metadata);
|
|
594
|
-
}
|
|
595
|
-
function prepareMetadataForDisk(metadata, opts) {
|
|
596
|
-
try {
|
|
597
|
-
const preBounded = boundMetadataValue(
|
|
598
|
-
"metadata",
|
|
599
|
-
metadata,
|
|
600
|
-
opts,
|
|
601
|
-
/* @__PURE__ */ new WeakSet(),
|
|
602
|
-
0
|
|
603
|
-
);
|
|
604
|
-
const redacted = redactMetadata(
|
|
605
|
-
isRecord3(preBounded) ? preBounded : {},
|
|
606
|
-
opts
|
|
607
|
-
);
|
|
608
|
-
const bounded = boundMetadataValue(
|
|
609
|
-
"metadata",
|
|
610
|
-
redacted,
|
|
611
|
-
opts,
|
|
612
|
-
/* @__PURE__ */ new WeakSet(),
|
|
613
|
-
0
|
|
614
|
-
);
|
|
615
|
-
return isRecord3(bounded) ? bounded : {};
|
|
616
|
-
} catch {
|
|
617
|
-
return { truncated: true, reason: "metadataPreparationFailed" };
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
function truncateErrorStack(event, maxLen) {
|
|
621
|
-
if (event.event !== "run_completed" && event.event !== "step_completed") {
|
|
622
|
-
return event;
|
|
623
|
-
}
|
|
624
|
-
if (!event.error?.stack || typeof event.error.stack !== "string") {
|
|
625
|
-
return event;
|
|
626
|
-
}
|
|
627
|
-
return {
|
|
628
|
-
...event,
|
|
629
|
-
error: {
|
|
630
|
-
...event.error,
|
|
631
|
-
stack: truncateString(event.error.stack, maxLen)
|
|
632
|
-
}
|
|
633
|
-
};
|
|
634
|
-
}
|
|
635
|
-
function replaceMetadataWithTruncationMarker(event, originalApproxBytes) {
|
|
636
|
-
const marker = {
|
|
637
|
-
truncated: true,
|
|
638
|
-
reason: "maxEventBytes",
|
|
639
|
-
originalApproxBytes
|
|
640
|
-
};
|
|
641
|
-
if (event.event === "run_started") {
|
|
642
|
-
return { ...event, metadata: marker };
|
|
643
|
-
}
|
|
644
|
-
if (event.event === "step_started") {
|
|
645
|
-
return { ...event, metadata: marker };
|
|
646
|
-
}
|
|
647
|
-
return event;
|
|
648
|
-
}
|
|
649
|
-
function shrinkMetadataLimits(opts, factor) {
|
|
650
|
-
return {
|
|
651
|
-
...opts,
|
|
652
|
-
maxMetadataValueLength: Math.max(32, Math.floor(opts.maxMetadataValueLength * factor)),
|
|
653
|
-
maxPreviewLength: Math.max(16, Math.floor(opts.maxPreviewLength * factor))
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
function applyMetadataToEvent(event, metadata) {
|
|
657
|
-
if (event.event === "run_started") {
|
|
658
|
-
return { ...event, metadata };
|
|
659
|
-
}
|
|
660
|
-
if (event.event === "step_started") {
|
|
661
|
-
return { ...event, metadata };
|
|
662
|
-
}
|
|
663
|
-
return event;
|
|
664
|
-
}
|
|
665
|
-
function eventHasMetadata(event) {
|
|
666
|
-
return (event.event === "run_started" || event.event === "step_started") && event.metadata !== void 0;
|
|
667
|
-
}
|
|
668
|
-
function getEventMetadata(event) {
|
|
669
|
-
if (event.event === "run_started" || event.event === "step_started") {
|
|
670
|
-
return event.metadata;
|
|
671
|
-
}
|
|
672
|
-
return void 0;
|
|
673
|
-
}
|
|
674
|
-
function prepareTraceEventErrorForDisk(event, opts) {
|
|
675
|
-
if (event.event !== "run_completed" && event.event !== "step_completed" || !event.error) {
|
|
676
|
-
return event;
|
|
677
|
-
}
|
|
678
|
-
if (!opts.redactEnabled) return event;
|
|
679
|
-
const redactor = new Redactor({
|
|
680
|
-
rules: opts.redactionRules,
|
|
681
|
-
extraKeys: opts.profileExtraKeys
|
|
682
|
-
});
|
|
683
|
-
const nextError = { ...event.error };
|
|
684
|
-
let changed = false;
|
|
685
|
-
if (typeof nextError.message === "string") {
|
|
686
|
-
const keyRedacted = redactor.redactValue("message", nextError.message);
|
|
687
|
-
const message = typeof keyRedacted === "string" ? redactHighConfidenceCredentialsInString(keyRedacted) : "[REDACTED]";
|
|
688
|
-
if (message !== nextError.message) {
|
|
689
|
-
nextError.message = message.length > 0 ? message : "Unknown error";
|
|
690
|
-
changed = true;
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
if (typeof nextError.stack === "string") {
|
|
694
|
-
const scrubbedStack = redactHighConfidenceCredentialsInString(nextError.stack);
|
|
695
|
-
if (scrubbedStack !== nextError.stack) {
|
|
696
|
-
nextError.stack = scrubbedStack;
|
|
697
|
-
changed = true;
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
if (!changed) return event;
|
|
701
|
-
return { ...event, error: nextError };
|
|
702
|
-
}
|
|
703
|
-
function prepareTraceEventForDisk(event, opts) {
|
|
704
|
-
try {
|
|
705
|
-
let working = prepareTraceEventErrorForDisk({ ...event }, opts);
|
|
706
|
-
const rawMetadata = getEventMetadata(working);
|
|
707
|
-
if (rawMetadata !== void 0) {
|
|
708
|
-
const safe = prepareMetadataForDisk(rawMetadata, opts);
|
|
709
|
-
working = applyMetadataToEvent(working, safe);
|
|
710
|
-
}
|
|
711
|
-
let serialized = serializeEvent(working);
|
|
712
|
-
if (serialized === "") {
|
|
713
|
-
return working;
|
|
714
|
-
}
|
|
715
|
-
let bytes = byteLength(serialized);
|
|
716
|
-
if (bytes <= opts.maxEventBytes) {
|
|
717
|
-
return working;
|
|
718
|
-
}
|
|
719
|
-
if (rawMetadata !== void 0) {
|
|
720
|
-
for (const factor of [0.5, 0.25, 0.1]) {
|
|
721
|
-
const tighter = shrinkMetadataLimits(opts, factor);
|
|
722
|
-
const shrunk = prepareMetadataForDisk(rawMetadata, tighter);
|
|
723
|
-
working = applyMetadataToEvent(working, shrunk);
|
|
724
|
-
serialized = serializeEvent(working);
|
|
725
|
-
if (serialized !== "" && byteLength(serialized) <= opts.maxEventBytes) {
|
|
726
|
-
return working;
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
working = replaceMetadataWithTruncationMarker(working, bytes);
|
|
730
|
-
serialized = serializeEvent(working);
|
|
731
|
-
if (serialized !== "" && byteLength(serialized) <= opts.maxEventBytes) {
|
|
732
|
-
return working;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
working = truncateErrorStack(working, Math.min(opts.maxMetadataValueLength, 500));
|
|
736
|
-
serialized = serializeEvent(working);
|
|
737
|
-
if (serialized !== "" && byteLength(serialized) <= opts.maxEventBytes) {
|
|
738
|
-
return working;
|
|
739
|
-
}
|
|
740
|
-
if (eventHasMetadata(working)) {
|
|
741
|
-
working = replaceMetadataWithTruncationMarker(working, bytes);
|
|
742
|
-
serialized = serializeEvent(working);
|
|
743
|
-
if (serialized !== "" && byteLength(serialized) <= opts.maxEventBytes) {
|
|
744
|
-
return working;
|
|
745
|
-
}
|
|
746
|
-
if (working.event === "run_started") {
|
|
747
|
-
const { metadata: _meta, ...rest } = working;
|
|
748
|
-
working = rest;
|
|
749
|
-
} else if (working.event === "step_started") {
|
|
750
|
-
const { metadata: _meta, ...rest } = working;
|
|
751
|
-
working = rest;
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
return working;
|
|
755
|
-
} catch {
|
|
756
|
-
if (event.event === "run_started" || event.event === "step_started") {
|
|
757
|
-
return applyMetadataToEvent(event, {
|
|
758
|
-
truncated: true,
|
|
759
|
-
reason: "prepareTraceEventFailed"
|
|
760
|
-
});
|
|
761
|
-
}
|
|
762
|
-
return event;
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
var storage = new async_hooks.AsyncLocalStorage();
|
|
766
|
-
function toPublicContext(ctx) {
|
|
767
|
-
return {
|
|
768
|
-
runId: ctx.runId,
|
|
769
|
-
runName: ctx.runName,
|
|
770
|
-
traceDir: ctx.traceDir,
|
|
771
|
-
silent: ctx.silent,
|
|
772
|
-
metadata: ctx.metadata
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
|
-
function invoke(fn) {
|
|
776
|
-
return new Promise((resolve, reject) => {
|
|
777
|
-
try {
|
|
778
|
-
Promise.resolve(fn()).then(resolve, reject);
|
|
779
|
-
} catch (e) {
|
|
780
|
-
reject(e);
|
|
781
|
-
}
|
|
782
|
-
});
|
|
783
|
-
}
|
|
784
|
-
function getCurrentContext() {
|
|
785
|
-
try {
|
|
786
|
-
const s = storage.getStore();
|
|
787
|
-
if (!s) return void 0;
|
|
788
|
-
return toPublicContext(s);
|
|
789
|
-
} catch {
|
|
790
|
-
return void 0;
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
function getCurrentStepId() {
|
|
794
|
-
try {
|
|
795
|
-
return storage.getStore()?.currentStepId;
|
|
796
|
-
} catch {
|
|
797
|
-
return void 0;
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
function getParentStepId() {
|
|
801
|
-
return getCurrentStepId();
|
|
802
|
-
}
|
|
803
|
-
function getCurrentDepth() {
|
|
804
|
-
try {
|
|
805
|
-
const d = storage.getStore()?.currentDepth;
|
|
806
|
-
return typeof d === "number" && Number.isFinite(d) ? d : 0;
|
|
807
|
-
} catch {
|
|
808
|
-
return 0;
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
function isSilentContext() {
|
|
812
|
-
try {
|
|
813
|
-
const s = storage.getStore();
|
|
814
|
-
return s ? s.silent : false;
|
|
815
|
-
} catch {
|
|
816
|
-
return false;
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
function getTraceSafetyFromContext() {
|
|
820
|
-
try {
|
|
821
|
-
return storage.getStore()?.traceSafety;
|
|
822
|
-
} catch {
|
|
823
|
-
return void 0;
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
function runWithStepContext(stepId, fn) {
|
|
827
|
-
let parent;
|
|
828
|
-
try {
|
|
829
|
-
parent = storage.getStore();
|
|
830
|
-
} catch {
|
|
831
|
-
parent = void 0;
|
|
832
|
-
}
|
|
833
|
-
if (!parent) {
|
|
834
|
-
return invoke(fn);
|
|
835
|
-
}
|
|
836
|
-
const derived = {
|
|
837
|
-
runId: parent.runId,
|
|
838
|
-
runName: parent.runName,
|
|
839
|
-
traceDir: parent.traceDir,
|
|
840
|
-
silent: parent.silent,
|
|
841
|
-
metadata: parent.metadata,
|
|
842
|
-
traceSafety: parent.traceSafety,
|
|
843
|
-
currentStepId: stepId,
|
|
844
|
-
currentDepth: parent.currentDepth + 1
|
|
845
|
-
};
|
|
846
|
-
return new Promise((resolve, reject) => {
|
|
847
|
-
storage.run(derived, () => {
|
|
848
|
-
try {
|
|
849
|
-
Promise.resolve(fn()).then(resolve, reject);
|
|
850
|
-
} catch (e) {
|
|
851
|
-
reject(e);
|
|
852
|
-
}
|
|
853
|
-
});
|
|
854
|
-
});
|
|
855
|
-
}
|
|
856
|
-
var TERMINAL_INDENT = " ";
|
|
857
|
-
var MAX_TERMINAL_NAME_LENGTH = 80;
|
|
858
|
-
var MAX_TERMINAL_DEPTH = 10;
|
|
859
|
-
function normalizeDepth(depth) {
|
|
860
|
-
if (!Number.isFinite(depth) || depth < 0) {
|
|
861
|
-
return 0;
|
|
862
|
-
}
|
|
863
|
-
return Math.min(Math.floor(depth), MAX_TERMINAL_DEPTH);
|
|
864
|
-
}
|
|
865
|
-
function safePrint(line = "") {
|
|
866
|
-
try {
|
|
867
|
-
console.log(line);
|
|
868
|
-
} catch {
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
function getIndent(depth) {
|
|
872
|
-
return TERMINAL_INDENT.repeat(normalizeDepth(depth));
|
|
873
|
-
}
|
|
874
|
-
function formatTerminalName(name) {
|
|
875
|
-
if (typeof name !== "string" || name.trim() === "") {
|
|
876
|
-
return "unnamed";
|
|
877
|
-
}
|
|
878
|
-
return truncateName(name, MAX_TERMINAL_NAME_LENGTH);
|
|
879
|
-
}
|
|
880
|
-
function getStatusIcon(status) {
|
|
881
|
-
if (status === "success") return chalk__default.default.green("\u2714");
|
|
882
|
-
if (status === "error") return chalk__default.default.red("\u2716");
|
|
883
|
-
return chalk__default.default.yellow("\u23F3");
|
|
884
|
-
}
|
|
885
|
-
function renderStepLine(name, durationMs, status, depth) {
|
|
886
|
-
try {
|
|
887
|
-
const nm = formatTerminalName(name);
|
|
888
|
-
const ind = getIndent(depth ?? 0);
|
|
889
|
-
if (status === "running" && durationMs === void 0) {
|
|
890
|
-
return `${ind}${chalk__default.default.yellow("\u23F3")} ${nm}`;
|
|
891
|
-
}
|
|
892
|
-
const hasDur = durationMs !== void 0 && Number.isFinite(durationMs);
|
|
893
|
-
const dur = hasDur ? formatDuration2(durationMs) : void 0;
|
|
894
|
-
if (status === "running") {
|
|
895
|
-
return dur !== void 0 ? `${ind}${chalk__default.default.yellow("\u23F3")} ${nm} (${dur})` : `${ind}${chalk__default.default.yellow("\u23F3")} ${nm}`;
|
|
896
|
-
}
|
|
897
|
-
if (!hasDur || dur === void 0) {
|
|
898
|
-
return `${ind}${chalk__default.default.yellow("\u23F3")} ${nm}`;
|
|
899
|
-
}
|
|
900
|
-
if (status === "success") {
|
|
901
|
-
return `${ind}${getStatusIcon("success")} ${nm} (${dur})`;
|
|
902
|
-
}
|
|
903
|
-
return `${ind}${getStatusIcon("error")} ${nm} (${dur})`;
|
|
904
|
-
} catch {
|
|
905
|
-
return "";
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
function renderErrorLine(error, depth) {
|
|
909
|
-
try {
|
|
910
|
-
const msg = typeof error.message === "string" ? error.message : "";
|
|
911
|
-
const ind = getIndent((depth ?? 0) + 1);
|
|
912
|
-
return `${ind}Error: ${msg}`;
|
|
913
|
-
} catch {
|
|
914
|
-
return "";
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
function printStepStart(name, depth = 0) {
|
|
918
|
-
if (isSilentContext()) return;
|
|
919
|
-
try {
|
|
920
|
-
safePrint(renderStepLine(name, void 0, "running", depth));
|
|
921
|
-
} catch {
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
function printStepComplete(name, durationMs, status, depth = 0) {
|
|
925
|
-
if (isSilentContext()) return;
|
|
926
|
-
try {
|
|
927
|
-
safePrint(renderStepLine(name, durationMs, status, depth));
|
|
928
|
-
} catch {
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
function printError(error, depth = 0) {
|
|
932
|
-
if (isSilentContext()) return;
|
|
933
|
-
try {
|
|
934
|
-
safePrint(renderErrorLine(error, depth));
|
|
935
|
-
} catch {
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
function printFailedAt(stepName) {
|
|
939
|
-
if (isSilentContext()) return;
|
|
940
|
-
try {
|
|
941
|
-
safePrint(`Failed at: ${formatTerminalName(stepName)}`);
|
|
942
|
-
} catch {
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
// packages/core/src/step.ts
|
|
947
|
-
function normalizeStepName(name) {
|
|
948
|
-
if (typeof name !== "string" || name.trim() === "") {
|
|
949
|
-
return "unnamed-step";
|
|
950
|
-
}
|
|
951
|
-
return truncateName(name.trim(), 100);
|
|
952
|
-
}
|
|
953
|
-
async function safeInstrumentation(label, op) {
|
|
954
|
-
try {
|
|
955
|
-
await Promise.resolve(op());
|
|
956
|
-
} catch (e) {
|
|
957
|
-
warn(`step: ${label}`, e);
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
async function stepImpl(name, fn, options) {
|
|
961
|
-
if (typeof fn !== "function") {
|
|
962
|
-
throw new TypeError("step requires `fn` to be a function");
|
|
963
|
-
}
|
|
964
|
-
const stepName = normalizeStepName(name);
|
|
965
|
-
const context = getCurrentContext();
|
|
966
|
-
if (!context) {
|
|
967
|
-
warn("step() called outside inspectRun(); executing without instrumentation");
|
|
968
|
-
return Promise.resolve(fn());
|
|
969
|
-
}
|
|
970
|
-
const stepId = createStepId();
|
|
971
|
-
const renderDepth = getCurrentDepth();
|
|
972
|
-
const parentId = getParentStepId();
|
|
973
|
-
const stepType = options?.type ?? "logic";
|
|
974
|
-
const metadata = options?.metadata;
|
|
975
|
-
const traceSafety = getTraceSafetyFromContext();
|
|
976
|
-
const startTime = Date.now();
|
|
977
|
-
await safeInstrumentation("writeTraceEvent(step_started)", async () => {
|
|
978
|
-
const started = {
|
|
979
|
-
schemaVersion: "0.1",
|
|
980
|
-
event: "step_started",
|
|
981
|
-
timestamp: startTime,
|
|
982
|
-
runId: context.runId,
|
|
983
|
-
stepId,
|
|
984
|
-
...typeof parentId === "string" && parentId.trim() !== "" ? { parentId } : {},
|
|
985
|
-
name: stepName,
|
|
986
|
-
type: stepType,
|
|
987
|
-
startTime,
|
|
988
|
-
...metadata !== void 0 ? { metadata } : {}
|
|
989
|
-
};
|
|
990
|
-
const safe = traceSafety !== void 0 ? prepareTraceEventForDisk(started, traceSafety) : started;
|
|
991
|
-
await writeTraceEvent(safe, context.traceDir);
|
|
992
|
-
});
|
|
993
|
-
await safeInstrumentation("printStepStart", () => {
|
|
994
|
-
printStepStart(stepName, renderDepth);
|
|
995
|
-
});
|
|
996
|
-
let result;
|
|
997
|
-
try {
|
|
998
|
-
result = await runWithStepContext(stepId, async () => {
|
|
999
|
-
return await Promise.resolve(fn());
|
|
1000
|
-
});
|
|
1001
|
-
} catch (userError) {
|
|
1002
|
-
const endTime2 = Date.now();
|
|
1003
|
-
const durationMs2 = endTime2 - startTime;
|
|
1004
|
-
const formatted = formatError(userError);
|
|
1005
|
-
await safeInstrumentation("writeTraceEvent(step_completed error)", async () => {
|
|
1006
|
-
const completed = {
|
|
1007
|
-
schemaVersion: "0.1",
|
|
1008
|
-
event: "step_completed",
|
|
1009
|
-
timestamp: endTime2,
|
|
1010
|
-
runId: context.runId,
|
|
1011
|
-
stepId,
|
|
1012
|
-
status: "error",
|
|
1013
|
-
endTime: endTime2,
|
|
1014
|
-
durationMs: durationMs2,
|
|
1015
|
-
error: formatted
|
|
1016
|
-
};
|
|
1017
|
-
const safe = traceSafety !== void 0 ? prepareTraceEventForDisk(completed, traceSafety) : completed;
|
|
1018
|
-
await writeTraceEvent(safe, context.traceDir);
|
|
1019
|
-
});
|
|
1020
|
-
await safeInstrumentation("printStepComplete(error)", () => {
|
|
1021
|
-
printStepComplete(stepName, durationMs2, "error", renderDepth);
|
|
1022
|
-
});
|
|
1023
|
-
await safeInstrumentation("printError", () => {
|
|
1024
|
-
printError(formatted, renderDepth);
|
|
1025
|
-
});
|
|
1026
|
-
await safeInstrumentation("printFailedAt", () => {
|
|
1027
|
-
printFailedAt(stepName);
|
|
1028
|
-
});
|
|
1029
|
-
throw userError;
|
|
1030
|
-
}
|
|
1031
|
-
const endTime = Date.now();
|
|
1032
|
-
const durationMs = endTime - startTime;
|
|
1033
|
-
await safeInstrumentation("writeTraceEvent(step_completed success)", async () => {
|
|
1034
|
-
const completed = {
|
|
1035
|
-
schemaVersion: "0.1",
|
|
1036
|
-
event: "step_completed",
|
|
1037
|
-
timestamp: endTime,
|
|
1038
|
-
runId: context.runId,
|
|
1039
|
-
stepId,
|
|
1040
|
-
status: "success",
|
|
1041
|
-
endTime,
|
|
1042
|
-
durationMs
|
|
1043
|
-
};
|
|
1044
|
-
const safe = traceSafety !== void 0 ? prepareTraceEventForDisk(completed, traceSafety) : completed;
|
|
1045
|
-
await writeTraceEvent(safe, context.traceDir);
|
|
1046
|
-
});
|
|
1047
|
-
await safeInstrumentation("printStepComplete(success)", () => {
|
|
1048
|
-
printStepComplete(stepName, durationMs, "success", renderDepth);
|
|
1049
|
-
});
|
|
1050
|
-
return result;
|
|
1051
|
-
}
|
|
1052
|
-
async function stepLlm(model, fn) {
|
|
1053
|
-
const modelName = typeof model === "string" && model.trim() !== "" ? model.trim() : "unknown-model";
|
|
1054
|
-
return stepImpl(`llm:${modelName}`, fn, {
|
|
1055
|
-
type: "llm",
|
|
1056
|
-
metadata: { model: modelName }
|
|
1057
|
-
});
|
|
1058
|
-
}
|
|
1059
|
-
async function stepTool(toolName, fn) {
|
|
1060
|
-
const normalized = typeof toolName === "string" && toolName.trim() !== "" ? toolName.trim() : "unknown-tool";
|
|
1061
|
-
return stepImpl(`tool:${normalized}`, fn, {
|
|
1062
|
-
type: "tool",
|
|
1063
|
-
metadata: { toolName: normalized }
|
|
1064
|
-
});
|
|
1065
|
-
}
|
|
1066
|
-
var step = Object.assign(stepImpl, {
|
|
1067
|
-
llm: stepLlm,
|
|
1068
|
-
tool: stepTool
|
|
1069
|
-
});
|
|
1070
|
-
|
|
1071
|
-
// packages/mcp/src/wrap.ts
|
|
1072
36
|
var toolCallCounter = 0;
|
|
1073
37
|
function nextToolCallId(prefix) {
|
|
1074
38
|
toolCallCounter += 1;
|
|
@@ -1090,7 +54,7 @@ function wrapMcpClient(client, options = {}) {
|
|
|
1090
54
|
const wrapped = { ...client };
|
|
1091
55
|
if (typeof client.listTools === "function") {
|
|
1092
56
|
const listTools = client.listTools.bind(client);
|
|
1093
|
-
wrapped.listTools = async (params) => step(
|
|
57
|
+
wrapped.listTools = async (params) => agentInspect.step(
|
|
1094
58
|
"mcp:tools/list",
|
|
1095
59
|
async () => {
|
|
1096
60
|
const result = await listTools(params);
|
|
@@ -1106,7 +70,7 @@ function wrapMcpClient(client, options = {}) {
|
|
|
1106
70
|
);
|
|
1107
71
|
}
|
|
1108
72
|
const callTool = client.callTool.bind(client);
|
|
1109
|
-
wrapped.callTool = async (params) => step(
|
|
73
|
+
wrapped.callTool = async (params) => agentInspect.step(
|
|
1110
74
|
`mcp:${params.name}`,
|
|
1111
75
|
async () => callTool(params),
|
|
1112
76
|
{
|