@tangle-network/agent-eval 0.120.0 → 0.120.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.
Files changed (171) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +1 -1
  3. package/dist/analyst/index.d.ts +0 -3111
  4. package/dist/analyst/index.js +0 -403
  5. package/dist/analyst/index.js.map +0 -1
  6. package/dist/authenticity/index.d.ts +0 -161
  7. package/dist/authenticity/index.js +0 -215
  8. package/dist/authenticity/index.js.map +0 -1
  9. package/dist/belief-state/index.d.ts +0 -1301
  10. package/dist/belief-state/index.js +0 -2152
  11. package/dist/belief-state/index.js.map +0 -1
  12. package/dist/benchmarks/index.d.ts +0 -974
  13. package/dist/benchmarks/index.js +0 -60
  14. package/dist/benchmarks/index.js.map +0 -1
  15. package/dist/builder-eval/index.d.ts +0 -695
  16. package/dist/builder-eval/index.js +0 -366
  17. package/dist/builder-eval/index.js.map +0 -1
  18. package/dist/campaign/index.d.ts +0 -7454
  19. package/dist/campaign/index.js +0 -272
  20. package/dist/campaign/index.js.map +0 -1
  21. package/dist/chunk-32BZXMSO.js +0 -3878
  22. package/dist/chunk-32BZXMSO.js.map +0 -1
  23. package/dist/chunk-3A246TSA.js +0 -998
  24. package/dist/chunk-3A246TSA.js.map +0 -1
  25. package/dist/chunk-3RF76KTD.js +0 -84
  26. package/dist/chunk-3RF76KTD.js.map +0 -1
  27. package/dist/chunk-3YYRZDON.js +0 -45
  28. package/dist/chunk-3YYRZDON.js.map +0 -1
  29. package/dist/chunk-4I2E3LLO.js +0 -1030
  30. package/dist/chunk-4I2E3LLO.js.map +0 -1
  31. package/dist/chunk-ARU2PZFM.js +0 -312
  32. package/dist/chunk-ARU2PZFM.js.map +0 -1
  33. package/dist/chunk-BOD4O7OF.js +0 -40
  34. package/dist/chunk-BOD4O7OF.js.map +0 -1
  35. package/dist/chunk-DPZAEKA6.js +0 -880
  36. package/dist/chunk-DPZAEKA6.js.map +0 -1
  37. package/dist/chunk-DTJ6QUQB.js +0 -131
  38. package/dist/chunk-DTJ6QUQB.js.map +0 -1
  39. package/dist/chunk-GGE4NNQT.js +0 -65
  40. package/dist/chunk-GGE4NNQT.js.map +0 -1
  41. package/dist/chunk-H5UD2323.js +0 -286
  42. package/dist/chunk-H5UD2323.js.map +0 -1
  43. package/dist/chunk-HHWE3POT.js +0 -94
  44. package/dist/chunk-HHWE3POT.js.map +0 -1
  45. package/dist/chunk-HKUCJ437.js +0 -787
  46. package/dist/chunk-HKUCJ437.js.map +0 -1
  47. package/dist/chunk-JHCHEVET.js +0 -274
  48. package/dist/chunk-JHCHEVET.js.map +0 -1
  49. package/dist/chunk-JHOJHHU7.js +0 -867
  50. package/dist/chunk-JHOJHHU7.js.map +0 -1
  51. package/dist/chunk-JM2SKQMS.js +0 -750
  52. package/dist/chunk-JM2SKQMS.js.map +0 -1
  53. package/dist/chunk-JN2FCO5W.js +0 -7958
  54. package/dist/chunk-JN2FCO5W.js.map +0 -1
  55. package/dist/chunk-K4DBDHLK.js +0 -158
  56. package/dist/chunk-K4DBDHLK.js.map +0 -1
  57. package/dist/chunk-K6N6XJJX.js +0 -306
  58. package/dist/chunk-K6N6XJJX.js.map +0 -1
  59. package/dist/chunk-MA6HLL3S.js +0 -65
  60. package/dist/chunk-MA6HLL3S.js.map +0 -1
  61. package/dist/chunk-MAZ26DC7.js +0 -99
  62. package/dist/chunk-MAZ26DC7.js.map +0 -1
  63. package/dist/chunk-MOXWMGPC.js +0 -577
  64. package/dist/chunk-MOXWMGPC.js.map +0 -1
  65. package/dist/chunk-NJC7U437.js +0 -626
  66. package/dist/chunk-NJC7U437.js.map +0 -1
  67. package/dist/chunk-NPCTHQIO.js +0 -91
  68. package/dist/chunk-NPCTHQIO.js.map +0 -1
  69. package/dist/chunk-ONWEPEDO.js +0 -57
  70. package/dist/chunk-ONWEPEDO.js.map +0 -1
  71. package/dist/chunk-OYZAPX5G.js +0 -1526
  72. package/dist/chunk-OYZAPX5G.js.map +0 -1
  73. package/dist/chunk-PC4UYEBM.js +0 -166
  74. package/dist/chunk-PC4UYEBM.js.map +0 -1
  75. package/dist/chunk-PICTDURQ.js +0 -766
  76. package/dist/chunk-PICTDURQ.js.map +0 -1
  77. package/dist/chunk-PJQFMIOX.js +0 -1182
  78. package/dist/chunk-PJQFMIOX.js.map +0 -1
  79. package/dist/chunk-PXD6ZFNY.js +0 -1107
  80. package/dist/chunk-PXD6ZFNY.js.map +0 -1
  81. package/dist/chunk-PXE2VKMX.js +0 -140
  82. package/dist/chunk-PXE2VKMX.js.map +0 -1
  83. package/dist/chunk-PZ5AY32C.js +0 -10
  84. package/dist/chunk-PZ5AY32C.js.map +0 -1
  85. package/dist/chunk-QBRSJK47.js +0 -622
  86. package/dist/chunk-QBRSJK47.js.map +0 -1
  87. package/dist/chunk-QWMPPZ3X.js +0 -550
  88. package/dist/chunk-QWMPPZ3X.js.map +0 -1
  89. package/dist/chunk-S3UZOQ5Y.js +0 -328
  90. package/dist/chunk-S3UZOQ5Y.js.map +0 -1
  91. package/dist/chunk-S5TT5R3L.js +0 -2668
  92. package/dist/chunk-S5TT5R3L.js.map +0 -1
  93. package/dist/chunk-T4SQEITX.js +0 -95
  94. package/dist/chunk-T4SQEITX.js.map +0 -1
  95. package/dist/chunk-TT4KNT67.js +0 -124
  96. package/dist/chunk-TT4KNT67.js.map +0 -1
  97. package/dist/chunk-U5CHZ5M3.js +0 -357
  98. package/dist/chunk-U5CHZ5M3.js.map +0 -1
  99. package/dist/chunk-ULOKLHIQ.js +0 -1937
  100. package/dist/chunk-ULOKLHIQ.js.map +0 -1
  101. package/dist/chunk-VI2UW6B6.js +0 -162
  102. package/dist/chunk-VI2UW6B6.js.map +0 -1
  103. package/dist/chunk-VQMK5FMP.js +0 -247
  104. package/dist/chunk-VQMK5FMP.js.map +0 -1
  105. package/dist/chunk-VSMTAMNK.js +0 -53
  106. package/dist/chunk-VSMTAMNK.js.map +0 -1
  107. package/dist/chunk-VZSRQ272.js +0 -149
  108. package/dist/chunk-VZSRQ272.js.map +0 -1
  109. package/dist/chunk-WW2A73HW.js +0 -159
  110. package/dist/chunk-WW2A73HW.js.map +0 -1
  111. package/dist/chunk-X4UCIOTZ.js +0 -136
  112. package/dist/chunk-X4UCIOTZ.js.map +0 -1
  113. package/dist/chunk-XDIRG3TO.js +0 -1266
  114. package/dist/chunk-XDIRG3TO.js.map +0 -1
  115. package/dist/chunk-XJYR7XFV.js +0 -317
  116. package/dist/chunk-XJYR7XFV.js.map +0 -1
  117. package/dist/chunk-ZET2UAYW.js +0 -89
  118. package/dist/chunk-ZET2UAYW.js.map +0 -1
  119. package/dist/chunk-ZZUXHH3R.js +0 -99
  120. package/dist/chunk-ZZUXHH3R.js.map +0 -1
  121. package/dist/cli.d.ts +0 -1
  122. package/dist/cli.js +0 -112
  123. package/dist/cli.js.map +0 -1
  124. package/dist/contract/index.d.ts +0 -4969
  125. package/dist/contract/index.js +0 -1653
  126. package/dist/contract/index.js.map +0 -1
  127. package/dist/control.d.ts +0 -1013
  128. package/dist/control.js +0 -34
  129. package/dist/control.js.map +0 -1
  130. package/dist/fuzz.d.ts +0 -759
  131. package/dist/fuzz.js +0 -714
  132. package/dist/fuzz.js.map +0 -1
  133. package/dist/hosted/index.d.ts +0 -730
  134. package/dist/hosted/index.js +0 -14
  135. package/dist/hosted/index.js.map +0 -1
  136. package/dist/index.d.ts +0 -16780
  137. package/dist/index.js +0 -12168
  138. package/dist/index.js.map +0 -1
  139. package/dist/matrix/index.d.ts +0 -155
  140. package/dist/matrix/index.js +0 -8
  141. package/dist/matrix/index.js.map +0 -1
  142. package/dist/meta-eval/index.d.ts +0 -1030
  143. package/dist/meta-eval/index.js +0 -417
  144. package/dist/meta-eval/index.js.map +0 -1
  145. package/dist/multishot/index.d.ts +0 -579
  146. package/dist/multishot/index.js +0 -589
  147. package/dist/multishot/index.js.map +0 -1
  148. package/dist/openapi.json +0 -992
  149. package/dist/pipelines/index.d.ts +0 -567
  150. package/dist/pipelines/index.js +0 -515
  151. package/dist/pipelines/index.js.map +0 -1
  152. package/dist/reporting.d.ts +0 -1277
  153. package/dist/reporting.js +0 -48
  154. package/dist/reporting.js.map +0 -1
  155. package/dist/rl.d.ts +0 -4092
  156. package/dist/rl.js +0 -1724
  157. package/dist/rl.js.map +0 -1
  158. package/dist/run-campaign-HNFPJET4.js +0 -14
  159. package/dist/run-campaign-HNFPJET4.js.map +0 -1
  160. package/dist/storyboard/index.d.ts +0 -279
  161. package/dist/storyboard/index.js +0 -767
  162. package/dist/storyboard/index.js.map +0 -1
  163. package/dist/trace-attributes.d.ts +0 -52
  164. package/dist/trace-attributes.js +0 -62
  165. package/dist/trace-attributes.js.map +0 -1
  166. package/dist/traces.d.ts +0 -2343
  167. package/dist/traces.js +0 -249
  168. package/dist/traces.js.map +0 -1
  169. package/dist/wire/index.d.ts +0 -1252
  170. package/dist/wire/index.js +0 -81
  171. package/dist/wire/index.js.map +0 -1
@@ -1,626 +0,0 @@
1
- import {
2
- defaultProviderRedactor,
3
- providerFromBaseUrl
4
- } from "./chunk-PC4UYEBM.js";
5
- import {
6
- AgentEvalError,
7
- CaptureIntegrityError
8
- } from "./chunk-ONWEPEDO.js";
9
-
10
- // src/llm-client.ts
11
- function maximumChargeForLlmRequest(request, options = {}) {
12
- if (request.maxTokens === void 0) return void 0;
13
- if (!Number.isInteger(request.maxTokens) || request.maxTokens <= 0) {
14
- throw new RangeError(`maximumChargeForLlmRequest: maxTokens must be a positive integer`);
15
- }
16
- if (request.messages.some(
17
- (message) => Array.isArray(message.content) && message.content.some((part) => part.type === "image_url")
18
- )) {
19
- return void 0;
20
- }
21
- const attempts = resolveMaximumAttempts(options.maxRetries);
22
- const requestBytes = new TextEncoder().encode(
23
- JSON.stringify(buildBody(request, false))
24
- ).byteLength;
25
- const batches = request.jsonSchema ? 2 : 1;
26
- return {
27
- model: request.model,
28
- inputTokens: requestBytes * attempts * batches,
29
- outputTokens: request.maxTokens * attempts * batches
30
- };
31
- }
32
- function costReceiptFromLlm(result) {
33
- const cachedTokens = result.usage.cachedPromptTokens ?? 0;
34
- return {
35
- model: result.model,
36
- inputTokens: Math.max(0, result.usage.promptTokens - cachedTokens),
37
- outputTokens: result.usage.completionTokens,
38
- cachedTokens: cachedTokens > 0 ? cachedTokens : void 0,
39
- actualCostUsd: result.costUsd ?? void 0,
40
- usageUnknown: result.usage.captured === false
41
- };
42
- }
43
- function costReceiptFromLlmError(error) {
44
- return error instanceof LlmResponseError ? costReceiptFromLlm(error.result) : void 0;
45
- }
46
- var LlmCallError = class extends AgentEvalError {
47
- constructor(message, status, body, model) {
48
- super("judge", message);
49
- this.status = status;
50
- this.body = body;
51
- this.model = model;
52
- }
53
- status;
54
- body;
55
- model;
56
- };
57
- var LlmResponseError = class extends AgentEvalError {
58
- constructor(message, result, options) {
59
- super("judge", message, options);
60
- this.result = result;
61
- }
62
- result;
63
- };
64
- var DEFAULT_BASE_URL = "https://router.tangle.tools/v1";
65
- var DEFAULT_TIMEOUT_MS = Number(process.env.TANGLE_LLM_TIMEOUT_MS) || 3e5;
66
- var DEFAULT_MAX_RETRIES = Number(process.env.TANGLE_LLM_MAX_RETRIES) || 3;
67
- function resolveMaximumAttempts(configured) {
68
- const attempts = configured ?? DEFAULT_MAX_RETRIES;
69
- if (!Number.isInteger(attempts) || attempts <= 0) {
70
- throw new RangeError("LLM maximum attempts must be a positive integer");
71
- }
72
- return attempts;
73
- }
74
- function providerTokenCount(value) {
75
- return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
76
- }
77
- var RETRYABLE_STATUS = /* @__PURE__ */ new Set([429, 502, 503, 504]);
78
- var TRANSIENT_ERROR_PATTERNS = [
79
- /AbortError/i,
80
- /TimeoutError/i,
81
- /this operation was aborted/i,
82
- /fetch failed/i,
83
- /ECONNRESET/i,
84
- /ETIMEDOUT/i,
85
- /EAI_AGAIN/i,
86
- /socket hang up/i,
87
- /stream.*ended.*unexpectedly/i,
88
- /terminated/i,
89
- /other side closed/i,
90
- /NGHTTP2/i,
91
- /UND_ERR/i
92
- ];
93
- function isTransientLlmError(err) {
94
- return classifyTransient(err, 0);
95
- }
96
- function classifyTransient(err, depth) {
97
- if (err instanceof LlmCallError) return RETRYABLE_STATUS.has(err.status);
98
- if (!(err instanceof Error)) return false;
99
- const status = err.status;
100
- if (typeof status === "number" && RETRYABLE_STATUS.has(status)) return true;
101
- const code = err.code;
102
- const haystack = `${err.name}
103
- ${err.message}
104
- ${typeof code === "string" ? code : ""}`;
105
- if (TRANSIENT_ERROR_PATTERNS.some((p) => p.test(haystack))) return true;
106
- const cause = err.cause;
107
- if (depth < 4 && cause instanceof Error && cause !== err) {
108
- return classifyTransient(cause, depth + 1);
109
- }
110
- return false;
111
- }
112
- function parseRetryAfter(headers) {
113
- const h = headers.get("retry-after");
114
- if (!h) return null;
115
- const asNumber = Number(h);
116
- if (Number.isFinite(asNumber) && asNumber > 0) return asNumber * 1e3;
117
- const asDate = Date.parse(h);
118
- if (Number.isFinite(asDate)) return Math.max(0, asDate - Date.now());
119
- return null;
120
- }
121
- function backoffMs(attempt) {
122
- return Math.min(500 * 2 ** attempt, 16e3);
123
- }
124
- function buildHeaders(opts) {
125
- const headers = {
126
- "Content-Type": "application/json",
127
- Accept: "application/json"
128
- };
129
- if (opts.authHeader) {
130
- headers[opts.authHeader.name] = opts.authHeader.value;
131
- } else if (opts.bearer || opts.apiKey) {
132
- headers.Authorization = `Bearer ${opts.bearer ?? opts.apiKey}`;
133
- }
134
- if (opts.idempotencyKey) headers["Idempotency-Key"] = opts.idempotencyKey;
135
- return headers;
136
- }
137
- function isSchemaRejection(status, body) {
138
- if (status !== 400) return false;
139
- const lower = body.toLowerCase();
140
- return lower.includes("response_format") || lower.includes("json_schema") || lower.includes("is unavailable") || lower.includes("not supported");
141
- }
142
- function buildBody(req, forceJsonObject) {
143
- const body = {
144
- model: req.model,
145
- messages: req.messages,
146
- temperature: req.temperature ?? 0
147
- };
148
- if (req.maxTokens != null) {
149
- if (usesMaxCompletionTokens(req.model)) body.max_completion_tokens = req.maxTokens;
150
- else body.max_tokens = req.maxTokens;
151
- }
152
- if (req.jsonSchema && !forceJsonObject) {
153
- body.response_format = {
154
- type: "json_schema",
155
- json_schema: { name: req.jsonSchema.name, schema: req.jsonSchema.schema, strict: true }
156
- };
157
- } else if (req.jsonMode || req.jsonSchema) {
158
- body.response_format = { type: "json_object" };
159
- }
160
- return body;
161
- }
162
- function usesMaxCompletionTokens(model) {
163
- return /^gpt-5(?:[.-]|$)/i.test(model);
164
- }
165
- async function sleep(ms) {
166
- return new Promise((resolve) => setTimeout(resolve, ms));
167
- }
168
- function linkSignals(timeoutController, caller) {
169
- if (!caller) return timeoutController.signal;
170
- if (typeof AbortSignal.any === "function") {
171
- return AbortSignal.any([timeoutController.signal, caller]);
172
- }
173
- if (caller.aborted) {
174
- timeoutController.abort();
175
- } else {
176
- caller.addEventListener("abort", () => timeoutController.abort(), { once: true });
177
- }
178
- return timeoutController.signal;
179
- }
180
- function deadlineExceeded(start, deadlineMs) {
181
- return deadlineMs != null && Date.now() - start >= deadlineMs;
182
- }
183
- function stripFencedJson(raw) {
184
- const trimmed = raw.trim();
185
- const m = trimmed.match(/^```(?:json)?\s*\n?([\s\S]*?)\n?```\s*$/);
186
- return m ? m[1].trim() : trimmed;
187
- }
188
- function extractJsonPayload(raw) {
189
- const stripped = stripFencedJson(raw);
190
- try {
191
- JSON.parse(stripped);
192
- return stripped;
193
- } catch {
194
- if (stripped.startsWith("{") || stripped.startsWith("[")) return stripped;
195
- }
196
- const starts = [...stripped.matchAll(/[[{]/g)].map((match) => match.index).filter((index) => index != null);
197
- for (const start of starts) {
198
- const candidate = extractBalancedJson(stripped, start);
199
- if (!candidate) continue;
200
- try {
201
- JSON.parse(candidate);
202
- return candidate;
203
- } catch {
204
- }
205
- }
206
- return stripped;
207
- }
208
- function extractBalancedJson(input, start) {
209
- const opener = input[start];
210
- const closer = opener === "{" ? "}" : opener === "[" ? "]" : null;
211
- if (!closer) return null;
212
- const stack = [closer];
213
- let isInString = false;
214
- let isEscaped = false;
215
- for (let i = start + 1; i < input.length; i++) {
216
- const char = input[i];
217
- if (isEscaped) {
218
- isEscaped = false;
219
- continue;
220
- }
221
- if (char === "\\") {
222
- isEscaped = isInString;
223
- continue;
224
- }
225
- if (char === '"') {
226
- isInString = !isInString;
227
- continue;
228
- }
229
- if (isInString) continue;
230
- if (char === "{") stack.push("}");
231
- else if (char === "[") stack.push("]");
232
- else if (char === stack[stack.length - 1]) {
233
- stack.pop();
234
- if (stack.length === 0) return input.slice(start, i + 1);
235
- }
236
- }
237
- return null;
238
- }
239
- async function callLlm(req, opts = {}) {
240
- const baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
241
- const url = `${baseUrl}/chat/completions`;
242
- const endpoint = "/chat/completions";
243
- const timeoutMs = req.timeoutMs ?? opts.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS;
244
- const maximumAttempts = resolveMaximumAttempts(opts.maxRetries);
245
- const fetchFn = opts.fetch ?? globalThis.fetch;
246
- const headers = buildHeaders(opts);
247
- const provider = opts.provider ?? providerFromBaseUrl(baseUrl);
248
- const sink = opts.rawSink;
249
- const redactor = opts.redactor ?? defaultProviderRedactor;
250
- const traceContext = opts.traceContext;
251
- const callerSignal = opts.signal;
252
- const deadlineMs = opts.deadlineMs;
253
- const deadlineStart = Date.now();
254
- let lastErr;
255
- for (let attempt = 0; attempt < maximumAttempts; attempt++) {
256
- if (callerSignal?.aborted) {
257
- throw new DOMException("callLlm aborted by caller signal", "AbortError");
258
- }
259
- if (attempt > 0 && deadlineExceeded(deadlineStart, deadlineMs)) {
260
- throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
261
- }
262
- const controller = new AbortController();
263
- const attemptSignal = linkSignals(controller, callerSignal);
264
- const timeoutHandle = setTimeout(() => controller.abort(), timeoutMs);
265
- const started = Date.now();
266
- const requestBody = buildBody(req, false);
267
- let attemptErrorRecorded = false;
268
- if (sink) {
269
- await recordRaw(sink, redactor, {
270
- eventId: cryptoEventId(),
271
- runId: traceContext?.runId,
272
- spanId: traceContext?.spanId,
273
- provider,
274
- model: req.model,
275
- endpoint,
276
- baseUrl,
277
- attemptIndex: attempt,
278
- direction: "request",
279
- timestamp: started,
280
- requestHeaders: headers,
281
- requestBody,
282
- redactedFields: []
283
- });
284
- }
285
- try {
286
- const res = await fetchFn(url, {
287
- method: "POST",
288
- headers,
289
- body: JSON.stringify(requestBody),
290
- signal: attemptSignal
291
- });
292
- clearTimeout(timeoutHandle);
293
- const responseHeaders = sink ? headersToObject(res.headers) : void 0;
294
- if (!res.ok) {
295
- const body = await res.text();
296
- if (sink) {
297
- await recordRaw(sink, redactor, {
298
- eventId: cryptoEventId(),
299
- runId: traceContext?.runId,
300
- spanId: traceContext?.spanId,
301
- provider,
302
- model: req.model,
303
- endpoint,
304
- baseUrl,
305
- attemptIndex: attempt,
306
- direction: "error",
307
- timestamp: Date.now(),
308
- durationMs: Date.now() - started,
309
- statusCode: res.status,
310
- responseHeaders,
311
- responseBody: body,
312
- errorMessage: `HTTP ${res.status}`,
313
- redactedFields: []
314
- });
315
- attemptErrorRecorded = true;
316
- }
317
- const err = new LlmCallError(
318
- `LLM call ${res.status}: ${body.slice(0, 300)}`,
319
- res.status,
320
- body,
321
- req.model
322
- );
323
- if (RETRYABLE_STATUS.has(res.status) && attempt < maximumAttempts - 1 && !deadlineExceeded(deadlineStart, deadlineMs)) {
324
- lastErr = err;
325
- const retryAfter = parseRetryAfter(res.headers);
326
- await sleep(retryAfter ?? backoffMs(attempt));
327
- continue;
328
- }
329
- throw err;
330
- }
331
- const text = await res.text();
332
- let json;
333
- try {
334
- json = JSON.parse(text);
335
- } catch (parseErr) {
336
- if (sink) {
337
- await recordRaw(sink, redactor, {
338
- eventId: cryptoEventId(),
339
- runId: traceContext?.runId,
340
- spanId: traceContext?.spanId,
341
- provider,
342
- model: req.model,
343
- endpoint,
344
- baseUrl,
345
- attemptIndex: attempt,
346
- direction: "error",
347
- timestamp: Date.now(),
348
- durationMs: Date.now() - started,
349
- statusCode: res.status,
350
- responseHeaders,
351
- responseBody: text,
352
- errorMessage: `non-JSON response: ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`,
353
- redactedFields: []
354
- });
355
- attemptErrorRecorded = true;
356
- }
357
- throw parseErr;
358
- }
359
- if (sink) {
360
- await recordRaw(sink, redactor, {
361
- eventId: cryptoEventId(),
362
- runId: traceContext?.runId,
363
- spanId: traceContext?.spanId,
364
- provider,
365
- model: req.model,
366
- endpoint,
367
- baseUrl,
368
- attemptIndex: attempt,
369
- direction: "response",
370
- timestamp: Date.now(),
371
- durationMs: Date.now() - started,
372
- statusCode: res.status,
373
- responseHeaders,
374
- responseBody: json,
375
- redactedFields: []
376
- });
377
- }
378
- const choice = json.choices?.[0];
379
- const usageRaw = json.usage && typeof json.usage === "object" && !Array.isArray(json.usage) ? json.usage : void 0;
380
- const promptTokens = providerTokenCount(usageRaw?.prompt_tokens);
381
- const completionTokens = providerTokenCount(usageRaw?.completion_tokens);
382
- const totalTokens = providerTokenCount(usageRaw?.total_tokens);
383
- const cachedRaw = usageRaw?.prompt_tokens_details && typeof usageRaw.prompt_tokens_details === "object" && !Array.isArray(usageRaw.prompt_tokens_details) ? usageRaw.prompt_tokens_details.cached_tokens : void 0;
384
- const cachedPromptTokens = cachedRaw === void 0 ? void 0 : providerTokenCount(cachedRaw);
385
- const usageCaptured = promptTokens !== void 0 && completionTokens !== void 0 && (cachedRaw === void 0 || cachedPromptTokens !== void 0 && cachedPromptTokens <= promptTokens) && (totalTokens === void 0 || totalTokens === promptTokens + completionTokens);
386
- const costFromProxy = json._response_cost ?? json.cost_usd;
387
- const content = choice?.message?.content ?? "";
388
- return {
389
- content,
390
- finishReason: choice?.finish_reason ?? null,
391
- contentEmpty: content.trim().length === 0,
392
- usage: {
393
- promptTokens: promptTokens ?? 0,
394
- completionTokens: completionTokens ?? 0,
395
- totalTokens: totalTokens ?? (promptTokens ?? 0) + (completionTokens ?? 0),
396
- captured: usageCaptured,
397
- cachedPromptTokens
398
- },
399
- costUsd: typeof costFromProxy === "number" ? costFromProxy : null,
400
- model: json.model ?? req.model,
401
- durationMs: Date.now() - started,
402
- raw: json
403
- };
404
- } catch (err) {
405
- clearTimeout(timeoutHandle);
406
- lastErr = err;
407
- if (callerSignal?.aborted) {
408
- if (sink && !attemptErrorRecorded) {
409
- await recordRaw(sink, redactor, {
410
- eventId: cryptoEventId(),
411
- runId: traceContext?.runId,
412
- spanId: traceContext?.spanId,
413
- provider,
414
- model: req.model,
415
- endpoint,
416
- baseUrl,
417
- attemptIndex: attempt,
418
- direction: "error",
419
- timestamp: Date.now(),
420
- durationMs: Date.now() - started,
421
- errorMessage: err instanceof Error ? err.message : String(err),
422
- redactedFields: []
423
- });
424
- }
425
- throw err;
426
- }
427
- if (sink && !attemptErrorRecorded) {
428
- await recordRaw(sink, redactor, {
429
- eventId: cryptoEventId(),
430
- runId: traceContext?.runId,
431
- spanId: traceContext?.spanId,
432
- provider,
433
- model: req.model,
434
- endpoint,
435
- baseUrl,
436
- attemptIndex: attempt,
437
- direction: "error",
438
- timestamp: Date.now(),
439
- durationMs: Date.now() - started,
440
- errorMessage: err instanceof Error ? err.message : String(err),
441
- redactedFields: []
442
- });
443
- }
444
- if (attempt < maximumAttempts - 1 && isTransientLlmError(err) && !deadlineExceeded(deadlineStart, deadlineMs)) {
445
- await sleep(backoffMs(attempt));
446
- continue;
447
- }
448
- throw err;
449
- }
450
- }
451
- throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
452
- }
453
- async function recordRaw(sink, redactor, event) {
454
- try {
455
- await sink.record(redactor(event));
456
- } catch {
457
- }
458
- }
459
- function headersToObject(h) {
460
- const out = {};
461
- h.forEach((value, key) => {
462
- out[key] = value;
463
- });
464
- return out;
465
- }
466
- function cryptoEventId() {
467
- if (typeof globalThis.crypto?.randomUUID === "function") return globalThis.crypto.randomUUID();
468
- return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
469
- }
470
- async function callLlmJson(req, opts = {}) {
471
- const result = await callLlmStructured(req, opts);
472
- const value = parseJsonResult(result);
473
- return { value, result };
474
- }
475
- async function callLlmStructured(req, opts = {}) {
476
- try {
477
- return await callLlm({ ...req, jsonMode: req.jsonMode ?? !req.jsonSchema }, opts);
478
- } catch (err) {
479
- if (err instanceof LlmCallError && isSchemaRejection(err.status, err.body) && req.jsonSchema) {
480
- const degradedReq = { ...req, jsonMode: true, jsonSchema: void 0 };
481
- return await callLlm(degradedReq, opts);
482
- }
483
- throw err;
484
- }
485
- }
486
- function parseJsonResult(result) {
487
- try {
488
- if (result.finishReason === "length") {
489
- throw new Error(
490
- `LLM returned truncated JSON content (model=${result.model}, finishReason=length)`
491
- );
492
- }
493
- return parseJsonSafely(result.content, result.model);
494
- } catch (error) {
495
- if (error instanceof LlmResponseError) throw error;
496
- const cause = error instanceof Error ? error : new Error(String(error));
497
- throw new LlmResponseError(cause.message, result, { cause });
498
- }
499
- }
500
- function parseJsonSafely(content, model) {
501
- const stripped = extractJsonPayload(content);
502
- try {
503
- return JSON.parse(stripped);
504
- } catch (err) {
505
- throw new Error(
506
- `LLM returned non-JSON content (model=${model}): ${err instanceof Error ? err.message : String(err)}
507
- --- raw content ---
508
- ${content.slice(0, 800)}`
509
- );
510
- }
511
- }
512
- var LlmRouteAssertionError = class extends CaptureIntegrityError {
513
- constructor(message, reason, baseUrl) {
514
- super(message);
515
- this.reason = reason;
516
- this.baseUrl = baseUrl;
517
- }
518
- reason;
519
- baseUrl;
520
- };
521
- function assertLlmRoute(opts, req = {}) {
522
- const baseUrlExplicit = opts.baseUrl !== void 0;
523
- const baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
524
- if (req.requireExplicitBaseUrl && !baseUrlExplicit) {
525
- throw new LlmRouteAssertionError(
526
- `assertLlmRoute: requireExplicitBaseUrl set but opts.baseUrl is undefined; would fall back to ${DEFAULT_BASE_URL}.`,
527
- "no_explicit_base_url",
528
- baseUrl
529
- );
530
- }
531
- if (req.blockedBaseUrls?.some((p) => matchUrl(baseUrl, p))) {
532
- throw new LlmRouteAssertionError(
533
- `assertLlmRoute: baseUrl ${baseUrl} matches a blocked pattern.`,
534
- "base_url_blocked",
535
- baseUrl
536
- );
537
- }
538
- if (req.allowedBaseUrls && req.allowedBaseUrls.length > 0) {
539
- const ok = req.allowedBaseUrls.some((p) => matchUrl(baseUrl, p));
540
- if (!ok) {
541
- throw new LlmRouteAssertionError(
542
- `assertLlmRoute: baseUrl ${baseUrl} is not in the allowed list (${req.allowedBaseUrls.map(describePattern).join(", ")}).`,
543
- "base_url_not_allowed",
544
- baseUrl
545
- );
546
- }
547
- }
548
- if (req.requireAuth && !opts.apiKey && !opts.bearer && !opts.authHeader) {
549
- throw new LlmRouteAssertionError(
550
- `assertLlmRoute: requireAuth set but no apiKey, bearer, or authHeader was supplied.`,
551
- "no_auth",
552
- baseUrl
553
- );
554
- }
555
- if (req.expectedProvider) {
556
- const actual = opts.provider ?? providerFromBaseUrl(baseUrl);
557
- if (actual !== req.expectedProvider) {
558
- throw new LlmRouteAssertionError(
559
- `assertLlmRoute: expected provider ${req.expectedProvider} but baseUrl ${baseUrl} resolves to ${actual}.`,
560
- "wrong_provider",
561
- baseUrl
562
- );
563
- }
564
- }
565
- }
566
- function matchUrl(url, pattern) {
567
- if (pattern instanceof RegExp) return pattern.test(url);
568
- return url.toLowerCase().startsWith(pattern.toLowerCase());
569
- }
570
- function describePattern(p) {
571
- return p instanceof RegExp ? p.source : p;
572
- }
573
- async function probeLlm(model, opts = {}) {
574
- const start = Date.now();
575
- try {
576
- await callLlm(
577
- {
578
- model,
579
- messages: [{ role: "user", content: "ping" }],
580
- maxTokens: 64,
581
- timeoutMs: opts.timeoutMs ?? 3e4
582
- },
583
- opts
584
- );
585
- return { ok: true, latencyMs: Date.now() - start, error: null };
586
- } catch (err) {
587
- return {
588
- ok: false,
589
- latencyMs: Date.now() - start,
590
- error: err instanceof Error ? err.message : String(err)
591
- };
592
- }
593
- }
594
- var LlmClient = class {
595
- maximumAttempts;
596
- opts;
597
- constructor(opts = {}) {
598
- this.opts = opts;
599
- this.maximumAttempts = resolveMaximumAttempts(opts.maxRetries);
600
- }
601
- call(req, per) {
602
- const options = { ...this.opts, ...per };
603
- return req.jsonSchema ? callLlmStructured(req, options) : callLlm(req, options);
604
- }
605
- callJson(req, per) {
606
- return callLlmJson(req, { ...this.opts, ...per });
607
- }
608
- };
609
-
610
- export {
611
- maximumChargeForLlmRequest,
612
- costReceiptFromLlm,
613
- costReceiptFromLlmError,
614
- LlmCallError,
615
- LlmResponseError,
616
- isTransientLlmError,
617
- backoffMs,
618
- stripFencedJson,
619
- callLlm,
620
- callLlmJson,
621
- LlmRouteAssertionError,
622
- assertLlmRoute,
623
- probeLlm,
624
- LlmClient
625
- };
626
- //# sourceMappingURL=chunk-NJC7U437.js.map