agent-inspect 6.31.21 → 6.31.23
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/package.json +1 -1
- package/packages/cli/dist/{chunk-N5JN26MW.mjs → chunk-P27XTK5U.mjs} +347 -36
- package/packages/cli/dist/chunk-P27XTK5U.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +434 -63
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +81 -33
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-VMGRSTG7.mjs → src-EWZYLDST.mjs} +3 -3
- package/packages/cli/dist/{src-VMGRSTG7.mjs.map → src-EWZYLDST.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +280 -10
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.mjs +6 -5
- package/packages/core/dist/advanced.mjs.map +1 -1
- package/packages/core/dist/checks.cjs +185 -27
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.mjs +2 -1
- package/packages/core/dist/{chunk-JE3TUFAQ.mjs → chunk-77PUPLPG.mjs} +14 -8
- package/packages/core/dist/chunk-77PUPLPG.mjs.map +1 -0
- package/packages/core/dist/chunk-AN5MOADW.mjs +204 -0
- package/packages/core/dist/chunk-AN5MOADW.mjs.map +1 -0
- package/packages/core/dist/{chunk-4CDX5GDS.mjs → chunk-IMCM42W6.mjs} +110 -99
- package/packages/core/dist/chunk-IMCM42W6.mjs.map +1 -0
- package/packages/core/dist/{chunk-YU6XT5A2.mjs → chunk-J2ST4VCX.mjs} +45 -3
- package/packages/core/dist/chunk-J2ST4VCX.mjs.map +1 -0
- package/packages/core/dist/{chunk-EIP5CNEL.mjs → chunk-JJSL346L.mjs} +58 -3
- package/packages/core/dist/chunk-JJSL346L.mjs.map +1 -0
- package/packages/core/dist/exporters.cjs +91 -29
- package/packages/core/dist/exporters.cjs.map +1 -1
- package/packages/core/dist/exporters.mjs +78 -29
- package/packages/core/dist/exporters.mjs.map +1 -1
- package/packages/core/dist/logs.cjs +206 -1
- package/packages/core/dist/logs.cjs.map +1 -1
- package/packages/core/dist/logs.mjs +3 -2
- package/packages/core/dist/logs.mjs.map +1 -1
- package/packages/core/dist/persisted.cjs +226 -8
- package/packages/core/dist/persisted.cjs.map +1 -1
- package/packages/core/dist/persisted.mjs +9 -5
- package/packages/core/dist/persisted.mjs.map +1 -1
- package/packages/core/dist/readers.cjs +276 -6
- package/packages/core/dist/readers.cjs.map +1 -1
- package/packages/core/dist/readers.mjs +4 -3
- package/packages/cli/dist/chunk-N5JN26MW.mjs.map +0 -1
- package/packages/core/dist/chunk-4CDX5GDS.mjs.map +0 -1
- package/packages/core/dist/chunk-EIP5CNEL.mjs.map +0 -1
- package/packages/core/dist/chunk-JE3TUFAQ.mjs.map +0 -1
- package/packages/core/dist/chunk-YU6XT5A2.mjs.map +0 -1
|
@@ -1704,6 +1704,84 @@ function evaluateToolArgumentValue(value, check, evidencePresent) {
|
|
|
1704
1704
|
};
|
|
1705
1705
|
}
|
|
1706
1706
|
|
|
1707
|
+
// packages/core/src/persisted/delivery-identity.ts
|
|
1708
|
+
var DELIVERY_CONFLICT_ATTR = "agent_inspect.delivery_conflict";
|
|
1709
|
+
var DELIVERY_EVENT_BASE_ATTR = "agent_inspect.delivery_event_base";
|
|
1710
|
+
var IDENTITY_CONFLICT_ATTR = {
|
|
1711
|
+
/** Comma-separated field names when a conflict survives lossy bounding. */
|
|
1712
|
+
fields: "agent_inspect.identity_conflict.fields"
|
|
1713
|
+
};
|
|
1714
|
+
var MAX_CONFLICT_FIELDS = 8;
|
|
1715
|
+
var MAX_DELIVERY_BASE_LEN = 500;
|
|
1716
|
+
function stripReaderDeliveryDiscriminator(eventId, attributes) {
|
|
1717
|
+
if (!eventId) return eventId;
|
|
1718
|
+
const rawBase = attributes?.[DELIVERY_EVENT_BASE_ATTR];
|
|
1719
|
+
if (typeof rawBase !== "string" || rawBase.trim() === "") return eventId;
|
|
1720
|
+
const base = rawBase.trim().slice(0, MAX_DELIVERY_BASE_LEN);
|
|
1721
|
+
if (eventId === base) return base;
|
|
1722
|
+
const prefix = `${base}:`;
|
|
1723
|
+
if (!eventId.startsWith(prefix)) return eventId;
|
|
1724
|
+
const suffix = eventId.slice(prefix.length);
|
|
1725
|
+
if (/^\d+$/.test(suffix)) return base;
|
|
1726
|
+
return eventId;
|
|
1727
|
+
}
|
|
1728
|
+
function canonicalDigest(value) {
|
|
1729
|
+
if (value === void 0) return null;
|
|
1730
|
+
const encoded = encodeCanonicalStructured(value);
|
|
1731
|
+
return encoded.ok ? encoded.value : `unencodable:${encoded.code}`;
|
|
1732
|
+
}
|
|
1733
|
+
function capturedContentDigest(attributes) {
|
|
1734
|
+
if (!attributes || typeof attributes !== "object") {
|
|
1735
|
+
return { args: null, result: null };
|
|
1736
|
+
}
|
|
1737
|
+
const nested = attributes.metadata && typeof attributes.metadata === "object" ? attributes.metadata : void 0;
|
|
1738
|
+
const args = attributes.arguments ?? attributes.args ?? attributes.input ?? nested?.arguments ?? nested?.args ?? nested?.input;
|
|
1739
|
+
const result = attributes.result ?? attributes.output ?? attributes.response ?? nested?.result ?? nested?.output ?? nested?.response;
|
|
1740
|
+
return {
|
|
1741
|
+
args: args === void 0 ? null : canonicalDigest(args),
|
|
1742
|
+
result: result === void 0 ? null : canonicalDigest(result)
|
|
1743
|
+
};
|
|
1744
|
+
}
|
|
1745
|
+
function timeKey(fields) {
|
|
1746
|
+
if (typeof fields.startedAt === "string" && fields.startedAt.trim() !== "") {
|
|
1747
|
+
return fields.startedAt;
|
|
1748
|
+
}
|
|
1749
|
+
if (typeof fields.timestamp === "string" && fields.timestamp.trim() !== "") {
|
|
1750
|
+
return fields.timestamp;
|
|
1751
|
+
}
|
|
1752
|
+
if (typeof fields.timestamp === "number" && Number.isFinite(fields.timestamp)) {
|
|
1753
|
+
return String(fields.timestamp);
|
|
1754
|
+
}
|
|
1755
|
+
return null;
|
|
1756
|
+
}
|
|
1757
|
+
function deliverySemanticFingerprint(fields) {
|
|
1758
|
+
const content = capturedContentDigest(fields.attributes);
|
|
1759
|
+
return JSON.stringify({
|
|
1760
|
+
stableEventId: stripReaderDeliveryDiscriminator(fields.eventId, fields.attributes),
|
|
1761
|
+
runId: fields.runId,
|
|
1762
|
+
kind: fields.kind,
|
|
1763
|
+
name: fields.name,
|
|
1764
|
+
status: fields.status ?? null,
|
|
1765
|
+
parentId: fields.parentId ?? null,
|
|
1766
|
+
sourceType: fields.sourceType ?? null,
|
|
1767
|
+
time: timeKey(fields),
|
|
1768
|
+
operationId: fields.operationId ?? null,
|
|
1769
|
+
attemptId: fields.attemptId ?? null,
|
|
1770
|
+
attemptNumber: fields.attemptNumber ?? null,
|
|
1771
|
+
retryOf: fields.retryOf ?? null,
|
|
1772
|
+
argsDigest: content.args,
|
|
1773
|
+
resultDigest: content.result
|
|
1774
|
+
});
|
|
1775
|
+
}
|
|
1776
|
+
function identityConflictFieldsFromAttributes(attributes) {
|
|
1777
|
+
const raw = attributes?.[IDENTITY_CONFLICT_ATTR.fields];
|
|
1778
|
+
if (typeof raw !== "string" || raw.trim() === "") return [];
|
|
1779
|
+
return raw.split(",").map((part) => part.trim()).filter((part) => part.length > 0).slice(0, MAX_CONFLICT_FIELDS);
|
|
1780
|
+
}
|
|
1781
|
+
function hasDeliveryConflictMarker(attributes) {
|
|
1782
|
+
return attributes?.[DELIVERY_CONFLICT_ATTR] === true;
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1707
1785
|
// packages/core/src/checks/retry-safety.ts
|
|
1708
1786
|
function fail2(ruleId, message, evidence, expected, actual) {
|
|
1709
1787
|
return {
|
|
@@ -1759,7 +1837,7 @@ function attemptIdOf(event) {
|
|
|
1759
1837
|
}
|
|
1760
1838
|
function countOperationAttempts(members) {
|
|
1761
1839
|
const identified = /* @__PURE__ */ new Set();
|
|
1762
|
-
|
|
1840
|
+
const unidentifiedFingerprints = /* @__PURE__ */ new Set();
|
|
1763
1841
|
for (const event of members) {
|
|
1764
1842
|
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
1765
1843
|
const id = attemptIdOf(event);
|
|
@@ -1767,13 +1845,13 @@ function countOperationAttempts(members) {
|
|
|
1767
1845
|
identified.add(id);
|
|
1768
1846
|
continue;
|
|
1769
1847
|
}
|
|
1770
|
-
|
|
1848
|
+
unidentifiedFingerprints.add(redeliveryFingerprint(event));
|
|
1771
1849
|
}
|
|
1772
1850
|
if (identified.size > 0) {
|
|
1773
|
-
return identified.size +
|
|
1851
|
+
return identified.size + unidentifiedFingerprints.size;
|
|
1774
1852
|
}
|
|
1775
1853
|
const numbered = /* @__PURE__ */ new Set();
|
|
1776
|
-
|
|
1854
|
+
const unnumberedFingerprints = /* @__PURE__ */ new Set();
|
|
1777
1855
|
for (const event of members) {
|
|
1778
1856
|
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
1779
1857
|
const num = attemptNumberOf(event);
|
|
@@ -1781,12 +1859,12 @@ function countOperationAttempts(members) {
|
|
|
1781
1859
|
numbered.add(num);
|
|
1782
1860
|
continue;
|
|
1783
1861
|
}
|
|
1784
|
-
|
|
1862
|
+
unnumberedFingerprints.add(redeliveryFingerprint(event));
|
|
1785
1863
|
}
|
|
1786
1864
|
if (numbered.size > 0) {
|
|
1787
|
-
return numbered.size +
|
|
1865
|
+
return numbered.size + unnumberedFingerprints.size;
|
|
1788
1866
|
}
|
|
1789
|
-
return
|
|
1867
|
+
return unnumberedFingerprints.size;
|
|
1790
1868
|
}
|
|
1791
1869
|
function classifyRetryAttempt(event, priorOrdered, allMembers) {
|
|
1792
1870
|
const workflow = workflowFor(event);
|
|
@@ -1838,19 +1916,55 @@ function classifyRetryAttempt(event, priorOrdered, allMembers) {
|
|
|
1838
1916
|
}
|
|
1839
1917
|
function redeliveryFingerprint(event) {
|
|
1840
1918
|
const workflow = workflowFor(event);
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
stableEventId,
|
|
1919
|
+
return deliverySemanticFingerprint({
|
|
1920
|
+
eventId: event.eventId ?? "",
|
|
1844
1921
|
runId: event.runId,
|
|
1845
1922
|
kind: event.kind,
|
|
1846
1923
|
name: event.name,
|
|
1847
1924
|
status: event.status,
|
|
1925
|
+
parentId: event.parentId,
|
|
1926
|
+
timestamp: event.timestamp,
|
|
1927
|
+
startedAt: event.startedAt,
|
|
1928
|
+
sourceType: event.source?.type,
|
|
1929
|
+
attributes: event.attributes && typeof event.attributes === "object" ? event.attributes : void 0,
|
|
1848
1930
|
operationId: workflow.operationId ?? null,
|
|
1849
1931
|
attemptId: workflow.attemptId ?? null,
|
|
1850
1932
|
attemptNumber: workflow.attemptNumber ?? null,
|
|
1851
1933
|
retryOf: workflow.retryOf ?? null
|
|
1852
1934
|
});
|
|
1853
1935
|
}
|
|
1936
|
+
var IDENTITY_KEYS = ["operationId", "attemptId", "retryOf", "attemptNumber"];
|
|
1937
|
+
function identityValuesEqual(a, b) {
|
|
1938
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
1939
|
+
return Number.isFinite(a) && Number.isFinite(b) && a === b;
|
|
1940
|
+
}
|
|
1941
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
1942
|
+
return a.trim() === b.trim();
|
|
1943
|
+
}
|
|
1944
|
+
return a === b;
|
|
1945
|
+
}
|
|
1946
|
+
function directNestedIdentityConflicts(event) {
|
|
1947
|
+
const attrs2 = event.attributes;
|
|
1948
|
+
if (!attrs2 || typeof attrs2 !== "object") return [];
|
|
1949
|
+
const nested = attrs2.metadata && typeof attrs2.metadata === "object" && !Array.isArray(attrs2.metadata) ? attrs2.metadata : void 0;
|
|
1950
|
+
const conflicts = [];
|
|
1951
|
+
if (nested) {
|
|
1952
|
+
for (const key of IDENTITY_KEYS) {
|
|
1953
|
+
const direct = attrs2[key];
|
|
1954
|
+
const nestedValue = nested[key];
|
|
1955
|
+
if (direct === void 0 || nestedValue === void 0) continue;
|
|
1956
|
+
if (!identityValuesEqual(direct, nestedValue)) {
|
|
1957
|
+
conflicts.push(key);
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
for (const key of identityConflictFieldsFromAttributes(attrs2)) {
|
|
1962
|
+
if (IDENTITY_KEYS.includes(key) && !conflicts.includes(key)) {
|
|
1963
|
+
conflicts.push(key);
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
return conflicts;
|
|
1967
|
+
}
|
|
1854
1968
|
function hasConflictingAttemptIdReuse(members) {
|
|
1855
1969
|
const byAttempt = /* @__PURE__ */ new Map();
|
|
1856
1970
|
for (const event of members) {
|
|
@@ -1866,6 +1980,31 @@ function hasConflictingAttemptIdReuse(members) {
|
|
|
1866
1980
|
}
|
|
1867
1981
|
return false;
|
|
1868
1982
|
}
|
|
1983
|
+
function hasConflictingEventIdReuse(members) {
|
|
1984
|
+
const byEventId = /* @__PURE__ */ new Map();
|
|
1985
|
+
for (const event of members) {
|
|
1986
|
+
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
1987
|
+
const eventId = event.eventId;
|
|
1988
|
+
if (!eventId) continue;
|
|
1989
|
+
if (hasDeliveryConflictMarker(event.attributes)) {
|
|
1990
|
+
return true;
|
|
1991
|
+
}
|
|
1992
|
+
const fingerprints = byEventId.get(eventId) ?? /* @__PURE__ */ new Set();
|
|
1993
|
+
fingerprints.add(redeliveryFingerprint(event));
|
|
1994
|
+
byEventId.set(eventId, fingerprints);
|
|
1995
|
+
}
|
|
1996
|
+
for (const fingerprints of byEventId.values()) {
|
|
1997
|
+
if (fingerprints.size > 1) return true;
|
|
1998
|
+
}
|
|
1999
|
+
return false;
|
|
2000
|
+
}
|
|
2001
|
+
function hasIdentityRepresentationConflict(members) {
|
|
2002
|
+
for (const event of members) {
|
|
2003
|
+
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
2004
|
+
if (directNestedIdentityConflicts(event).length > 0) return true;
|
|
2005
|
+
}
|
|
2006
|
+
return false;
|
|
2007
|
+
}
|
|
1869
2008
|
function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
1870
2009
|
const findings = [];
|
|
1871
2010
|
const byOperation = /* @__PURE__ */ new Map();
|
|
@@ -1873,13 +2012,14 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
1873
2012
|
const workflow = workflowFor(event);
|
|
1874
2013
|
const operationId = workflow.operationId;
|
|
1875
2014
|
if (!operationId) continue;
|
|
1876
|
-
const
|
|
1877
|
-
|
|
1878
|
-
|
|
2015
|
+
const key = `${event.runId}\0${operationId}`;
|
|
2016
|
+
const group = byOperation.get(key) ?? { operationId, members: [] };
|
|
2017
|
+
group.members.push(event);
|
|
2018
|
+
byOperation.set(key, group);
|
|
1879
2019
|
}
|
|
1880
2020
|
if (rules.maxAttempts !== void 0) {
|
|
1881
|
-
for (const
|
|
1882
|
-
if (hasConflictingAttemptIdReuse(members)) {
|
|
2021
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
2022
|
+
if (hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members)) {
|
|
1883
2023
|
findings.push(
|
|
1884
2024
|
fail2(
|
|
1885
2025
|
"contract.retry.duplicate-attempt-id",
|
|
@@ -1890,6 +2030,31 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
1890
2030
|
)
|
|
1891
2031
|
);
|
|
1892
2032
|
}
|
|
2033
|
+
if (hasIdentityRepresentationConflict(members)) {
|
|
2034
|
+
findings.push(
|
|
2035
|
+
fail2(
|
|
2036
|
+
"contract.retry.ambiguous-identity",
|
|
2037
|
+
`Operation ${operationId} has conflicting direct vs nested identity fields; strict identity cannot pass.`,
|
|
2038
|
+
members.slice(0, 4).map(eventEvidence),
|
|
2039
|
+
"agreeing identity representation",
|
|
2040
|
+
"direct/nested conflict"
|
|
2041
|
+
)
|
|
2042
|
+
);
|
|
2043
|
+
}
|
|
2044
|
+
const toolish = members.filter((event) => event.kind === "TOOL" || event.kind === "LLM");
|
|
2045
|
+
const hasAttemptId = toolish.some((event) => attemptIdOf(event) !== void 0);
|
|
2046
|
+
const missingAttemptId = toolish.some((event) => attemptIdOf(event) === void 0);
|
|
2047
|
+
if (hasAttemptId && missingAttemptId) {
|
|
2048
|
+
findings.push(
|
|
2049
|
+
fail2(
|
|
2050
|
+
"contract.retry.ambiguous-identity",
|
|
2051
|
+
`Operation ${operationId} has partial attempt identity; strict identity conformance cannot pass.`,
|
|
2052
|
+
members.slice(0, 4).map(eventEvidence),
|
|
2053
|
+
"complete attempt identity",
|
|
2054
|
+
"partial attemptId coverage"
|
|
2055
|
+
)
|
|
2056
|
+
);
|
|
2057
|
+
}
|
|
1893
2058
|
const count = countOperationAttempts(members);
|
|
1894
2059
|
if (count > rules.maxAttempts) {
|
|
1895
2060
|
findings.push(
|
|
@@ -1905,7 +2070,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
1905
2070
|
}
|
|
1906
2071
|
}
|
|
1907
2072
|
if (rules.requireTerminalResult) {
|
|
1908
|
-
for (const
|
|
2073
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
1909
2074
|
const hasTerminal = members.some((event) => event.status === "ok" || event.status === "error");
|
|
1910
2075
|
if (!hasTerminal) {
|
|
1911
2076
|
findings.push(
|
|
@@ -1925,7 +2090,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
1925
2090
|
const workflow = workflowFor(event);
|
|
1926
2091
|
const fallbackOf = workflow.fallbackOf;
|
|
1927
2092
|
if (!fallbackOf) continue;
|
|
1928
|
-
const prior = byOperation.get(fallbackOf) ?? [];
|
|
2093
|
+
const prior = byOperation.get(`${event.runId}\0${fallbackOf}`)?.members ?? [];
|
|
1929
2094
|
const fallbackStart = eventTime(event);
|
|
1930
2095
|
const earlierFailure = prior.some(
|
|
1931
2096
|
(candidate) => candidate.status === "error" && eventTime(candidate) !== "" && fallbackStart !== "" && eventTime(candidate) < fallbackStart
|
|
@@ -1952,7 +2117,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
1952
2117
|
for (const event of toolEvents) {
|
|
1953
2118
|
const name = resolveCanonicalToolName(event);
|
|
1954
2119
|
const workflow = workflowFor(event);
|
|
1955
|
-
const key = `${workflow.operationId ?? name}::${name}`;
|
|
2120
|
+
const key = `${event.runId}::${workflow.operationId ?? name}::${name}`;
|
|
1956
2121
|
const list = byToolOp.get(key) ?? [];
|
|
1957
2122
|
list.push(event);
|
|
1958
2123
|
byToolOp.set(key, list);
|
|
@@ -2010,7 +2175,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
2010
2175
|
}
|
|
2011
2176
|
}
|
|
2012
2177
|
if (rules.requireRecoveredFailureVisible) {
|
|
2013
|
-
for (const
|
|
2178
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
2014
2179
|
const ordered = sortByTime(members);
|
|
2015
2180
|
const toolish = ordered.filter(
|
|
2016
2181
|
(event) => (event.kind === "TOOL" || event.kind === "LLM") && (event.status === "ok" || event.status === "error")
|
|
@@ -2269,14 +2434,7 @@ function attemptIdOf2(event) {
|
|
|
2269
2434
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
2270
2435
|
}
|
|
2271
2436
|
function hasDuplicateAttemptIds(members) {
|
|
2272
|
-
|
|
2273
|
-
for (const event of members) {
|
|
2274
|
-
const id = attemptIdOf2(event);
|
|
2275
|
-
if (!id) continue;
|
|
2276
|
-
if (seen.has(id)) return true;
|
|
2277
|
-
seen.add(id);
|
|
2278
|
-
}
|
|
2279
|
-
return false;
|
|
2437
|
+
return hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members);
|
|
2280
2438
|
}
|
|
2281
2439
|
function findRetryTarget(members, retryOf) {
|
|
2282
2440
|
return members.find(
|