@attest-ai/core 1.0.0-rc.1 → 1.0.0-rc.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/dist/cjs/index.cjs +285 -110
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +129 -24
- package/dist/cjs/proto/index.cjs +14 -0
- package/dist/cjs/proto/index.cjs.map +1 -1
- package/dist/cjs/proto/index.d.cts +74 -1
- package/dist/esm/cli.js +2 -2
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/index.d.ts +129 -24
- package/dist/esm/index.js +275 -109
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/proto/index.d.ts +74 -1
- package/dist/esm/proto/index.js +11 -0
- package/dist/esm/proto/index.js.map +1 -1
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -12,6 +12,8 @@ var REASON_PROVIDER_NOT_CONFIGURED = "provider_not_configured";
|
|
|
12
12
|
var REASON_SIMULATION = "simulation";
|
|
13
13
|
var REASON_MISSING_EVIDENCE = "missing_evidence";
|
|
14
14
|
var REASON_SHORT_CIRCUITED = "short_circuited";
|
|
15
|
+
var REASON_BUDGET_EXHAUSTED = "budget_exhausted";
|
|
16
|
+
var REASON_JUDGE_ABSTAINED = "judge_abstained";
|
|
15
17
|
var OUTCOME_PASS = "pass";
|
|
16
18
|
var OUTCOME_FAIL = "fail";
|
|
17
19
|
var OUTCOME_SKIP = "skip";
|
|
@@ -102,6 +104,12 @@ var ProtocolDesyncError = class extends Error {
|
|
|
102
104
|
this.diagnostics = diagnostics;
|
|
103
105
|
}
|
|
104
106
|
};
|
|
107
|
+
var OTLPConversionError = class extends Error {
|
|
108
|
+
constructor(message) {
|
|
109
|
+
super(message);
|
|
110
|
+
this.name = "OTLPConversionError";
|
|
111
|
+
}
|
|
112
|
+
};
|
|
105
113
|
|
|
106
114
|
// src/proto/diagnostics.ts
|
|
107
115
|
var DEFAULT_BUFFER_SIZE = 32;
|
|
@@ -208,8 +216,8 @@ function extractId(response) {
|
|
|
208
216
|
}
|
|
209
217
|
|
|
210
218
|
// src/version.ts
|
|
211
|
-
var VERSION = "1.0.0-rc.
|
|
212
|
-
var ENGINE_VERSION = "1.0.0-rc.
|
|
219
|
+
var VERSION = "1.0.0-rc.2";
|
|
220
|
+
var ENGINE_VERSION = "1.0.0-rc.2";
|
|
213
221
|
|
|
214
222
|
// src/engine-manager.ts
|
|
215
223
|
import { spawn, spawnSync } from "child_process";
|
|
@@ -602,6 +610,76 @@ function resetConfig() {
|
|
|
602
610
|
_sampleRate = 0;
|
|
603
611
|
}
|
|
604
612
|
|
|
613
|
+
// src/usage.ts
|
|
614
|
+
var INT_FIELDS = [
|
|
615
|
+
"model_calls",
|
|
616
|
+
"judge_calls",
|
|
617
|
+
"input_tokens",
|
|
618
|
+
"output_tokens",
|
|
619
|
+
"cached_tokens",
|
|
620
|
+
"unpriced_calls",
|
|
621
|
+
"budget_refused"
|
|
622
|
+
];
|
|
623
|
+
var USD_FIELDS = ["cost_usd", "retry_cost_usd"];
|
|
624
|
+
function zeroUsage() {
|
|
625
|
+
return {
|
|
626
|
+
model_calls: 0,
|
|
627
|
+
judge_calls: 0,
|
|
628
|
+
input_tokens: 0,
|
|
629
|
+
output_tokens: 0,
|
|
630
|
+
cached_tokens: 0,
|
|
631
|
+
cost_usd: 0,
|
|
632
|
+
retry_cost_usd: 0,
|
|
633
|
+
unpriced_calls: 0,
|
|
634
|
+
budget_refused: 0
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
function addUsage(a, b) {
|
|
638
|
+
return {
|
|
639
|
+
model_calls: a.model_calls + b.model_calls,
|
|
640
|
+
judge_calls: a.judge_calls + b.judge_calls,
|
|
641
|
+
input_tokens: a.input_tokens + b.input_tokens,
|
|
642
|
+
output_tokens: a.output_tokens + b.output_tokens,
|
|
643
|
+
cached_tokens: a.cached_tokens + b.cached_tokens,
|
|
644
|
+
cost_usd: a.cost_usd + b.cost_usd,
|
|
645
|
+
retry_cost_usd: a.retry_cost_usd + b.retry_cost_usd,
|
|
646
|
+
unpriced_calls: a.unpriced_calls + b.unpriced_calls,
|
|
647
|
+
budget_refused: a.budget_refused + b.budget_refused
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
function sumUsage(usages) {
|
|
651
|
+
let total = zeroUsage();
|
|
652
|
+
for (const u of usages) total = addUsage(total, u);
|
|
653
|
+
return total;
|
|
654
|
+
}
|
|
655
|
+
function parseUsage(raw) {
|
|
656
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
657
|
+
throw new TypeError(`evaluate_batch result: usage must be an object, got ${JSON.stringify(raw)}`);
|
|
658
|
+
}
|
|
659
|
+
const obj = raw;
|
|
660
|
+
const field = (name, integer) => {
|
|
661
|
+
const v = obj[name];
|
|
662
|
+
if (typeof v !== "number" || !Number.isFinite(v) || v < 0 || integer && !Number.isInteger(v)) {
|
|
663
|
+
const kind = integer ? "a non-negative integer" : "a non-negative number";
|
|
664
|
+
throw new TypeError(`evaluate_batch result: usage.${name} must be ${kind}, got ${JSON.stringify(v)}`);
|
|
665
|
+
}
|
|
666
|
+
return v;
|
|
667
|
+
};
|
|
668
|
+
const ints = Object.fromEntries(INT_FIELDS.map((f) => [f, field(f, true)]));
|
|
669
|
+
const usd = Object.fromEntries(USD_FIELDS.map((f) => [f, field(f, false)]));
|
|
670
|
+
return { ...ints, ...usd };
|
|
671
|
+
}
|
|
672
|
+
function formatUsage(u) {
|
|
673
|
+
let line = `${u.model_calls} model calls \xB7 ${u.input_tokens + u.output_tokens} tokens (${u.cached_tokens} cached) \xB7 $${u.cost_usd.toFixed(4)} \xB7 retry cost $${u.retry_cost_usd.toFixed(4)}`;
|
|
674
|
+
if (u.budget_refused > 0) line += ` \xB7 ${u.budget_refused} calls refused by budget`;
|
|
675
|
+
if (u.unpriced_calls > 0) line += ` \xB7 ${u.unpriced_calls} unpriced calls not in $`;
|
|
676
|
+
return line;
|
|
677
|
+
}
|
|
678
|
+
function usageSummaryLine(u) {
|
|
679
|
+
if (u.model_calls === 0 && u.budget_refused === 0) return void 0;
|
|
680
|
+
return `attest usage: ${formatUsage(u)}`;
|
|
681
|
+
}
|
|
682
|
+
|
|
605
683
|
// src/client.ts
|
|
606
684
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
607
685
|
var DEFAULT_DIAGNOSTIC_BUFFER = 32;
|
|
@@ -855,14 +933,15 @@ var AttestClient = class {
|
|
|
855
933
|
}
|
|
856
934
|
const params = {
|
|
857
935
|
trace,
|
|
858
|
-
assertions: [...assertions]
|
|
936
|
+
assertions: [...assertions],
|
|
937
|
+
...options?.budget !== void 0 ? { budget: options.budget } : {}
|
|
859
938
|
};
|
|
860
939
|
const raw = await this.sendRequest(
|
|
861
940
|
"evaluate_batch",
|
|
862
941
|
params,
|
|
863
942
|
options?.timeout
|
|
864
943
|
);
|
|
865
|
-
return raw;
|
|
944
|
+
return { ...raw, usage: parseUsage(raw["usage"]) };
|
|
866
945
|
}
|
|
867
946
|
async submitPluginResult(traceId2, pluginName, assertionId2, status, score, explanation, options) {
|
|
868
947
|
const result = {
|
|
@@ -1050,11 +1129,14 @@ var AgentResult = class {
|
|
|
1050
1129
|
assertionResults;
|
|
1051
1130
|
totalCost;
|
|
1052
1131
|
totalDurationMs;
|
|
1053
|
-
|
|
1132
|
+
/** Attest model usage of the evaluation that produced this result. */
|
|
1133
|
+
usage;
|
|
1134
|
+
constructor(trace, assertionResults = [], totalCost = 0, totalDurationMs = 0, usage = zeroUsage()) {
|
|
1054
1135
|
this.trace = trace;
|
|
1055
1136
|
this.assertionResults = assertionResults.map(normalizeAssertionResult);
|
|
1056
1137
|
this.totalCost = totalCost;
|
|
1057
1138
|
this.totalDurationMs = totalDurationMs;
|
|
1139
|
+
this.usage = usage;
|
|
1058
1140
|
}
|
|
1059
1141
|
/** True if every assertion has status "pass". */
|
|
1060
1142
|
get passed() {
|
|
@@ -1233,7 +1315,8 @@ function appendJudgeMetadata(lines, meta) {
|
|
|
1233
1315
|
if (meta.rubric_version) {
|
|
1234
1316
|
rubric = `${rubric} @ ${meta.rubric_version}`;
|
|
1235
1317
|
}
|
|
1236
|
-
|
|
1318
|
+
const judge = meta.provider ? `${meta.provider}/${meta.model}` : meta.model;
|
|
1319
|
+
lines.push(` judge: ${judge} / ${rubric}`);
|
|
1237
1320
|
}
|
|
1238
1321
|
if (meta.prompt_hash) {
|
|
1239
1322
|
lines.push(` prompt: #${meta.prompt_hash}`);
|
|
@@ -1757,6 +1840,86 @@ var ExpectChain = class {
|
|
|
1757
1840
|
soft: opts?.soft ?? false
|
|
1758
1841
|
});
|
|
1759
1842
|
}
|
|
1843
|
+
// -- Layer 3: Behavior contracts (tool calls only, retries counted) --
|
|
1844
|
+
/**
|
|
1845
|
+
* Assert how many times a tool is called, per value of argument `per` when set.
|
|
1846
|
+
*
|
|
1847
|
+
* @example
|
|
1848
|
+
* ```ts
|
|
1849
|
+
* // fails with "issue_refund called 2× for order_id=O-1042 (max 1)"
|
|
1850
|
+
* expect(result).toolCardinality("issue_refund", { per: "order_id", atMost: 1 });
|
|
1851
|
+
* ```
|
|
1852
|
+
*/
|
|
1853
|
+
toolCardinality(tool, opts) {
|
|
1854
|
+
if (opts.atMost === void 0 && opts.atLeast === void 0) {
|
|
1855
|
+
throw new Error("toolCardinality needs atMost, atLeast or both");
|
|
1856
|
+
}
|
|
1857
|
+
const spec = { check: "tool_cardinality", tool };
|
|
1858
|
+
if (opts.per !== void 0) spec.per = opts.per;
|
|
1859
|
+
if (opts.atLeast !== void 0) spec.min = opts.atLeast;
|
|
1860
|
+
if (opts.atMost !== void 0) spec.max = opts.atMost;
|
|
1861
|
+
spec.soft = opts.soft ?? false;
|
|
1862
|
+
return this.add(TYPE_TRACE, spec);
|
|
1863
|
+
}
|
|
1864
|
+
/**
|
|
1865
|
+
* Assert the tool-call trajectory matches `tools`: `strict` (same sequence,
|
|
1866
|
+
* the default), `unordered` (same calls, any order), `subset` (no call
|
|
1867
|
+
* outside `tools`) or `superset` (every call in `tools` made). Use
|
|
1868
|
+
* {@link trajectoryPartialOrder} for ordering constraints.
|
|
1869
|
+
*/
|
|
1870
|
+
trajectory(tools, opts) {
|
|
1871
|
+
return this.add(TYPE_TRACE, {
|
|
1872
|
+
check: "trajectory",
|
|
1873
|
+
mode: opts?.mode ?? "strict",
|
|
1874
|
+
tools,
|
|
1875
|
+
soft: opts?.soft ?? false
|
|
1876
|
+
});
|
|
1877
|
+
}
|
|
1878
|
+
/**
|
|
1879
|
+
* Assert every tool in `tools` and `order` is called and each
|
|
1880
|
+
* `[before, after]` pair holds as in {@link toolCalledBefore}.
|
|
1881
|
+
*/
|
|
1882
|
+
trajectoryPartialOrder(order, opts) {
|
|
1883
|
+
const spec = {
|
|
1884
|
+
check: "trajectory",
|
|
1885
|
+
mode: "partial_order",
|
|
1886
|
+
order: order.map(([before, after]) => [before, after])
|
|
1887
|
+
};
|
|
1888
|
+
if (opts?.tools !== void 0) spec.tools = opts.tools;
|
|
1889
|
+
spec.soft = opts?.soft ?? false;
|
|
1890
|
+
return this.add(TYPE_TRACE, spec);
|
|
1891
|
+
}
|
|
1892
|
+
/** Assert every call to `after` has an earlier call to `before`; holds when `after` is never called. */
|
|
1893
|
+
toolCalledBefore(before, after, opts) {
|
|
1894
|
+
return this.add(TYPE_TRACE, { check: "tool_order", before, after, soft: opts?.soft ?? false });
|
|
1895
|
+
}
|
|
1896
|
+
/** Assert no block of `period` (1–4) tool calls repeats `minRepeats` (default 2) times in a row; A→B→A→B fails period 2. */
|
|
1897
|
+
noToolCycles(period, opts) {
|
|
1898
|
+
return this.add(TYPE_TRACE, {
|
|
1899
|
+
check: "cycle",
|
|
1900
|
+
period,
|
|
1901
|
+
min_repeats: opts?.minRepeats ?? 2,
|
|
1902
|
+
soft: opts?.soft ?? false
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
/** Assert at most `maxStreak` consecutive tool calls end in error (trace v2). */
|
|
1906
|
+
maxToolFailureStreak(maxStreak, opts) {
|
|
1907
|
+
return this.add(TYPE_TRACE, { check: "failure_streak", max: maxStreak, soft: opts?.soft ?? false });
|
|
1908
|
+
}
|
|
1909
|
+
/**
|
|
1910
|
+
* Assert every call to `tool` has argument `arg` (a dot path) satisfying
|
|
1911
|
+
* `op value`; holds when `tool` is never called.
|
|
1912
|
+
*/
|
|
1913
|
+
toolArgSatisfies(tool, arg, op, value, opts) {
|
|
1914
|
+
return this.add(TYPE_TRACE, {
|
|
1915
|
+
check: "arg_predicate",
|
|
1916
|
+
tool,
|
|
1917
|
+
arg,
|
|
1918
|
+
op,
|
|
1919
|
+
value,
|
|
1920
|
+
soft: opts?.soft ?? false
|
|
1921
|
+
});
|
|
1922
|
+
}
|
|
1760
1923
|
// -- Layer 4: Content --
|
|
1761
1924
|
/**
|
|
1762
1925
|
* Assert the output message contains the given string.
|
|
@@ -2927,119 +3090,113 @@ var OllamaAdapter = class {
|
|
|
2927
3090
|
};
|
|
2928
3091
|
|
|
2929
3092
|
// src/adapters/otel.ts
|
|
3093
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
3094
|
+
var CONVERT_TIMEOUT_MS = 6e4;
|
|
3095
|
+
var MAX_TRACE_OUTPUT_BYTES = 64 * 1024 * 1024;
|
|
3096
|
+
var STATUS_CODE_ERROR = 2;
|
|
2930
3097
|
var OTelAdapter = class _OTelAdapter {
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
3098
|
+
/**
|
|
3099
|
+
* Build a trace from finished OpenTelemetry spans of one trace.
|
|
3100
|
+
*
|
|
3101
|
+
* @param agentId Trace `agent_id`; defaults to the first turn's `gen_ai.agent.name`.
|
|
3102
|
+
* @throws OTLPConversionError when the engine rejects the spans.
|
|
3103
|
+
*/
|
|
3104
|
+
static async fromSpans(spans, agentId2) {
|
|
3105
|
+
return _OTelAdapter.fromOtlp(spansToOtlp(spans), agentId2);
|
|
2938
3106
|
}
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
3107
|
+
/**
|
|
3108
|
+
* Convert an OTLP/JSON export (`resourceSpans` → `scopeSpans` → `spans`).
|
|
3109
|
+
*
|
|
3110
|
+
* @param agentId Trace `agent_id`; defaults to the first turn's `gen_ai.agent.name`.
|
|
3111
|
+
* @throws OTLPConversionError when the engine rejects the export (malformed JSON, invalid
|
|
3112
|
+
* ids or timestamps, more than one trace, non-numeric token counts, ...).
|
|
3113
|
+
* @throws RangeError when a parsed export holds a non-finite number.
|
|
3114
|
+
* @throws OTLPConversionError when the engine times out, overflows the output buffer or
|
|
3115
|
+
* prints no trace.
|
|
3116
|
+
* @throws Error from `spawnSync` when the engine cannot start.
|
|
3117
|
+
*/
|
|
3118
|
+
static async fromOtlp(otlp, agentId2) {
|
|
3119
|
+
const payload = typeof otlp === "string" || otlp instanceof Uint8Array ? otlp : JSON.stringify(otlp, (_key, v) => {
|
|
3120
|
+
if (typeof v === "number" && !Number.isFinite(v)) {
|
|
3121
|
+
throw new RangeError(`OTLP export holds a non-finite number: ${String(v)}`);
|
|
3122
|
+
}
|
|
3123
|
+
return v;
|
|
2944
3124
|
});
|
|
2945
|
-
const
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
3125
|
+
const args = ["trace", "convert"];
|
|
3126
|
+
if (agentId2 !== void 0) args.push("--agent-id", agentId2);
|
|
3127
|
+
args.push("-");
|
|
3128
|
+
const proc = spawnSync2(await resolveEngine(), args, {
|
|
3129
|
+
input: payload,
|
|
3130
|
+
timeout: CONVERT_TIMEOUT_MS,
|
|
3131
|
+
maxBuffer: MAX_TRACE_OUTPUT_BYTES
|
|
3132
|
+
});
|
|
3133
|
+
if (proc.error) {
|
|
3134
|
+
const code = proc.error.code;
|
|
3135
|
+
if (code === "ETIMEDOUT") {
|
|
3136
|
+
throw new OTLPConversionError(
|
|
3137
|
+
`attest-engine trace convert timed out after ${CONVERT_TIMEOUT_MS / 1e3}s`
|
|
3138
|
+
);
|
|
2951
3139
|
}
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
let model;
|
|
2957
|
-
for (const span of sorted) {
|
|
2958
|
-
const attrs = span.attributes ?? {};
|
|
2959
|
-
const stepType = this.classifySpan(attrs, span.name);
|
|
2960
|
-
if (stepType === "llm_call") {
|
|
2961
|
-
const [stepArgs, stepResult] = this.extractLlmStep(attrs);
|
|
2962
|
-
builder.addLlmCall(span.name, {
|
|
2963
|
-
args: stepArgs,
|
|
2964
|
-
result: stepResult,
|
|
2965
|
-
metadata: this.spanMetadata(span)
|
|
2966
|
-
});
|
|
2967
|
-
const completion = attrs["gen_ai.completion"];
|
|
2968
|
-
if (completion) outputMessage = String(completion);
|
|
2969
|
-
const inputTokens = Number(attrs["gen_ai.usage.input_tokens"] ?? 0);
|
|
2970
|
-
const outputTokens = Number(attrs["gen_ai.usage.output_tokens"] ?? 0);
|
|
2971
|
-
const spanTokens = inputTokens + outputTokens;
|
|
2972
|
-
if (spanTokens > 0) totalTokens = (totalTokens ?? 0) + spanTokens;
|
|
2973
|
-
if (model === void 0) {
|
|
2974
|
-
const responseModel = attrs["gen_ai.response.model"];
|
|
2975
|
-
const requestModel = attrs["gen_ai.request.model"];
|
|
2976
|
-
if (responseModel) model = String(responseModel);
|
|
2977
|
-
else if (requestModel) model = String(requestModel);
|
|
2978
|
-
}
|
|
2979
|
-
} else if (stepType === "tool_call") {
|
|
2980
|
-
const [stepArgs, stepResult] = this.extractToolStep(attrs);
|
|
2981
|
-
const toolName = String(attrs["gen_ai.tool.name"] ?? span.name);
|
|
2982
|
-
builder.addToolCall(toolName, {
|
|
2983
|
-
args: stepArgs,
|
|
2984
|
-
result: stepResult,
|
|
2985
|
-
metadata: this.spanMetadata(span)
|
|
2986
|
-
});
|
|
3140
|
+
if (code === "ENOBUFS") {
|
|
3141
|
+
throw new OTLPConversionError(
|
|
3142
|
+
`attest-engine trace convert printed more than ${MAX_TRACE_OUTPUT_BYTES} bytes`
|
|
3143
|
+
);
|
|
2987
3144
|
}
|
|
3145
|
+
throw proc.error;
|
|
2988
3146
|
}
|
|
2989
|
-
if (
|
|
2990
|
-
const
|
|
2991
|
-
|
|
2992
|
-
|
|
3147
|
+
if (proc.status !== 0) {
|
|
3148
|
+
const message = proc.stderr.toString("utf8").trim();
|
|
3149
|
+
throw new OTLPConversionError(
|
|
3150
|
+
message || `attest-engine trace convert exited ${String(proc.status ?? proc.signal)}`
|
|
3151
|
+
);
|
|
2993
3152
|
}
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
if (!span.parentSpanId) return span;
|
|
3153
|
+
try {
|
|
3154
|
+
return JSON.parse(proc.stdout.toString("utf8"));
|
|
3155
|
+
} catch (err) {
|
|
3156
|
+
throw new OTLPConversionError(
|
|
3157
|
+
`attest-engine trace convert printed output that is not JSON: ${String(err)}`
|
|
3158
|
+
);
|
|
3001
3159
|
}
|
|
3002
|
-
return spans[0];
|
|
3003
3160
|
}
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
}
|
|
3009
|
-
if (op === "tool" || "gen_ai.tool.name" in attrs) {
|
|
3010
|
-
return "tool_call";
|
|
3011
|
-
}
|
|
3012
|
-
const lower = name.toLowerCase();
|
|
3013
|
-
if (lower.includes("completion") || lower.includes("chat")) return "llm_call";
|
|
3014
|
-
if (lower.includes("tool")) return "tool_call";
|
|
3015
|
-
return void 0;
|
|
3161
|
+
};
|
|
3162
|
+
function hrTimeToNanos(time, spanName) {
|
|
3163
|
+
if (!Number.isSafeInteger(time[0]) || !Number.isSafeInteger(time[1])) {
|
|
3164
|
+
throw new RangeError(`span ${JSON.stringify(spanName)} has a non-integer HrTime`);
|
|
3016
3165
|
}
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
if (
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
return
|
|
3028
|
-
}
|
|
3029
|
-
extractToolStep(attrs) {
|
|
3030
|
-
const args = {};
|
|
3031
|
-
const result = {};
|
|
3032
|
-
if ("gen_ai.tool.call.id" in attrs) args.call_id = String(attrs["gen_ai.tool.call.id"]);
|
|
3033
|
-
if ("gen_ai.tool.parameters" in attrs) args.parameters = attrs["gen_ai.tool.parameters"];
|
|
3034
|
-
if ("gen_ai.tool.output" in attrs) result.output = attrs["gen_ai.tool.output"];
|
|
3035
|
-
return [args, result];
|
|
3036
|
-
}
|
|
3037
|
-
spanMetadata(span) {
|
|
3038
|
-
const startNs = span.startTime[0] * 1e9 + span.startTime[1];
|
|
3039
|
-
const endNs = span.endTime[0] * 1e9 + span.endTime[1];
|
|
3040
|
-
return { duration_ms: Math.floor((endNs - startNs) / 1e6) };
|
|
3166
|
+
return (BigInt(time[0]) * 1000000000n + BigInt(time[1])).toString();
|
|
3167
|
+
}
|
|
3168
|
+
function anyValue(value) {
|
|
3169
|
+
if (value === null || value === void 0) return {};
|
|
3170
|
+
if (typeof value === "boolean") return { boolValue: value };
|
|
3171
|
+
if (typeof value === "string") return { stringValue: value };
|
|
3172
|
+
if (typeof value === "number") {
|
|
3173
|
+
if (!Number.isFinite(value)) {
|
|
3174
|
+
throw new RangeError(`OTel attribute value must be finite, got ${String(value)}`);
|
|
3175
|
+
}
|
|
3176
|
+
return Number.isSafeInteger(value) ? { intValue: String(value) } : { doubleValue: value };
|
|
3041
3177
|
}
|
|
3042
|
-
};
|
|
3178
|
+
return { arrayValue: { values: value.map((v) => anyValue(v)) } };
|
|
3179
|
+
}
|
|
3180
|
+
function spansToOtlp(spans) {
|
|
3181
|
+
const encoded = spans.map((span) => {
|
|
3182
|
+
const ctx = span.spanContext();
|
|
3183
|
+
const out = {
|
|
3184
|
+
traceId: ctx.traceId,
|
|
3185
|
+
spanId: ctx.spanId,
|
|
3186
|
+
name: span.name,
|
|
3187
|
+
startTimeUnixNano: hrTimeToNanos(span.startTime, span.name),
|
|
3188
|
+
endTimeUnixNano: hrTimeToNanos(span.endTime, span.name),
|
|
3189
|
+
attributes: Object.entries(span.attributes ?? {}).filter(([, v]) => v !== void 0).map(([key, v]) => ({ key, value: anyValue(v) }))
|
|
3190
|
+
};
|
|
3191
|
+
const parent = span.parentSpanContext?.spanId ?? span.parentSpanId;
|
|
3192
|
+
if (parent) out["parentSpanId"] = parent;
|
|
3193
|
+
if (span.status?.code === STATUS_CODE_ERROR) {
|
|
3194
|
+
out["status"] = { code: STATUS_CODE_ERROR, message: span.status.message ?? "" };
|
|
3195
|
+
}
|
|
3196
|
+
return out;
|
|
3197
|
+
});
|
|
3198
|
+
return { resourceSpans: [{ scopeSpans: [{ spans: encoded }] }] };
|
|
3199
|
+
}
|
|
3043
3200
|
|
|
3044
3201
|
// src/adapters/langchain.ts
|
|
3045
3202
|
var LangChainAdapter = class {
|
|
@@ -3162,6 +3319,7 @@ export {
|
|
|
3162
3319
|
GeminiAdapter,
|
|
3163
3320
|
LangChainAdapter,
|
|
3164
3321
|
ManualAdapter,
|
|
3322
|
+
OTLPConversionError,
|
|
3165
3323
|
OTelAdapter,
|
|
3166
3324
|
OUTCOME_FAIL,
|
|
3167
3325
|
OUTCOME_PASS,
|
|
@@ -3172,6 +3330,8 @@ export {
|
|
|
3172
3330
|
ProtocolDesyncError,
|
|
3173
3331
|
ProtocolDiagnosticBuffer,
|
|
3174
3332
|
ProtocolError,
|
|
3333
|
+
REASON_BUDGET_EXHAUSTED,
|
|
3334
|
+
REASON_JUDGE_ABSTAINED,
|
|
3175
3335
|
REASON_MISSING_EVIDENCE,
|
|
3176
3336
|
REASON_PROVIDER_NOT_CONFIGURED,
|
|
3177
3337
|
REASON_PROVIDER_UNAVAILABLE,
|
|
@@ -3201,6 +3361,7 @@ export {
|
|
|
3201
3361
|
TraceTree,
|
|
3202
3362
|
VERSION,
|
|
3203
3363
|
activeBuilder,
|
|
3364
|
+
addUsage,
|
|
3204
3365
|
agent,
|
|
3205
3366
|
agentId,
|
|
3206
3367
|
assertionId,
|
|
@@ -3213,11 +3374,13 @@ export {
|
|
|
3213
3374
|
executePluginAssertion,
|
|
3214
3375
|
extractId,
|
|
3215
3376
|
extractResult,
|
|
3377
|
+
formatUsage,
|
|
3216
3378
|
getSampleRate,
|
|
3217
3379
|
isSimulationMode,
|
|
3218
3380
|
layerForType,
|
|
3219
3381
|
loadLabelsCSV,
|
|
3220
3382
|
loadLabelsJSONL,
|
|
3383
|
+
parseUsage,
|
|
3221
3384
|
previewLine,
|
|
3222
3385
|
promptHash,
|
|
3223
3386
|
renderAssertionFailure,
|
|
@@ -3226,7 +3389,10 @@ export {
|
|
|
3226
3389
|
requireSimulationCapability,
|
|
3227
3390
|
resetConfig,
|
|
3228
3391
|
simulationEnvEnabled,
|
|
3392
|
+
sumUsage,
|
|
3229
3393
|
tier,
|
|
3230
|
-
traceId
|
|
3394
|
+
traceId,
|
|
3395
|
+
usageSummaryLine,
|
|
3396
|
+
zeroUsage
|
|
3231
3397
|
};
|
|
3232
3398
|
//# sourceMappingURL=index.js.map
|