braintrust 3.32.0 → 3.33.0
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/README.md +0 -43
- package/dev/dist/index.d.mts +31 -0
- package/dev/dist/index.d.ts +31 -0
- package/dev/dist/index.js +2275 -920
- package/dev/dist/index.mjs +1610 -255
- package/dist/apply-auto-instrumentation.js +263 -224
- package/dist/apply-auto-instrumentation.mjs +45 -6
- package/dist/auto-instrumentations/bundler/esbuild.cjs +78 -5
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +78 -5
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +78 -5
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +78 -5
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +78 -5
- package/dist/auto-instrumentations/bundler/webpack.cjs +78 -5
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-AFND2U7E.mjs → chunk-T2DMPWFI.mjs} +75 -5
- package/dist/auto-instrumentations/{chunk-RI4Y55ZF.mjs → chunk-UHJ2DNYJ.mjs} +6 -1
- package/dist/auto-instrumentations/{chunk-QEEPRBIS.mjs → chunk-W5QNG3PV.mjs} +1 -1
- package/dist/auto-instrumentations/hook.mjs +86 -7
- package/dist/auto-instrumentations/index.cjs +76 -5
- package/dist/auto-instrumentations/index.d.mts +3 -1
- package/dist/auto-instrumentations/index.d.ts +3 -1
- package/dist/auto-instrumentations/index.mjs +3 -1
- package/dist/browser.d.mts +202 -342
- package/dist/browser.d.ts +202 -342
- package/dist/browser.js +2586 -623
- package/dist/browser.mjs +2586 -623
- package/dist/chunk-7P6ASYW6.mjs +9 -0
- package/dist/{chunk-BTRLPQG5.js → chunk-AXJTOUOC.js} +2250 -1172
- package/dist/{chunk-AW4QECG5.js → chunk-G3VHOHRC.js} +40 -9
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/{chunk-4QSAHP7D.mjs → chunk-MZLBAFVJ.mjs} +1236 -158
- package/dist/{chunk-WV6QZI2W.mjs → chunk-TZVZN2JJ.mjs} +39 -8
- package/dist/cli.js +1695 -293
- package/dist/custom-views.d.mts +112 -0
- package/dist/custom-views.d.ts +112 -0
- package/dist/custom-views.js +13 -0
- package/dist/custom-views.mjs +13 -0
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2586 -623
- package/dist/edge-light.mjs +2586 -623
- package/dist/index.d.mts +202 -342
- package/dist/index.d.ts +202 -342
- package/dist/index.js +1842 -986
- package/dist/index.mjs +1310 -454
- package/dist/instrumentation/index.d.mts +5 -245
- package/dist/instrumentation/index.d.ts +5 -245
- package/dist/instrumentation/index.js +1694 -254
- package/dist/instrumentation/index.mjs +1694 -254
- package/dist/vitest-evals-reporter.js +17 -16
- package/dist/vitest-evals-reporter.mjs +3 -2
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2586 -623
- package/dist/workerd.mjs +2586 -623
- package/package.json +10 -2
package/dist/index.mjs
CHANGED
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
UUIDGenerator,
|
|
55
55
|
X_CACHED_HEADER,
|
|
56
56
|
_exportsForTestingOnly,
|
|
57
|
+
_internalExportParentSynchronously,
|
|
57
58
|
_internalGetGlobalState,
|
|
58
59
|
_internalResumeSpan,
|
|
59
60
|
_internalSetInitialState,
|
|
@@ -117,6 +118,7 @@ import {
|
|
|
117
118
|
renderMessage,
|
|
118
119
|
renderPromptParams,
|
|
119
120
|
renderTemplateContent,
|
|
121
|
+
resolveUseLegacyUuidIds,
|
|
120
122
|
runWithAutoInstrumentationSuppressed,
|
|
121
123
|
setFetch,
|
|
122
124
|
setMaskingFunction,
|
|
@@ -143,10 +145,9 @@ import {
|
|
|
143
145
|
wrapMastraAgent,
|
|
144
146
|
wrapTraced,
|
|
145
147
|
zodToJsonSchema
|
|
146
|
-
} from "./chunk-
|
|
148
|
+
} from "./chunk-MZLBAFVJ.mjs";
|
|
147
149
|
import {
|
|
148
150
|
INSTRUMENTATION_NAMES,
|
|
149
|
-
__export,
|
|
150
151
|
aiSDKChannels,
|
|
151
152
|
anthropicChannels,
|
|
152
153
|
bedrockRuntimeChannels,
|
|
@@ -168,6 +169,7 @@ import {
|
|
|
168
169
|
huggingFaceTransformersChannels,
|
|
169
170
|
isSupportedHuggingFaceTransformersTask,
|
|
170
171
|
isomorph_default,
|
|
172
|
+
langGraphSDKChannels,
|
|
171
173
|
langSmithChannels,
|
|
172
174
|
mistralChannels,
|
|
173
175
|
ollamaChannels,
|
|
@@ -179,7 +181,10 @@ import {
|
|
|
179
181
|
strandsAgentSDKChannels,
|
|
180
182
|
voyageAIChannels,
|
|
181
183
|
withSpanInstrumentationName
|
|
182
|
-
} from "./chunk-
|
|
184
|
+
} from "./chunk-TZVZN2JJ.mjs";
|
|
185
|
+
import {
|
|
186
|
+
__export
|
|
187
|
+
} from "./chunk-7P6ASYW6.mjs";
|
|
183
188
|
|
|
184
189
|
// src/exports.ts
|
|
185
190
|
var exports_exports = {};
|
|
@@ -192,8 +197,6 @@ __export(exports_exports, {
|
|
|
192
197
|
BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
|
|
193
198
|
BaseAttachment: () => BaseAttachment,
|
|
194
199
|
BaseExperiment: () => BaseExperiment,
|
|
195
|
-
BatchScorer: () => BatchScorer,
|
|
196
|
-
BatchTask: () => BatchTask,
|
|
197
200
|
BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
|
|
198
201
|
BraintrustMiddleware: () => BraintrustMiddleware,
|
|
199
202
|
BraintrustObservabilityExporter: () => BraintrustObservabilityExporter,
|
|
@@ -207,8 +210,6 @@ __export(exports_exports, {
|
|
|
207
210
|
DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
|
|
208
211
|
Dataset: () => Dataset,
|
|
209
212
|
DatasetPipeline: () => DatasetPipeline,
|
|
210
|
-
DurableEvalMemoryStore: () => DurableEvalMemoryStore,
|
|
211
|
-
DurableEvalRedisStore: () => DurableEvalRedisStore,
|
|
212
213
|
ERR_PERMALINK: () => ERR_PERMALINK,
|
|
213
214
|
Eval: () => Eval,
|
|
214
215
|
EvalResultWithSummary: () => EvalResultWithSummary,
|
|
@@ -243,6 +244,10 @@ __export(exports_exports, {
|
|
|
243
244
|
TestBackgroundLogger: () => TestBackgroundLogger,
|
|
244
245
|
ToolBuilder: () => ToolBuilder,
|
|
245
246
|
UUIDGenerator: () => UUIDGenerator,
|
|
247
|
+
WorkflowEvalMemoryStore: () => WorkflowEvalMemoryStore,
|
|
248
|
+
WorkflowEvalRedisStore: () => WorkflowEvalRedisStore,
|
|
249
|
+
WorkflowScorer: () => WorkflowScorer,
|
|
250
|
+
WorkflowTask: () => WorkflowTask,
|
|
246
251
|
X_CACHED_HEADER: () => X_CACHED_HEADER,
|
|
247
252
|
_exportsForTestingOnly: () => _exportsForTestingOnly,
|
|
248
253
|
_internalGetGlobalState: () => _internalGetGlobalState,
|
|
@@ -267,12 +272,13 @@ __export(exports_exports, {
|
|
|
267
272
|
currentSpan: () => currentSpan,
|
|
268
273
|
deepCopyEvent: () => deepCopyEvent,
|
|
269
274
|
defaultErrorScoreHandler: () => defaultErrorScoreHandler,
|
|
270
|
-
|
|
275
|
+
defineWorkflowEval: () => defineWorkflowEval,
|
|
271
276
|
deserializePlainStringAsJSON: () => deserializePlainStringAsJSON,
|
|
272
277
|
devNullWritableStream: () => devNullWritableStream,
|
|
273
278
|
evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
|
|
274
279
|
evaluatorDefinitionsSchema: () => evaluatorDefinitionsSchema,
|
|
275
280
|
extractTraceContextFromHeaders: () => extractTraceContextFromHeaders,
|
|
281
|
+
failOpenAIAgentsTrace: () => failOpenAIAgentsTrace,
|
|
276
282
|
flush: () => flush,
|
|
277
283
|
getContextManager: () => getContextManager,
|
|
278
284
|
getIdGenerator: () => getIdGenerator,
|
|
@@ -319,12 +325,14 @@ __export(exports_exports, {
|
|
|
319
325
|
setFetch: () => setFetch,
|
|
320
326
|
setMaskingFunction: () => setMaskingFunction,
|
|
321
327
|
spanComponentsToObjectId: () => spanComponentsToObjectId,
|
|
328
|
+
startOpenAIAgentsTrace: () => startOpenAIAgentsTrace,
|
|
322
329
|
startSpan: () => startSpan,
|
|
323
330
|
summarize: () => summarize,
|
|
324
331
|
templateRegistry: () => templateRegistry,
|
|
325
332
|
toolFunctionDefinitionSchema: () => ToolFunctionDefinition,
|
|
326
333
|
traceable: () => traceable,
|
|
327
334
|
traced: () => traced,
|
|
335
|
+
updateOpenAIAgentsTrace: () => updateOpenAIAgentsTrace,
|
|
328
336
|
updateSpan: () => updateSpan,
|
|
329
337
|
uploadLogs3OverflowPayload: () => uploadLogs3OverflowPayload,
|
|
330
338
|
utf8ByteLength: () => utf8ByteLength,
|
|
@@ -353,6 +361,7 @@ __export(exports_exports, {
|
|
|
353
361
|
wrapGroq: () => wrapGroq,
|
|
354
362
|
wrapHuggingFace: () => wrapHuggingFace,
|
|
355
363
|
wrapHuggingFaceTransformers: () => wrapHuggingFaceTransformers,
|
|
364
|
+
wrapLangGraphSDK: () => wrapLangGraphSDK,
|
|
356
365
|
wrapLangSmithClient: () => wrapLangSmithClient,
|
|
357
366
|
wrapLangSmithRunTrees: () => wrapLangSmithRunTrees,
|
|
358
367
|
wrapLangSmithTraceable: () => wrapLangSmithTraceable,
|
|
@@ -719,6 +728,143 @@ async function completeOpenAIBatchTrace(args) {
|
|
|
719
728
|
);
|
|
720
729
|
}
|
|
721
730
|
|
|
731
|
+
// src/openai-agents-api.ts
|
|
732
|
+
function isRecord(value) {
|
|
733
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
734
|
+
}
|
|
735
|
+
function validateStartArgs(value) {
|
|
736
|
+
if (!isRecord(value)) {
|
|
737
|
+
throw new TypeError(
|
|
738
|
+
"startOpenAIAgentsTrace expected an OpenAI Agents parameters object"
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
const agent = value.agent;
|
|
742
|
+
if (agent !== void 0 && agent !== null && !isRecord(agent)) {
|
|
743
|
+
throw new TypeError(
|
|
744
|
+
"startOpenAIAgentsTrace expected agent to be an object or null"
|
|
745
|
+
);
|
|
746
|
+
}
|
|
747
|
+
if (isRecord(agent) && (agent.id !== void 0 && typeof agent.id !== "string" || agent.model !== void 0 && typeof agent.model !== "string" || agent.name !== void 0 && agent.name !== null && typeof agent.name !== "string")) {
|
|
748
|
+
throw new TypeError(
|
|
749
|
+
"startOpenAIAgentsTrace received invalid agent identity fields"
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
if (value.agent_id !== void 0 && typeof value.agent_id !== "string") {
|
|
753
|
+
throw new TypeError(
|
|
754
|
+
"startOpenAIAgentsTrace expected agent_id to be a string"
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
if (value.metadata !== void 0 && value.metadata !== null && !isRecord(value.metadata)) {
|
|
758
|
+
throw new TypeError(
|
|
759
|
+
"startOpenAIAgentsTrace expected metadata to be an object or null"
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
return value;
|
|
763
|
+
}
|
|
764
|
+
function validateEvent(event) {
|
|
765
|
+
if (!isRecord(event) || typeof event.type !== "string" || event.type.length === 0) {
|
|
766
|
+
throw new TypeError(
|
|
767
|
+
"updateOpenAIAgentsTrace expected an OpenAI Agents event object"
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
return event;
|
|
771
|
+
}
|
|
772
|
+
function createTraceState() {
|
|
773
|
+
const parent = _internalExportParentSynchronously(getSpanParentObject());
|
|
774
|
+
if (!parent) {
|
|
775
|
+
return null;
|
|
776
|
+
}
|
|
777
|
+
const parentComponents = SpanComponentsV4.fromStr(parent);
|
|
778
|
+
const rowId = newId();
|
|
779
|
+
const useLegacyIds = resolveUseLegacyUuidIds();
|
|
780
|
+
const spanId = useLegacyIds ? newId() : newId().replaceAll("-", "").slice(0, 16);
|
|
781
|
+
const rootSpanId = useLegacyIds ? spanId : newId().replaceAll("-", "");
|
|
782
|
+
const root = new SpanComponentsV4({
|
|
783
|
+
object_type: parentComponents.data.object_type,
|
|
784
|
+
...parentComponents.data.object_id ? { object_id: parentComponents.data.object_id } : {
|
|
785
|
+
compute_object_metadata_args: parentComponents.data.compute_object_metadata_args ?? {}
|
|
786
|
+
},
|
|
787
|
+
propagated_event: parentComponents.data.propagated_event,
|
|
788
|
+
root_span_id: rootSpanId,
|
|
789
|
+
row_id: rowId,
|
|
790
|
+
span_id: spanId
|
|
791
|
+
}).toStr();
|
|
792
|
+
return {
|
|
793
|
+
callItems: {},
|
|
794
|
+
ended: false,
|
|
795
|
+
eventIds: [],
|
|
796
|
+
openTools: {},
|
|
797
|
+
root,
|
|
798
|
+
rootKey: spanId,
|
|
799
|
+
rootParent: parent,
|
|
800
|
+
startTime: getCurrentUnixTimestamp(),
|
|
801
|
+
subagents: {},
|
|
802
|
+
turnSubagents: {},
|
|
803
|
+
version: 1
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
function startOpenAIAgentsTrace(args) {
|
|
807
|
+
const validatedArgs = validateStartArgs(args);
|
|
808
|
+
const state = createTraceState();
|
|
809
|
+
if (!state) {
|
|
810
|
+
return null;
|
|
811
|
+
}
|
|
812
|
+
try {
|
|
813
|
+
void openAIChannels.agentsTraceStart.invoke(
|
|
814
|
+
async () => state,
|
|
815
|
+
void 0,
|
|
816
|
+
[{ args: validatedArgs, state }],
|
|
817
|
+
{}
|
|
818
|
+
).catch((error) => {
|
|
819
|
+
debugLogger.debug(
|
|
820
|
+
"OpenAI Agents API instrumentation could not start:",
|
|
821
|
+
error
|
|
822
|
+
);
|
|
823
|
+
});
|
|
824
|
+
} catch (error) {
|
|
825
|
+
debugLogger.debug(
|
|
826
|
+
"OpenAI Agents API instrumentation could not start:",
|
|
827
|
+
error
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
return state;
|
|
831
|
+
}
|
|
832
|
+
async function updateOpenAIAgentsTrace(token, event) {
|
|
833
|
+
const state = token;
|
|
834
|
+
const validatedEvent = validateEvent(event);
|
|
835
|
+
try {
|
|
836
|
+
return await openAIChannels.agentsTraceCapture.invoke(
|
|
837
|
+
async () => state,
|
|
838
|
+
void 0,
|
|
839
|
+
[{ state, event: validatedEvent }],
|
|
840
|
+
{}
|
|
841
|
+
);
|
|
842
|
+
} catch (error) {
|
|
843
|
+
debugLogger.debug(
|
|
844
|
+
"OpenAI Agents API instrumentation could not update:",
|
|
845
|
+
error
|
|
846
|
+
);
|
|
847
|
+
return token;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
async function failOpenAIAgentsTrace(token, error) {
|
|
851
|
+
const state = token;
|
|
852
|
+
try {
|
|
853
|
+
return await openAIChannels.agentsTraceFail.invoke(
|
|
854
|
+
async () => state,
|
|
855
|
+
void 0,
|
|
856
|
+
[{ state, error }],
|
|
857
|
+
{}
|
|
858
|
+
);
|
|
859
|
+
} catch (instrumentationError) {
|
|
860
|
+
debugLogger.debug(
|
|
861
|
+
"OpenAI Agents API instrumentation could not record failure:",
|
|
862
|
+
instrumentationError
|
|
863
|
+
);
|
|
864
|
+
return token;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
722
868
|
// src/functions/invoke.ts
|
|
723
869
|
async function invoke(args) {
|
|
724
870
|
const {
|
|
@@ -2168,7 +2314,31 @@ var MAX_STORED_LLM_INPUTS = 100;
|
|
|
2168
2314
|
var MAX_STORED_REASONING_BLOCKS = 100;
|
|
2169
2315
|
var MAX_STORED_SPAN_REFERENCES = 1e4;
|
|
2170
2316
|
var MAX_STORED_STEP_STARTS = 1e4;
|
|
2317
|
+
var EVE_HANDLED_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
2318
|
+
"action.result",
|
|
2319
|
+
"actions.requested",
|
|
2320
|
+
"message.completed",
|
|
2321
|
+
"message.received",
|
|
2322
|
+
"reasoning.completed",
|
|
2323
|
+
"result.completed",
|
|
2324
|
+
"session.completed",
|
|
2325
|
+
"session.failed",
|
|
2326
|
+
"session.started",
|
|
2327
|
+
"step.completed",
|
|
2328
|
+
"step.failed",
|
|
2329
|
+
"step.started",
|
|
2330
|
+
"subagent.called",
|
|
2331
|
+
"subagent.completed",
|
|
2332
|
+
"turn.completed",
|
|
2333
|
+
"turn.failed",
|
|
2334
|
+
"turn.started"
|
|
2335
|
+
]);
|
|
2171
2336
|
function braintrustEveHook(options) {
|
|
2337
|
+
if (!options || typeof options.defineState !== "function") {
|
|
2338
|
+
throw new TypeError(
|
|
2339
|
+
"braintrustEveHook requires Eve's defineState function"
|
|
2340
|
+
);
|
|
2341
|
+
}
|
|
2172
2342
|
const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
|
|
2173
2343
|
const bridge = new EveBridge(state);
|
|
2174
2344
|
return {
|
|
@@ -2180,15 +2350,27 @@ function braintrustEveHook(options) {
|
|
|
2180
2350
|
};
|
|
2181
2351
|
}
|
|
2182
2352
|
function createLegacyEveInstrumentation(options) {
|
|
2353
|
+
if (!options || typeof options.defineState !== "function") {
|
|
2354
|
+
throw new TypeError(
|
|
2355
|
+
"braintrustEveInstrumentation requires Eve's defineState function"
|
|
2356
|
+
);
|
|
2357
|
+
}
|
|
2183
2358
|
const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
|
|
2184
2359
|
return {
|
|
2185
2360
|
events: {
|
|
2186
2361
|
"step.started": (input) => {
|
|
2187
2362
|
try {
|
|
2363
|
+
if (!isEveInstrumentationStepStartedEventInput(input)) {
|
|
2364
|
+
debugLogger.warn(
|
|
2365
|
+
"Ignoring malformed Eve instrumentation step.started event"
|
|
2366
|
+
);
|
|
2367
|
+
return void 0;
|
|
2368
|
+
}
|
|
2188
2369
|
captureEveModelInput(state, input);
|
|
2189
2370
|
} catch (error) {
|
|
2190
2371
|
debugLogger.warn("Error in Eve LLM input capture:", error);
|
|
2191
2372
|
}
|
|
2373
|
+
return void 0;
|
|
2192
2374
|
}
|
|
2193
2375
|
},
|
|
2194
2376
|
recordInputs: false,
|
|
@@ -2197,7 +2379,77 @@ function createLegacyEveInstrumentation(options) {
|
|
|
2197
2379
|
};
|
|
2198
2380
|
}
|
|
2199
2381
|
function isEveHandleMessageStreamEvent(event) {
|
|
2200
|
-
|
|
2382
|
+
if (!isObject(event) || typeof event["type"] !== "string") {
|
|
2383
|
+
return false;
|
|
2384
|
+
}
|
|
2385
|
+
const type = event["type"];
|
|
2386
|
+
if (type === "session.completed") {
|
|
2387
|
+
return true;
|
|
2388
|
+
}
|
|
2389
|
+
if (!isObject(event["data"])) {
|
|
2390
|
+
return false;
|
|
2391
|
+
}
|
|
2392
|
+
const data = event["data"];
|
|
2393
|
+
if (type === "session.started") {
|
|
2394
|
+
return true;
|
|
2395
|
+
}
|
|
2396
|
+
if (type === "session.failed") {
|
|
2397
|
+
return typeof data["sessionId"] === "string" && typeof data["code"] === "string" && typeof data["message"] === "string";
|
|
2398
|
+
}
|
|
2399
|
+
if (type === "session.waiting") {
|
|
2400
|
+
return data["wait"] === "next-user-message";
|
|
2401
|
+
}
|
|
2402
|
+
if (typeof data["turnId"] !== "string" || typeof data["sequence"] !== "number" || !Number.isFinite(data["sequence"])) {
|
|
2403
|
+
return false;
|
|
2404
|
+
}
|
|
2405
|
+
if (type === "turn.started" || type === "turn.completed" || type === "subagent.called" || type === "subagent.completed") {
|
|
2406
|
+
if (type === "subagent.called") {
|
|
2407
|
+
return typeof data["callId"] === "string" && typeof data["childSessionId"] === "string" && typeof data["name"] === "string";
|
|
2408
|
+
}
|
|
2409
|
+
if (type === "subagent.completed") {
|
|
2410
|
+
return typeof data["callId"] === "string" && typeof data["subagentName"] === "string";
|
|
2411
|
+
}
|
|
2412
|
+
return true;
|
|
2413
|
+
}
|
|
2414
|
+
if (type === "turn.failed") {
|
|
2415
|
+
return typeof data["code"] === "string" && typeof data["message"] === "string";
|
|
2416
|
+
}
|
|
2417
|
+
if (type === "message.received") {
|
|
2418
|
+
return typeof data["message"] === "string";
|
|
2419
|
+
}
|
|
2420
|
+
if (typeof data["stepIndex"] !== "number" || !Number.isFinite(data["stepIndex"]) || data["stepIndex"] < 0) {
|
|
2421
|
+
return false;
|
|
2422
|
+
}
|
|
2423
|
+
switch (type) {
|
|
2424
|
+
case "step.started":
|
|
2425
|
+
return true;
|
|
2426
|
+
case "message.completed":
|
|
2427
|
+
return typeof data["finishReason"] === "string" && (typeof data["message"] === "string" || data["message"] === null);
|
|
2428
|
+
case "reasoning.completed":
|
|
2429
|
+
return typeof data["reasoning"] === "string";
|
|
2430
|
+
case "result.completed":
|
|
2431
|
+
return true;
|
|
2432
|
+
case "step.completed":
|
|
2433
|
+
return typeof data["finishReason"] === "string";
|
|
2434
|
+
case "step.failed":
|
|
2435
|
+
return typeof data["code"] === "string" && typeof data["message"] === "string";
|
|
2436
|
+
case "actions.requested":
|
|
2437
|
+
return Array.isArray(data["actions"]);
|
|
2438
|
+
case "action.result":
|
|
2439
|
+
return isObject(data["result"]) && (data["status"] === "completed" || data["status"] === "failed" || data["status"] === "rejected");
|
|
2440
|
+
default:
|
|
2441
|
+
return false;
|
|
2442
|
+
}
|
|
2443
|
+
}
|
|
2444
|
+
function isEveInstrumentationStepStartedEventInput(input) {
|
|
2445
|
+
if (!isObject(input)) {
|
|
2446
|
+
return false;
|
|
2447
|
+
}
|
|
2448
|
+
const modelInput = input["modelInput"];
|
|
2449
|
+
const session = input["session"];
|
|
2450
|
+
const step = input["step"];
|
|
2451
|
+
const turn = input["turn"];
|
|
2452
|
+
return isObject(modelInput) && Array.isArray(modelInput["messages"]) && isObject(session) && typeof session["id"] === "string" && isObject(step) && typeof step["index"] === "number" && Number.isFinite(step["index"]) && step["index"] >= 0 && isObject(turn) && typeof turn["id"] === "string" && typeof turn["sequence"] === "number" && Number.isFinite(turn["sequence"]);
|
|
2201
2453
|
}
|
|
2202
2454
|
var ResumedEveSpan = class {
|
|
2203
2455
|
constructor(reference) {
|
|
@@ -2366,7 +2618,17 @@ var EveBridge = class {
|
|
|
2366
2618
|
});
|
|
2367
2619
|
}
|
|
2368
2620
|
async handle(event, ctx, hookMetadata) {
|
|
2621
|
+
try {
|
|
2622
|
+
await this.handleUnchecked(event, ctx, hookMetadata);
|
|
2623
|
+
} catch (error) {
|
|
2624
|
+
debugLogger.warn("Error in Eve hook instrumentation:", error);
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
async handleUnchecked(event, ctx, hookMetadata) {
|
|
2369
2628
|
if (!isEveHandleMessageStreamEvent(event)) {
|
|
2629
|
+
if (isObject(event) && typeof event["type"] === "string" && EVE_HANDLED_EVENT_TYPES.has(event["type"])) {
|
|
2630
|
+
debugLogger.warn(`Ignoring malformed Eve hook ${event["type"]} event`);
|
|
2631
|
+
}
|
|
2370
2632
|
return;
|
|
2371
2633
|
}
|
|
2372
2634
|
const run = async () => {
|
|
@@ -2692,9 +2954,14 @@ var EveBridge = class {
|
|
|
2692
2954
|
}
|
|
2693
2955
|
for (const action of traceActions) {
|
|
2694
2956
|
const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
|
|
2957
|
+
let args = "null";
|
|
2958
|
+
try {
|
|
2959
|
+
args = JSON.stringify(action.input) ?? "null";
|
|
2960
|
+
} catch {
|
|
2961
|
+
}
|
|
2695
2962
|
toolCallsById.set(action.callId, {
|
|
2696
2963
|
function: {
|
|
2697
|
-
arguments:
|
|
2964
|
+
arguments: args,
|
|
2698
2965
|
name
|
|
2699
2966
|
},
|
|
2700
2967
|
id: action.callId,
|
|
@@ -3563,17 +3830,33 @@ function consumeCapturedEveModelInput(state, sessionId, turnId, stepIndex) {
|
|
|
3563
3830
|
}
|
|
3564
3831
|
}
|
|
3565
3832
|
function capturedModelInput(modelInput) {
|
|
3566
|
-
const { instructions, messages } = modelInput;
|
|
3567
|
-
const value = [];
|
|
3568
|
-
if (typeof instructions === "string") {
|
|
3569
|
-
value.push({ content: instructions, role: "system" });
|
|
3570
|
-
} else if (Array.isArray(instructions)) {
|
|
3571
|
-
value.push(...instructions.map(capturedEveModelMessage));
|
|
3572
|
-
} else if (instructions) {
|
|
3573
|
-
value.push(capturedEveModelMessage(instructions));
|
|
3574
|
-
}
|
|
3575
|
-
value.push(...messages.map(capturedEveModelMessage));
|
|
3576
3833
|
try {
|
|
3834
|
+
if (!isObject(modelInput) || !Array.isArray(modelInput["messages"])) {
|
|
3835
|
+
return void 0;
|
|
3836
|
+
}
|
|
3837
|
+
const value = [];
|
|
3838
|
+
const instructions = modelInput["instructions"];
|
|
3839
|
+
if (typeof instructions === "string") {
|
|
3840
|
+
value.push({ content: instructions, role: "system" });
|
|
3841
|
+
} else if (Array.isArray(instructions)) {
|
|
3842
|
+
for (const instruction of instructions) {
|
|
3843
|
+
const captured = capturedEveModelMessage(instruction);
|
|
3844
|
+
if (captured?.role === "system") {
|
|
3845
|
+
value.push(captured);
|
|
3846
|
+
}
|
|
3847
|
+
}
|
|
3848
|
+
} else {
|
|
3849
|
+
const captured = capturedEveModelMessage(instructions);
|
|
3850
|
+
if (captured?.role === "system") {
|
|
3851
|
+
value.push(captured);
|
|
3852
|
+
}
|
|
3853
|
+
}
|
|
3854
|
+
for (const message of modelInput["messages"]) {
|
|
3855
|
+
const captured = capturedEveModelMessage(message);
|
|
3856
|
+
if (captured) {
|
|
3857
|
+
value.push(captured);
|
|
3858
|
+
}
|
|
3859
|
+
}
|
|
3577
3860
|
const cloned = JSON.parse(JSON.stringify(value));
|
|
3578
3861
|
if (!Array.isArray(cloned)) {
|
|
3579
3862
|
return void 0;
|
|
@@ -3584,116 +3867,202 @@ function capturedModelInput(modelInput) {
|
|
|
3584
3867
|
}
|
|
3585
3868
|
}
|
|
3586
3869
|
function capturedEveModelMessage(message) {
|
|
3587
|
-
|
|
3870
|
+
if (!isObject(message)) {
|
|
3871
|
+
return void 0;
|
|
3872
|
+
}
|
|
3873
|
+
const role = message["role"];
|
|
3874
|
+
if (role !== "system" && role !== "user" && role !== "assistant" && role !== "tool") {
|
|
3875
|
+
return void 0;
|
|
3876
|
+
}
|
|
3877
|
+
const content = message["content"];
|
|
3588
3878
|
if (typeof content === "string") {
|
|
3589
3879
|
return { content, role };
|
|
3590
3880
|
}
|
|
3591
|
-
|
|
3881
|
+
if (!Array.isArray(content)) {
|
|
3882
|
+
return void 0;
|
|
3883
|
+
}
|
|
3884
|
+
const capturedContent = [];
|
|
3885
|
+
for (const part of content) {
|
|
3886
|
+
const captured = capturedEveModelContentPart(part);
|
|
3887
|
+
if (captured) {
|
|
3888
|
+
capturedContent.push(captured);
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
3891
|
+
return { content: capturedContent, role };
|
|
3592
3892
|
}
|
|
3593
3893
|
function capturedEveModelContentPart(part) {
|
|
3594
|
-
|
|
3894
|
+
if (!isObject(part) || typeof part["type"] !== "string") {
|
|
3895
|
+
return void 0;
|
|
3896
|
+
}
|
|
3897
|
+
switch (part["type"]) {
|
|
3595
3898
|
case "text":
|
|
3596
|
-
case "reasoning":
|
|
3597
|
-
|
|
3899
|
+
case "reasoning": {
|
|
3900
|
+
const text = part["text"];
|
|
3901
|
+
return typeof text === "string" ? { text, type: part["type"] } : void 0;
|
|
3902
|
+
}
|
|
3598
3903
|
case "image":
|
|
3904
|
+
if (!Object.hasOwn(part, "image")) {
|
|
3905
|
+
return void 0;
|
|
3906
|
+
}
|
|
3599
3907
|
return {
|
|
3600
|
-
image: part
|
|
3601
|
-
...part
|
|
3908
|
+
image: part["image"],
|
|
3909
|
+
...typeof part["mediaType"] === "string" ? { mediaType: part["mediaType"] } : {},
|
|
3602
3910
|
type: "image"
|
|
3603
3911
|
};
|
|
3604
3912
|
case "file":
|
|
3605
|
-
case "reasoning-file":
|
|
3913
|
+
case "reasoning-file": {
|
|
3914
|
+
if (!Object.hasOwn(part, "data") || typeof part["mediaType"] !== "string") {
|
|
3915
|
+
return void 0;
|
|
3916
|
+
}
|
|
3606
3917
|
return {
|
|
3607
|
-
data: part
|
|
3608
|
-
...part
|
|
3609
|
-
mediaType: part
|
|
3610
|
-
type: part
|
|
3918
|
+
data: part["data"],
|
|
3919
|
+
...part["type"] === "file" && typeof part["filename"] === "string" ? { filename: part["filename"] } : {},
|
|
3920
|
+
mediaType: part["mediaType"],
|
|
3921
|
+
type: part["type"]
|
|
3611
3922
|
};
|
|
3923
|
+
}
|
|
3612
3924
|
case "custom":
|
|
3613
3925
|
return {
|
|
3614
|
-
..."kind"
|
|
3926
|
+
...typeof part["kind"] === "string" ? { kind: part["kind"] } : {},
|
|
3615
3927
|
type: "custom"
|
|
3616
3928
|
};
|
|
3617
|
-
case "tool-call":
|
|
3929
|
+
case "tool-call": {
|
|
3930
|
+
if (typeof part["toolCallId"] !== "string" || typeof part["toolName"] !== "string") {
|
|
3931
|
+
return void 0;
|
|
3932
|
+
}
|
|
3618
3933
|
return {
|
|
3619
|
-
input: part
|
|
3620
|
-
...part
|
|
3621
|
-
toolCallId: part
|
|
3622
|
-
toolName: part
|
|
3934
|
+
input: part["input"],
|
|
3935
|
+
...typeof part["providerExecuted"] === "boolean" ? { providerExecuted: part["providerExecuted"] } : {},
|
|
3936
|
+
toolCallId: part["toolCallId"],
|
|
3937
|
+
toolName: part["toolName"],
|
|
3623
3938
|
type: "tool-call"
|
|
3624
3939
|
};
|
|
3940
|
+
}
|
|
3625
3941
|
case "tool-result": {
|
|
3626
|
-
const output = part
|
|
3942
|
+
const output = part["output"];
|
|
3943
|
+
if (typeof part["toolCallId"] !== "string" || typeof part["toolName"] !== "string" || !isObject(output) || typeof output["type"] !== "string") {
|
|
3944
|
+
return void 0;
|
|
3945
|
+
}
|
|
3627
3946
|
let capturedOutput;
|
|
3628
|
-
switch (output
|
|
3947
|
+
switch (output["type"]) {
|
|
3629
3948
|
case "text":
|
|
3630
|
-
case "error-text":
|
|
3631
|
-
|
|
3949
|
+
case "error-text": {
|
|
3950
|
+
if (typeof output["value"] !== "string") {
|
|
3951
|
+
return void 0;
|
|
3952
|
+
}
|
|
3953
|
+
capturedOutput = {
|
|
3954
|
+
type: output["type"],
|
|
3955
|
+
value: output["value"]
|
|
3956
|
+
};
|
|
3632
3957
|
break;
|
|
3958
|
+
}
|
|
3633
3959
|
case "json":
|
|
3634
3960
|
case "error-json":
|
|
3635
|
-
capturedOutput = {
|
|
3961
|
+
capturedOutput = {
|
|
3962
|
+
type: output["type"],
|
|
3963
|
+
value: output["value"]
|
|
3964
|
+
};
|
|
3636
3965
|
break;
|
|
3637
3966
|
case "execution-denied":
|
|
3638
3967
|
capturedOutput = {
|
|
3639
|
-
...output
|
|
3968
|
+
...typeof output["reason"] === "string" ? { reason: output["reason"] } : {},
|
|
3640
3969
|
type: "execution-denied"
|
|
3641
3970
|
};
|
|
3642
3971
|
break;
|
|
3643
|
-
case "content":
|
|
3972
|
+
case "content": {
|
|
3973
|
+
if (!Array.isArray(output["value"])) {
|
|
3974
|
+
return void 0;
|
|
3975
|
+
}
|
|
3976
|
+
const value = [];
|
|
3977
|
+
for (const outputPart of output["value"]) {
|
|
3978
|
+
const captured = capturedEveModelContentPart(outputPart);
|
|
3979
|
+
if (captured) {
|
|
3980
|
+
value.push(captured);
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3644
3983
|
capturedOutput = {
|
|
3645
3984
|
type: "content",
|
|
3646
|
-
value
|
|
3985
|
+
value
|
|
3647
3986
|
};
|
|
3648
3987
|
break;
|
|
3988
|
+
}
|
|
3989
|
+
default:
|
|
3990
|
+
return void 0;
|
|
3649
3991
|
}
|
|
3650
3992
|
return {
|
|
3651
3993
|
output: capturedOutput,
|
|
3652
|
-
toolCallId: part
|
|
3653
|
-
toolName: part
|
|
3994
|
+
toolCallId: part["toolCallId"],
|
|
3995
|
+
toolName: part["toolName"],
|
|
3654
3996
|
type: "tool-result"
|
|
3655
3997
|
};
|
|
3656
3998
|
}
|
|
3657
|
-
case "tool-approval-request":
|
|
3999
|
+
case "tool-approval-request": {
|
|
4000
|
+
if (typeof part["approvalId"] !== "string" || typeof part["toolCallId"] !== "string") {
|
|
4001
|
+
return void 0;
|
|
4002
|
+
}
|
|
3658
4003
|
return {
|
|
3659
|
-
approvalId: part
|
|
3660
|
-
...part
|
|
3661
|
-
...part
|
|
3662
|
-
toolCallId: part
|
|
4004
|
+
approvalId: part["approvalId"],
|
|
4005
|
+
...typeof part["isAutomatic"] === "boolean" ? { isAutomatic: part["isAutomatic"] } : {},
|
|
4006
|
+
...typeof part["signature"] === "string" ? { signature: part["signature"] } : {},
|
|
4007
|
+
toolCallId: part["toolCallId"],
|
|
3663
4008
|
type: "tool-approval-request"
|
|
3664
4009
|
};
|
|
3665
|
-
|
|
4010
|
+
}
|
|
4011
|
+
case "tool-approval-response": {
|
|
4012
|
+
if (typeof part["approvalId"] !== "string" || typeof part["approved"] !== "boolean") {
|
|
4013
|
+
return void 0;
|
|
4014
|
+
}
|
|
3666
4015
|
return {
|
|
3667
|
-
approvalId: part
|
|
3668
|
-
approved: part
|
|
3669
|
-
...part
|
|
3670
|
-
...part
|
|
4016
|
+
approvalId: part["approvalId"],
|
|
4017
|
+
approved: part["approved"],
|
|
4018
|
+
...typeof part["providerExecuted"] === "boolean" ? { providerExecuted: part["providerExecuted"] } : {},
|
|
4019
|
+
...typeof part["reason"] === "string" ? { reason: part["reason"] } : {},
|
|
3671
4020
|
type: "tool-approval-response"
|
|
3672
4021
|
};
|
|
4022
|
+
}
|
|
3673
4023
|
case "file-data":
|
|
3674
|
-
case "image-data":
|
|
4024
|
+
case "image-data": {
|
|
4025
|
+
if (typeof part["data"] !== "string" || typeof part["mediaType"] !== "string") {
|
|
4026
|
+
return void 0;
|
|
4027
|
+
}
|
|
3675
4028
|
return {
|
|
3676
|
-
data: part
|
|
3677
|
-
...part
|
|
3678
|
-
mediaType: part
|
|
3679
|
-
type: part
|
|
4029
|
+
data: part["data"],
|
|
4030
|
+
...part["type"] === "file-data" && typeof part["filename"] === "string" ? { filename: part["filename"] } : {},
|
|
4031
|
+
mediaType: part["mediaType"],
|
|
4032
|
+
type: part["type"]
|
|
3680
4033
|
};
|
|
4034
|
+
}
|
|
3681
4035
|
case "file-url":
|
|
3682
|
-
case "image-url":
|
|
4036
|
+
case "image-url": {
|
|
4037
|
+
if (typeof part["url"] !== "string") {
|
|
4038
|
+
return void 0;
|
|
4039
|
+
}
|
|
3683
4040
|
return {
|
|
3684
|
-
...part
|
|
3685
|
-
type: part
|
|
3686
|
-
url: part
|
|
4041
|
+
...part["type"] === "file-url" && typeof part["mediaType"] === "string" ? { mediaType: part["mediaType"] } : {},
|
|
4042
|
+
type: part["type"],
|
|
4043
|
+
url: part["url"]
|
|
3687
4044
|
};
|
|
4045
|
+
}
|
|
3688
4046
|
case "file-id":
|
|
3689
|
-
case "image-file-id":
|
|
3690
|
-
|
|
4047
|
+
case "image-file-id": {
|
|
4048
|
+
const fileId = part["fileId"];
|
|
4049
|
+
if (typeof fileId !== "string" && !isObject(fileId)) {
|
|
4050
|
+
return void 0;
|
|
4051
|
+
}
|
|
4052
|
+
return { fileId, type: part["type"] };
|
|
4053
|
+
}
|
|
3691
4054
|
case "file-reference":
|
|
3692
|
-
case "image-file-reference":
|
|
4055
|
+
case "image-file-reference": {
|
|
4056
|
+
if (!isObject(part["providerReference"])) {
|
|
4057
|
+
return void 0;
|
|
4058
|
+
}
|
|
3693
4059
|
return {
|
|
3694
|
-
providerReference: part
|
|
3695
|
-
type: part
|
|
4060
|
+
providerReference: part["providerReference"],
|
|
4061
|
+
type: part["type"]
|
|
3696
4062
|
};
|
|
4063
|
+
}
|
|
4064
|
+
default:
|
|
4065
|
+
return void 0;
|
|
3697
4066
|
}
|
|
3698
4067
|
}
|
|
3699
4068
|
function isCapturedModelInput(input) {
|
|
@@ -3829,18 +4198,54 @@ function createEveInstrumentationProvider(options = {}) {
|
|
|
3829
4198
|
recordOutputs: true
|
|
3830
4199
|
}),
|
|
3831
4200
|
events: {
|
|
3832
|
-
"action.completed": (
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
"
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
"
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
4201
|
+
"action.completed": providerHandler(
|
|
4202
|
+
"action.completed",
|
|
4203
|
+
bridge.handleActionTerminal.bind(bridge)
|
|
4204
|
+
),
|
|
4205
|
+
"action.failed": providerHandler(
|
|
4206
|
+
"action.failed",
|
|
4207
|
+
bridge.handleActionTerminal.bind(bridge)
|
|
4208
|
+
),
|
|
4209
|
+
"action.started": providerHandler(
|
|
4210
|
+
"action.started",
|
|
4211
|
+
bridge.handleActionStarted.bind(bridge)
|
|
4212
|
+
),
|
|
4213
|
+
"model.call.completed": providerHandler(
|
|
4214
|
+
"model.call.completed",
|
|
4215
|
+
bridge.handleModelTerminal.bind(bridge)
|
|
4216
|
+
),
|
|
4217
|
+
"model.call.failed": providerHandler(
|
|
4218
|
+
"model.call.failed",
|
|
4219
|
+
bridge.handleModelTerminal.bind(bridge)
|
|
4220
|
+
),
|
|
4221
|
+
"model.call.started": providerHandler(
|
|
4222
|
+
"model.call.started",
|
|
4223
|
+
bridge.handleModelStarted.bind(bridge)
|
|
4224
|
+
),
|
|
4225
|
+
"step.attempt.completed": providerHandler(
|
|
4226
|
+
"step.attempt.completed",
|
|
4227
|
+
(event) => bridge.handleStepAttemptTerminal(event)
|
|
4228
|
+
),
|
|
4229
|
+
"step.attempt.failed": providerHandler(
|
|
4230
|
+
"step.attempt.failed",
|
|
4231
|
+
(event) => bridge.handleStepAttemptTerminal(event)
|
|
4232
|
+
),
|
|
4233
|
+
"turn.cancelled": providerHandler(
|
|
4234
|
+
"turn.cancelled",
|
|
4235
|
+
bridge.handleTurnTerminal.bind(bridge)
|
|
4236
|
+
),
|
|
4237
|
+
"turn.completed": providerHandler(
|
|
4238
|
+
"turn.completed",
|
|
4239
|
+
bridge.handleTurnTerminal.bind(bridge)
|
|
4240
|
+
),
|
|
4241
|
+
"turn.failed": providerHandler(
|
|
4242
|
+
"turn.failed",
|
|
4243
|
+
bridge.handleTurnTerminal.bind(bridge)
|
|
4244
|
+
),
|
|
4245
|
+
"turn.started": providerHandler(
|
|
4246
|
+
"turn.started",
|
|
4247
|
+
bridge.handleTurnStarted.bind(bridge)
|
|
4248
|
+
)
|
|
3844
4249
|
},
|
|
3845
4250
|
flush,
|
|
3846
4251
|
setup: options.setup
|
|
@@ -4196,17 +4601,20 @@ function modelOutput(event) {
|
|
|
4196
4601
|
const reasoning = [];
|
|
4197
4602
|
const toolCalls2 = [];
|
|
4198
4603
|
for (const part of content) {
|
|
4199
|
-
if (part
|
|
4200
|
-
|
|
4201
|
-
}
|
|
4202
|
-
|
|
4203
|
-
|
|
4604
|
+
if (!isObject(part)) {
|
|
4605
|
+
continue;
|
|
4606
|
+
}
|
|
4607
|
+
if (part["type"] === "text" && typeof part["text"] === "string") {
|
|
4608
|
+
text += part["text"];
|
|
4609
|
+
} else if (part["type"] === "reasoning" && typeof part["text"] === "string" && part["text"].trim().length > 0) {
|
|
4610
|
+
reasoning.push({ content: part["text"] });
|
|
4611
|
+
} else if (part["type"] === "tool-call" && typeof part["toolName"] === "string" && typeof part["callId"] === "string") {
|
|
4204
4612
|
toolCalls2.push({
|
|
4205
4613
|
function: {
|
|
4206
|
-
arguments: safeJsonStringify(part
|
|
4207
|
-
name: part
|
|
4614
|
+
arguments: safeJsonStringify(part["input"]),
|
|
4615
|
+
name: part["toolName"]
|
|
4208
4616
|
},
|
|
4209
|
-
id: part
|
|
4617
|
+
id: part["callId"],
|
|
4210
4618
|
type: "function"
|
|
4211
4619
|
});
|
|
4212
4620
|
}
|
|
@@ -4225,13 +4633,13 @@ function modelOutput(event) {
|
|
|
4225
4633
|
];
|
|
4226
4634
|
}
|
|
4227
4635
|
function usageMetrics(usage) {
|
|
4228
|
-
const promptTokens = nonNegativeNumber(usage
|
|
4229
|
-
const completionTokens = nonNegativeNumber(usage
|
|
4636
|
+
const promptTokens = nonNegativeNumber(usage?.inputTokens);
|
|
4637
|
+
const completionTokens = nonNegativeNumber(usage?.outputTokens);
|
|
4230
4638
|
const cachedTokens = nonNegativeNumber(
|
|
4231
|
-
usage
|
|
4639
|
+
usage?.inputTokenDetails?.cacheReadTokens
|
|
4232
4640
|
);
|
|
4233
4641
|
const cacheCreationTokens = nonNegativeNumber(
|
|
4234
|
-
usage
|
|
4642
|
+
usage?.inputTokenDetails?.cacheWriteTokens
|
|
4235
4643
|
);
|
|
4236
4644
|
return {
|
|
4237
4645
|
...promptTokens !== void 0 ? { prompt_tokens: promptTokens } : {},
|
|
@@ -4268,10 +4676,76 @@ function turnIdempotencyKey(sessionId, turnId) {
|
|
|
4268
4676
|
function actionIdempotencyKey(sessionId, turnId, callId) {
|
|
4269
4677
|
return `action:${sessionId}:${turnId}:${callId}`;
|
|
4270
4678
|
}
|
|
4679
|
+
function providerHandler(type, handler) {
|
|
4680
|
+
return async (event, context) => {
|
|
4681
|
+
try {
|
|
4682
|
+
if (!isEveProviderEvent(event, type) || !isEveProviderContext(context)) {
|
|
4683
|
+
debugLogger.warn(`Ignoring malformed Eve provider ${type} event`);
|
|
4684
|
+
return;
|
|
4685
|
+
}
|
|
4686
|
+
await handler(event, context);
|
|
4687
|
+
} catch (error) {
|
|
4688
|
+
debugLogger.warn(`Error in Eve provider ${type}:`, error);
|
|
4689
|
+
}
|
|
4690
|
+
};
|
|
4691
|
+
}
|
|
4692
|
+
function isEveProviderEvent(event, type) {
|
|
4693
|
+
if (!isObject(event) || event["type"] !== type || typeof event["idempotencyKey"] !== "string" || event["idempotencyKey"].length === 0) {
|
|
4694
|
+
return false;
|
|
4695
|
+
}
|
|
4696
|
+
if (type === "turn.started") {
|
|
4697
|
+
const parentLineage = event["parentLineage"];
|
|
4698
|
+
return typeof event["rootSessionId"] === "string" && typeof event["sessionId"] === "string" && typeof event["turnId"] === "string" && typeof event["sequence"] === "number" && Number.isFinite(event["sequence"]) && (parentLineage === void 0 || isEveProviderParentLineage(parentLineage));
|
|
4699
|
+
}
|
|
4700
|
+
if (type === "turn.cancelled" || type === "turn.completed" || type === "turn.failed") {
|
|
4701
|
+
return typeof event["sessionId"] === "string" && typeof event["turnId"] === "string";
|
|
4702
|
+
}
|
|
4703
|
+
if (!isEveProviderScope(event["scope"])) {
|
|
4704
|
+
return false;
|
|
4705
|
+
}
|
|
4706
|
+
if (type === "model.call.started") {
|
|
4707
|
+
const model = event["model"];
|
|
4708
|
+
return isObject(model) && typeof model["modelId"] === "string" && typeof model["provider"] === "string";
|
|
4709
|
+
}
|
|
4710
|
+
if (type === "model.call.completed") {
|
|
4711
|
+
return typeof event["finishReason"] === "string" && isObject(event["usage"]) && (event["content"] === void 0 || Array.isArray(event["content"]));
|
|
4712
|
+
}
|
|
4713
|
+
if (type === "model.call.failed") {
|
|
4714
|
+
return true;
|
|
4715
|
+
}
|
|
4716
|
+
if (type === "action.started") {
|
|
4717
|
+
return typeof event["callId"] === "string" && typeof event["name"] === "string" && (event["kind"] === "load-skill" || event["kind"] === "remote-agent-call" || event["kind"] === "subagent-call" || event["kind"] === "tool-call");
|
|
4718
|
+
}
|
|
4719
|
+
if (type === "action.completed") {
|
|
4720
|
+
const output = event["output"];
|
|
4721
|
+
return event["outcome"] === "completed" && isObject(output) && (output["type"] === "result" || output["type"] === "error");
|
|
4722
|
+
}
|
|
4723
|
+
if (type === "action.failed") {
|
|
4724
|
+
return event["outcome"] === "abandoned" || event["outcome"] === "cancelled" || event["outcome"] === "failed" || event["outcome"] === "rejected";
|
|
4725
|
+
}
|
|
4726
|
+
return type === "step.attempt.completed" || type === "step.attempt.failed";
|
|
4727
|
+
}
|
|
4728
|
+
function isEveProviderContext(value) {
|
|
4729
|
+
if (!isObject(value) || !isObject(value["state"])) {
|
|
4730
|
+
return false;
|
|
4731
|
+
}
|
|
4732
|
+
return typeof value["state"]["get"] === "function" && typeof value["state"]["set"] === "function";
|
|
4733
|
+
}
|
|
4734
|
+
function isEveProviderScope(value) {
|
|
4735
|
+
return isObject(value) && typeof value["attemptId"] === "string" && typeof value["attemptIndex"] === "number" && Number.isFinite(value["attemptIndex"]) && typeof value["sessionId"] === "string" && typeof value["stepIndex"] === "number" && Number.isFinite(value["stepIndex"]) && typeof value["turnId"] === "string" && (value["rootSessionId"] === void 0 || typeof value["rootSessionId"] === "string");
|
|
4736
|
+
}
|
|
4737
|
+
function isEveProviderParentLineage(value) {
|
|
4738
|
+
return isObject(value) && typeof value["callId"] === "string" && typeof value["sessionId"] === "string" && typeof value["turnId"] === "string";
|
|
4739
|
+
}
|
|
4271
4740
|
|
|
4272
4741
|
// src/instrumentation/plugins/eve-instrumentation.ts
|
|
4273
4742
|
var EVE_INSTRUMENTATION_PROVIDER = /* @__PURE__ */ Symbol.for("eve.instrumentation.provider");
|
|
4274
4743
|
function braintrustEveInstrumentation(options) {
|
|
4744
|
+
if (!options || typeof options !== "object") {
|
|
4745
|
+
throw new TypeError(
|
|
4746
|
+
"braintrustEveInstrumentation requires an options object"
|
|
4747
|
+
);
|
|
4748
|
+
}
|
|
4275
4749
|
const definition = "defineState" in options ? createLegacyEveInstrumentation(options) : createEveInstrumentationProvider(options);
|
|
4276
4750
|
const declaration = {
|
|
4277
4751
|
...definition,
|
|
@@ -5288,6 +5762,7 @@ function wrapClient(client) {
|
|
|
5288
5762
|
}
|
|
5289
5763
|
|
|
5290
5764
|
// src/wrappers/google-genai.ts
|
|
5765
|
+
var patchedHttpResponses = /* @__PURE__ */ new WeakSet();
|
|
5291
5766
|
function wrapGoogleGenAI(googleGenAI) {
|
|
5292
5767
|
if (!googleGenAI || typeof googleGenAI !== "object") {
|
|
5293
5768
|
console.warn("Invalid Google GenAI module. Not wrapping.");
|
|
@@ -5299,6 +5774,21 @@ function wrapGoogleGenAI(googleGenAI) {
|
|
|
5299
5774
|
);
|
|
5300
5775
|
return googleGenAI;
|
|
5301
5776
|
}
|
|
5777
|
+
const httpResponse = googleGenAI.HttpResponse;
|
|
5778
|
+
if (typeof httpResponse === "function" && isObject(httpResponse.prototype) && typeof httpResponse.prototype.json === "function" && !patchedHttpResponses.has(httpResponse.prototype)) {
|
|
5779
|
+
const prototype = httpResponse.prototype;
|
|
5780
|
+
const originalJson = prototype.json;
|
|
5781
|
+
if (Reflect.set(prototype, "json", function() {
|
|
5782
|
+
return googleGenAIChannels.httpResponseJson.invoke(
|
|
5783
|
+
originalJson,
|
|
5784
|
+
this,
|
|
5785
|
+
[],
|
|
5786
|
+
{}
|
|
5787
|
+
);
|
|
5788
|
+
})) {
|
|
5789
|
+
patchedHttpResponses.add(prototype);
|
|
5790
|
+
}
|
|
5791
|
+
}
|
|
5302
5792
|
return new Proxy(googleGenAI, {
|
|
5303
5793
|
get(target, prop, receiver) {
|
|
5304
5794
|
if (prop === "GoogleGenAI") {
|
|
@@ -5549,17 +6039,17 @@ function wrapGenkit(genkit) {
|
|
|
5549
6039
|
console.warn("Unsupported Genkit object. Not wrapping.");
|
|
5550
6040
|
return genkit;
|
|
5551
6041
|
}
|
|
5552
|
-
function
|
|
6042
|
+
function isRecord2(value) {
|
|
5553
6043
|
return typeof value === "object" && value !== null;
|
|
5554
6044
|
}
|
|
5555
6045
|
function isPropertyBag(value) {
|
|
5556
|
-
return
|
|
6046
|
+
return isRecord2(value) || typeof value === "function";
|
|
5557
6047
|
}
|
|
5558
6048
|
function hasFunction(value, methodName) {
|
|
5559
6049
|
return isPropertyBag(value) && methodName in value && typeof value[methodName] === "function";
|
|
5560
6050
|
}
|
|
5561
6051
|
function isGenkitInstance(value) {
|
|
5562
|
-
return
|
|
6052
|
+
return isRecord2(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
|
|
5563
6053
|
}
|
|
5564
6054
|
function isGenkitModule(value) {
|
|
5565
6055
|
return hasFunction(value, "genkit");
|
|
@@ -5613,7 +6103,7 @@ function patchGenkitRegistry(instance) {
|
|
|
5613
6103
|
patchGenkitRegistryConstructor(registry);
|
|
5614
6104
|
}
|
|
5615
6105
|
function patchGenkitRegistryLookup(registry) {
|
|
5616
|
-
if (!
|
|
6106
|
+
if (!isRecord2(registry) || hasRegistryPatchedFlag(registry) || !hasFunction(registry, "lookupAction")) {
|
|
5617
6107
|
return;
|
|
5618
6108
|
}
|
|
5619
6109
|
const originalLookupAction = registry.lookupAction;
|
|
@@ -5639,7 +6129,7 @@ function patchGenkitRegistryLookup(registry) {
|
|
|
5639
6129
|
}
|
|
5640
6130
|
}
|
|
5641
6131
|
function patchGenkitRegistryConstructor(registry) {
|
|
5642
|
-
if (!
|
|
6132
|
+
if (!isRecord2(registry)) {
|
|
5643
6133
|
return;
|
|
5644
6134
|
}
|
|
5645
6135
|
const constructor = registry.constructor;
|
|
@@ -5655,7 +6145,7 @@ function patchGenkitRegistryConstructor(registry) {
|
|
|
5655
6145
|
configurable: true,
|
|
5656
6146
|
value: (...args) => {
|
|
5657
6147
|
const childRegistry = originalWithParent.apply(constructor, args);
|
|
5658
|
-
if (args.some((arg) =>
|
|
6148
|
+
if (args.some((arg) => isRecord2(arg) && hasRegistryPatchedFlag(arg))) {
|
|
5659
6149
|
patchGenkitRegistryLookup(childRegistry);
|
|
5660
6150
|
patchGenkitRegistryConstructor(childRegistry);
|
|
5661
6151
|
}
|
|
@@ -5754,7 +6244,7 @@ function hasRegistryConstructorPatchedFlag(value) {
|
|
|
5754
6244
|
);
|
|
5755
6245
|
}
|
|
5756
6246
|
function isPromiseLike(value) {
|
|
5757
|
-
return
|
|
6247
|
+
return isRecord2(value) && "then" in value && typeof value.then === "function";
|
|
5758
6248
|
}
|
|
5759
6249
|
|
|
5760
6250
|
// src/wrappers/huggingface.ts
|
|
@@ -6231,14 +6721,14 @@ function wrapMistral(mistral) {
|
|
|
6231
6721
|
console.warn("Unsupported Mistral library. Not wrapping.");
|
|
6232
6722
|
return mistral;
|
|
6233
6723
|
}
|
|
6234
|
-
function
|
|
6724
|
+
function isRecord3(value) {
|
|
6235
6725
|
return typeof value === "object" && value !== null;
|
|
6236
6726
|
}
|
|
6237
6727
|
function hasFunction3(value, methodName) {
|
|
6238
|
-
return
|
|
6728
|
+
return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
|
|
6239
6729
|
}
|
|
6240
6730
|
function isSupportedMistralClient(value) {
|
|
6241
|
-
if (!
|
|
6731
|
+
if (!isRecord3(value)) {
|
|
6242
6732
|
return false;
|
|
6243
6733
|
}
|
|
6244
6734
|
return value.chat !== void 0 && hasChat(value.chat) || value.embeddings !== void 0 && hasEmbeddings(value.embeddings) || value.fim !== void 0 && hasFim(value.fim) || value.agents !== void 0 && hasAgents(value.agents) || value.classifiers !== void 0 && hasClassifiers(value.classifiers);
|
|
@@ -6413,6 +6903,42 @@ function wrapAgentsStream(stream) {
|
|
|
6413
6903
|
});
|
|
6414
6904
|
}
|
|
6415
6905
|
|
|
6906
|
+
// src/wrappers/langgraph-sdk.ts
|
|
6907
|
+
var clients = /* @__PURE__ */ new WeakMap();
|
|
6908
|
+
function wrapLangGraphSDK(client) {
|
|
6909
|
+
const runsClient = isObject(client) ? client.runs : void 0;
|
|
6910
|
+
if (!isObject(client) || !isObject(runsClient) || !["wait", "stream"].every((key) => typeof runsClient[key] === "function")) {
|
|
6911
|
+
debugLogger.warn("Unsupported LangGraph SDK client. Not wrapping.");
|
|
6912
|
+
return client;
|
|
6913
|
+
}
|
|
6914
|
+
const sdk = client;
|
|
6915
|
+
const cached = clients.get(sdk);
|
|
6916
|
+
if (cached) return cached;
|
|
6917
|
+
const runs = new Proxy(sdk.runs, {
|
|
6918
|
+
get(target, key) {
|
|
6919
|
+
switch (key) {
|
|
6920
|
+
case "wait":
|
|
6921
|
+
return (...args) => langGraphSDKChannels.wait.invoke(target.wait, target, args, {});
|
|
6922
|
+
case "stream":
|
|
6923
|
+
return (...args) => langGraphSDKChannels.stream.invoke(target.stream, target, args, {});
|
|
6924
|
+
default:
|
|
6925
|
+
const value = Reflect.get(target, key, target);
|
|
6926
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
6927
|
+
}
|
|
6928
|
+
}
|
|
6929
|
+
});
|
|
6930
|
+
const wrapped = new Proxy(sdk, {
|
|
6931
|
+
get(target, key) {
|
|
6932
|
+
if (key === "runs") return runs;
|
|
6933
|
+
const value = Reflect.get(target, key, target);
|
|
6934
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
6935
|
+
}
|
|
6936
|
+
});
|
|
6937
|
+
clients.set(sdk, wrapped);
|
|
6938
|
+
clients.set(wrapped, wrapped);
|
|
6939
|
+
return wrapped;
|
|
6940
|
+
}
|
|
6941
|
+
|
|
6416
6942
|
// src/wrappers/ollama.ts
|
|
6417
6943
|
function wrapOllama(ollama) {
|
|
6418
6944
|
if (isSupportedOllamaClient(ollama)) {
|
|
@@ -6499,14 +7025,14 @@ function wrapCohere(cohere) {
|
|
|
6499
7025
|
return cohere;
|
|
6500
7026
|
}
|
|
6501
7027
|
var cohereProxyCache = /* @__PURE__ */ new WeakMap();
|
|
6502
|
-
function
|
|
7028
|
+
function isRecord4(value) {
|
|
6503
7029
|
return typeof value === "object" && value !== null;
|
|
6504
7030
|
}
|
|
6505
7031
|
function hasFunction4(value, methodName) {
|
|
6506
|
-
return
|
|
7032
|
+
return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
|
|
6507
7033
|
}
|
|
6508
7034
|
function isSupportedCohereClient(value) {
|
|
6509
|
-
if (!
|
|
7035
|
+
if (!isRecord4(value)) {
|
|
6510
7036
|
return false;
|
|
6511
7037
|
}
|
|
6512
7038
|
return hasFunction4(value, "chat") || hasFunction4(value, "chatStream") || hasFunction4(value, "embed") || hasFunction4(value, "rerank");
|
|
@@ -6644,20 +7170,20 @@ function wrapGroq(groq) {
|
|
|
6644
7170
|
console.warn("Unsupported Groq library. Not wrapping.");
|
|
6645
7171
|
return groq;
|
|
6646
7172
|
}
|
|
6647
|
-
function
|
|
7173
|
+
function isRecord5(value) {
|
|
6648
7174
|
return typeof value === "object" && value !== null;
|
|
6649
7175
|
}
|
|
6650
7176
|
function hasFunction6(value, methodName) {
|
|
6651
|
-
return
|
|
7177
|
+
return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
|
|
6652
7178
|
}
|
|
6653
7179
|
function hasChat2(value) {
|
|
6654
|
-
return
|
|
7180
|
+
return isRecord5(value) && isRecord5(value.completions) && hasFunction6(value.completions, "create");
|
|
6655
7181
|
}
|
|
6656
7182
|
function hasEmbeddings2(value) {
|
|
6657
7183
|
return hasFunction6(value, "create");
|
|
6658
7184
|
}
|
|
6659
7185
|
function isSupportedGroqClient(value) {
|
|
6660
|
-
return
|
|
7186
|
+
return isRecord5(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
|
|
6661
7187
|
}
|
|
6662
7188
|
function groqProxy(groq) {
|
|
6663
7189
|
const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -6740,11 +7266,11 @@ var BEDROCK_RUNTIME_OPERATION_METHODS = /* @__PURE__ */ new Set([
|
|
|
6740
7266
|
"invokeModelWithBidirectionalStream",
|
|
6741
7267
|
"invokeModelWithResponseStream"
|
|
6742
7268
|
]);
|
|
6743
|
-
function
|
|
7269
|
+
function isRecord6(value) {
|
|
6744
7270
|
return typeof value === "object" && value !== null;
|
|
6745
7271
|
}
|
|
6746
7272
|
function isSupportedBedrockRuntimeClient(value) {
|
|
6747
|
-
return
|
|
7273
|
+
return isRecord6(value) && typeof value.send === "function";
|
|
6748
7274
|
}
|
|
6749
7275
|
function bedrockRuntimeProxy(client) {
|
|
6750
7276
|
const cached = bedrockRuntimeProxyCache.get(client);
|
|
@@ -9029,12 +9555,272 @@ function waterfall(tasks, callback) {
|
|
|
9029
9555
|
}
|
|
9030
9556
|
var waterfall$1 = awaitify(waterfall);
|
|
9031
9557
|
|
|
9558
|
+
// src/framework.ts
|
|
9559
|
+
import { v5 as uuidv5 } from "uuid";
|
|
9560
|
+
|
|
9032
9561
|
// src/trace.ts
|
|
9562
|
+
var spanFilterFields = /* @__PURE__ */ new Set([
|
|
9563
|
+
"spanType",
|
|
9564
|
+
"name",
|
|
9565
|
+
"hasError",
|
|
9566
|
+
"metadata",
|
|
9567
|
+
"duration"
|
|
9568
|
+
]);
|
|
9569
|
+
function isRecord7(value) {
|
|
9570
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
9571
|
+
return false;
|
|
9572
|
+
}
|
|
9573
|
+
const prototype = Object.getPrototypeOf(value);
|
|
9574
|
+
return prototype === Object.prototype || prototype === null;
|
|
9575
|
+
}
|
|
9576
|
+
function validateMetadataValue(value, ancestors) {
|
|
9577
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
9578
|
+
return;
|
|
9579
|
+
}
|
|
9580
|
+
if (typeof value === "number") {
|
|
9581
|
+
if (Number.isFinite(value)) {
|
|
9582
|
+
return;
|
|
9583
|
+
}
|
|
9584
|
+
throw new Error("filters.metadata numbers must be finite");
|
|
9585
|
+
}
|
|
9586
|
+
if (typeof value !== "object" || value === null) {
|
|
9587
|
+
throw new Error("filters.metadata values must be JSON-serializable");
|
|
9588
|
+
}
|
|
9589
|
+
if (!Array.isArray(value) && !isRecord7(value)) {
|
|
9590
|
+
throw new Error("filters.metadata values must be JSON-serializable");
|
|
9591
|
+
}
|
|
9592
|
+
if (ancestors.has(value)) {
|
|
9593
|
+
throw new Error("filters.metadata must not contain cycles");
|
|
9594
|
+
}
|
|
9595
|
+
ancestors.add(value);
|
|
9596
|
+
if (Array.isArray(value)) {
|
|
9597
|
+
for (let index = 0; index < value.length; index++) {
|
|
9598
|
+
validateMetadataValue(value[index], ancestors);
|
|
9599
|
+
}
|
|
9600
|
+
} else {
|
|
9601
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
9602
|
+
throw new Error("filters.metadata keys must be strings");
|
|
9603
|
+
}
|
|
9604
|
+
for (const nested of Object.values(value)) {
|
|
9605
|
+
validateMetadataValue(nested, ancestors);
|
|
9606
|
+
}
|
|
9607
|
+
}
|
|
9608
|
+
ancestors.delete(value);
|
|
9609
|
+
}
|
|
9610
|
+
function compileMetadataLeaves(metadata, path = [], ancestors = /* @__PURE__ */ new WeakSet()) {
|
|
9611
|
+
if (Object.getOwnPropertySymbols(metadata).length > 0) {
|
|
9612
|
+
throw new Error("filters.metadata keys must be strings");
|
|
9613
|
+
}
|
|
9614
|
+
if (ancestors.has(metadata)) {
|
|
9615
|
+
throw new Error("filters.metadata must not contain cycles");
|
|
9616
|
+
}
|
|
9617
|
+
ancestors.add(metadata);
|
|
9618
|
+
const leaves = [];
|
|
9619
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
9620
|
+
const childPath = [...path, key];
|
|
9621
|
+
if (isRecord7(value)) {
|
|
9622
|
+
leaves.push(...compileMetadataLeaves(value, childPath, ancestors));
|
|
9623
|
+
} else {
|
|
9624
|
+
validateMetadataValue(value, ancestors);
|
|
9625
|
+
leaves.push([childPath, value]);
|
|
9626
|
+
}
|
|
9627
|
+
}
|
|
9628
|
+
ancestors.delete(metadata);
|
|
9629
|
+
return leaves;
|
|
9630
|
+
}
|
|
9631
|
+
function normalizeSpanFilters(filters, spanType) {
|
|
9632
|
+
if (filters != null && !isRecord7(filters)) {
|
|
9633
|
+
throw new Error("filters must be an object");
|
|
9634
|
+
}
|
|
9635
|
+
const values = { ...filters ?? {} };
|
|
9636
|
+
if (spanType !== void 0) {
|
|
9637
|
+
if (!Array.isArray(spanType) || !spanType.every((item) => typeof item === "string")) {
|
|
9638
|
+
throw new Error("spanType must be an array of strings");
|
|
9639
|
+
}
|
|
9640
|
+
if (Object.hasOwn(values, "spanType")) {
|
|
9641
|
+
throw new Error(
|
|
9642
|
+
"spanType cannot be provided both directly and in filters"
|
|
9643
|
+
);
|
|
9644
|
+
}
|
|
9645
|
+
if (spanType.length > 0) {
|
|
9646
|
+
values.spanType = spanType;
|
|
9647
|
+
}
|
|
9648
|
+
}
|
|
9649
|
+
if (Object.keys(values).some((field) => !spanFilterFields.has(field))) {
|
|
9650
|
+
throw new Error("Unsupported span filter fields");
|
|
9651
|
+
}
|
|
9652
|
+
for (const field of ["spanType", "name"]) {
|
|
9653
|
+
if (Object.hasOwn(values, field)) {
|
|
9654
|
+
const items = values[field];
|
|
9655
|
+
if (!Array.isArray(items) || !items.every((item) => typeof item === "string")) {
|
|
9656
|
+
throw new Error(`filters.${field} must be an array of strings`);
|
|
9657
|
+
}
|
|
9658
|
+
}
|
|
9659
|
+
}
|
|
9660
|
+
if (Object.hasOwn(values, "hasError") && typeof values.hasError !== "boolean") {
|
|
9661
|
+
throw new Error("filters.hasError must be a boolean");
|
|
9662
|
+
}
|
|
9663
|
+
let compiledMetadataLeaves = [];
|
|
9664
|
+
if (Object.hasOwn(values, "metadata")) {
|
|
9665
|
+
if (!isRecord7(values.metadata)) {
|
|
9666
|
+
throw new Error("filters.metadata must be an object");
|
|
9667
|
+
}
|
|
9668
|
+
compiledMetadataLeaves = compileMetadataLeaves(values.metadata);
|
|
9669
|
+
}
|
|
9670
|
+
if (Object.hasOwn(values, "duration")) {
|
|
9671
|
+
if (!isRecord7(values.duration) || Object.keys(values.duration).some(
|
|
9672
|
+
(bound) => bound !== "min" && bound !== "max"
|
|
9673
|
+
)) {
|
|
9674
|
+
throw new Error("filters.duration must contain only min and/or max");
|
|
9675
|
+
}
|
|
9676
|
+
if (Object.values(values.duration).some(
|
|
9677
|
+
(bound) => typeof bound !== "number" || !Number.isFinite(bound)
|
|
9678
|
+
)) {
|
|
9679
|
+
throw new Error("filters.duration bounds must be finite numbers");
|
|
9680
|
+
}
|
|
9681
|
+
}
|
|
9682
|
+
const normalized = {};
|
|
9683
|
+
if (Array.isArray(values.spanType)) {
|
|
9684
|
+
normalized.spanType = values.spanType;
|
|
9685
|
+
}
|
|
9686
|
+
if (Array.isArray(values.name)) {
|
|
9687
|
+
normalized.name = values.name;
|
|
9688
|
+
}
|
|
9689
|
+
if (typeof values.hasError === "boolean") {
|
|
9690
|
+
normalized.hasError = values.hasError;
|
|
9691
|
+
}
|
|
9692
|
+
if (isRecord7(values.metadata)) {
|
|
9693
|
+
normalized.metadata = values.metadata;
|
|
9694
|
+
}
|
|
9695
|
+
if (isRecord7(values.duration)) {
|
|
9696
|
+
normalized.duration = {};
|
|
9697
|
+
if (typeof values.duration.min === "number") {
|
|
9698
|
+
normalized.duration.min = values.duration.min;
|
|
9699
|
+
}
|
|
9700
|
+
if (typeof values.duration.max === "number") {
|
|
9701
|
+
normalized.duration.max = values.duration.max;
|
|
9702
|
+
}
|
|
9703
|
+
}
|
|
9704
|
+
return { filters: normalized, metadataLeaves: compiledMetadataLeaves };
|
|
9705
|
+
}
|
|
9706
|
+
function metadataEqual(actual, expected) {
|
|
9707
|
+
if (expected === null) {
|
|
9708
|
+
return actual === null || actual === void 0;
|
|
9709
|
+
}
|
|
9710
|
+
if (Array.isArray(expected)) {
|
|
9711
|
+
return Array.isArray(actual) && actual.length === expected.length && expected.every((value, index) => metadataEqual(actual[index], value));
|
|
9712
|
+
}
|
|
9713
|
+
if (isRecord7(expected)) {
|
|
9714
|
+
if (!isRecord7(actual)) {
|
|
9715
|
+
return false;
|
|
9716
|
+
}
|
|
9717
|
+
const expectedKeys = Object.keys(expected);
|
|
9718
|
+
const actualKeys = Object.keys(actual);
|
|
9719
|
+
return actualKeys.length === expectedKeys.length && expectedKeys.every(
|
|
9720
|
+
(key) => Object.hasOwn(actual, key) && metadataEqual(actual[key], expected[key])
|
|
9721
|
+
);
|
|
9722
|
+
}
|
|
9723
|
+
return actual === expected;
|
|
9724
|
+
}
|
|
9725
|
+
function matchesSpanFilters(span, compiledFilters) {
|
|
9726
|
+
const { filters, metadataLeaves } = compiledFilters;
|
|
9727
|
+
if (filters.spanType !== void 0 && !filters.spanType.includes(span.span_attributes?.type ?? "")) {
|
|
9728
|
+
return false;
|
|
9729
|
+
}
|
|
9730
|
+
if (filters.name !== void 0 && !filters.name.includes(span.span_attributes?.name ?? "")) {
|
|
9731
|
+
return false;
|
|
9732
|
+
}
|
|
9733
|
+
if (filters.hasError !== void 0 && (span.error !== null && span.error !== void 0) !== filters.hasError) {
|
|
9734
|
+
return false;
|
|
9735
|
+
}
|
|
9736
|
+
for (const [path, expected] of metadataLeaves) {
|
|
9737
|
+
let actual = span.metadata;
|
|
9738
|
+
for (const key of path) {
|
|
9739
|
+
actual = isRecord7(actual) && Object.hasOwn(actual, key) ? actual[key] : void 0;
|
|
9740
|
+
}
|
|
9741
|
+
if (!metadataEqual(actual, expected)) {
|
|
9742
|
+
return false;
|
|
9743
|
+
}
|
|
9744
|
+
}
|
|
9745
|
+
if (filters.duration && Object.keys(filters.duration).length > 0) {
|
|
9746
|
+
const metrics = span.metrics;
|
|
9747
|
+
const start = isRecord7(metrics) ? metrics.start : void 0;
|
|
9748
|
+
const end = isRecord7(metrics) ? metrics.end : void 0;
|
|
9749
|
+
if (typeof start !== "number" || !Number.isFinite(start) || typeof end !== "number" || !Number.isFinite(end)) {
|
|
9750
|
+
return false;
|
|
9751
|
+
}
|
|
9752
|
+
const elapsed = end - start;
|
|
9753
|
+
if (filters.duration.min !== void 0 && elapsed < filters.duration.min) {
|
|
9754
|
+
return false;
|
|
9755
|
+
}
|
|
9756
|
+
if (filters.duration.max !== void 0 && elapsed > filters.duration.max) {
|
|
9757
|
+
return false;
|
|
9758
|
+
}
|
|
9759
|
+
}
|
|
9760
|
+
return true;
|
|
9761
|
+
}
|
|
9762
|
+
function btqlComparison(op, name, value) {
|
|
9763
|
+
return {
|
|
9764
|
+
op,
|
|
9765
|
+
left: { op: "ident", name },
|
|
9766
|
+
right: { op: "literal", value }
|
|
9767
|
+
};
|
|
9768
|
+
}
|
|
9769
|
+
function btqlNullCheck(op, name) {
|
|
9770
|
+
return { op, expr: { op: "ident", name } };
|
|
9771
|
+
}
|
|
9772
|
+
function spanFilterClauses(compiledFilters) {
|
|
9773
|
+
const { filters, metadataLeaves } = compiledFilters;
|
|
9774
|
+
const children = [];
|
|
9775
|
+
for (const [field, attribute] of [
|
|
9776
|
+
["spanType", "type"],
|
|
9777
|
+
["name", "name"]
|
|
9778
|
+
]) {
|
|
9779
|
+
const values = filters[field];
|
|
9780
|
+
if (values !== void 0) {
|
|
9781
|
+
children.push(
|
|
9782
|
+
values.length > 0 ? btqlComparison("in", ["span_attributes", attribute], values) : { op: "literal", value: false }
|
|
9783
|
+
);
|
|
9784
|
+
}
|
|
9785
|
+
}
|
|
9786
|
+
if (filters.hasError !== void 0) {
|
|
9787
|
+
children.push(
|
|
9788
|
+
btqlNullCheck(filters.hasError ? "isnotnull" : "isnull", ["error"])
|
|
9789
|
+
);
|
|
9790
|
+
}
|
|
9791
|
+
for (const [path, value] of metadataLeaves) {
|
|
9792
|
+
const name = ["metadata", ...path];
|
|
9793
|
+
children.push(
|
|
9794
|
+
value === null ? btqlNullCheck("isnull", name) : btqlComparison("eq", name, value)
|
|
9795
|
+
);
|
|
9796
|
+
}
|
|
9797
|
+
const elapsed = {
|
|
9798
|
+
op: "sub",
|
|
9799
|
+
left: { op: "ident", name: ["metrics", "end"] },
|
|
9800
|
+
right: { op: "ident", name: ["metrics", "start"] }
|
|
9801
|
+
};
|
|
9802
|
+
if (filters.duration?.min !== void 0) {
|
|
9803
|
+
children.push({
|
|
9804
|
+
op: "ge",
|
|
9805
|
+
left: elapsed,
|
|
9806
|
+
right: { op: "literal", value: filters.duration.min }
|
|
9807
|
+
});
|
|
9808
|
+
}
|
|
9809
|
+
if (filters.duration?.max !== void 0) {
|
|
9810
|
+
children.push({
|
|
9811
|
+
op: "le",
|
|
9812
|
+
left: elapsed,
|
|
9813
|
+
right: { op: "literal", value: filters.duration.max }
|
|
9814
|
+
});
|
|
9815
|
+
}
|
|
9816
|
+
return children;
|
|
9817
|
+
}
|
|
9033
9818
|
var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
9034
|
-
constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true) {
|
|
9819
|
+
constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true, filters) {
|
|
9820
|
+
const normalizedFilters = normalizeSpanFilters(filters, spanTypeFilter);
|
|
9035
9821
|
const filterExpr = _SpanFetcher.buildFilter(
|
|
9036
9822
|
rootSpanId,
|
|
9037
|
-
|
|
9823
|
+
normalizedFilters,
|
|
9038
9824
|
includeScorers
|
|
9039
9825
|
);
|
|
9040
9826
|
super(
|
|
@@ -9055,42 +9841,22 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
|
9055
9841
|
rootSpanId;
|
|
9056
9842
|
_state;
|
|
9057
9843
|
spanTypeFilter;
|
|
9058
|
-
static buildFilter(rootSpanId,
|
|
9844
|
+
static buildFilter(rootSpanId, filters, includeScorers = false) {
|
|
9845
|
+
const purpose = ["span_attributes", "purpose"];
|
|
9059
9846
|
const children = [
|
|
9060
|
-
|
|
9061
|
-
{
|
|
9062
|
-
op: "eq",
|
|
9063
|
-
left: { op: "ident", name: ["root_span_id"] },
|
|
9064
|
-
right: { op: "literal", value: rootSpanId }
|
|
9065
|
-
}
|
|
9847
|
+
btqlComparison("eq", ["root_span_id"], rootSpanId)
|
|
9066
9848
|
];
|
|
9067
9849
|
if (!includeScorers) {
|
|
9068
9850
|
children.push({
|
|
9069
9851
|
op: "or",
|
|
9070
9852
|
children: [
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
expr: { op: "ident", name: ["span_attributes", "purpose"] }
|
|
9074
|
-
},
|
|
9075
|
-
{
|
|
9076
|
-
op: "ne",
|
|
9077
|
-
left: { op: "ident", name: ["span_attributes", "purpose"] },
|
|
9078
|
-
right: { op: "literal", value: "scorer" }
|
|
9079
|
-
}
|
|
9853
|
+
btqlNullCheck("isnull", purpose),
|
|
9854
|
+
btqlComparison("ne", purpose, "scorer")
|
|
9080
9855
|
]
|
|
9081
9856
|
});
|
|
9082
9857
|
}
|
|
9083
|
-
|
|
9084
|
-
|
|
9085
|
-
op: "in",
|
|
9086
|
-
left: { op: "ident", name: ["span_attributes", "type"] },
|
|
9087
|
-
right: { op: "literal", value: spanTypeFilter }
|
|
9088
|
-
});
|
|
9089
|
-
}
|
|
9090
|
-
return {
|
|
9091
|
-
op: "and",
|
|
9092
|
-
children
|
|
9093
|
-
};
|
|
9858
|
+
children.push(...spanFilterClauses(filters));
|
|
9859
|
+
return { op: "and", children };
|
|
9094
9860
|
}
|
|
9095
9861
|
get id() {
|
|
9096
9862
|
return Promise.resolve(this._objectId);
|
|
@@ -9105,67 +9871,80 @@ var CachedSpanFetcher = class {
|
|
|
9105
9871
|
fetchFn;
|
|
9106
9872
|
constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState, brainstoreRealtime = true) {
|
|
9107
9873
|
if (typeof objectTypeOrFetchFn === "function") {
|
|
9108
|
-
this.fetchFn = (
|
|
9874
|
+
this.fetchFn = async (filters) => (await objectTypeOrFetchFn(filters.filters.spanType)).filter(
|
|
9875
|
+
(span) => matchesSpanFilters(span, filters)
|
|
9876
|
+
);
|
|
9109
9877
|
} else {
|
|
9110
9878
|
const objectType = objectTypeOrFetchFn;
|
|
9111
|
-
this.fetchFn = async (
|
|
9879
|
+
this.fetchFn = async (filters, includeScorers) => {
|
|
9112
9880
|
const state = await getState();
|
|
9113
9881
|
const fetcher = new SpanFetcher(
|
|
9114
9882
|
objectType,
|
|
9115
9883
|
objectId,
|
|
9116
9884
|
rootSpanId,
|
|
9117
9885
|
state,
|
|
9118
|
-
|
|
9886
|
+
void 0,
|
|
9119
9887
|
includeScorers,
|
|
9120
|
-
brainstoreRealtime
|
|
9888
|
+
brainstoreRealtime,
|
|
9889
|
+
filters.filters
|
|
9121
9890
|
);
|
|
9122
|
-
|
|
9123
|
-
|
|
9124
|
-
|
|
9125
|
-
|
|
9126
|
-
|
|
9127
|
-
|
|
9128
|
-
|
|
9129
|
-
metrics: row.metrics,
|
|
9130
|
-
metadata: row.metadata,
|
|
9131
|
-
span_id: row.span_id,
|
|
9132
|
-
span_parents: row.span_parents,
|
|
9133
|
-
is_root: row.is_root,
|
|
9134
|
-
span_attributes: row.span_attributes,
|
|
9135
|
-
id: row.id,
|
|
9136
|
-
_xact_id: row._xact_id,
|
|
9137
|
-
_pagination_key: row._pagination_key,
|
|
9138
|
-
root_span_id: row.root_span_id,
|
|
9139
|
-
created: row.created,
|
|
9140
|
-
tags: row.tags
|
|
9141
|
-
}));
|
|
9891
|
+
let spans = (await fetcher.fetchedData()).map(
|
|
9892
|
+
(row) => ({ ...row })
|
|
9893
|
+
);
|
|
9894
|
+
if (filters.filters.metadata !== void 0) {
|
|
9895
|
+
spans = spans.filter((span) => matchesSpanFilters(span, filters));
|
|
9896
|
+
}
|
|
9897
|
+
return spans;
|
|
9142
9898
|
};
|
|
9143
9899
|
}
|
|
9144
9900
|
}
|
|
9145
9901
|
async getSpans({
|
|
9146
|
-
spanType,
|
|
9902
|
+
spanType: requestedSpanType,
|
|
9903
|
+
filters,
|
|
9147
9904
|
includeScorers = false
|
|
9148
9905
|
} = {}) {
|
|
9906
|
+
const normalizedFilters = normalizeSpanFilters(filters, requestedSpanType);
|
|
9907
|
+
const spanType = normalizedFilters.filters.spanType;
|
|
9908
|
+
const hasAdvancedFilters = Object.keys(normalizedFilters.filters).some(
|
|
9909
|
+
(field) => field !== "spanType"
|
|
9910
|
+
);
|
|
9911
|
+
if (spanType?.length === 0) {
|
|
9912
|
+
return [];
|
|
9913
|
+
}
|
|
9149
9914
|
if (includeScorers) {
|
|
9150
|
-
return this.fetchFn(
|
|
9915
|
+
return this.fetchFn(normalizedFilters, true);
|
|
9151
9916
|
}
|
|
9152
9917
|
if (this.allFetched) {
|
|
9153
|
-
|
|
9918
|
+
const spans = this.getFromCache(spanType);
|
|
9919
|
+
return hasAdvancedFilters ? spans.filter((span) => matchesSpanFilters(span, normalizedFilters)) : spans;
|
|
9154
9920
|
}
|
|
9155
|
-
if (
|
|
9921
|
+
if (hasAdvancedFilters && spanType && spanType.every((type) => this.spanCache.has(type))) {
|
|
9922
|
+
return this.getFromCache(spanType).filter(
|
|
9923
|
+
(span) => matchesSpanFilters(span, normalizedFilters)
|
|
9924
|
+
);
|
|
9925
|
+
}
|
|
9926
|
+
if (hasAdvancedFilters) {
|
|
9927
|
+
return this.fetchFn(normalizedFilters, false);
|
|
9928
|
+
}
|
|
9929
|
+
if (!spanType) {
|
|
9930
|
+
this.spanCache.clear();
|
|
9156
9931
|
await this.fetchSpans(void 0);
|
|
9157
|
-
this.
|
|
9932
|
+
if (this.spanCache.size > 0) {
|
|
9933
|
+
this.allFetched = true;
|
|
9934
|
+
}
|
|
9158
9935
|
return this.getFromCache(void 0);
|
|
9159
9936
|
}
|
|
9160
|
-
const missingTypes = spanType.filter((
|
|
9161
|
-
if (missingTypes.length
|
|
9162
|
-
|
|
9937
|
+
const missingTypes = spanType.filter((type) => !this.spanCache.has(type));
|
|
9938
|
+
if (missingTypes.length > 0) {
|
|
9939
|
+
await this.fetchSpans(missingTypes);
|
|
9163
9940
|
}
|
|
9164
|
-
await this.fetchSpans(missingTypes);
|
|
9165
9941
|
return this.getFromCache(spanType);
|
|
9166
9942
|
}
|
|
9167
9943
|
async fetchSpans(spanType) {
|
|
9168
|
-
const spans = await this.fetchFn(
|
|
9944
|
+
const spans = await this.fetchFn(
|
|
9945
|
+
normalizeSpanFilters(spanType ? { spanType } : void 0),
|
|
9946
|
+
false
|
|
9947
|
+
);
|
|
9169
9948
|
for (const span of spans) {
|
|
9170
9949
|
const type = span.span_attributes?.type ?? "";
|
|
9171
9950
|
const existing = this.spanCache.get(type) ?? [];
|
|
@@ -9245,34 +10024,20 @@ var LocalTrace = class {
|
|
|
9245
10024
|
*/
|
|
9246
10025
|
async getSpans({
|
|
9247
10026
|
spanType,
|
|
10027
|
+
filters,
|
|
9248
10028
|
includeScorers = false
|
|
9249
10029
|
} = {}) {
|
|
10030
|
+
const normalizedFilters = normalizeSpanFilters(filters, spanType);
|
|
9250
10031
|
const cachedSpans = this.state.spanCache.getByRootSpanId(this.rootSpanId);
|
|
9251
10032
|
if (cachedSpans && cachedSpans.length > 0) {
|
|
9252
|
-
|
|
9253
|
-
(span) => span.span_attributes?.purpose !== "scorer"
|
|
9254
|
-
);
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
return spans.map((span) => ({
|
|
9261
|
-
input: span.input,
|
|
9262
|
-
output: span.output,
|
|
9263
|
-
expected: span.expected,
|
|
9264
|
-
error: span.error,
|
|
9265
|
-
scores: span.scores,
|
|
9266
|
-
metrics: span.metrics,
|
|
9267
|
-
metadata: span.metadata,
|
|
9268
|
-
span_id: span.span_id,
|
|
9269
|
-
span_parents: span.span_parents,
|
|
9270
|
-
is_root: span.is_root,
|
|
9271
|
-
span_attributes: span.span_attributes,
|
|
9272
|
-
tags: span.tags
|
|
9273
|
-
}));
|
|
9274
|
-
}
|
|
9275
|
-
return this.cachedFetcher.getSpans({ spanType, includeScorers });
|
|
10033
|
+
return cachedSpans.filter(
|
|
10034
|
+
(span) => (includeScorers || span.span_attributes?.purpose !== "scorer") && matchesSpanFilters({ ...span }, normalizedFilters)
|
|
10035
|
+
).map((span) => ({ ...span }));
|
|
10036
|
+
}
|
|
10037
|
+
return this.cachedFetcher.getSpans({
|
|
10038
|
+
filters: normalizedFilters.filters,
|
|
10039
|
+
includeScorers
|
|
10040
|
+
});
|
|
9276
10041
|
}
|
|
9277
10042
|
/**
|
|
9278
10043
|
* Get the thread (preprocessed messages) for this trace.
|
|
@@ -9692,7 +10457,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
|
|
|
9692
10457
|
data,
|
|
9693
10458
|
{ disabled: Boolean(options.parent || options.noSendLogs) }
|
|
9694
10459
|
);
|
|
9695
|
-
if (experiment
|
|
10460
|
+
if (experiment) {
|
|
9696
10461
|
await experiment._waitForId();
|
|
9697
10462
|
}
|
|
9698
10463
|
if (experiment && options.onStart) {
|
|
@@ -10017,6 +10782,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
10017
10782
|
} : void 0;
|
|
10018
10783
|
const parsedDatumOrigin = ObjectReference.safeParse(datum.origin);
|
|
10019
10784
|
const origin = inlineDatasetOrigin ?? (parsedDatumOrigin?.success ? parsedDatumOrigin.data : void 0);
|
|
10785
|
+
const upsertId = datum.upsert_id && trialIndex > 0 ? uuidv5(
|
|
10786
|
+
`braintrust:eval:${datum.upsert_id}:trial:${trialIndex}`,
|
|
10787
|
+
uuidv5.URL
|
|
10788
|
+
) : datum.upsert_id;
|
|
10020
10789
|
const baseEvent = {
|
|
10021
10790
|
name: "eval",
|
|
10022
10791
|
spanAttributes: {
|
|
@@ -10027,7 +10796,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
10027
10796
|
expected: "expected" in datum ? datum.expected : void 0,
|
|
10028
10797
|
tags: datum.tags,
|
|
10029
10798
|
origin,
|
|
10030
|
-
...
|
|
10799
|
+
...upsertId ? { id: upsertId } : {}
|
|
10031
10800
|
}
|
|
10032
10801
|
};
|
|
10033
10802
|
const callback = async (rootSpan) => {
|
|
@@ -10536,14 +11305,14 @@ var defaultReporter = {
|
|
|
10536
11305
|
}
|
|
10537
11306
|
};
|
|
10538
11307
|
|
|
10539
|
-
// src/
|
|
11308
|
+
// src/workflow-eval.ts
|
|
10540
11309
|
var encoder = new TextEncoder();
|
|
10541
11310
|
var decoder = new TextDecoder();
|
|
10542
|
-
var
|
|
10543
|
-
var
|
|
10544
|
-
var
|
|
10545
|
-
var DurableEvalMemoryStore = class {
|
|
11311
|
+
var WORKFLOW_TASK_KIND = "braintrust.workflow.task";
|
|
11312
|
+
var WORKFLOW_SCORER_KIND = "braintrust.workflow.scorer";
|
|
11313
|
+
var WorkflowEvalMemoryStore = class {
|
|
10546
11314
|
values = /* @__PURE__ */ new Map();
|
|
11315
|
+
sets = /* @__PURE__ */ new Map();
|
|
10547
11316
|
async read(key) {
|
|
10548
11317
|
return this.values.get(key)?.slice();
|
|
10549
11318
|
}
|
|
@@ -10556,8 +11325,16 @@ var DurableEvalMemoryStore = class {
|
|
|
10556
11325
|
this.values.set(key, value.slice());
|
|
10557
11326
|
return { value: value.slice(), created: true };
|
|
10558
11327
|
}
|
|
11328
|
+
async addToSet(key, member) {
|
|
11329
|
+
let members = this.sets.get(key);
|
|
11330
|
+
if (!members) this.sets.set(key, members = /* @__PURE__ */ new Set());
|
|
11331
|
+
members.add(member);
|
|
11332
|
+
}
|
|
11333
|
+
async getSetSize(key) {
|
|
11334
|
+
return this.sets.get(key)?.size ?? 0;
|
|
11335
|
+
}
|
|
10559
11336
|
};
|
|
10560
|
-
var
|
|
11337
|
+
var WorkflowEvalRedisStore = class {
|
|
10561
11338
|
client;
|
|
10562
11339
|
keyPrefix;
|
|
10563
11340
|
ttlMs;
|
|
@@ -10566,14 +11343,16 @@ var DurableEvalRedisStore = class {
|
|
|
10566
11343
|
this.keyPrefix = options.keyPrefix ?? "braintrust-eval:";
|
|
10567
11344
|
this.ttlMs = options.ttlMs ?? 1e3 * 60 * 60 * 24 * 7;
|
|
10568
11345
|
if (!Number.isInteger(this.ttlMs) || this.ttlMs < 1) {
|
|
10569
|
-
throw new Error(
|
|
11346
|
+
throw new Error(
|
|
11347
|
+
"WorkflowEvalRedisStore ttlMs must be a positive integer"
|
|
11348
|
+
);
|
|
10570
11349
|
}
|
|
10571
11350
|
}
|
|
10572
11351
|
async read(key) {
|
|
10573
11352
|
const value = await this.client.get(`${this.keyPrefix}${key}`);
|
|
10574
11353
|
if (value == null) return void 0;
|
|
10575
11354
|
if (typeof value !== "string") {
|
|
10576
|
-
throw new Error("
|
|
11355
|
+
throw new Error("WorkflowEvalRedisStore expected GET to return a string");
|
|
10577
11356
|
}
|
|
10578
11357
|
return base64ToUint8Array(value);
|
|
10579
11358
|
}
|
|
@@ -10590,7 +11369,7 @@ var DurableEvalRedisStore = class {
|
|
|
10590
11369
|
await set.call(client, redisKey, encoded, { px: this.ttlMs });
|
|
10591
11370
|
} else {
|
|
10592
11371
|
throw new Error(
|
|
10593
|
-
"
|
|
11372
|
+
"WorkflowEvalRedisStore requires a node-redis, ioredis, or @upstash/redis client"
|
|
10594
11373
|
);
|
|
10595
11374
|
}
|
|
10596
11375
|
}
|
|
@@ -10608,49 +11387,73 @@ var DurableEvalRedisStore = class {
|
|
|
10608
11387
|
setOptions = [{ px: this.ttlMs, nx: true, get: true }];
|
|
10609
11388
|
} else {
|
|
10610
11389
|
throw new Error(
|
|
10611
|
-
"
|
|
11390
|
+
"WorkflowEvalRedisStore getOrSet requires a node-redis, ioredis, or @upstash/redis client"
|
|
10612
11391
|
);
|
|
10613
11392
|
}
|
|
10614
11393
|
const existing = await set.call(client, redisKey, encoded, ...setOptions);
|
|
10615
11394
|
if (existing === null) return { value: value.slice(), created: true };
|
|
10616
11395
|
if (typeof existing !== "string") {
|
|
10617
11396
|
throw new Error(
|
|
10618
|
-
"
|
|
11397
|
+
"WorkflowEvalRedisStore expected atomic SET to return a string or null"
|
|
10619
11398
|
);
|
|
10620
11399
|
}
|
|
10621
11400
|
return { value: base64ToUint8Array(existing), created: false };
|
|
10622
11401
|
}
|
|
11402
|
+
async addToSet(key, member) {
|
|
11403
|
+
await this.evalSet(
|
|
11404
|
+
"redis.call('SADD', KEYS[1], ARGV[1]); redis.call('PEXPIRE', KEYS[1], ARGV[2]); return 1",
|
|
11405
|
+
key,
|
|
11406
|
+
[member, String(this.ttlMs)]
|
|
11407
|
+
);
|
|
11408
|
+
}
|
|
11409
|
+
async getSetSize(key) {
|
|
11410
|
+
return this.evalSet("return redis.call('SCARD', KEYS[1])", key, []);
|
|
11411
|
+
}
|
|
11412
|
+
async evalSet(script, key, args) {
|
|
11413
|
+
const client = this.client;
|
|
11414
|
+
const redisKey = `${this.keyPrefix}${key}`;
|
|
11415
|
+
const result = typeof client.defineCommand === "function" ? await client.eval(script, 1, redisKey, ...args) : typeof client.sendCommand === "function" ? await client.eval(script, { keys: [redisKey], arguments: args }) : await client.eval(script, [redisKey], args);
|
|
11416
|
+
if (typeof result !== "number") {
|
|
11417
|
+
throw new Error(
|
|
11418
|
+
"WorkflowEvalRedisStore expected EVAL to return a number"
|
|
11419
|
+
);
|
|
11420
|
+
}
|
|
11421
|
+
return result;
|
|
11422
|
+
}
|
|
10623
11423
|
};
|
|
10624
|
-
var
|
|
11424
|
+
var WorkflowTask = class {
|
|
10625
11425
|
constructor(processor) {
|
|
10626
11426
|
this.processor = processor;
|
|
10627
11427
|
}
|
|
10628
11428
|
processor;
|
|
10629
|
-
kind =
|
|
11429
|
+
kind = WORKFLOW_TASK_KIND;
|
|
10630
11430
|
};
|
|
10631
|
-
var
|
|
11431
|
+
var WorkflowScorer = class {
|
|
10632
11432
|
constructor(processor) {
|
|
10633
11433
|
this.processor = processor;
|
|
10634
11434
|
this.name = processor.name;
|
|
10635
11435
|
}
|
|
10636
11436
|
processor;
|
|
10637
|
-
kind =
|
|
11437
|
+
kind = WORKFLOW_SCORER_KIND;
|
|
10638
11438
|
name;
|
|
10639
11439
|
};
|
|
10640
|
-
function
|
|
11440
|
+
function defineWorkflowEval(projectName, evaluator) {
|
|
11441
|
+
if (evaluator.maxConcurrency !== void 0 && (!Number.isInteger(evaluator.maxConcurrency) || evaluator.maxConcurrency < 1)) {
|
|
11442
|
+
throw new Error("maxConcurrency must be a positive integer");
|
|
11443
|
+
}
|
|
10641
11444
|
const definition = {
|
|
10642
11445
|
projectName,
|
|
10643
11446
|
evalName: evaluator.experimentName ?? projectName,
|
|
10644
11447
|
evaluator
|
|
10645
11448
|
};
|
|
10646
11449
|
return {
|
|
10647
|
-
start: (options = {}) =>
|
|
10648
|
-
status: (options) =>
|
|
10649
|
-
poll: (options) =>
|
|
10650
|
-
|
|
11450
|
+
start: (options = {}) => startWorkflowEval(definition, options),
|
|
11451
|
+
status: (options) => getWorkflowEvalStatus(definition, options),
|
|
11452
|
+
poll: (options) => pollWorkflowEval(definition, options),
|
|
11453
|
+
processSubmissionResult: (result) => processWorkflowSubmissionResult(definition, result)
|
|
10651
11454
|
};
|
|
10652
11455
|
}
|
|
10653
|
-
async function
|
|
11456
|
+
async function startWorkflowEval(definition, options) {
|
|
10654
11457
|
const store = definition.evaluator.store;
|
|
10655
11458
|
const runId = newId();
|
|
10656
11459
|
const key = runKey(definition.projectName, definition.evalName, runId);
|
|
@@ -10670,7 +11473,7 @@ async function startDurableEval(definition, options) {
|
|
|
10670
11473
|
update: true
|
|
10671
11474
|
}
|
|
10672
11475
|
);
|
|
10673
|
-
if (!
|
|
11476
|
+
if (!isWorkflowTask(definition.evaluator.task) && !(definition.evaluator.scores ?? []).some(isWorkflowScorer)) {
|
|
10674
11477
|
const result = await runEvaluator(
|
|
10675
11478
|
experiment,
|
|
10676
11479
|
{
|
|
@@ -10697,67 +11500,91 @@ async function startDurableEval(definition, options) {
|
|
|
10697
11500
|
parameters: assertJsonValue(parameters, "eval parameters"),
|
|
10698
11501
|
status: "completed",
|
|
10699
11502
|
summary: result.summary,
|
|
11503
|
+
caseCount: 0,
|
|
10700
11504
|
cases: [],
|
|
10701
|
-
|
|
11505
|
+
submissions: []
|
|
10702
11506
|
};
|
|
10703
11507
|
await experiment?.flush();
|
|
10704
11508
|
await writeRunRecord(store, key, state2);
|
|
10705
11509
|
return currentStatus(definition, state2);
|
|
10706
11510
|
}
|
|
11511
|
+
const cases = await materializeCases(definition, data, experiment);
|
|
10707
11512
|
const state = {
|
|
10708
11513
|
runId,
|
|
10709
11514
|
experimentName,
|
|
10710
11515
|
noSendLogs: options.noSendLogs ?? false,
|
|
10711
11516
|
parameters: assertJsonValue(parameters, "eval parameters"),
|
|
10712
11517
|
status: "running",
|
|
10713
|
-
|
|
10714
|
-
|
|
11518
|
+
caseCount: cases.length,
|
|
11519
|
+
cases,
|
|
11520
|
+
submissions: []
|
|
10715
11521
|
};
|
|
11522
|
+
await writeJson(
|
|
11523
|
+
store,
|
|
11524
|
+
`${key}/case-ids`,
|
|
11525
|
+
cases.map(({ id }) => id)
|
|
11526
|
+
);
|
|
10716
11527
|
await writeCaseBaseRecords(store, key, state.cases);
|
|
10717
11528
|
await writeRunRecord(store, key, state);
|
|
10718
|
-
return
|
|
11529
|
+
return advanceWorkflowEval(definition, state, store, key, experiment);
|
|
10719
11530
|
}
|
|
10720
|
-
async function
|
|
11531
|
+
async function getWorkflowEvalStatus(definition, options) {
|
|
10721
11532
|
const store = definition.evaluator.store;
|
|
10722
|
-
const
|
|
10723
|
-
definition,
|
|
10724
|
-
|
|
10725
|
-
|
|
11533
|
+
const key = runKey(
|
|
11534
|
+
definition.projectName,
|
|
11535
|
+
definition.evalName,
|
|
11536
|
+
options.runId
|
|
10726
11537
|
);
|
|
10727
|
-
|
|
11538
|
+
const state = await readJson(store, key);
|
|
11539
|
+
if (!state) throw new Error(`Workflow eval run ${options.runId} is missing`);
|
|
10728
11540
|
return currentStatus(definition, state);
|
|
10729
11541
|
}
|
|
10730
|
-
async function
|
|
10731
|
-
if (!result.
|
|
10732
|
-
throw new Error("
|
|
11542
|
+
async function processWorkflowSubmissionResult(definition, result) {
|
|
11543
|
+
if (!result.submissionId && !result.externalId) {
|
|
11544
|
+
throw new Error("Submission results require submissionId or externalId");
|
|
10733
11545
|
}
|
|
10734
11546
|
const store = definition.evaluator.store;
|
|
10735
11547
|
const key = runKey(definition.projectName, definition.evalName, result.runId);
|
|
10736
|
-
const
|
|
10737
|
-
if (!
|
|
10738
|
-
const
|
|
10739
|
-
|
|
10740
|
-
(
|
|
11548
|
+
const run = await readJson(store, key);
|
|
11549
|
+
if (!run) throw new Error(`Workflow eval run ${result.runId} is missing`);
|
|
11550
|
+
const externalSubmissionId = result.externalId ? await readJson(
|
|
11551
|
+
store,
|
|
11552
|
+
`${key}/external/${encodedKeyPart(result.externalId)}`
|
|
11553
|
+
) : void 0;
|
|
11554
|
+
if (result.submissionId && externalSubmissionId && result.submissionId !== externalSubmissionId) {
|
|
11555
|
+
throw new Error(
|
|
11556
|
+
"submissionId and externalId identify different submissions"
|
|
11557
|
+
);
|
|
11558
|
+
}
|
|
11559
|
+
const submissionId = result.submissionId ?? externalSubmissionId;
|
|
11560
|
+
const submission = submissionId ? await readJson(
|
|
11561
|
+
store,
|
|
11562
|
+
submissionRecordKey(key, submissionId)
|
|
10741
11563
|
) : void 0;
|
|
10742
|
-
if (
|
|
10743
|
-
|
|
10744
|
-
|
|
10745
|
-
|
|
10746
|
-
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
|
|
11564
|
+
if (!submission) throw new Error("No submission matches this result");
|
|
11565
|
+
if (result.externalId && submission.externalId !== result.externalId) {
|
|
11566
|
+
throw new Error(
|
|
11567
|
+
"submissionId and externalId identify different submissions"
|
|
11568
|
+
);
|
|
11569
|
+
}
|
|
11570
|
+
if (run.status === "completed") return currentStatus(definition, run);
|
|
11571
|
+
const state = await readRunState(definition, store, key, [
|
|
11572
|
+
submission.itemId
|
|
11573
|
+
]);
|
|
11574
|
+
if (submission.status !== "complete") {
|
|
11575
|
+
const record = await collectSubmission(definition, state, submission);
|
|
11576
|
+
await writeCaseRecords(store, key, [record]);
|
|
11577
|
+
submission.status = "complete";
|
|
11578
|
+
}
|
|
11579
|
+
await writeSubmissionRecords(store, key, [submission]);
|
|
11580
|
+
return advanceWorkflowEval(
|
|
10754
11581
|
definition,
|
|
10755
|
-
await readRunState(definition, store, key),
|
|
11582
|
+
await readRunState(definition, store, key, [submission.itemId]),
|
|
10756
11583
|
store,
|
|
10757
11584
|
key
|
|
10758
11585
|
);
|
|
10759
11586
|
}
|
|
10760
|
-
async function
|
|
11587
|
+
async function pollWorkflowEval(definition, options) {
|
|
10761
11588
|
const store = definition.evaluator.store;
|
|
10762
11589
|
const key = runKey(
|
|
10763
11590
|
definition.projectName,
|
|
@@ -10765,39 +11592,53 @@ async function pollDurableEval(definition, options) {
|
|
|
10765
11592
|
options.runId
|
|
10766
11593
|
);
|
|
10767
11594
|
const state = await readRunState(definition, store, key);
|
|
10768
|
-
if (!state) throw new Error(`
|
|
10769
|
-
const
|
|
10770
|
-
if (
|
|
10771
|
-
return processorForStage(definition,
|
|
10772
|
-
});
|
|
10773
|
-
const
|
|
10774
|
-
|
|
10775
|
-
|
|
10776
|
-
|
|
10777
|
-
|
|
10778
|
-
|
|
10779
|
-
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
|
|
10783
|
-
|
|
10784
|
-
for (const { batch, result } of results) {
|
|
11595
|
+
if (!state) throw new Error(`Workflow eval run ${options.runId} is missing`);
|
|
11596
|
+
const submissions = state.submissions.filter((submission) => {
|
|
11597
|
+
if (submission.status === "complete") return false;
|
|
11598
|
+
return processorForStage(definition, submission.kind, submission.scorerName).completion.mode === "poll";
|
|
11599
|
+
});
|
|
11600
|
+
const workers = queue(async (submission) => {
|
|
11601
|
+
const completion = processorForStage(
|
|
11602
|
+
definition,
|
|
11603
|
+
submission.kind,
|
|
11604
|
+
submission.scorerName
|
|
11605
|
+
).completion;
|
|
11606
|
+
if (completion.mode !== "poll") return;
|
|
11607
|
+
const result = await completion.poll(submission.submissionData, {
|
|
11608
|
+
runId: state.runId,
|
|
11609
|
+
submissionId: submission.id
|
|
11610
|
+
});
|
|
10785
11611
|
if (result.status === "failed") throw asError(result.error);
|
|
10786
|
-
if (result.status
|
|
10787
|
-
|
|
10788
|
-
|
|
10789
|
-
|
|
10790
|
-
|
|
10791
|
-
|
|
10792
|
-
}
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
11612
|
+
if (result.status === "complete") {
|
|
11613
|
+
const record = await collectSubmission(definition, state, submission);
|
|
11614
|
+
await writeCaseRecords(store, key, [record]);
|
|
11615
|
+
submission.status = "complete";
|
|
11616
|
+
await writeSubmissionRecords(store, key, [submission]);
|
|
11617
|
+
}
|
|
11618
|
+
}, definition.evaluator.maxConcurrency ?? 10);
|
|
11619
|
+
const results = await Promise.allSettled(
|
|
11620
|
+
submissions.map((submission) => workers.pushAsync(submission))
|
|
11621
|
+
);
|
|
11622
|
+
let status;
|
|
11623
|
+
const errors = results.flatMap(
|
|
11624
|
+
(result) => result.status === "rejected" ? [asError(result.reason)] : []
|
|
11625
|
+
);
|
|
11626
|
+
try {
|
|
11627
|
+
status = await advanceWorkflowEval(
|
|
11628
|
+
definition,
|
|
11629
|
+
await readRunState(definition, store, key),
|
|
11630
|
+
store,
|
|
11631
|
+
key
|
|
11632
|
+
);
|
|
11633
|
+
} catch (error) {
|
|
11634
|
+
errors.push(asError(error));
|
|
10796
11635
|
}
|
|
10797
|
-
|
|
10798
|
-
|
|
11636
|
+
if (errors.length === 1) throw errors[0];
|
|
11637
|
+
if (errors.length > 1)
|
|
11638
|
+
throw new AggregateError(errors, "Workflow submission callbacks failed");
|
|
11639
|
+
return status;
|
|
10799
11640
|
}
|
|
10800
|
-
async function
|
|
11641
|
+
async function openWorkflowExperiment(definition, state) {
|
|
10801
11642
|
const data = [];
|
|
10802
11643
|
return await _internalInitEvaluatorExperiment(
|
|
10803
11644
|
definition.projectName,
|
|
@@ -10810,45 +11651,49 @@ async function openDurableExperiment(definition, state) {
|
|
|
10810
11651
|
}
|
|
10811
11652
|
);
|
|
10812
11653
|
}
|
|
10813
|
-
async function
|
|
11654
|
+
async function advanceWorkflowEval(definition, state, store, key, existingExperiment) {
|
|
10814
11655
|
if (state.status === "completed") return currentStatus(definition, state);
|
|
10815
|
-
const experiment = existingExperiment === void 0 ? await
|
|
11656
|
+
const experiment = existingExperiment === void 0 ? await openWorkflowExperiment(definition, state) : existingExperiment;
|
|
11657
|
+
const caseIds = state.cases.map(({ id }) => id);
|
|
10816
11658
|
await runTaskStage(definition, state, store, key, experiment);
|
|
10817
11659
|
await logCompletedTasks(definition, state, store, key, experiment);
|
|
10818
|
-
state = await readRunState(definition, store, key) ?? state;
|
|
10819
|
-
if (state.cases.some((record) => !record.taskComplete || !record.taskLogged)) {
|
|
10820
|
-
return currentStatus(definition, state);
|
|
10821
|
-
}
|
|
11660
|
+
state = await readRunState(definition, store, key, caseIds) ?? state;
|
|
10822
11661
|
await runScoreStages(definition, state, store, key, experiment);
|
|
10823
|
-
state = await readRunState(definition, store, key) ?? state;
|
|
11662
|
+
state = await readRunState(definition, store, key, caseIds) ?? state;
|
|
10824
11663
|
const scorerNames = resolveScorers(definition.evaluator.scores ?? []).map(
|
|
10825
11664
|
({ name }) => name
|
|
10826
11665
|
);
|
|
10827
11666
|
const classifierNames = (definition.evaluator.classifiers ?? []).map(
|
|
10828
11667
|
classifierName
|
|
10829
11668
|
);
|
|
10830
|
-
|
|
10831
|
-
(record) =>
|
|
10832
|
-
(
|
|
10833
|
-
|
|
10834
|
-
|
|
10835
|
-
|
|
10836
|
-
|
|
11669
|
+
await Promise.all(
|
|
11670
|
+
state.cases.map(async (record) => {
|
|
11671
|
+
if (record.taskComplete && record.taskLogged && scorerNames.every(
|
|
11672
|
+
(name) => Object.hasOwn(record.scores, name) && Object.hasOwn(record.loggedScores, name)
|
|
11673
|
+
) && classifierNames.every(
|
|
11674
|
+
(name) => Object.hasOwn(record.loggedClassifications, name)
|
|
11675
|
+
)) {
|
|
11676
|
+
await store.addToSet(`${key}/progress/cases`, record.id);
|
|
11677
|
+
}
|
|
11678
|
+
})
|
|
11679
|
+
);
|
|
11680
|
+
if (await store.getSetSize(`${key}/progress/cases`) !== state.caseCount) {
|
|
10837
11681
|
return currentStatus(definition, state);
|
|
10838
11682
|
}
|
|
10839
11683
|
if (!await claimAction(store, key, "finish")) {
|
|
10840
|
-
const latest = await
|
|
11684
|
+
const latest = await readJson(store, key);
|
|
10841
11685
|
return currentStatus(definition, latest ?? state);
|
|
10842
11686
|
}
|
|
11687
|
+
state = await readRunState(definition, store, key);
|
|
10843
11688
|
state.summary = await finishExperiment(definition, state, experiment);
|
|
10844
11689
|
state.status = "completed";
|
|
10845
11690
|
await writeRunRecord(store, key, state);
|
|
10846
11691
|
return currentStatus(definition, state);
|
|
10847
11692
|
}
|
|
10848
|
-
function currentStatus(definition, state) {
|
|
11693
|
+
async function currentStatus(definition, state) {
|
|
10849
11694
|
if (state.status === "completed") {
|
|
10850
11695
|
if (!state.summary) {
|
|
10851
|
-
throw new Error(`
|
|
11696
|
+
throw new Error(`Workflow eval run ${state.runId} has no saved summary`);
|
|
10852
11697
|
}
|
|
10853
11698
|
return {
|
|
10854
11699
|
status: "completed",
|
|
@@ -10857,11 +11702,20 @@ function currentStatus(definition, state) {
|
|
|
10857
11702
|
summary: state.summary
|
|
10858
11703
|
};
|
|
10859
11704
|
}
|
|
11705
|
+
const key = runKey(definition.projectName, definition.evalName, state.runId);
|
|
11706
|
+
const store = definition.evaluator.store;
|
|
10860
11707
|
const pending = { poll: 0, webhook: 0 };
|
|
10861
|
-
|
|
10862
|
-
|
|
10863
|
-
|
|
10864
|
-
|
|
11708
|
+
await Promise.all(
|
|
11709
|
+
["poll", "webhook"].map(async (mode) => {
|
|
11710
|
+
const completed = await store.getSetSize(
|
|
11711
|
+
`${key}/progress/${mode}/complete`
|
|
11712
|
+
);
|
|
11713
|
+
const submitted = await store.getSetSize(
|
|
11714
|
+
`${key}/progress/${mode}/submitted`
|
|
11715
|
+
);
|
|
11716
|
+
pending[mode] = submitted - completed;
|
|
11717
|
+
})
|
|
11718
|
+
);
|
|
10865
11719
|
return { status: "waiting", runId: state.runId, pending };
|
|
10866
11720
|
}
|
|
10867
11721
|
async function startCaseRoot(definition, state, record, experiment) {
|
|
@@ -10922,7 +11776,7 @@ async function logTaskResult(definition, state, record, experiment, task) {
|
|
|
10922
11776
|
expected: "expected" in datum ? datum.expected : void 0,
|
|
10923
11777
|
metadata: {
|
|
10924
11778
|
...record.metadata,
|
|
10925
|
-
|
|
11779
|
+
workflow_eval: {
|
|
10926
11780
|
run_id: state.runId,
|
|
10927
11781
|
case_id: record.caseId,
|
|
10928
11782
|
trial_index: record.trialIndex
|
|
@@ -10953,8 +11807,8 @@ async function logCompletedTasks(definition, state, store, key, experiment) {
|
|
|
10953
11807
|
}
|
|
10954
11808
|
}
|
|
10955
11809
|
async function runTaskStage(definition, state, store, key, experiment) {
|
|
10956
|
-
if (
|
|
10957
|
-
await
|
|
11810
|
+
if (isWorkflowTask(definition.evaluator.task)) {
|
|
11811
|
+
await ensureSubmissions(definition, state, store, key, "task");
|
|
10958
11812
|
return;
|
|
10959
11813
|
}
|
|
10960
11814
|
const task = definition.evaluator.task;
|
|
@@ -10980,8 +11834,9 @@ async function runScoreStages(definition, state, store, key, experiment) {
|
|
|
10980
11834
|
changed.clear();
|
|
10981
11835
|
};
|
|
10982
11836
|
for (const { name, scorer } of scorers) {
|
|
10983
|
-
if (
|
|
11837
|
+
if (isWorkflowScorer(scorer)) {
|
|
10984
11838
|
for (const record of state.cases) {
|
|
11839
|
+
if (!record.taskComplete || !record.taskLogged) continue;
|
|
10985
11840
|
if (Object.hasOwn(record.scores, name) && !Object.hasOwn(record.loggedScores, name)) {
|
|
10986
11841
|
if (!await claimAction(store, key, "score-log", record.id, name)) {
|
|
10987
11842
|
continue;
|
|
@@ -10997,10 +11852,11 @@ async function runScoreStages(definition, state, store, key, experiment) {
|
|
|
10997
11852
|
}
|
|
10998
11853
|
}
|
|
10999
11854
|
await persistChangedCases();
|
|
11000
|
-
await
|
|
11855
|
+
await ensureSubmissions(definition, state, store, key, "score", name);
|
|
11001
11856
|
continue;
|
|
11002
11857
|
}
|
|
11003
11858
|
for (const record of state.cases) {
|
|
11859
|
+
if (!record.taskComplete || !record.taskLogged) continue;
|
|
11004
11860
|
if (Object.hasOwn(record.loggedScores, name)) continue;
|
|
11005
11861
|
if (!await claimAction(store, key, "score", record.id, name)) continue;
|
|
11006
11862
|
await evaluateAndLogScore(
|
|
@@ -11017,6 +11873,7 @@ async function runScoreStages(definition, state, store, key, experiment) {
|
|
|
11017
11873
|
for (const [index, classifier] of (definition.evaluator.classifiers ?? []).entries()) {
|
|
11018
11874
|
const name = classifierName(classifier, index);
|
|
11019
11875
|
for (const record of state.cases) {
|
|
11876
|
+
if (!record.taskComplete || !record.taskLogged) continue;
|
|
11020
11877
|
if (Object.hasOwn(record.loggedClassifications, name)) continue;
|
|
11021
11878
|
if (!await claimAction(store, key, "classification", record.id, name)) {
|
|
11022
11879
|
continue;
|
|
@@ -11039,13 +11896,14 @@ function scorerArgs(record) {
|
|
|
11039
11896
|
return {
|
|
11040
11897
|
...datum,
|
|
11041
11898
|
metadata: record.metadata,
|
|
11899
|
+
tags: record.tags,
|
|
11042
11900
|
output: record.output
|
|
11043
11901
|
};
|
|
11044
11902
|
}
|
|
11045
11903
|
function resumeCaseRoot(definition, record, experiment) {
|
|
11046
11904
|
if (!experiment) return NOOP_SPAN;
|
|
11047
11905
|
if (!record.rootSpan) {
|
|
11048
|
-
throw new Error(`
|
|
11906
|
+
throw new Error(`Workflow eval case ${record.caseId} has no root span`);
|
|
11049
11907
|
}
|
|
11050
11908
|
return _internalResumeSpan({
|
|
11051
11909
|
exported: record.rootSpan,
|
|
@@ -11133,117 +11991,110 @@ async function evaluateAndLogClassification(definition, state, record, name, cla
|
|
|
11133
11991
|
root.end();
|
|
11134
11992
|
}
|
|
11135
11993
|
}
|
|
11136
|
-
async function
|
|
11994
|
+
async function ensureSubmissions(definition, state, store, key, kind, scorerName2) {
|
|
11137
11995
|
const processor = processorForStage(definition, kind, scorerName2);
|
|
11138
|
-
const plans =
|
|
11996
|
+
const plans = plannedSubmissions(
|
|
11139
11997
|
definition,
|
|
11140
11998
|
state.runId,
|
|
11141
11999
|
state.cases.map(({ id }) => id)
|
|
11142
12000
|
);
|
|
11143
12001
|
const casesById = new Map(state.cases.map((record) => [record.id, record]));
|
|
11144
|
-
|
|
11145
|
-
|
|
11146
|
-
if (
|
|
11147
|
-
|
|
11148
|
-
const
|
|
11149
|
-
|
|
11150
|
-
);
|
|
11151
|
-
|
|
11152
|
-
const batchId = plan.id;
|
|
12002
|
+
const existingIds = new Set(state.submissions.map(({ id }) => id));
|
|
12003
|
+
const workers = queue(async (plan) => {
|
|
12004
|
+
if (plan.kind !== kind || plan.scorerName !== scorerName2) return;
|
|
12005
|
+
if (existingIds.has(plan.id)) return;
|
|
12006
|
+
const record = casesById.get(plan.itemId);
|
|
12007
|
+
const ready = kind === "task" ? !record.taskComplete : record.taskComplete && record.taskLogged && !Object.hasOwn(record.scores, scorerName2);
|
|
12008
|
+
if (!ready) return;
|
|
12009
|
+
const submissionId = plan.id;
|
|
11153
12010
|
const claim = await store.getOrSet(
|
|
11154
|
-
claimRecordKey(key, "
|
|
11155
|
-
encoder.encode(
|
|
11156
|
-
);
|
|
11157
|
-
if (!claim.created) continue;
|
|
11158
|
-
const context = { runId: state.runId, batchId };
|
|
11159
|
-
const items = records.map(
|
|
11160
|
-
(record) => kind === "task" ? taskBatchItem(record, state.parameters) : scorerBatchItem(record)
|
|
12011
|
+
claimRecordKey(key, "submission", submissionId),
|
|
12012
|
+
encoder.encode(submissionId)
|
|
11161
12013
|
);
|
|
12014
|
+
if (!claim.created) return;
|
|
12015
|
+
const context = { runId: state.runId, submissionId };
|
|
12016
|
+
const item = kind === "task" ? taskSubmissionItem(record, state.parameters) : scorerSubmissionItem(record);
|
|
11162
12017
|
const submissionData = assertJsonValue(
|
|
11163
|
-
await processor.submit(
|
|
11164
|
-
`submission data for
|
|
12018
|
+
await processor.submit(item, context),
|
|
12019
|
+
`submission data for submission ${submissionId}`
|
|
11165
12020
|
);
|
|
11166
12021
|
const externalId = processor.completion.mode === "webhook" ? processor.completion.getExternalId(submissionData, context) : void 0;
|
|
11167
12022
|
if (externalId !== void 0 && !externalId.trim()) {
|
|
11168
|
-
throw new Error(
|
|
12023
|
+
throw new Error(
|
|
12024
|
+
`Submission ${submissionId} produced an empty externalId`
|
|
12025
|
+
);
|
|
11169
12026
|
}
|
|
11170
|
-
const
|
|
11171
|
-
id:
|
|
12027
|
+
const submission = {
|
|
12028
|
+
id: submissionId,
|
|
11172
12029
|
kind,
|
|
11173
12030
|
scorerName: scorerName2,
|
|
11174
|
-
|
|
12031
|
+
itemId: record.id,
|
|
11175
12032
|
submissionData,
|
|
11176
12033
|
externalId,
|
|
11177
|
-
status: "submitted"
|
|
12034
|
+
status: "submitted",
|
|
12035
|
+
completionMode: processor.completion.mode
|
|
11178
12036
|
};
|
|
11179
|
-
state.
|
|
11180
|
-
await
|
|
11181
|
-
}
|
|
12037
|
+
state.submissions.push(submission);
|
|
12038
|
+
await writeSubmissionRecords(store, key, [submission]);
|
|
12039
|
+
}, definition.evaluator.maxConcurrency ?? 10);
|
|
12040
|
+
const results = await Promise.allSettled(
|
|
12041
|
+
plans.map((plan) => workers.pushAsync(plan))
|
|
12042
|
+
);
|
|
12043
|
+
const errors = results.flatMap(
|
|
12044
|
+
(result) => result.status === "rejected" ? [asError(result.reason)] : []
|
|
12045
|
+
);
|
|
12046
|
+
if (errors.length === 1) throw errors[0];
|
|
12047
|
+
if (errors.length > 1)
|
|
12048
|
+
throw new AggregateError(errors, "Workflow submissions failed");
|
|
11182
12049
|
}
|
|
11183
|
-
async function
|
|
11184
|
-
const processor = processorForStage(
|
|
11185
|
-
|
|
11186
|
-
|
|
11187
|
-
|
|
11188
|
-
|
|
12050
|
+
async function collectSubmission(definition, state, submission) {
|
|
12051
|
+
const processor = processorForStage(
|
|
12052
|
+
definition,
|
|
12053
|
+
submission.kind,
|
|
12054
|
+
submission.scorerName
|
|
12055
|
+
);
|
|
12056
|
+
const context = { runId: state.runId, submissionId: submission.id };
|
|
12057
|
+
const result = await processor.collect(submission.submissionData, context);
|
|
12058
|
+
if (typeof result !== "object" || result === null || Array.isArray(result)) {
|
|
12059
|
+
throw new Error(
|
|
12060
|
+
`collect for submission ${submission.id} must return a result object`
|
|
12061
|
+
);
|
|
11189
12062
|
}
|
|
11190
|
-
const
|
|
11191
|
-
|
|
11192
|
-
|
|
11193
|
-
|
|
11194
|
-
|
|
11195
|
-
|
|
11196
|
-
|
|
11197
|
-
|
|
11198
|
-
if (
|
|
11199
|
-
|
|
11200
|
-
|
|
11201
|
-
|
|
11202
|
-
const record = state.cases.find((candidate) => candidate.id === id);
|
|
11203
|
-
records.push(record);
|
|
11204
|
-
if (batch.kind === "task") {
|
|
11205
|
-
record.output = assertJsonValue(
|
|
11206
|
-
result.output,
|
|
11207
|
-
`task output for item ${id}`
|
|
11208
|
-
);
|
|
11209
|
-
if ("metadata" in result && result.metadata !== void 0) {
|
|
11210
|
-
record.metadata = assertJsonValue(
|
|
11211
|
-
{
|
|
11212
|
-
...record.metadata,
|
|
11213
|
-
...result.metadata
|
|
11214
|
-
},
|
|
11215
|
-
`metadata for ${id}`
|
|
11216
|
-
);
|
|
11217
|
-
}
|
|
11218
|
-
if ("tags" in result && result.tags !== void 0)
|
|
11219
|
-
record.tags = result.tags;
|
|
11220
|
-
record.taskComplete = true;
|
|
11221
|
-
} else {
|
|
11222
|
-
record.scores[batch.scorerName] = assertJsonValue(
|
|
11223
|
-
result.score,
|
|
11224
|
-
`score output for item ${id}`
|
|
12063
|
+
const record = state.cases.find(
|
|
12064
|
+
(candidate) => candidate.id === submission.itemId
|
|
12065
|
+
);
|
|
12066
|
+
if (submission.kind === "task") {
|
|
12067
|
+
record.output = assertJsonValue(
|
|
12068
|
+
result.output,
|
|
12069
|
+
`task output for item ${record.id}`
|
|
12070
|
+
);
|
|
12071
|
+
if (result.metadata !== void 0) {
|
|
12072
|
+
record.metadata = assertJsonValue(
|
|
12073
|
+
{ ...record.metadata, ...result.metadata },
|
|
12074
|
+
`metadata for ${record.id}`
|
|
11225
12075
|
);
|
|
11226
12076
|
}
|
|
11227
|
-
|
|
11228
|
-
|
|
11229
|
-
|
|
11230
|
-
|
|
11231
|
-
|
|
12077
|
+
if (result.tags !== void 0) record.tags = result.tags;
|
|
12078
|
+
record.taskComplete = true;
|
|
12079
|
+
} else {
|
|
12080
|
+
record.scores[submission.scorerName] = assertJsonValue(
|
|
12081
|
+
result.score,
|
|
12082
|
+
`score output for item ${record.id}`
|
|
11232
12083
|
);
|
|
11233
12084
|
}
|
|
11234
|
-
return
|
|
12085
|
+
return record;
|
|
11235
12086
|
}
|
|
11236
12087
|
function processorForStage(definition, kind, scorerName2) {
|
|
11237
12088
|
if (kind === "task") {
|
|
11238
|
-
if (!
|
|
11239
|
-
throw new Error("Definition no longer contains the
|
|
12089
|
+
if (!isWorkflowTask(definition.evaluator.task)) {
|
|
12090
|
+
throw new Error("Definition no longer contains the submission task");
|
|
11240
12091
|
}
|
|
11241
12092
|
return definition.evaluator.task.processor;
|
|
11242
12093
|
}
|
|
11243
12094
|
const scorer = resolveScorers(definition.evaluator.scores ?? []).find(
|
|
11244
12095
|
({ name }) => name === scorerName2
|
|
11245
12096
|
)?.scorer;
|
|
11246
|
-
if (!
|
|
12097
|
+
if (!isWorkflowScorer(scorer)) {
|
|
11247
12098
|
throw new Error(`Definition no longer contains scorer ${scorerName2}`);
|
|
11248
12099
|
}
|
|
11249
12100
|
return scorer.processor;
|
|
@@ -11265,15 +12116,15 @@ async function materializeCases(definition, data, experiment) {
|
|
|
11265
12116
|
const caseId = datum.id ?? datum.upsert_id ?? (evaluator.caseId ? await evaluator.caseId(datum) : void 0);
|
|
11266
12117
|
if (!caseId) {
|
|
11267
12118
|
throw new Error(
|
|
11268
|
-
"Every
|
|
12119
|
+
"Every workflow eval case requires id, upsert_id, or caseId"
|
|
11269
12120
|
);
|
|
11270
12121
|
}
|
|
11271
12122
|
if (seen.has(caseId))
|
|
11272
|
-
throw new Error(`Duplicate
|
|
12123
|
+
throw new Error(`Duplicate workflow eval case id: ${caseId}`);
|
|
11273
12124
|
seen.add(caseId);
|
|
11274
12125
|
const trialCount = datum.trialCount ?? evaluator.trialCount ?? 1;
|
|
11275
12126
|
if (!Number.isInteger(trialCount) || trialCount < 1) {
|
|
11276
|
-
throw new Error(`Invalid trialCount for
|
|
12127
|
+
throw new Error(`Invalid trialCount for workflow eval case ${caseId}`);
|
|
11277
12128
|
}
|
|
11278
12129
|
for (let trialIndex = 0; trialIndex < trialCount; trialIndex++) {
|
|
11279
12130
|
records.push({
|
|
@@ -11297,7 +12148,7 @@ async function materializeCases(definition, data, experiment) {
|
|
|
11297
12148
|
}
|
|
11298
12149
|
return records;
|
|
11299
12150
|
}
|
|
11300
|
-
function
|
|
12151
|
+
function taskSubmissionItem(record, parameters) {
|
|
11301
12152
|
const datum = record.datum;
|
|
11302
12153
|
return {
|
|
11303
12154
|
id: record.id,
|
|
@@ -11309,7 +12160,7 @@ function taskBatchItem(record, parameters) {
|
|
|
11309
12160
|
trialIndex: record.trialIndex
|
|
11310
12161
|
};
|
|
11311
12162
|
}
|
|
11312
|
-
function
|
|
12163
|
+
function scorerSubmissionItem(record) {
|
|
11313
12164
|
const datum = record.datum;
|
|
11314
12165
|
return {
|
|
11315
12166
|
id: record.id,
|
|
@@ -11380,12 +12231,12 @@ async function finishExperiment(definition, state, experiment) {
|
|
|
11380
12231
|
}
|
|
11381
12232
|
function resolveScorers(scorers) {
|
|
11382
12233
|
return scorers.map((scorer, index) => ({
|
|
11383
|
-
name:
|
|
12234
|
+
name: isWorkflowScorer(scorer) ? scorer.name : scorer.name || `scorer_${index}`,
|
|
11384
12235
|
scorer
|
|
11385
12236
|
}));
|
|
11386
12237
|
}
|
|
11387
12238
|
function runKey(projectName, evalName, runId) {
|
|
11388
|
-
return `
|
|
12239
|
+
return `workflow-eval/v1/runs/${contentVersion(encoder.encode(`${projectName}\0${evalName}\0${runId}`))}`;
|
|
11389
12240
|
}
|
|
11390
12241
|
function encodedKeyPart(value) {
|
|
11391
12242
|
return uint8ArrayToBase64(encoder.encode(value)).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
|
|
@@ -11394,8 +12245,8 @@ function caseRecordKey(key, caseId, kind, ...names) {
|
|
|
11394
12245
|
const suffix = names.map(encodedKeyPart).join("/");
|
|
11395
12246
|
return `${key}/cases/${encodedKeyPart(caseId)}/${kind}${suffix ? `/${suffix}` : ""}`;
|
|
11396
12247
|
}
|
|
11397
|
-
function
|
|
11398
|
-
return `${key}/
|
|
12248
|
+
function submissionRecordKey(key, submissionId) {
|
|
12249
|
+
return `${key}/submissions/${encodedKeyPart(submissionId)}`;
|
|
11399
12250
|
}
|
|
11400
12251
|
function claimRecordKey(key, kind, ...parts) {
|
|
11401
12252
|
const identity = stableStringify([kind, parts]);
|
|
@@ -11407,33 +12258,24 @@ async function claimAction(store, key, kind, ...parts) {
|
|
|
11407
12258
|
encoder.encode("claimed")
|
|
11408
12259
|
)).created;
|
|
11409
12260
|
}
|
|
11410
|
-
function
|
|
12261
|
+
function plannedSubmissions(definition, runId, caseIds) {
|
|
11411
12262
|
const stages = [];
|
|
11412
|
-
if (
|
|
12263
|
+
if (isWorkflowTask(definition.evaluator.task)) stages.push({ kind: "task" });
|
|
11413
12264
|
for (const { name, scorer } of resolveScorers(
|
|
11414
12265
|
definition.evaluator.scores ?? []
|
|
11415
12266
|
)) {
|
|
11416
|
-
if (
|
|
12267
|
+
if (isWorkflowScorer(scorer)) {
|
|
11417
12268
|
stages.push({ kind: "score", scorerName: name });
|
|
11418
12269
|
}
|
|
11419
12270
|
}
|
|
11420
12271
|
const plans = [];
|
|
11421
12272
|
for (const { kind, scorerName: scorerName2 } of stages) {
|
|
11422
|
-
const
|
|
11423
|
-
if (!Number.isInteger(batchSize) || batchSize < 1) {
|
|
11424
|
-
throw new Error(
|
|
11425
|
-
`Invalid batchSize for ${scorerName2 ?? "task"}: ${batchSize}`
|
|
11426
|
-
);
|
|
11427
|
-
}
|
|
11428
|
-
for (let offset = 0; offset < caseIds.length; offset += batchSize) {
|
|
11429
|
-
const itemIds = caseIds.slice(offset, offset + batchSize);
|
|
12273
|
+
for (const itemId of caseIds) {
|
|
11430
12274
|
plans.push({
|
|
11431
|
-
id: deterministicId(
|
|
11432
|
-
stableStringify([runId, kind, scorerName2, itemIds])
|
|
11433
|
-
),
|
|
12275
|
+
id: deterministicId(stableStringify([runId, kind, scorerName2, itemId])),
|
|
11434
12276
|
kind,
|
|
11435
12277
|
scorerName: scorerName2,
|
|
11436
|
-
|
|
12278
|
+
itemId
|
|
11437
12279
|
});
|
|
11438
12280
|
}
|
|
11439
12281
|
}
|
|
@@ -11493,7 +12335,7 @@ async function readCaseRecord(definition, store, key, id) {
|
|
|
11493
12335
|
}))
|
|
11494
12336
|
)
|
|
11495
12337
|
]);
|
|
11496
|
-
if (!base) throw new Error(`
|
|
12338
|
+
if (!base) throw new Error(`Workflow eval case ${id} is missing`);
|
|
11497
12339
|
const scores = /* @__PURE__ */ Object.create(null);
|
|
11498
12340
|
for (const { name, value } of scoreValues) {
|
|
11499
12341
|
if (value !== void 0) scores[name] = value;
|
|
@@ -11524,32 +12366,34 @@ async function readCaseRecord(definition, store, key, id) {
|
|
|
11524
12366
|
loggedClassifications
|
|
11525
12367
|
};
|
|
11526
12368
|
}
|
|
11527
|
-
async function readRunState(definition, store, key) {
|
|
12369
|
+
async function readRunState(definition, store, key, caseIds) {
|
|
11528
12370
|
const record = await readJson(store, key);
|
|
11529
12371
|
if (!record) return void 0;
|
|
11530
|
-
const
|
|
11531
|
-
|
|
12372
|
+
const selectedIds = caseIds ?? (record.caseCount === 0 ? [] : await readJson(store, `${key}/case-ids`));
|
|
12373
|
+
if (!selectedIds)
|
|
12374
|
+
throw new Error(`Workflow eval run ${record.runId} has no case index`);
|
|
12375
|
+
const plans = plannedSubmissions(definition, record.runId, selectedIds);
|
|
12376
|
+
const [cases, submissionRecords] = await Promise.all([
|
|
11532
12377
|
Promise.all(
|
|
11533
|
-
|
|
12378
|
+
selectedIds.map((id) => readCaseRecord(definition, store, key, id))
|
|
11534
12379
|
),
|
|
11535
12380
|
Promise.all(
|
|
11536
12381
|
plans.map(async ({ id }) => {
|
|
11537
|
-
return readJson(
|
|
12382
|
+
return readJson(
|
|
12383
|
+
store,
|
|
12384
|
+
submissionRecordKey(key, id)
|
|
12385
|
+
);
|
|
11538
12386
|
})
|
|
11539
12387
|
)
|
|
11540
12388
|
]);
|
|
11541
|
-
const
|
|
12389
|
+
const submissions = submissionRecords.filter(
|
|
11542
12390
|
(value) => value !== void 0
|
|
11543
12391
|
);
|
|
11544
|
-
|
|
11545
|
-
return { ...state, cases, batches };
|
|
12392
|
+
return { ...record, cases, submissions };
|
|
11546
12393
|
}
|
|
11547
12394
|
async function writeRunRecord(store, key, state) {
|
|
11548
|
-
const { cases,
|
|
11549
|
-
await writeJson(store, key,
|
|
11550
|
-
...record,
|
|
11551
|
-
caseIds: cases.map(({ id }) => id)
|
|
11552
|
-
});
|
|
12395
|
+
const { cases: _cases, submissions: _submissions, ...record } = state;
|
|
12396
|
+
await writeJson(store, key, record);
|
|
11553
12397
|
}
|
|
11554
12398
|
async function writeCaseBaseRecords(store, key, records) {
|
|
11555
12399
|
await Promise.all(
|
|
@@ -11621,11 +12465,25 @@ async function writeCaseRecords(store, key, records) {
|
|
|
11621
12465
|
}
|
|
11622
12466
|
await Promise.all(writes);
|
|
11623
12467
|
}
|
|
11624
|
-
async function
|
|
12468
|
+
async function writeSubmissionRecords(store, key, records) {
|
|
11625
12469
|
await Promise.all(
|
|
11626
|
-
records.map(
|
|
11627
|
-
(record
|
|
11628
|
-
|
|
12470
|
+
records.map(async (record) => {
|
|
12471
|
+
if (record.externalId !== void 0) {
|
|
12472
|
+
const locator = await store.getOrSet(
|
|
12473
|
+
`${key}/external/${encodedKeyPart(record.externalId)}`,
|
|
12474
|
+
encoder.encode(JSON.stringify(record.id))
|
|
12475
|
+
);
|
|
12476
|
+
if (JSON.parse(decoder.decode(locator.value)) !== record.id) {
|
|
12477
|
+
throw new Error(`Duplicate externalId: ${record.externalId}`);
|
|
12478
|
+
}
|
|
12479
|
+
}
|
|
12480
|
+
const progressKey = `${key}/progress/${record.completionMode}`;
|
|
12481
|
+
await store.addToSet(`${progressKey}/submitted`, record.id);
|
|
12482
|
+
if (record.status === "complete") {
|
|
12483
|
+
await store.addToSet(`${progressKey}/complete`, record.id);
|
|
12484
|
+
}
|
|
12485
|
+
await writeJson(store, submissionRecordKey(key, record.id), record);
|
|
12486
|
+
})
|
|
11629
12487
|
);
|
|
11630
12488
|
}
|
|
11631
12489
|
function deterministicId(value) {
|
|
@@ -11670,17 +12528,11 @@ function assertJsonValue(value, label) {
|
|
|
11670
12528
|
throw new Error(`${label} must be JSON serializable`, { cause: error });
|
|
11671
12529
|
}
|
|
11672
12530
|
}
|
|
11673
|
-
function
|
|
11674
|
-
|
|
11675
|
-
throw new Error("Batch results must contain a string id");
|
|
11676
|
-
}
|
|
11677
|
-
return value.id;
|
|
11678
|
-
}
|
|
11679
|
-
function isBatchTask(value) {
|
|
11680
|
-
return typeof value === "object" && value !== null && "kind" in value && value.kind === BATCH_TASK_KIND;
|
|
12531
|
+
function isWorkflowTask(value) {
|
|
12532
|
+
return typeof value === "object" && value !== null && "kind" in value && value.kind === WORKFLOW_TASK_KIND;
|
|
11681
12533
|
}
|
|
11682
|
-
function
|
|
11683
|
-
return typeof value === "object" && value !== null && "kind" in value && value.kind ===
|
|
12534
|
+
function isWorkflowScorer(value) {
|
|
12535
|
+
return typeof value === "object" && value !== null && "kind" in value && value.kind === WORKFLOW_SCORER_KIND;
|
|
11684
12536
|
}
|
|
11685
12537
|
function asError(error) {
|
|
11686
12538
|
return error instanceof Error ? error : new Error(String(error));
|
|
@@ -12608,13 +13460,13 @@ var evaluatorDefinitionsSchema = z5.record(
|
|
|
12608
13460
|
);
|
|
12609
13461
|
|
|
12610
13462
|
// src/wrappers/elevenlabs.ts
|
|
12611
|
-
var
|
|
13463
|
+
var clients2 = /* @__PURE__ */ new WeakMap();
|
|
12612
13464
|
function wrapElevenLabs(client) {
|
|
12613
13465
|
if (!isObject(client) || !isObject(client.textToSpeech) || typeof client.textToSpeech.convert !== "function") {
|
|
12614
13466
|
debugLogger.warn("Unsupported ElevenLabs client. Not wrapping.");
|
|
12615
13467
|
return client;
|
|
12616
13468
|
}
|
|
12617
|
-
const cached =
|
|
13469
|
+
const cached = clients2.get(client);
|
|
12618
13470
|
if (cached) return cached;
|
|
12619
13471
|
const sdk = client;
|
|
12620
13472
|
const speech = new Proxy(sdk.textToSpeech, {
|
|
@@ -12661,8 +13513,8 @@ function wrapElevenLabs(client) {
|
|
|
12661
13513
|
return Reflect.get(target, prop, receiver);
|
|
12662
13514
|
}
|
|
12663
13515
|
});
|
|
12664
|
-
|
|
12665
|
-
|
|
13516
|
+
clients2.set(client, proxy);
|
|
13517
|
+
clients2.set(proxy, proxy);
|
|
12666
13518
|
return proxy;
|
|
12667
13519
|
}
|
|
12668
13520
|
|
|
@@ -12677,8 +13529,6 @@ export {
|
|
|
12677
13529
|
BRAINTRUST_PARENT_KEY,
|
|
12678
13530
|
BaseAttachment,
|
|
12679
13531
|
BaseExperiment,
|
|
12680
|
-
BatchScorer,
|
|
12681
|
-
BatchTask,
|
|
12682
13532
|
BraintrustLangChainCallbackHandler,
|
|
12683
13533
|
BraintrustMiddleware,
|
|
12684
13534
|
BraintrustObservabilityExporter,
|
|
@@ -12692,8 +13542,6 @@ export {
|
|
|
12692
13542
|
DEFAULT_MAX_REQUEST_SIZE,
|
|
12693
13543
|
Dataset,
|
|
12694
13544
|
DatasetPipeline,
|
|
12695
|
-
DurableEvalMemoryStore,
|
|
12696
|
-
DurableEvalRedisStore,
|
|
12697
13545
|
ERR_PERMALINK,
|
|
12698
13546
|
Eval,
|
|
12699
13547
|
EvalResultWithSummary,
|
|
@@ -12728,6 +13576,10 @@ export {
|
|
|
12728
13576
|
TestBackgroundLogger,
|
|
12729
13577
|
ToolBuilder,
|
|
12730
13578
|
UUIDGenerator,
|
|
13579
|
+
WorkflowEvalMemoryStore,
|
|
13580
|
+
WorkflowEvalRedisStore,
|
|
13581
|
+
WorkflowScorer,
|
|
13582
|
+
WorkflowTask,
|
|
12731
13583
|
X_CACHED_HEADER,
|
|
12732
13584
|
_exportsForTestingOnly,
|
|
12733
13585
|
_internalGetGlobalState,
|
|
@@ -12753,12 +13605,13 @@ export {
|
|
|
12753
13605
|
deepCopyEvent,
|
|
12754
13606
|
exports_exports as default,
|
|
12755
13607
|
defaultErrorScoreHandler,
|
|
12756
|
-
|
|
13608
|
+
defineWorkflowEval,
|
|
12757
13609
|
deserializePlainStringAsJSON,
|
|
12758
13610
|
devNullWritableStream,
|
|
12759
13611
|
evaluatorDefinitionSchema,
|
|
12760
13612
|
evaluatorDefinitionsSchema,
|
|
12761
13613
|
extractTraceContextFromHeaders,
|
|
13614
|
+
failOpenAIAgentsTrace,
|
|
12762
13615
|
flush,
|
|
12763
13616
|
getContextManager,
|
|
12764
13617
|
getIdGenerator,
|
|
@@ -12805,12 +13658,14 @@ export {
|
|
|
12805
13658
|
setFetch,
|
|
12806
13659
|
setMaskingFunction,
|
|
12807
13660
|
spanComponentsToObjectId,
|
|
13661
|
+
startOpenAIAgentsTrace,
|
|
12808
13662
|
startSpan,
|
|
12809
13663
|
summarize,
|
|
12810
13664
|
templateRegistry,
|
|
12811
13665
|
ToolFunctionDefinition as toolFunctionDefinitionSchema,
|
|
12812
13666
|
traceable,
|
|
12813
13667
|
traced,
|
|
13668
|
+
updateOpenAIAgentsTrace,
|
|
12814
13669
|
updateSpan,
|
|
12815
13670
|
uploadLogs3OverflowPayload,
|
|
12816
13671
|
utf8ByteLength,
|
|
@@ -12839,6 +13694,7 @@ export {
|
|
|
12839
13694
|
wrapGroq,
|
|
12840
13695
|
wrapHuggingFace,
|
|
12841
13696
|
wrapHuggingFaceTransformers,
|
|
13697
|
+
wrapLangGraphSDK,
|
|
12842
13698
|
wrapLangSmithClient,
|
|
12843
13699
|
wrapLangSmithRunTrees,
|
|
12844
13700
|
wrapLangSmithTraceable,
|