agent-inspect 6.31.32 → 6.31.34
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 +12 -0
- package/README.md +1 -1
- package/docs/TRACE-CONTRACTS.md +2 -0
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-PEGM6T2X.mjs → chunk-6TXW53UR.mjs} +138 -36
- package/packages/cli/dist/chunk-6TXW53UR.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +197 -50
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +64 -19
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-CWUJTMRD.mjs → src-GCLC4DIC.mjs} +3 -3
- package/packages/cli/dist/{src-CWUJTMRD.mjs.map → src-GCLC4DIC.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +79 -20
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.mjs +9 -9
- package/packages/core/dist/checks.cjs +133 -32
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.mjs +3 -3
- package/packages/core/dist/{chunk-6S666BF4.mjs → chunk-2SKAI5ZN.mjs} +3 -3
- package/packages/core/dist/{chunk-6S666BF4.mjs.map → chunk-2SKAI5ZN.mjs.map} +1 -1
- package/packages/core/dist/{chunk-FBPDF7HO.mjs → chunk-6F6KLGCR.mjs} +3 -3
- package/packages/core/dist/{chunk-FBPDF7HO.mjs.map → chunk-6F6KLGCR.mjs.map} +1 -1
- package/packages/core/dist/{chunk-6G67ZN72.mjs → chunk-CXC7L4PY.mjs} +136 -35
- package/packages/core/dist/chunk-CXC7L4PY.mjs.map +1 -0
- package/packages/core/dist/{chunk-RB6WANSW.mjs → chunk-PU3FF5AP.mjs} +5 -4
- package/packages/core/dist/chunk-PU3FF5AP.mjs.map +1 -0
- package/packages/core/dist/{chunk-VIEJJ5JB.mjs → chunk-X5RP2E2H.mjs} +4 -4
- package/packages/core/dist/{chunk-VIEJJ5JB.mjs.map → chunk-X5RP2E2H.mjs.map} +1 -1
- package/packages/core/dist/exporters.cjs +33 -9
- package/packages/core/dist/exporters.cjs.map +1 -1
- package/packages/core/dist/exporters.mjs +33 -10
- package/packages/core/dist/exporters.mjs.map +1 -1
- package/packages/core/dist/index.cjs +3 -2
- package/packages/core/dist/index.cjs.map +1 -1
- package/packages/core/dist/index.mjs +4 -4
- package/packages/core/dist/writers.cjs +3 -2
- package/packages/core/dist/writers.cjs.map +1 -1
- package/packages/core/dist/writers.mjs +1 -1
- package/packages/cli/dist/chunk-PEGM6T2X.mjs.map +0 -1
- package/packages/core/dist/chunk-6G67ZN72.mjs.map +0 -1
- package/packages/core/dist/chunk-RB6WANSW.mjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OBSERVED_OUTCOME_METHODS, extractOutcomesFromPersistedEvents, outcomesMatchingStatus } from './chunk-
|
|
1
|
+
import { OBSERVED_OUTCOME_METHODS, extractOutcomesFromPersistedEvents, outcomesMatchingStatus } from './chunk-6F6KLGCR.mjs';
|
|
2
2
|
import { DEFAULT_CREDENTIAL_SENSITIVE_KEYS, isCredentialSensitiveKey } from './chunk-VLVCLAPB.mjs';
|
|
3
3
|
import { projectLogicalEvents, resolveCanonicalToolName } from './chunk-AHUZNHFI.mjs';
|
|
4
4
|
import { formatProgrammaticDiagnostic } from './chunk-S6LQBLX5.mjs';
|
|
@@ -2345,10 +2345,17 @@ function contractToRules(contract) {
|
|
|
2345
2345
|
(event) => event.status === "running"
|
|
2346
2346
|
);
|
|
2347
2347
|
if (running.length > 0) {
|
|
2348
|
+
const labels = running.map((event) => {
|
|
2349
|
+
if (event.kind === "TOOL") {
|
|
2350
|
+
return `tool ${resolveCanonicalToolName(event)}`;
|
|
2351
|
+
}
|
|
2352
|
+
return `${event.kind} ${event.name}`;
|
|
2353
|
+
});
|
|
2354
|
+
const message = labels.length === 1 ? `Run contains incomplete running events: ${labels[0]} never completed.` : `Run contains incomplete running events: ${labels.join("; ")}.`;
|
|
2348
2355
|
findings.push(
|
|
2349
2356
|
contractFailFinding(
|
|
2350
2357
|
"contract.run.allowedStatuses",
|
|
2351
|
-
|
|
2358
|
+
message,
|
|
2352
2359
|
running.map((event) => ({
|
|
2353
2360
|
runId: event.runId,
|
|
2354
2361
|
eventId: event.eventId,
|
|
@@ -2357,7 +2364,10 @@ function contractToRules(contract) {
|
|
|
2357
2364
|
status: event.status
|
|
2358
2365
|
})),
|
|
2359
2366
|
"no running events",
|
|
2360
|
-
|
|
2367
|
+
{
|
|
2368
|
+
count: running.length,
|
|
2369
|
+
unfinished: labels
|
|
2370
|
+
}
|
|
2361
2371
|
)
|
|
2362
2372
|
);
|
|
2363
2373
|
}
|
|
@@ -3307,10 +3317,11 @@ var SAFE_USAGE_LEAF_KEYS = /* @__PURE__ */ new Set([
|
|
|
3307
3317
|
var DEFAULT_SECRET_PATTERNS = [
|
|
3308
3318
|
{ id: "bearer-token", pattern: /Bearer\s+[A-Za-z0-9._~+/-]{12,}=*/ },
|
|
3309
3319
|
{ id: "openai-key", pattern: /sk-[A-Za-z0-9_-]{16,}/ },
|
|
3310
|
-
// Stripe + Slack: keep in sync with packages/redact + credential-value-patterns (#520).
|
|
3320
|
+
// Stripe + Slack: keep in sync with packages/redact + credential-value-patterns (#520/#528).
|
|
3321
|
+
// Non-alnum lookarounds so underscore-adjacent forms (acct_sk_live_…, …_eu) match.
|
|
3311
3322
|
{
|
|
3312
3323
|
id: "stripe-key",
|
|
3313
|
-
pattern:
|
|
3324
|
+
pattern: /(?<![A-Za-z0-9])(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}(?![A-Za-z0-9])/
|
|
3314
3325
|
},
|
|
3315
3326
|
{ id: "slack-token", pattern: /\bxox[abposr]-[A-Za-z0-9-]{10,}\b/ },
|
|
3316
3327
|
{ id: "aws-access-key", pattern: /AKIA[0-9A-Z]{16}/ },
|
|
@@ -3494,6 +3505,11 @@ function compareFindings(eventById) {
|
|
|
3494
3505
|
if (STATUS_RANK[a.status] !== STATUS_RANK[b.status]) {
|
|
3495
3506
|
return STATUS_RANK[a.status] - STATUS_RANK[b.status];
|
|
3496
3507
|
}
|
|
3508
|
+
if (a.ruleId === "tool.usage") {
|
|
3509
|
+
const aHasEvent = a.evidence[0]?.eventId !== void 0;
|
|
3510
|
+
const bHasEvent = b.evidence[0]?.eventId !== void 0;
|
|
3511
|
+
if (aHasEvent !== bHasEvent) return aHasEvent ? -1 : 1;
|
|
3512
|
+
}
|
|
3497
3513
|
const byRun = compareStrings(a.evidence[0]?.runId, b.evidence[0]?.runId);
|
|
3498
3514
|
if (byRun !== 0) return byRun;
|
|
3499
3515
|
const byTime = eventTimestamp(a, eventById).localeCompare(eventTimestamp(b, eventById));
|
|
@@ -3619,6 +3635,37 @@ function failFinding(ruleId, message, evidence, expected, actual, meta) {
|
|
|
3619
3635
|
function toolName(event) {
|
|
3620
3636
|
return resolveCanonicalToolName(event);
|
|
3621
3637
|
}
|
|
3638
|
+
function formatToolNameForMessage(name) {
|
|
3639
|
+
const details = [];
|
|
3640
|
+
for (let index = 0; index < name.length; ) {
|
|
3641
|
+
const codePoint = name.codePointAt(index);
|
|
3642
|
+
const width = codePoint > 65535 ? 2 : 1;
|
|
3643
|
+
if (codePoint > 127) {
|
|
3644
|
+
details.push(
|
|
3645
|
+
`U+${codePoint.toString(16).toUpperCase().padStart(4, "0")} at index ${index}`
|
|
3646
|
+
);
|
|
3647
|
+
}
|
|
3648
|
+
index += width;
|
|
3649
|
+
}
|
|
3650
|
+
if (details.length === 0) return name;
|
|
3651
|
+
return `"${name}" (contains ${details.join("; ")})`;
|
|
3652
|
+
}
|
|
3653
|
+
function describeRunningEvent(event) {
|
|
3654
|
+
if (event.kind === "TOOL") {
|
|
3655
|
+
return `tool ${formatToolNameForMessage(resolveCanonicalToolName(event))}`;
|
|
3656
|
+
}
|
|
3657
|
+
if (event.kind === "LLM") {
|
|
3658
|
+
return `llm ${stepEndpointName(event, "LLM")}`;
|
|
3659
|
+
}
|
|
3660
|
+
return `${event.kind} ${event.name}`;
|
|
3661
|
+
}
|
|
3662
|
+
function incompleteRunningMessage(prefix, running) {
|
|
3663
|
+
const labels = running.map(describeRunningEvent);
|
|
3664
|
+
if (labels.length === 1) {
|
|
3665
|
+
return `${prefix}: ${labels[0]} never completed.`;
|
|
3666
|
+
}
|
|
3667
|
+
return `${prefix}: ${labels.join("; ")}.`;
|
|
3668
|
+
}
|
|
3622
3669
|
function stepEndpointName(event, kind) {
|
|
3623
3670
|
if (kind === "TOOL") return resolveCanonicalToolName(event);
|
|
3624
3671
|
for (const prefix of ["llm:", "generation:", "transcription:", "speech:"]) {
|
|
@@ -3963,10 +4010,13 @@ function createRunStatusRule(options = {}) {
|
|
|
3963
4010
|
findings.push(
|
|
3964
4011
|
failFinding(
|
|
3965
4012
|
"run.status",
|
|
3966
|
-
"Run contains incomplete running events
|
|
4013
|
+
incompleteRunningMessage("Run contains incomplete running events", running),
|
|
3967
4014
|
running.map((event) => eventEvidence3(event)),
|
|
3968
4015
|
"no running events",
|
|
3969
|
-
|
|
4016
|
+
{
|
|
4017
|
+
count: running.length,
|
|
4018
|
+
unfinished: running.map(describeRunningEvent)
|
|
4019
|
+
}
|
|
3970
4020
|
)
|
|
3971
4021
|
);
|
|
3972
4022
|
}
|
|
@@ -4172,6 +4222,34 @@ function createToolUsageRule(options) {
|
|
|
4172
4222
|
const names = tools.map(toolName);
|
|
4173
4223
|
const nameSet = new Set(names);
|
|
4174
4224
|
const findings = [];
|
|
4225
|
+
const forbidden = new Set(options.forbidden ?? []);
|
|
4226
|
+
const allowed = options.allowed?.length ? new Set(options.allowed) : void 0;
|
|
4227
|
+
for (const event of tools) {
|
|
4228
|
+
const name = toolName(event);
|
|
4229
|
+
const display = formatToolNameForMessage(name);
|
|
4230
|
+
if (forbidden.has(name)) {
|
|
4231
|
+
findings.push(
|
|
4232
|
+
failFinding(
|
|
4233
|
+
"tool.usage",
|
|
4234
|
+
`Forbidden tool ${display} appeared.`,
|
|
4235
|
+
[eventEvidence3(event)],
|
|
4236
|
+
"tool absent",
|
|
4237
|
+
name
|
|
4238
|
+
)
|
|
4239
|
+
);
|
|
4240
|
+
}
|
|
4241
|
+
if (allowed && !allowed.has(name)) {
|
|
4242
|
+
findings.push(
|
|
4243
|
+
failFinding(
|
|
4244
|
+
"tool.usage",
|
|
4245
|
+
`Tool ${display} is not in the allowed tool set.`,
|
|
4246
|
+
[eventEvidence3(event)],
|
|
4247
|
+
[...allowed].sort(),
|
|
4248
|
+
name
|
|
4249
|
+
)
|
|
4250
|
+
);
|
|
4251
|
+
}
|
|
4252
|
+
}
|
|
4175
4253
|
for (const required of options.required ?? []) {
|
|
4176
4254
|
if (!nameSet.has(required)) {
|
|
4177
4255
|
const otherKinds = [
|
|
@@ -4189,7 +4267,7 @@ function createToolUsageRule(options) {
|
|
|
4189
4267
|
findings.push(
|
|
4190
4268
|
failFinding(
|
|
4191
4269
|
"tool.usage",
|
|
4192
|
-
`Required tool ${required} did not appear.${hint}`,
|
|
4270
|
+
`Required tool ${formatToolNameForMessage(required)} did not appear.${hint}`,
|
|
4193
4271
|
runEvidence(context.selectedRun),
|
|
4194
4272
|
required,
|
|
4195
4273
|
names
|
|
@@ -4197,21 +4275,6 @@ function createToolUsageRule(options) {
|
|
|
4197
4275
|
);
|
|
4198
4276
|
}
|
|
4199
4277
|
}
|
|
4200
|
-
const forbidden = new Set(options.forbidden ?? []);
|
|
4201
|
-
const allowed = options.allowed?.length ? new Set(options.allowed) : void 0;
|
|
4202
|
-
for (const event of tools) {
|
|
4203
|
-
const name = toolName(event);
|
|
4204
|
-
if (forbidden.has(name)) {
|
|
4205
|
-
findings.push(
|
|
4206
|
-
failFinding("tool.usage", `Forbidden tool ${name} appeared.`, [eventEvidence3(event)], "tool absent", name)
|
|
4207
|
-
);
|
|
4208
|
-
}
|
|
4209
|
-
if (allowed && !allowed.has(name)) {
|
|
4210
|
-
findings.push(
|
|
4211
|
-
failFinding("tool.usage", `Tool ${name} is not in the allowed tool set.`, [eventEvidence3(event)], [...allowed].sort(), name)
|
|
4212
|
-
);
|
|
4213
|
-
}
|
|
4214
|
-
}
|
|
4215
4278
|
if (options.minCount !== void 0 && tools.length < options.minCount) {
|
|
4216
4279
|
findings.push(
|
|
4217
4280
|
failFinding("tool.usage", `Tool count ${tools.length} was below minimum ${options.minCount}.`, runEvidence(context.selectedRun), { minCount: options.minCount }, tools.length)
|
|
@@ -4245,7 +4308,36 @@ function createStepOrderingRule(options) {
|
|
|
4245
4308
|
const afterEvents = finishedEvents(context, options.after.kind).filter(
|
|
4246
4309
|
(event) => stepEndpointName(event, options.after.kind) === options.after.name
|
|
4247
4310
|
);
|
|
4248
|
-
|
|
4311
|
+
const beforeRunning = semanticEvents(context).filter(
|
|
4312
|
+
(event) => event.kind === options.before.kind && event.status === "running" && stepEndpointName(event, options.before.kind) === options.before.name
|
|
4313
|
+
);
|
|
4314
|
+
const afterRunning = semanticEvents(context).filter(
|
|
4315
|
+
(event) => event.kind === options.after.kind && event.status === "running" && stepEndpointName(event, options.after.kind) === options.after.name
|
|
4316
|
+
);
|
|
4317
|
+
const afterStarted = afterEvents.length > 0 || afterRunning.length > 0;
|
|
4318
|
+
const afterEvidenceEvent = afterEvents[0] ?? afterRunning[0];
|
|
4319
|
+
if (beforeRunning.length > 0 && afterStarted && afterEvidenceEvent !== void 0) {
|
|
4320
|
+
const endpointExpected2 = bothTools ? { before: options.before.name, after: options.after.name } : { before: options.before, after: options.after };
|
|
4321
|
+
return [
|
|
4322
|
+
failFinding(
|
|
4323
|
+
ruleId,
|
|
4324
|
+
`${subject} ${beforeLabel} started but never finished before ${afterLabel} ran.`,
|
|
4325
|
+
[
|
|
4326
|
+
...beforeRunning.map((event) => eventEvidence3(event)),
|
|
4327
|
+
eventEvidence3(afterEvidenceEvent)
|
|
4328
|
+
],
|
|
4329
|
+
{ ...endpointExpected2, mode },
|
|
4330
|
+
{
|
|
4331
|
+
code: bothTools ? "tool.order.interval-unresolved" : "step.order.interval-unresolved",
|
|
4332
|
+
unfinishedBefore: true,
|
|
4333
|
+
beforeStatus: "running",
|
|
4334
|
+
...beforeEvents.length > 0 ? { finishedBeforeMasked: true } : {},
|
|
4335
|
+
...afterEvents.length === 0 ? { afterStatus: "running" } : {}
|
|
4336
|
+
}
|
|
4337
|
+
)
|
|
4338
|
+
];
|
|
4339
|
+
}
|
|
4340
|
+
if (beforeEvents.length === 0 || !afterStarted) {
|
|
4249
4341
|
if (!requireEndpoints) return [];
|
|
4250
4342
|
const findings = [];
|
|
4251
4343
|
if (beforeEvents.length === 0) {
|
|
@@ -4269,7 +4361,7 @@ function createStepOrderingRule(options) {
|
|
|
4269
4361
|
)
|
|
4270
4362
|
);
|
|
4271
4363
|
}
|
|
4272
|
-
if (
|
|
4364
|
+
if (!afterStarted) {
|
|
4273
4365
|
const otherKinds = otherKindsForStepName(
|
|
4274
4366
|
context,
|
|
4275
4367
|
options.after.kind,
|
|
@@ -4292,9 +4384,15 @@ function createStepOrderingRule(options) {
|
|
|
4292
4384
|
}
|
|
4293
4385
|
return findings;
|
|
4294
4386
|
}
|
|
4295
|
-
const
|
|
4296
|
-
|
|
4297
|
-
|
|
4387
|
+
const afterForOrder = afterEvents.length > 0 ? afterEvents : afterRunning;
|
|
4388
|
+
const encounter = [
|
|
4389
|
+
...finishedEvents(context).filter(
|
|
4390
|
+
(event) => event.kind === options.before.kind && stepEndpointName(event, options.before.kind) === options.before.name || event.kind === options.after.kind && stepEndpointName(event, options.after.kind) === options.after.name
|
|
4391
|
+
),
|
|
4392
|
+
...afterEvents.length === 0 ? afterRunning.filter(
|
|
4393
|
+
(event) => !finishedEvents(context).some((finished) => finished.eventId === event.eventId)
|
|
4394
|
+
) : []
|
|
4395
|
+
];
|
|
4298
4396
|
let beforeIndex;
|
|
4299
4397
|
let afterIndex;
|
|
4300
4398
|
for (const [position, event] of encounter.entries()) {
|
|
@@ -4325,7 +4423,7 @@ function createStepOrderingRule(options) {
|
|
|
4325
4423
|
];
|
|
4326
4424
|
}
|
|
4327
4425
|
const beforeEvent = beforeEvents[0];
|
|
4328
|
-
const afterEvent =
|
|
4426
|
+
const afterEvent = afterForOrder[0];
|
|
4329
4427
|
const beforeEnd = eventEndMs(beforeEvent);
|
|
4330
4428
|
const afterStart = eventStartMs(afterEvent);
|
|
4331
4429
|
const endpointExpected = bothTools ? { before: options.before.name, after: options.after.name } : { before: options.before, after: options.after };
|
|
@@ -4411,7 +4509,7 @@ function createStepOrderingRule(options) {
|
|
|
4411
4509
|
latestBefore = { event, end };
|
|
4412
4510
|
}
|
|
4413
4511
|
}
|
|
4414
|
-
for (const event of
|
|
4512
|
+
for (const event of afterForOrder) {
|
|
4415
4513
|
const start = eventStartMs(event);
|
|
4416
4514
|
if (start === void 0) {
|
|
4417
4515
|
missingAfterStarts += 1;
|
|
@@ -4440,7 +4538,7 @@ function createStepOrderingRule(options) {
|
|
|
4440
4538
|
const tie = tiedEnd === tiedStart ? recordedTieOrder(
|
|
4441
4539
|
context,
|
|
4442
4540
|
beforeEvents.filter((event) => eventEndMs(event) === tiedEnd),
|
|
4443
|
-
|
|
4541
|
+
afterForOrder.filter((event) => eventStartMs(event) === tiedStart)
|
|
4444
4542
|
) : void 0;
|
|
4445
4543
|
if (latestBefore.end > earliestAfter.start || tie !== void 0 && tie.inOrder !== true) {
|
|
4446
4544
|
return [
|
|
@@ -4621,10 +4719,13 @@ function createStructureIncompleteRule(options = {}) {
|
|
|
4621
4719
|
findings.push(
|
|
4622
4720
|
failFinding(
|
|
4623
4721
|
"structure.incomplete",
|
|
4624
|
-
"Trace contains incomplete running events
|
|
4722
|
+
incompleteRunningMessage("Trace contains incomplete running events", running),
|
|
4625
4723
|
running.map((event) => eventEvidence3(event, "status")),
|
|
4626
4724
|
"no running events",
|
|
4627
|
-
|
|
4725
|
+
{
|
|
4726
|
+
count: running.length,
|
|
4727
|
+
unfinished: running.map(describeRunningEvent)
|
|
4728
|
+
}
|
|
4628
4729
|
)
|
|
4629
4730
|
);
|
|
4630
4731
|
}
|
|
@@ -5418,5 +5519,5 @@ function runTraceChecks(input, options = {}) {
|
|
|
5418
5519
|
}
|
|
5419
5520
|
|
|
5420
5521
|
export { buildTraceFacts, createBaselineRegressionRule, createDecisionRule, createGuardrailRule, createLlmUsageRule, createMaxStepDurationRule, createObservedOutcomeRule, createRequireCompletedRule, createRetrievalRule, createRunDepthRule, createRunDurationRule, createRunEventCountRule, createRunStatusRule, createSafetyOversizedAttributeRule, createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createStallDetectionRule, createStepOrderingRule, createStructureCycleRule, createStructureIncompleteRule, createStructureOrphanRule, createStructureParallelWidthRule, createStructureRelationshipRule, createToolFailureRule, createToolOrderingRule, createToolUsageRule, defineTraceContract, deriveFailureFacts, deriveRelationshipFacts, evaluateToolArgumentValue, evaluateTraceContract, evaluateTraceContractRead, explainTraceContract, extractSessionWorkflowMetadata, extractToolArgumentPayload, lintTraceContract, resolveJsonPointer, resolveTraceContractScope, runTraceChecks, sessionKeyForRun, summarizeSemanticParity, workflowMetadataForRun };
|
|
5421
|
-
//# sourceMappingURL=chunk-
|
|
5422
|
-
//# sourceMappingURL=chunk-
|
|
5522
|
+
//# sourceMappingURL=chunk-CXC7L4PY.mjs.map
|
|
5523
|
+
//# sourceMappingURL=chunk-CXC7L4PY.mjs.map
|