agent-inspect 6.31.21 → 6.31.22
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 +6 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-N5JN26MW.mjs → chunk-EMWA5EKU.mjs} +300 -31
- package/packages/cli/dist/chunk-EMWA5EKU.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +379 -56
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +75 -31
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-VMGRSTG7.mjs → src-VZHGOLTO.mjs} +3 -3
- package/packages/cli/dist/{src-VMGRSTG7.mjs.map → src-VZHGOLTO.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +247 -5
- 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 +160 -27
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.mjs +2 -1
- package/packages/core/dist/chunk-GCZUWY47.mjs +182 -0
- package/packages/core/dist/chunk-GCZUWY47.mjs.map +1 -0
- package/packages/core/dist/{chunk-JE3TUFAQ.mjs → chunk-RBXD7BNX.mjs} +3 -3
- package/packages/core/dist/{chunk-JE3TUFAQ.mjs.map → chunk-RBXD7BNX.mjs.map} +1 -1
- package/packages/core/dist/{chunk-YU6XT5A2.mjs → chunk-S4NU55LU.mjs} +45 -3
- package/packages/core/dist/chunk-S4NU55LU.mjs.map +1 -0
- package/packages/core/dist/{chunk-EIP5CNEL.mjs → chunk-UPGBMRL4.mjs} +49 -3
- package/packages/core/dist/chunk-UPGBMRL4.mjs.map +1 -0
- package/packages/core/dist/{chunk-4CDX5GDS.mjs → chunk-ZOF6ON65.mjs} +104 -99
- package/packages/core/dist/chunk-ZOF6ON65.mjs.map +1 -0
- package/packages/core/dist/exporters.cjs +82 -27
- package/packages/core/dist/exporters.cjs.map +1 -1
- package/packages/core/dist/exporters.mjs +72 -27
- package/packages/core/dist/exporters.mjs.map +1 -1
- package/packages/core/dist/logs.cjs +197 -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 +197 -1
- package/packages/core/dist/persisted.cjs.map +1 -1
- package/packages/core/dist/persisted.mjs +4 -3
- package/packages/core/dist/persisted.mjs.map +1 -1
- package/packages/core/dist/readers.cjs +243 -1
- 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-YU6XT5A2.mjs.map +0 -1
|
@@ -1704,6 +1704,65 @@ 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 SYNTHETIC_DELIVERY_ID = /^(?:manual|inspect):[A-Za-z0-9_-]+:[A-Za-z0-9_-]+:[A-Za-z0-9_-]+:\d+$/;
|
|
1710
|
+
function stripReaderDeliveryDiscriminator(eventId) {
|
|
1711
|
+
if (!SYNTHETIC_DELIVERY_ID.test(eventId)) return eventId;
|
|
1712
|
+
return eventId.replace(/:\d+$/, "");
|
|
1713
|
+
}
|
|
1714
|
+
function canonicalDigest(value) {
|
|
1715
|
+
if (value === void 0) return null;
|
|
1716
|
+
const encoded = encodeCanonicalStructured(value);
|
|
1717
|
+
return encoded.ok ? encoded.value : `unencodable:${encoded.code}`;
|
|
1718
|
+
}
|
|
1719
|
+
function capturedContentDigest(attributes) {
|
|
1720
|
+
if (!attributes || typeof attributes !== "object") {
|
|
1721
|
+
return { args: null, result: null };
|
|
1722
|
+
}
|
|
1723
|
+
const nested = attributes.metadata && typeof attributes.metadata === "object" ? attributes.metadata : void 0;
|
|
1724
|
+
const args = attributes.arguments ?? attributes.args ?? attributes.input ?? nested?.arguments ?? nested?.args ?? nested?.input;
|
|
1725
|
+
const result = attributes.result ?? attributes.output ?? attributes.response ?? nested?.result ?? nested?.output ?? nested?.response;
|
|
1726
|
+
return {
|
|
1727
|
+
args: args === void 0 ? null : canonicalDigest(args),
|
|
1728
|
+
result: result === void 0 ? null : canonicalDigest(result)
|
|
1729
|
+
};
|
|
1730
|
+
}
|
|
1731
|
+
function timeKey(fields) {
|
|
1732
|
+
if (typeof fields.startedAt === "string" && fields.startedAt.trim() !== "") {
|
|
1733
|
+
return fields.startedAt;
|
|
1734
|
+
}
|
|
1735
|
+
if (typeof fields.timestamp === "string" && fields.timestamp.trim() !== "") {
|
|
1736
|
+
return fields.timestamp;
|
|
1737
|
+
}
|
|
1738
|
+
if (typeof fields.timestamp === "number" && Number.isFinite(fields.timestamp)) {
|
|
1739
|
+
return String(fields.timestamp);
|
|
1740
|
+
}
|
|
1741
|
+
return null;
|
|
1742
|
+
}
|
|
1743
|
+
function deliverySemanticFingerprint(fields) {
|
|
1744
|
+
const content = capturedContentDigest(fields.attributes);
|
|
1745
|
+
return JSON.stringify({
|
|
1746
|
+
stableEventId: stripReaderDeliveryDiscriminator(fields.eventId),
|
|
1747
|
+
runId: fields.runId,
|
|
1748
|
+
kind: fields.kind,
|
|
1749
|
+
name: fields.name,
|
|
1750
|
+
status: fields.status ?? null,
|
|
1751
|
+
parentId: fields.parentId ?? null,
|
|
1752
|
+
sourceType: fields.sourceType ?? null,
|
|
1753
|
+
time: timeKey(fields),
|
|
1754
|
+
operationId: fields.operationId ?? null,
|
|
1755
|
+
attemptId: fields.attemptId ?? null,
|
|
1756
|
+
attemptNumber: fields.attemptNumber ?? null,
|
|
1757
|
+
retryOf: fields.retryOf ?? null,
|
|
1758
|
+
argsDigest: content.args,
|
|
1759
|
+
resultDigest: content.result
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
function hasDeliveryConflictMarker(attributes) {
|
|
1763
|
+
return attributes?.[DELIVERY_CONFLICT_ATTR] === true;
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1707
1766
|
// packages/core/src/checks/retry-safety.ts
|
|
1708
1767
|
function fail2(ruleId, message, evidence, expected, actual) {
|
|
1709
1768
|
return {
|
|
@@ -1759,7 +1818,7 @@ function attemptIdOf(event) {
|
|
|
1759
1818
|
}
|
|
1760
1819
|
function countOperationAttempts(members) {
|
|
1761
1820
|
const identified = /* @__PURE__ */ new Set();
|
|
1762
|
-
|
|
1821
|
+
const unidentifiedFingerprints = /* @__PURE__ */ new Set();
|
|
1763
1822
|
for (const event of members) {
|
|
1764
1823
|
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
1765
1824
|
const id = attemptIdOf(event);
|
|
@@ -1767,13 +1826,13 @@ function countOperationAttempts(members) {
|
|
|
1767
1826
|
identified.add(id);
|
|
1768
1827
|
continue;
|
|
1769
1828
|
}
|
|
1770
|
-
|
|
1829
|
+
unidentifiedFingerprints.add(redeliveryFingerprint(event));
|
|
1771
1830
|
}
|
|
1772
1831
|
if (identified.size > 0) {
|
|
1773
|
-
return identified.size +
|
|
1832
|
+
return identified.size + unidentifiedFingerprints.size;
|
|
1774
1833
|
}
|
|
1775
1834
|
const numbered = /* @__PURE__ */ new Set();
|
|
1776
|
-
|
|
1835
|
+
const unnumberedFingerprints = /* @__PURE__ */ new Set();
|
|
1777
1836
|
for (const event of members) {
|
|
1778
1837
|
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
1779
1838
|
const num = attemptNumberOf(event);
|
|
@@ -1781,12 +1840,12 @@ function countOperationAttempts(members) {
|
|
|
1781
1840
|
numbered.add(num);
|
|
1782
1841
|
continue;
|
|
1783
1842
|
}
|
|
1784
|
-
|
|
1843
|
+
unnumberedFingerprints.add(redeliveryFingerprint(event));
|
|
1785
1844
|
}
|
|
1786
1845
|
if (numbered.size > 0) {
|
|
1787
|
-
return numbered.size +
|
|
1846
|
+
return numbered.size + unnumberedFingerprints.size;
|
|
1788
1847
|
}
|
|
1789
|
-
return
|
|
1848
|
+
return unnumberedFingerprints.size;
|
|
1790
1849
|
}
|
|
1791
1850
|
function classifyRetryAttempt(event, priorOrdered, allMembers) {
|
|
1792
1851
|
const workflow = workflowFor(event);
|
|
@@ -1838,19 +1897,49 @@ function classifyRetryAttempt(event, priorOrdered, allMembers) {
|
|
|
1838
1897
|
}
|
|
1839
1898
|
function redeliveryFingerprint(event) {
|
|
1840
1899
|
const workflow = workflowFor(event);
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
stableEventId,
|
|
1900
|
+
return deliverySemanticFingerprint({
|
|
1901
|
+
eventId: event.eventId ?? "",
|
|
1844
1902
|
runId: event.runId,
|
|
1845
1903
|
kind: event.kind,
|
|
1846
1904
|
name: event.name,
|
|
1847
1905
|
status: event.status,
|
|
1906
|
+
parentId: event.parentId,
|
|
1907
|
+
timestamp: event.timestamp,
|
|
1908
|
+
startedAt: event.startedAt,
|
|
1909
|
+
sourceType: event.source?.type,
|
|
1910
|
+
attributes: event.attributes && typeof event.attributes === "object" ? event.attributes : void 0,
|
|
1848
1911
|
operationId: workflow.operationId ?? null,
|
|
1849
1912
|
attemptId: workflow.attemptId ?? null,
|
|
1850
1913
|
attemptNumber: workflow.attemptNumber ?? null,
|
|
1851
1914
|
retryOf: workflow.retryOf ?? null
|
|
1852
1915
|
});
|
|
1853
1916
|
}
|
|
1917
|
+
var IDENTITY_KEYS = ["operationId", "attemptId", "retryOf", "attemptNumber"];
|
|
1918
|
+
function identityValuesEqual(a, b) {
|
|
1919
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
1920
|
+
return Number.isFinite(a) && Number.isFinite(b) && a === b;
|
|
1921
|
+
}
|
|
1922
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
1923
|
+
return a.trim() === b.trim();
|
|
1924
|
+
}
|
|
1925
|
+
return a === b;
|
|
1926
|
+
}
|
|
1927
|
+
function directNestedIdentityConflicts(event) {
|
|
1928
|
+
const attrs2 = event.attributes;
|
|
1929
|
+
if (!attrs2 || typeof attrs2 !== "object") return [];
|
|
1930
|
+
const nested = attrs2.metadata && typeof attrs2.metadata === "object" && !Array.isArray(attrs2.metadata) ? attrs2.metadata : void 0;
|
|
1931
|
+
if (!nested) return [];
|
|
1932
|
+
const conflicts = [];
|
|
1933
|
+
for (const key of IDENTITY_KEYS) {
|
|
1934
|
+
const direct = attrs2[key];
|
|
1935
|
+
const nestedValue = nested[key];
|
|
1936
|
+
if (direct === void 0 || nestedValue === void 0) continue;
|
|
1937
|
+
if (!identityValuesEqual(direct, nestedValue)) {
|
|
1938
|
+
conflicts.push(key);
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
return conflicts;
|
|
1942
|
+
}
|
|
1854
1943
|
function hasConflictingAttemptIdReuse(members) {
|
|
1855
1944
|
const byAttempt = /* @__PURE__ */ new Map();
|
|
1856
1945
|
for (const event of members) {
|
|
@@ -1866,6 +1955,31 @@ function hasConflictingAttemptIdReuse(members) {
|
|
|
1866
1955
|
}
|
|
1867
1956
|
return false;
|
|
1868
1957
|
}
|
|
1958
|
+
function hasConflictingEventIdReuse(members) {
|
|
1959
|
+
const byEventId = /* @__PURE__ */ new Map();
|
|
1960
|
+
for (const event of members) {
|
|
1961
|
+
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
1962
|
+
const eventId = event.eventId;
|
|
1963
|
+
if (!eventId) continue;
|
|
1964
|
+
if (hasDeliveryConflictMarker(event.attributes)) {
|
|
1965
|
+
return true;
|
|
1966
|
+
}
|
|
1967
|
+
const fingerprints = byEventId.get(eventId) ?? /* @__PURE__ */ new Set();
|
|
1968
|
+
fingerprints.add(redeliveryFingerprint(event));
|
|
1969
|
+
byEventId.set(eventId, fingerprints);
|
|
1970
|
+
}
|
|
1971
|
+
for (const fingerprints of byEventId.values()) {
|
|
1972
|
+
if (fingerprints.size > 1) return true;
|
|
1973
|
+
}
|
|
1974
|
+
return false;
|
|
1975
|
+
}
|
|
1976
|
+
function hasIdentityRepresentationConflict(members) {
|
|
1977
|
+
for (const event of members) {
|
|
1978
|
+
if (event.kind !== "TOOL" && event.kind !== "LLM") continue;
|
|
1979
|
+
if (directNestedIdentityConflicts(event).length > 0) return true;
|
|
1980
|
+
}
|
|
1981
|
+
return false;
|
|
1982
|
+
}
|
|
1869
1983
|
function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
1870
1984
|
const findings = [];
|
|
1871
1985
|
const byOperation = /* @__PURE__ */ new Map();
|
|
@@ -1873,13 +1987,14 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
1873
1987
|
const workflow = workflowFor(event);
|
|
1874
1988
|
const operationId = workflow.operationId;
|
|
1875
1989
|
if (!operationId) continue;
|
|
1876
|
-
const
|
|
1877
|
-
|
|
1878
|
-
|
|
1990
|
+
const key = `${event.runId}\0${operationId}`;
|
|
1991
|
+
const group = byOperation.get(key) ?? { operationId, members: [] };
|
|
1992
|
+
group.members.push(event);
|
|
1993
|
+
byOperation.set(key, group);
|
|
1879
1994
|
}
|
|
1880
1995
|
if (rules.maxAttempts !== void 0) {
|
|
1881
|
-
for (const
|
|
1882
|
-
if (hasConflictingAttemptIdReuse(members)) {
|
|
1996
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
1997
|
+
if (hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members)) {
|
|
1883
1998
|
findings.push(
|
|
1884
1999
|
fail2(
|
|
1885
2000
|
"contract.retry.duplicate-attempt-id",
|
|
@@ -1890,6 +2005,31 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
1890
2005
|
)
|
|
1891
2006
|
);
|
|
1892
2007
|
}
|
|
2008
|
+
if (hasIdentityRepresentationConflict(members)) {
|
|
2009
|
+
findings.push(
|
|
2010
|
+
fail2(
|
|
2011
|
+
"contract.retry.ambiguous-identity",
|
|
2012
|
+
`Operation ${operationId} has conflicting direct vs nested identity fields; strict identity cannot pass.`,
|
|
2013
|
+
members.slice(0, 4).map(eventEvidence),
|
|
2014
|
+
"agreeing identity representation",
|
|
2015
|
+
"direct/nested conflict"
|
|
2016
|
+
)
|
|
2017
|
+
);
|
|
2018
|
+
}
|
|
2019
|
+
const toolish = members.filter((event) => event.kind === "TOOL" || event.kind === "LLM");
|
|
2020
|
+
const hasAttemptId = toolish.some((event) => attemptIdOf(event) !== void 0);
|
|
2021
|
+
const missingAttemptId = toolish.some((event) => attemptIdOf(event) === void 0);
|
|
2022
|
+
if (hasAttemptId && missingAttemptId) {
|
|
2023
|
+
findings.push(
|
|
2024
|
+
fail2(
|
|
2025
|
+
"contract.retry.ambiguous-identity",
|
|
2026
|
+
`Operation ${operationId} has partial attempt identity; strict identity conformance cannot pass.`,
|
|
2027
|
+
members.slice(0, 4).map(eventEvidence),
|
|
2028
|
+
"complete attempt identity",
|
|
2029
|
+
"partial attemptId coverage"
|
|
2030
|
+
)
|
|
2031
|
+
);
|
|
2032
|
+
}
|
|
1893
2033
|
const count = countOperationAttempts(members);
|
|
1894
2034
|
if (count > rules.maxAttempts) {
|
|
1895
2035
|
findings.push(
|
|
@@ -1905,7 +2045,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
1905
2045
|
}
|
|
1906
2046
|
}
|
|
1907
2047
|
if (rules.requireTerminalResult) {
|
|
1908
|
-
for (const
|
|
2048
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
1909
2049
|
const hasTerminal = members.some((event) => event.status === "ok" || event.status === "error");
|
|
1910
2050
|
if (!hasTerminal) {
|
|
1911
2051
|
findings.push(
|
|
@@ -1925,7 +2065,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
1925
2065
|
const workflow = workflowFor(event);
|
|
1926
2066
|
const fallbackOf = workflow.fallbackOf;
|
|
1927
2067
|
if (!fallbackOf) continue;
|
|
1928
|
-
const prior = byOperation.get(fallbackOf) ?? [];
|
|
2068
|
+
const prior = byOperation.get(`${event.runId}\0${fallbackOf}`)?.members ?? [];
|
|
1929
2069
|
const fallbackStart = eventTime(event);
|
|
1930
2070
|
const earlierFailure = prior.some(
|
|
1931
2071
|
(candidate) => candidate.status === "error" && eventTime(candidate) !== "" && fallbackStart !== "" && eventTime(candidate) < fallbackStart
|
|
@@ -1952,7 +2092,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
1952
2092
|
for (const event of toolEvents) {
|
|
1953
2093
|
const name = resolveCanonicalToolName(event);
|
|
1954
2094
|
const workflow = workflowFor(event);
|
|
1955
|
-
const key = `${workflow.operationId ?? name}::${name}`;
|
|
2095
|
+
const key = `${event.runId}::${workflow.operationId ?? name}::${name}`;
|
|
1956
2096
|
const list = byToolOp.get(key) ?? [];
|
|
1957
2097
|
list.push(event);
|
|
1958
2098
|
byToolOp.set(key, list);
|
|
@@ -2010,7 +2150,7 @@ function evaluateRetrySafetyRules(events, rules, _runEvidence) {
|
|
|
2010
2150
|
}
|
|
2011
2151
|
}
|
|
2012
2152
|
if (rules.requireRecoveredFailureVisible) {
|
|
2013
|
-
for (const
|
|
2153
|
+
for (const { operationId, members } of byOperation.values()) {
|
|
2014
2154
|
const ordered = sortByTime(members);
|
|
2015
2155
|
const toolish = ordered.filter(
|
|
2016
2156
|
(event) => (event.kind === "TOOL" || event.kind === "LLM") && (event.status === "ok" || event.status === "error")
|
|
@@ -2269,14 +2409,7 @@ function attemptIdOf2(event) {
|
|
|
2269
2409
|
return typeof value === "string" && value.trim() !== "" ? value.trim() : void 0;
|
|
2270
2410
|
}
|
|
2271
2411
|
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;
|
|
2412
|
+
return hasConflictingAttemptIdReuse(members) || hasConflictingEventIdReuse(members);
|
|
2280
2413
|
}
|
|
2281
2414
|
function findRetryTarget(members, retryOf) {
|
|
2282
2415
|
return members.find(
|