braintrust 3.31.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 +767 -0
- package/dev/dist/index.d.ts +767 -0
- package/dev/dist/index.js +3115 -908
- package/dev/dist/index.mjs +2466 -259
- package/dist/apply-auto-instrumentation.js +325 -221
- package/dist/apply-auto-instrumentation.mjs +110 -6
- package/dist/auto-instrumentations/bundler/esbuild.cjs +182 -7
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +182 -7
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +182 -7
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +182 -7
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +182 -7
- package/dist/auto-instrumentations/bundler/webpack.cjs +182 -7
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-U64OYU4Q.mjs → chunk-T2DMPWFI.mjs} +113 -6
- package/dist/auto-instrumentations/{chunk-LW4HDHXT.mjs → chunk-UHJ2DNYJ.mjs} +74 -2
- package/dist/auto-instrumentations/{chunk-OXINGIEZ.mjs → chunk-W5QNG3PV.mjs} +1 -1
- package/dist/auto-instrumentations/hook.mjs +209 -9
- package/dist/auto-instrumentations/index.cjs +115 -6
- package/dist/auto-instrumentations/index.d.mts +5 -1
- package/dist/auto-instrumentations/index.d.ts +5 -1
- package/dist/auto-instrumentations/index.mjs +5 -1
- package/dist/browser.d.mts +2324 -342
- package/dist/browser.d.ts +2324 -342
- package/dist/browser.js +3573 -626
- package/dist/browser.mjs +3573 -626
- package/dist/chunk-7P6ASYW6.mjs +9 -0
- package/dist/{chunk-V32LW47Z.js → chunk-AXJTOUOC.js} +3022 -1131
- package/dist/{chunk-4AQGZS6X.js → chunk-G3VHOHRC.js} +85 -11
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/{chunk-AJT4FR25.mjs → chunk-MZLBAFVJ.mjs} +2051 -160
- package/dist/{chunk-CE3BLB2L.mjs → chunk-TZVZN2JJ.mjs} +84 -10
- package/dist/cli.js +2614 -297
- 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 +3573 -626
- package/dist/edge-light.mjs +3573 -626
- package/dist/index.d.mts +2324 -342
- package/dist/index.d.ts +2324 -342
- package/dist/index.js +1959 -969
- package/dist/index.mjs +1450 -460
- package/dist/instrumentation/index.d.mts +439 -245
- package/dist/instrumentation/index.d.ts +439 -245
- package/dist/instrumentation/index.js +2550 -258
- package/dist/instrumentation/index.mjs +2550 -258
- 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 +3573 -626
- package/dist/workerd.mjs +3573 -626
- package/package.json +10 -2
- package/util/dist/index.d.mts +326 -0
- package/util/dist/index.d.ts +326 -0
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,
|
|
@@ -156,16 +157,19 @@ import {
|
|
|
156
157
|
cohereChannels,
|
|
157
158
|
cursorSDKChannels,
|
|
158
159
|
debugLogger,
|
|
160
|
+
elevenLabsChannels,
|
|
159
161
|
genkitChannels,
|
|
160
162
|
gitHubCopilotChannels,
|
|
161
163
|
googleADKChannels,
|
|
162
164
|
googleGenAIChannels,
|
|
165
|
+
googleGenerativeAIChannels,
|
|
163
166
|
groqChannels,
|
|
164
167
|
harnessAgentChannels,
|
|
165
168
|
huggingFaceChannels,
|
|
166
169
|
huggingFaceTransformersChannels,
|
|
167
170
|
isSupportedHuggingFaceTransformersTask,
|
|
168
171
|
isomorph_default,
|
|
172
|
+
langGraphSDKChannels,
|
|
169
173
|
langSmithChannels,
|
|
170
174
|
mistralChannels,
|
|
171
175
|
ollamaChannels,
|
|
@@ -177,7 +181,10 @@ import {
|
|
|
177
181
|
strandsAgentSDKChannels,
|
|
178
182
|
voyageAIChannels,
|
|
179
183
|
withSpanInstrumentationName
|
|
180
|
-
} from "./chunk-
|
|
184
|
+
} from "./chunk-TZVZN2JJ.mjs";
|
|
185
|
+
import {
|
|
186
|
+
__export
|
|
187
|
+
} from "./chunk-7P6ASYW6.mjs";
|
|
181
188
|
|
|
182
189
|
// src/exports.ts
|
|
183
190
|
var exports_exports = {};
|
|
@@ -190,8 +197,6 @@ __export(exports_exports, {
|
|
|
190
197
|
BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
|
|
191
198
|
BaseAttachment: () => BaseAttachment,
|
|
192
199
|
BaseExperiment: () => BaseExperiment,
|
|
193
|
-
BatchScorer: () => BatchScorer,
|
|
194
|
-
BatchTask: () => BatchTask,
|
|
195
200
|
BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
|
|
196
201
|
BraintrustMiddleware: () => BraintrustMiddleware,
|
|
197
202
|
BraintrustObservabilityExporter: () => BraintrustObservabilityExporter,
|
|
@@ -205,8 +210,6 @@ __export(exports_exports, {
|
|
|
205
210
|
DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
|
|
206
211
|
Dataset: () => Dataset,
|
|
207
212
|
DatasetPipeline: () => DatasetPipeline,
|
|
208
|
-
DurableEvalMemoryStore: () => DurableEvalMemoryStore,
|
|
209
|
-
DurableEvalRedisStore: () => DurableEvalRedisStore,
|
|
210
213
|
ERR_PERMALINK: () => ERR_PERMALINK,
|
|
211
214
|
Eval: () => Eval,
|
|
212
215
|
EvalResultWithSummary: () => EvalResultWithSummary,
|
|
@@ -241,6 +244,10 @@ __export(exports_exports, {
|
|
|
241
244
|
TestBackgroundLogger: () => TestBackgroundLogger,
|
|
242
245
|
ToolBuilder: () => ToolBuilder,
|
|
243
246
|
UUIDGenerator: () => UUIDGenerator,
|
|
247
|
+
WorkflowEvalMemoryStore: () => WorkflowEvalMemoryStore,
|
|
248
|
+
WorkflowEvalRedisStore: () => WorkflowEvalRedisStore,
|
|
249
|
+
WorkflowScorer: () => WorkflowScorer,
|
|
250
|
+
WorkflowTask: () => WorkflowTask,
|
|
244
251
|
X_CACHED_HEADER: () => X_CACHED_HEADER,
|
|
245
252
|
_exportsForTestingOnly: () => _exportsForTestingOnly,
|
|
246
253
|
_internalGetGlobalState: () => _internalGetGlobalState,
|
|
@@ -265,12 +272,13 @@ __export(exports_exports, {
|
|
|
265
272
|
currentSpan: () => currentSpan,
|
|
266
273
|
deepCopyEvent: () => deepCopyEvent,
|
|
267
274
|
defaultErrorScoreHandler: () => defaultErrorScoreHandler,
|
|
268
|
-
|
|
275
|
+
defineWorkflowEval: () => defineWorkflowEval,
|
|
269
276
|
deserializePlainStringAsJSON: () => deserializePlainStringAsJSON,
|
|
270
277
|
devNullWritableStream: () => devNullWritableStream,
|
|
271
278
|
evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
|
|
272
279
|
evaluatorDefinitionsSchema: () => evaluatorDefinitionsSchema,
|
|
273
280
|
extractTraceContextFromHeaders: () => extractTraceContextFromHeaders,
|
|
281
|
+
failOpenAIAgentsTrace: () => failOpenAIAgentsTrace,
|
|
274
282
|
flush: () => flush,
|
|
275
283
|
getContextManager: () => getContextManager,
|
|
276
284
|
getIdGenerator: () => getIdGenerator,
|
|
@@ -317,12 +325,14 @@ __export(exports_exports, {
|
|
|
317
325
|
setFetch: () => setFetch,
|
|
318
326
|
setMaskingFunction: () => setMaskingFunction,
|
|
319
327
|
spanComponentsToObjectId: () => spanComponentsToObjectId,
|
|
328
|
+
startOpenAIAgentsTrace: () => startOpenAIAgentsTrace,
|
|
320
329
|
startSpan: () => startSpan,
|
|
321
330
|
summarize: () => summarize,
|
|
322
331
|
templateRegistry: () => templateRegistry,
|
|
323
332
|
toolFunctionDefinitionSchema: () => ToolFunctionDefinition,
|
|
324
333
|
traceable: () => traceable,
|
|
325
334
|
traced: () => traced,
|
|
335
|
+
updateOpenAIAgentsTrace: () => updateOpenAIAgentsTrace,
|
|
326
336
|
updateSpan: () => updateSpan,
|
|
327
337
|
uploadLogs3OverflowPayload: () => uploadLogs3OverflowPayload,
|
|
328
338
|
utf8ByteLength: () => utf8ByteLength,
|
|
@@ -343,12 +353,15 @@ __export(exports_exports, {
|
|
|
343
353
|
wrapCohere: () => wrapCohere,
|
|
344
354
|
wrapCopilotClient: () => wrapCopilotClient,
|
|
345
355
|
wrapCursorSDK: () => wrapCursorSDK,
|
|
356
|
+
wrapElevenLabs: () => wrapElevenLabs,
|
|
346
357
|
wrapGenkit: () => wrapGenkit,
|
|
347
358
|
wrapGoogleADK: () => wrapGoogleADK,
|
|
348
359
|
wrapGoogleGenAI: () => wrapGoogleGenAI,
|
|
360
|
+
wrapGoogleGenerativeAI: () => wrapGoogleGenerativeAI,
|
|
349
361
|
wrapGroq: () => wrapGroq,
|
|
350
362
|
wrapHuggingFace: () => wrapHuggingFace,
|
|
351
363
|
wrapHuggingFaceTransformers: () => wrapHuggingFaceTransformers,
|
|
364
|
+
wrapLangGraphSDK: () => wrapLangGraphSDK,
|
|
352
365
|
wrapLangSmithClient: () => wrapLangSmithClient,
|
|
353
366
|
wrapLangSmithRunTrees: () => wrapLangSmithRunTrees,
|
|
354
367
|
wrapLangSmithTraceable: () => wrapLangSmithTraceable,
|
|
@@ -715,6 +728,143 @@ async function completeOpenAIBatchTrace(args) {
|
|
|
715
728
|
);
|
|
716
729
|
}
|
|
717
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
|
+
|
|
718
868
|
// src/functions/invoke.ts
|
|
719
869
|
async function invoke(args) {
|
|
720
870
|
const {
|
|
@@ -2164,7 +2314,31 @@ var MAX_STORED_LLM_INPUTS = 100;
|
|
|
2164
2314
|
var MAX_STORED_REASONING_BLOCKS = 100;
|
|
2165
2315
|
var MAX_STORED_SPAN_REFERENCES = 1e4;
|
|
2166
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
|
+
]);
|
|
2167
2336
|
function braintrustEveHook(options) {
|
|
2337
|
+
if (!options || typeof options.defineState !== "function") {
|
|
2338
|
+
throw new TypeError(
|
|
2339
|
+
"braintrustEveHook requires Eve's defineState function"
|
|
2340
|
+
);
|
|
2341
|
+
}
|
|
2168
2342
|
const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
|
|
2169
2343
|
const bridge = new EveBridge(state);
|
|
2170
2344
|
return {
|
|
@@ -2176,15 +2350,27 @@ function braintrustEveHook(options) {
|
|
|
2176
2350
|
};
|
|
2177
2351
|
}
|
|
2178
2352
|
function createLegacyEveInstrumentation(options) {
|
|
2353
|
+
if (!options || typeof options.defineState !== "function") {
|
|
2354
|
+
throw new TypeError(
|
|
2355
|
+
"braintrustEveInstrumentation requires Eve's defineState function"
|
|
2356
|
+
);
|
|
2357
|
+
}
|
|
2179
2358
|
const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
|
|
2180
2359
|
return {
|
|
2181
2360
|
events: {
|
|
2182
2361
|
"step.started": (input) => {
|
|
2183
2362
|
try {
|
|
2363
|
+
if (!isEveInstrumentationStepStartedEventInput(input)) {
|
|
2364
|
+
debugLogger.warn(
|
|
2365
|
+
"Ignoring malformed Eve instrumentation step.started event"
|
|
2366
|
+
);
|
|
2367
|
+
return void 0;
|
|
2368
|
+
}
|
|
2184
2369
|
captureEveModelInput(state, input);
|
|
2185
2370
|
} catch (error) {
|
|
2186
2371
|
debugLogger.warn("Error in Eve LLM input capture:", error);
|
|
2187
2372
|
}
|
|
2373
|
+
return void 0;
|
|
2188
2374
|
}
|
|
2189
2375
|
},
|
|
2190
2376
|
recordInputs: false,
|
|
@@ -2193,7 +2379,77 @@ function createLegacyEveInstrumentation(options) {
|
|
|
2193
2379
|
};
|
|
2194
2380
|
}
|
|
2195
2381
|
function isEveHandleMessageStreamEvent(event) {
|
|
2196
|
-
|
|
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"]);
|
|
2197
2453
|
}
|
|
2198
2454
|
var ResumedEveSpan = class {
|
|
2199
2455
|
constructor(reference) {
|
|
@@ -2362,7 +2618,17 @@ var EveBridge = class {
|
|
|
2362
2618
|
});
|
|
2363
2619
|
}
|
|
2364
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) {
|
|
2365
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
|
+
}
|
|
2366
2632
|
return;
|
|
2367
2633
|
}
|
|
2368
2634
|
const run = async () => {
|
|
@@ -2688,9 +2954,14 @@ var EveBridge = class {
|
|
|
2688
2954
|
}
|
|
2689
2955
|
for (const action of traceActions) {
|
|
2690
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
|
+
}
|
|
2691
2962
|
toolCallsById.set(action.callId, {
|
|
2692
2963
|
function: {
|
|
2693
|
-
arguments:
|
|
2964
|
+
arguments: args,
|
|
2694
2965
|
name
|
|
2695
2966
|
},
|
|
2696
2967
|
id: action.callId,
|
|
@@ -3559,17 +3830,33 @@ function consumeCapturedEveModelInput(state, sessionId, turnId, stepIndex) {
|
|
|
3559
3830
|
}
|
|
3560
3831
|
}
|
|
3561
3832
|
function capturedModelInput(modelInput) {
|
|
3562
|
-
const { instructions, messages } = modelInput;
|
|
3563
|
-
const value = [];
|
|
3564
|
-
if (typeof instructions === "string") {
|
|
3565
|
-
value.push({ content: instructions, role: "system" });
|
|
3566
|
-
} else if (Array.isArray(instructions)) {
|
|
3567
|
-
value.push(...instructions.map(capturedEveModelMessage));
|
|
3568
|
-
} else if (instructions) {
|
|
3569
|
-
value.push(capturedEveModelMessage(instructions));
|
|
3570
|
-
}
|
|
3571
|
-
value.push(...messages.map(capturedEveModelMessage));
|
|
3572
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
|
+
}
|
|
3573
3860
|
const cloned = JSON.parse(JSON.stringify(value));
|
|
3574
3861
|
if (!Array.isArray(cloned)) {
|
|
3575
3862
|
return void 0;
|
|
@@ -3580,116 +3867,202 @@ function capturedModelInput(modelInput) {
|
|
|
3580
3867
|
}
|
|
3581
3868
|
}
|
|
3582
3869
|
function capturedEveModelMessage(message) {
|
|
3583
|
-
|
|
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"];
|
|
3584
3878
|
if (typeof content === "string") {
|
|
3585
3879
|
return { content, role };
|
|
3586
3880
|
}
|
|
3587
|
-
|
|
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 };
|
|
3588
3892
|
}
|
|
3589
3893
|
function capturedEveModelContentPart(part) {
|
|
3590
|
-
|
|
3894
|
+
if (!isObject(part) || typeof part["type"] !== "string") {
|
|
3895
|
+
return void 0;
|
|
3896
|
+
}
|
|
3897
|
+
switch (part["type"]) {
|
|
3591
3898
|
case "text":
|
|
3592
|
-
case "reasoning":
|
|
3593
|
-
|
|
3899
|
+
case "reasoning": {
|
|
3900
|
+
const text = part["text"];
|
|
3901
|
+
return typeof text === "string" ? { text, type: part["type"] } : void 0;
|
|
3902
|
+
}
|
|
3594
3903
|
case "image":
|
|
3904
|
+
if (!Object.hasOwn(part, "image")) {
|
|
3905
|
+
return void 0;
|
|
3906
|
+
}
|
|
3595
3907
|
return {
|
|
3596
|
-
image: part
|
|
3597
|
-
...part
|
|
3908
|
+
image: part["image"],
|
|
3909
|
+
...typeof part["mediaType"] === "string" ? { mediaType: part["mediaType"] } : {},
|
|
3598
3910
|
type: "image"
|
|
3599
3911
|
};
|
|
3600
3912
|
case "file":
|
|
3601
|
-
case "reasoning-file":
|
|
3913
|
+
case "reasoning-file": {
|
|
3914
|
+
if (!Object.hasOwn(part, "data") || typeof part["mediaType"] !== "string") {
|
|
3915
|
+
return void 0;
|
|
3916
|
+
}
|
|
3602
3917
|
return {
|
|
3603
|
-
data: part
|
|
3604
|
-
...part
|
|
3605
|
-
mediaType: part
|
|
3606
|
-
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"]
|
|
3607
3922
|
};
|
|
3923
|
+
}
|
|
3608
3924
|
case "custom":
|
|
3609
3925
|
return {
|
|
3610
|
-
..."kind"
|
|
3926
|
+
...typeof part["kind"] === "string" ? { kind: part["kind"] } : {},
|
|
3611
3927
|
type: "custom"
|
|
3612
3928
|
};
|
|
3613
|
-
case "tool-call":
|
|
3929
|
+
case "tool-call": {
|
|
3930
|
+
if (typeof part["toolCallId"] !== "string" || typeof part["toolName"] !== "string") {
|
|
3931
|
+
return void 0;
|
|
3932
|
+
}
|
|
3614
3933
|
return {
|
|
3615
|
-
input: part
|
|
3616
|
-
...part
|
|
3617
|
-
toolCallId: part
|
|
3618
|
-
toolName: part
|
|
3934
|
+
input: part["input"],
|
|
3935
|
+
...typeof part["providerExecuted"] === "boolean" ? { providerExecuted: part["providerExecuted"] } : {},
|
|
3936
|
+
toolCallId: part["toolCallId"],
|
|
3937
|
+
toolName: part["toolName"],
|
|
3619
3938
|
type: "tool-call"
|
|
3620
3939
|
};
|
|
3940
|
+
}
|
|
3621
3941
|
case "tool-result": {
|
|
3622
|
-
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
|
+
}
|
|
3623
3946
|
let capturedOutput;
|
|
3624
|
-
switch (output
|
|
3947
|
+
switch (output["type"]) {
|
|
3625
3948
|
case "text":
|
|
3626
|
-
case "error-text":
|
|
3627
|
-
|
|
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
|
+
};
|
|
3628
3957
|
break;
|
|
3958
|
+
}
|
|
3629
3959
|
case "json":
|
|
3630
3960
|
case "error-json":
|
|
3631
|
-
capturedOutput = {
|
|
3961
|
+
capturedOutput = {
|
|
3962
|
+
type: output["type"],
|
|
3963
|
+
value: output["value"]
|
|
3964
|
+
};
|
|
3632
3965
|
break;
|
|
3633
3966
|
case "execution-denied":
|
|
3634
3967
|
capturedOutput = {
|
|
3635
|
-
...output
|
|
3968
|
+
...typeof output["reason"] === "string" ? { reason: output["reason"] } : {},
|
|
3636
3969
|
type: "execution-denied"
|
|
3637
3970
|
};
|
|
3638
3971
|
break;
|
|
3639
|
-
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
|
+
}
|
|
3640
3983
|
capturedOutput = {
|
|
3641
3984
|
type: "content",
|
|
3642
|
-
value
|
|
3985
|
+
value
|
|
3643
3986
|
};
|
|
3644
3987
|
break;
|
|
3988
|
+
}
|
|
3989
|
+
default:
|
|
3990
|
+
return void 0;
|
|
3645
3991
|
}
|
|
3646
3992
|
return {
|
|
3647
3993
|
output: capturedOutput,
|
|
3648
|
-
toolCallId: part
|
|
3649
|
-
toolName: part
|
|
3994
|
+
toolCallId: part["toolCallId"],
|
|
3995
|
+
toolName: part["toolName"],
|
|
3650
3996
|
type: "tool-result"
|
|
3651
3997
|
};
|
|
3652
3998
|
}
|
|
3653
|
-
case "tool-approval-request":
|
|
3999
|
+
case "tool-approval-request": {
|
|
4000
|
+
if (typeof part["approvalId"] !== "string" || typeof part["toolCallId"] !== "string") {
|
|
4001
|
+
return void 0;
|
|
4002
|
+
}
|
|
3654
4003
|
return {
|
|
3655
|
-
approvalId: part
|
|
3656
|
-
...part
|
|
3657
|
-
...part
|
|
3658
|
-
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"],
|
|
3659
4008
|
type: "tool-approval-request"
|
|
3660
4009
|
};
|
|
3661
|
-
|
|
4010
|
+
}
|
|
4011
|
+
case "tool-approval-response": {
|
|
4012
|
+
if (typeof part["approvalId"] !== "string" || typeof part["approved"] !== "boolean") {
|
|
4013
|
+
return void 0;
|
|
4014
|
+
}
|
|
3662
4015
|
return {
|
|
3663
|
-
approvalId: part
|
|
3664
|
-
approved: part
|
|
3665
|
-
...part
|
|
3666
|
-
...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"] } : {},
|
|
3667
4020
|
type: "tool-approval-response"
|
|
3668
4021
|
};
|
|
4022
|
+
}
|
|
3669
4023
|
case "file-data":
|
|
3670
|
-
case "image-data":
|
|
4024
|
+
case "image-data": {
|
|
4025
|
+
if (typeof part["data"] !== "string" || typeof part["mediaType"] !== "string") {
|
|
4026
|
+
return void 0;
|
|
4027
|
+
}
|
|
3671
4028
|
return {
|
|
3672
|
-
data: part
|
|
3673
|
-
...part
|
|
3674
|
-
mediaType: part
|
|
3675
|
-
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"]
|
|
3676
4033
|
};
|
|
4034
|
+
}
|
|
3677
4035
|
case "file-url":
|
|
3678
|
-
case "image-url":
|
|
4036
|
+
case "image-url": {
|
|
4037
|
+
if (typeof part["url"] !== "string") {
|
|
4038
|
+
return void 0;
|
|
4039
|
+
}
|
|
3679
4040
|
return {
|
|
3680
|
-
...part
|
|
3681
|
-
type: part
|
|
3682
|
-
url: part
|
|
4041
|
+
...part["type"] === "file-url" && typeof part["mediaType"] === "string" ? { mediaType: part["mediaType"] } : {},
|
|
4042
|
+
type: part["type"],
|
|
4043
|
+
url: part["url"]
|
|
3683
4044
|
};
|
|
4045
|
+
}
|
|
3684
4046
|
case "file-id":
|
|
3685
|
-
case "image-file-id":
|
|
3686
|
-
|
|
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
|
+
}
|
|
3687
4054
|
case "file-reference":
|
|
3688
|
-
case "image-file-reference":
|
|
4055
|
+
case "image-file-reference": {
|
|
4056
|
+
if (!isObject(part["providerReference"])) {
|
|
4057
|
+
return void 0;
|
|
4058
|
+
}
|
|
3689
4059
|
return {
|
|
3690
|
-
providerReference: part
|
|
3691
|
-
type: part
|
|
4060
|
+
providerReference: part["providerReference"],
|
|
4061
|
+
type: part["type"]
|
|
3692
4062
|
};
|
|
4063
|
+
}
|
|
4064
|
+
default:
|
|
4065
|
+
return void 0;
|
|
3693
4066
|
}
|
|
3694
4067
|
}
|
|
3695
4068
|
function isCapturedModelInput(input) {
|
|
@@ -3825,18 +4198,54 @@ function createEveInstrumentationProvider(options = {}) {
|
|
|
3825
4198
|
recordOutputs: true
|
|
3826
4199
|
}),
|
|
3827
4200
|
events: {
|
|
3828
|
-
"action.completed": (
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
"
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
"
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
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
|
+
)
|
|
3840
4249
|
},
|
|
3841
4250
|
flush,
|
|
3842
4251
|
setup: options.setup
|
|
@@ -4192,17 +4601,20 @@ function modelOutput(event) {
|
|
|
4192
4601
|
const reasoning = [];
|
|
4193
4602
|
const toolCalls2 = [];
|
|
4194
4603
|
for (const part of content) {
|
|
4195
|
-
if (part
|
|
4196
|
-
|
|
4197
|
-
}
|
|
4198
|
-
|
|
4199
|
-
|
|
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") {
|
|
4200
4612
|
toolCalls2.push({
|
|
4201
4613
|
function: {
|
|
4202
|
-
arguments: safeJsonStringify(part
|
|
4203
|
-
name: part
|
|
4614
|
+
arguments: safeJsonStringify(part["input"]),
|
|
4615
|
+
name: part["toolName"]
|
|
4204
4616
|
},
|
|
4205
|
-
id: part
|
|
4617
|
+
id: part["callId"],
|
|
4206
4618
|
type: "function"
|
|
4207
4619
|
});
|
|
4208
4620
|
}
|
|
@@ -4221,13 +4633,13 @@ function modelOutput(event) {
|
|
|
4221
4633
|
];
|
|
4222
4634
|
}
|
|
4223
4635
|
function usageMetrics(usage) {
|
|
4224
|
-
const promptTokens = nonNegativeNumber(usage
|
|
4225
|
-
const completionTokens = nonNegativeNumber(usage
|
|
4636
|
+
const promptTokens = nonNegativeNumber(usage?.inputTokens);
|
|
4637
|
+
const completionTokens = nonNegativeNumber(usage?.outputTokens);
|
|
4226
4638
|
const cachedTokens = nonNegativeNumber(
|
|
4227
|
-
usage
|
|
4639
|
+
usage?.inputTokenDetails?.cacheReadTokens
|
|
4228
4640
|
);
|
|
4229
4641
|
const cacheCreationTokens = nonNegativeNumber(
|
|
4230
|
-
usage
|
|
4642
|
+
usage?.inputTokenDetails?.cacheWriteTokens
|
|
4231
4643
|
);
|
|
4232
4644
|
return {
|
|
4233
4645
|
...promptTokens !== void 0 ? { prompt_tokens: promptTokens } : {},
|
|
@@ -4264,10 +4676,76 @@ function turnIdempotencyKey(sessionId, turnId) {
|
|
|
4264
4676
|
function actionIdempotencyKey(sessionId, turnId, callId) {
|
|
4265
4677
|
return `action:${sessionId}:${turnId}:${callId}`;
|
|
4266
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
|
+
}
|
|
4267
4740
|
|
|
4268
4741
|
// src/instrumentation/plugins/eve-instrumentation.ts
|
|
4269
4742
|
var EVE_INSTRUMENTATION_PROVIDER = /* @__PURE__ */ Symbol.for("eve.instrumentation.provider");
|
|
4270
4743
|
function braintrustEveInstrumentation(options) {
|
|
4744
|
+
if (!options || typeof options !== "object") {
|
|
4745
|
+
throw new TypeError(
|
|
4746
|
+
"braintrustEveInstrumentation requires an options object"
|
|
4747
|
+
);
|
|
4748
|
+
}
|
|
4271
4749
|
const definition = "defineState" in options ? createLegacyEveInstrumentation(options) : createEveInstrumentationProvider(options);
|
|
4272
4750
|
const declaration = {
|
|
4273
4751
|
...definition,
|
|
@@ -5214,7 +5692,77 @@ function isModuleNamespace5(value) {
|
|
|
5214
5692
|
}
|
|
5215
5693
|
}
|
|
5216
5694
|
|
|
5695
|
+
// src/wrappers/google-generative-ai.ts
|
|
5696
|
+
function wrapGoogleGenerativeAI(client) {
|
|
5697
|
+
if (!isObject(client) || typeof client.getGenerativeModel !== "function")
|
|
5698
|
+
return client;
|
|
5699
|
+
return wrapClient(client);
|
|
5700
|
+
}
|
|
5701
|
+
var proxies = /* @__PURE__ */ new WeakMap();
|
|
5702
|
+
function wrapClient(client) {
|
|
5703
|
+
const cached = proxies.get(client);
|
|
5704
|
+
if (cached) return cached;
|
|
5705
|
+
const proxy = new Proxy(client, {
|
|
5706
|
+
get(target, prop, receiver) {
|
|
5707
|
+
const value = Reflect.get(target, prop, receiver);
|
|
5708
|
+
if (typeof value !== "function") return value;
|
|
5709
|
+
if (prop === "getGenerativeModel" || prop === "getGenerativeModelFromCachedContent" || prop === "startChat") {
|
|
5710
|
+
return (...args) => wrapClient(Reflect.apply(value, target, args));
|
|
5711
|
+
}
|
|
5712
|
+
switch (prop) {
|
|
5713
|
+
case "generateContent":
|
|
5714
|
+
return (...args) => googleGenerativeAIChannels.generateContent.invoke(
|
|
5715
|
+
value,
|
|
5716
|
+
target,
|
|
5717
|
+
args,
|
|
5718
|
+
{}
|
|
5719
|
+
);
|
|
5720
|
+
case "generateContentStream":
|
|
5721
|
+
return (...args) => googleGenerativeAIChannels.generateContentStream.invoke(
|
|
5722
|
+
value,
|
|
5723
|
+
target,
|
|
5724
|
+
args,
|
|
5725
|
+
{}
|
|
5726
|
+
);
|
|
5727
|
+
case "embedContent":
|
|
5728
|
+
return (...args) => googleGenerativeAIChannels.embedContent.invoke(
|
|
5729
|
+
value,
|
|
5730
|
+
target,
|
|
5731
|
+
args,
|
|
5732
|
+
{}
|
|
5733
|
+
);
|
|
5734
|
+
case "batchEmbedContents":
|
|
5735
|
+
return (...args) => googleGenerativeAIChannels.batchEmbedContents.invoke(
|
|
5736
|
+
value,
|
|
5737
|
+
target,
|
|
5738
|
+
args,
|
|
5739
|
+
{}
|
|
5740
|
+
);
|
|
5741
|
+
case "sendMessage":
|
|
5742
|
+
return (...args) => googleGenerativeAIChannels.sendMessage.invoke(
|
|
5743
|
+
value,
|
|
5744
|
+
target,
|
|
5745
|
+
args,
|
|
5746
|
+
{}
|
|
5747
|
+
);
|
|
5748
|
+
case "sendMessageStream":
|
|
5749
|
+
return (...args) => googleGenerativeAIChannels.sendMessageStream.invoke(
|
|
5750
|
+
value,
|
|
5751
|
+
target,
|
|
5752
|
+
args,
|
|
5753
|
+
{}
|
|
5754
|
+
);
|
|
5755
|
+
}
|
|
5756
|
+
return value.bind(target);
|
|
5757
|
+
}
|
|
5758
|
+
});
|
|
5759
|
+
proxies.set(client, proxy);
|
|
5760
|
+
proxies.set(proxy, proxy);
|
|
5761
|
+
return proxy;
|
|
5762
|
+
}
|
|
5763
|
+
|
|
5217
5764
|
// src/wrappers/google-genai.ts
|
|
5765
|
+
var patchedHttpResponses = /* @__PURE__ */ new WeakSet();
|
|
5218
5766
|
function wrapGoogleGenAI(googleGenAI) {
|
|
5219
5767
|
if (!googleGenAI || typeof googleGenAI !== "object") {
|
|
5220
5768
|
console.warn("Invalid Google GenAI module. Not wrapping.");
|
|
@@ -5226,6 +5774,21 @@ function wrapGoogleGenAI(googleGenAI) {
|
|
|
5226
5774
|
);
|
|
5227
5775
|
return googleGenAI;
|
|
5228
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
|
+
}
|
|
5229
5792
|
return new Proxy(googleGenAI, {
|
|
5230
5793
|
get(target, prop, receiver) {
|
|
5231
5794
|
if (prop === "GoogleGenAI") {
|
|
@@ -5476,17 +6039,17 @@ function wrapGenkit(genkit) {
|
|
|
5476
6039
|
console.warn("Unsupported Genkit object. Not wrapping.");
|
|
5477
6040
|
return genkit;
|
|
5478
6041
|
}
|
|
5479
|
-
function
|
|
6042
|
+
function isRecord2(value) {
|
|
5480
6043
|
return typeof value === "object" && value !== null;
|
|
5481
6044
|
}
|
|
5482
6045
|
function isPropertyBag(value) {
|
|
5483
|
-
return
|
|
6046
|
+
return isRecord2(value) || typeof value === "function";
|
|
5484
6047
|
}
|
|
5485
6048
|
function hasFunction(value, methodName) {
|
|
5486
6049
|
return isPropertyBag(value) && methodName in value && typeof value[methodName] === "function";
|
|
5487
6050
|
}
|
|
5488
6051
|
function isGenkitInstance(value) {
|
|
5489
|
-
return
|
|
6052
|
+
return isRecord2(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
|
|
5490
6053
|
}
|
|
5491
6054
|
function isGenkitModule(value) {
|
|
5492
6055
|
return hasFunction(value, "genkit");
|
|
@@ -5540,7 +6103,7 @@ function patchGenkitRegistry(instance) {
|
|
|
5540
6103
|
patchGenkitRegistryConstructor(registry);
|
|
5541
6104
|
}
|
|
5542
6105
|
function patchGenkitRegistryLookup(registry) {
|
|
5543
|
-
if (!
|
|
6106
|
+
if (!isRecord2(registry) || hasRegistryPatchedFlag(registry) || !hasFunction(registry, "lookupAction")) {
|
|
5544
6107
|
return;
|
|
5545
6108
|
}
|
|
5546
6109
|
const originalLookupAction = registry.lookupAction;
|
|
@@ -5566,7 +6129,7 @@ function patchGenkitRegistryLookup(registry) {
|
|
|
5566
6129
|
}
|
|
5567
6130
|
}
|
|
5568
6131
|
function patchGenkitRegistryConstructor(registry) {
|
|
5569
|
-
if (!
|
|
6132
|
+
if (!isRecord2(registry)) {
|
|
5570
6133
|
return;
|
|
5571
6134
|
}
|
|
5572
6135
|
const constructor = registry.constructor;
|
|
@@ -5582,7 +6145,7 @@ function patchGenkitRegistryConstructor(registry) {
|
|
|
5582
6145
|
configurable: true,
|
|
5583
6146
|
value: (...args) => {
|
|
5584
6147
|
const childRegistry = originalWithParent.apply(constructor, args);
|
|
5585
|
-
if (args.some((arg) =>
|
|
6148
|
+
if (args.some((arg) => isRecord2(arg) && hasRegistryPatchedFlag(arg))) {
|
|
5586
6149
|
patchGenkitRegistryLookup(childRegistry);
|
|
5587
6150
|
patchGenkitRegistryConstructor(childRegistry);
|
|
5588
6151
|
}
|
|
@@ -5681,7 +6244,7 @@ function hasRegistryConstructorPatchedFlag(value) {
|
|
|
5681
6244
|
);
|
|
5682
6245
|
}
|
|
5683
6246
|
function isPromiseLike(value) {
|
|
5684
|
-
return
|
|
6247
|
+
return isRecord2(value) && "then" in value && typeof value.then === "function";
|
|
5685
6248
|
}
|
|
5686
6249
|
|
|
5687
6250
|
// src/wrappers/huggingface.ts
|
|
@@ -6158,14 +6721,14 @@ function wrapMistral(mistral) {
|
|
|
6158
6721
|
console.warn("Unsupported Mistral library. Not wrapping.");
|
|
6159
6722
|
return mistral;
|
|
6160
6723
|
}
|
|
6161
|
-
function
|
|
6724
|
+
function isRecord3(value) {
|
|
6162
6725
|
return typeof value === "object" && value !== null;
|
|
6163
6726
|
}
|
|
6164
6727
|
function hasFunction3(value, methodName) {
|
|
6165
|
-
return
|
|
6728
|
+
return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
|
|
6166
6729
|
}
|
|
6167
6730
|
function isSupportedMistralClient(value) {
|
|
6168
|
-
if (!
|
|
6731
|
+
if (!isRecord3(value)) {
|
|
6169
6732
|
return false;
|
|
6170
6733
|
}
|
|
6171
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);
|
|
@@ -6340,17 +6903,53 @@ function wrapAgentsStream(stream) {
|
|
|
6340
6903
|
});
|
|
6341
6904
|
}
|
|
6342
6905
|
|
|
6343
|
-
// src/wrappers/
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
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;
|
|
6347
6913
|
}
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
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
|
+
|
|
6942
|
+
// src/wrappers/ollama.ts
|
|
6943
|
+
function wrapOllama(ollama) {
|
|
6944
|
+
if (isSupportedOllamaClient(ollama)) {
|
|
6945
|
+
return ollamaProxy(ollama);
|
|
6946
|
+
}
|
|
6947
|
+
debugLogger.warn("Unsupported Ollama library. Not wrapping.");
|
|
6948
|
+
return ollama;
|
|
6949
|
+
}
|
|
6950
|
+
var ollamaProxyCache = /* @__PURE__ */ new WeakMap();
|
|
6951
|
+
function isSupportedOllamaClient(value) {
|
|
6952
|
+
return isObject(value) && ["chat", "generate", "embed"].some(
|
|
6354
6953
|
(name) => typeof value[name] === "function"
|
|
6355
6954
|
);
|
|
6356
6955
|
}
|
|
@@ -6426,14 +7025,14 @@ function wrapCohere(cohere) {
|
|
|
6426
7025
|
return cohere;
|
|
6427
7026
|
}
|
|
6428
7027
|
var cohereProxyCache = /* @__PURE__ */ new WeakMap();
|
|
6429
|
-
function
|
|
7028
|
+
function isRecord4(value) {
|
|
6430
7029
|
return typeof value === "object" && value !== null;
|
|
6431
7030
|
}
|
|
6432
7031
|
function hasFunction4(value, methodName) {
|
|
6433
|
-
return
|
|
7032
|
+
return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
|
|
6434
7033
|
}
|
|
6435
7034
|
function isSupportedCohereClient(value) {
|
|
6436
|
-
if (!
|
|
7035
|
+
if (!isRecord4(value)) {
|
|
6437
7036
|
return false;
|
|
6438
7037
|
}
|
|
6439
7038
|
return hasFunction4(value, "chat") || hasFunction4(value, "chatStream") || hasFunction4(value, "embed") || hasFunction4(value, "rerank");
|
|
@@ -6571,20 +7170,20 @@ function wrapGroq(groq) {
|
|
|
6571
7170
|
console.warn("Unsupported Groq library. Not wrapping.");
|
|
6572
7171
|
return groq;
|
|
6573
7172
|
}
|
|
6574
|
-
function
|
|
7173
|
+
function isRecord5(value) {
|
|
6575
7174
|
return typeof value === "object" && value !== null;
|
|
6576
7175
|
}
|
|
6577
7176
|
function hasFunction6(value, methodName) {
|
|
6578
|
-
return
|
|
7177
|
+
return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
|
|
6579
7178
|
}
|
|
6580
7179
|
function hasChat2(value) {
|
|
6581
|
-
return
|
|
7180
|
+
return isRecord5(value) && isRecord5(value.completions) && hasFunction6(value.completions, "create");
|
|
6582
7181
|
}
|
|
6583
7182
|
function hasEmbeddings2(value) {
|
|
6584
7183
|
return hasFunction6(value, "create");
|
|
6585
7184
|
}
|
|
6586
7185
|
function isSupportedGroqClient(value) {
|
|
6587
|
-
return
|
|
7186
|
+
return isRecord5(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
|
|
6588
7187
|
}
|
|
6589
7188
|
function groqProxy(groq) {
|
|
6590
7189
|
const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -6667,11 +7266,11 @@ var BEDROCK_RUNTIME_OPERATION_METHODS = /* @__PURE__ */ new Set([
|
|
|
6667
7266
|
"invokeModelWithBidirectionalStream",
|
|
6668
7267
|
"invokeModelWithResponseStream"
|
|
6669
7268
|
]);
|
|
6670
|
-
function
|
|
7269
|
+
function isRecord6(value) {
|
|
6671
7270
|
return typeof value === "object" && value !== null;
|
|
6672
7271
|
}
|
|
6673
7272
|
function isSupportedBedrockRuntimeClient(value) {
|
|
6674
|
-
return
|
|
7273
|
+
return isRecord6(value) && typeof value.send === "function";
|
|
6675
7274
|
}
|
|
6676
7275
|
function bedrockRuntimeProxy(client) {
|
|
6677
7276
|
const cached = bedrockRuntimeProxyCache.get(client);
|
|
@@ -8956,12 +9555,272 @@ function waterfall(tasks, callback) {
|
|
|
8956
9555
|
}
|
|
8957
9556
|
var waterfall$1 = awaitify(waterfall);
|
|
8958
9557
|
|
|
9558
|
+
// src/framework.ts
|
|
9559
|
+
import { v5 as uuidv5 } from "uuid";
|
|
9560
|
+
|
|
8959
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
|
+
}
|
|
8960
9818
|
var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
8961
|
-
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);
|
|
8962
9821
|
const filterExpr = _SpanFetcher.buildFilter(
|
|
8963
9822
|
rootSpanId,
|
|
8964
|
-
|
|
9823
|
+
normalizedFilters,
|
|
8965
9824
|
includeScorers
|
|
8966
9825
|
);
|
|
8967
9826
|
super(
|
|
@@ -8982,42 +9841,22 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
|
8982
9841
|
rootSpanId;
|
|
8983
9842
|
_state;
|
|
8984
9843
|
spanTypeFilter;
|
|
8985
|
-
static buildFilter(rootSpanId,
|
|
9844
|
+
static buildFilter(rootSpanId, filters, includeScorers = false) {
|
|
9845
|
+
const purpose = ["span_attributes", "purpose"];
|
|
8986
9846
|
const children = [
|
|
8987
|
-
|
|
8988
|
-
{
|
|
8989
|
-
op: "eq",
|
|
8990
|
-
left: { op: "ident", name: ["root_span_id"] },
|
|
8991
|
-
right: { op: "literal", value: rootSpanId }
|
|
8992
|
-
}
|
|
9847
|
+
btqlComparison("eq", ["root_span_id"], rootSpanId)
|
|
8993
9848
|
];
|
|
8994
9849
|
if (!includeScorers) {
|
|
8995
9850
|
children.push({
|
|
8996
9851
|
op: "or",
|
|
8997
9852
|
children: [
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
expr: { op: "ident", name: ["span_attributes", "purpose"] }
|
|
9001
|
-
},
|
|
9002
|
-
{
|
|
9003
|
-
op: "ne",
|
|
9004
|
-
left: { op: "ident", name: ["span_attributes", "purpose"] },
|
|
9005
|
-
right: { op: "literal", value: "scorer" }
|
|
9006
|
-
}
|
|
9853
|
+
btqlNullCheck("isnull", purpose),
|
|
9854
|
+
btqlComparison("ne", purpose, "scorer")
|
|
9007
9855
|
]
|
|
9008
9856
|
});
|
|
9009
9857
|
}
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
op: "in",
|
|
9013
|
-
left: { op: "ident", name: ["span_attributes", "type"] },
|
|
9014
|
-
right: { op: "literal", value: spanTypeFilter }
|
|
9015
|
-
});
|
|
9016
|
-
}
|
|
9017
|
-
return {
|
|
9018
|
-
op: "and",
|
|
9019
|
-
children
|
|
9020
|
-
};
|
|
9858
|
+
children.push(...spanFilterClauses(filters));
|
|
9859
|
+
return { op: "and", children };
|
|
9021
9860
|
}
|
|
9022
9861
|
get id() {
|
|
9023
9862
|
return Promise.resolve(this._objectId);
|
|
@@ -9032,67 +9871,80 @@ var CachedSpanFetcher = class {
|
|
|
9032
9871
|
fetchFn;
|
|
9033
9872
|
constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState, brainstoreRealtime = true) {
|
|
9034
9873
|
if (typeof objectTypeOrFetchFn === "function") {
|
|
9035
|
-
this.fetchFn = (
|
|
9874
|
+
this.fetchFn = async (filters) => (await objectTypeOrFetchFn(filters.filters.spanType)).filter(
|
|
9875
|
+
(span) => matchesSpanFilters(span, filters)
|
|
9876
|
+
);
|
|
9036
9877
|
} else {
|
|
9037
9878
|
const objectType = objectTypeOrFetchFn;
|
|
9038
|
-
this.fetchFn = async (
|
|
9879
|
+
this.fetchFn = async (filters, includeScorers) => {
|
|
9039
9880
|
const state = await getState();
|
|
9040
9881
|
const fetcher = new SpanFetcher(
|
|
9041
9882
|
objectType,
|
|
9042
9883
|
objectId,
|
|
9043
9884
|
rootSpanId,
|
|
9044
9885
|
state,
|
|
9045
|
-
|
|
9886
|
+
void 0,
|
|
9046
9887
|
includeScorers,
|
|
9047
|
-
brainstoreRealtime
|
|
9888
|
+
brainstoreRealtime,
|
|
9889
|
+
filters.filters
|
|
9048
9890
|
);
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
metrics: row.metrics,
|
|
9057
|
-
metadata: row.metadata,
|
|
9058
|
-
span_id: row.span_id,
|
|
9059
|
-
span_parents: row.span_parents,
|
|
9060
|
-
is_root: row.is_root,
|
|
9061
|
-
span_attributes: row.span_attributes,
|
|
9062
|
-
id: row.id,
|
|
9063
|
-
_xact_id: row._xact_id,
|
|
9064
|
-
_pagination_key: row._pagination_key,
|
|
9065
|
-
root_span_id: row.root_span_id,
|
|
9066
|
-
created: row.created,
|
|
9067
|
-
tags: row.tags
|
|
9068
|
-
}));
|
|
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;
|
|
9069
9898
|
};
|
|
9070
9899
|
}
|
|
9071
9900
|
}
|
|
9072
9901
|
async getSpans({
|
|
9073
|
-
spanType,
|
|
9902
|
+
spanType: requestedSpanType,
|
|
9903
|
+
filters,
|
|
9074
9904
|
includeScorers = false
|
|
9075
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
|
+
}
|
|
9076
9914
|
if (includeScorers) {
|
|
9077
|
-
return this.fetchFn(
|
|
9915
|
+
return this.fetchFn(normalizedFilters, true);
|
|
9078
9916
|
}
|
|
9079
9917
|
if (this.allFetched) {
|
|
9080
|
-
|
|
9918
|
+
const spans = this.getFromCache(spanType);
|
|
9919
|
+
return hasAdvancedFilters ? spans.filter((span) => matchesSpanFilters(span, normalizedFilters)) : spans;
|
|
9081
9920
|
}
|
|
9082
|
-
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();
|
|
9083
9931
|
await this.fetchSpans(void 0);
|
|
9084
|
-
this.
|
|
9932
|
+
if (this.spanCache.size > 0) {
|
|
9933
|
+
this.allFetched = true;
|
|
9934
|
+
}
|
|
9085
9935
|
return this.getFromCache(void 0);
|
|
9086
9936
|
}
|
|
9087
|
-
const missingTypes = spanType.filter((
|
|
9088
|
-
if (missingTypes.length
|
|
9089
|
-
|
|
9937
|
+
const missingTypes = spanType.filter((type) => !this.spanCache.has(type));
|
|
9938
|
+
if (missingTypes.length > 0) {
|
|
9939
|
+
await this.fetchSpans(missingTypes);
|
|
9090
9940
|
}
|
|
9091
|
-
await this.fetchSpans(missingTypes);
|
|
9092
9941
|
return this.getFromCache(spanType);
|
|
9093
9942
|
}
|
|
9094
9943
|
async fetchSpans(spanType) {
|
|
9095
|
-
const spans = await this.fetchFn(
|
|
9944
|
+
const spans = await this.fetchFn(
|
|
9945
|
+
normalizeSpanFilters(spanType ? { spanType } : void 0),
|
|
9946
|
+
false
|
|
9947
|
+
);
|
|
9096
9948
|
for (const span of spans) {
|
|
9097
9949
|
const type = span.span_attributes?.type ?? "";
|
|
9098
9950
|
const existing = this.spanCache.get(type) ?? [];
|
|
@@ -9172,34 +10024,20 @@ var LocalTrace = class {
|
|
|
9172
10024
|
*/
|
|
9173
10025
|
async getSpans({
|
|
9174
10026
|
spanType,
|
|
10027
|
+
filters,
|
|
9175
10028
|
includeScorers = false
|
|
9176
10029
|
} = {}) {
|
|
10030
|
+
const normalizedFilters = normalizeSpanFilters(filters, spanType);
|
|
9177
10031
|
const cachedSpans = this.state.spanCache.getByRootSpanId(this.rootSpanId);
|
|
9178
10032
|
if (cachedSpans && cachedSpans.length > 0) {
|
|
9179
|
-
|
|
9180
|
-
(span) => span.span_attributes?.purpose !== "scorer"
|
|
9181
|
-
);
|
|
9182
|
-
|
|
9183
|
-
|
|
9184
|
-
|
|
9185
|
-
|
|
9186
|
-
|
|
9187
|
-
return spans.map((span) => ({
|
|
9188
|
-
input: span.input,
|
|
9189
|
-
output: span.output,
|
|
9190
|
-
expected: span.expected,
|
|
9191
|
-
error: span.error,
|
|
9192
|
-
scores: span.scores,
|
|
9193
|
-
metrics: span.metrics,
|
|
9194
|
-
metadata: span.metadata,
|
|
9195
|
-
span_id: span.span_id,
|
|
9196
|
-
span_parents: span.span_parents,
|
|
9197
|
-
is_root: span.is_root,
|
|
9198
|
-
span_attributes: span.span_attributes,
|
|
9199
|
-
tags: span.tags
|
|
9200
|
-
}));
|
|
9201
|
-
}
|
|
9202
|
-
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
|
+
});
|
|
9203
10041
|
}
|
|
9204
10042
|
/**
|
|
9205
10043
|
* Get the thread (preprocessed messages) for this trace.
|
|
@@ -9619,7 +10457,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
|
|
|
9619
10457
|
data,
|
|
9620
10458
|
{ disabled: Boolean(options.parent || options.noSendLogs) }
|
|
9621
10459
|
);
|
|
9622
|
-
if (experiment
|
|
10460
|
+
if (experiment) {
|
|
9623
10461
|
await experiment._waitForId();
|
|
9624
10462
|
}
|
|
9625
10463
|
if (experiment && options.onStart) {
|
|
@@ -9944,6 +10782,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
9944
10782
|
} : void 0;
|
|
9945
10783
|
const parsedDatumOrigin = ObjectReference.safeParse(datum.origin);
|
|
9946
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;
|
|
9947
10789
|
const baseEvent = {
|
|
9948
10790
|
name: "eval",
|
|
9949
10791
|
spanAttributes: {
|
|
@@ -9954,7 +10796,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
9954
10796
|
expected: "expected" in datum ? datum.expected : void 0,
|
|
9955
10797
|
tags: datum.tags,
|
|
9956
10798
|
origin,
|
|
9957
|
-
...
|
|
10799
|
+
...upsertId ? { id: upsertId } : {}
|
|
9958
10800
|
}
|
|
9959
10801
|
};
|
|
9960
10802
|
const callback = async (rootSpan) => {
|
|
@@ -10463,14 +11305,14 @@ var defaultReporter = {
|
|
|
10463
11305
|
}
|
|
10464
11306
|
};
|
|
10465
11307
|
|
|
10466
|
-
// src/
|
|
11308
|
+
// src/workflow-eval.ts
|
|
10467
11309
|
var encoder = new TextEncoder();
|
|
10468
11310
|
var decoder = new TextDecoder();
|
|
10469
|
-
var
|
|
10470
|
-
var
|
|
10471
|
-
var
|
|
10472
|
-
var DurableEvalMemoryStore = class {
|
|
11311
|
+
var WORKFLOW_TASK_KIND = "braintrust.workflow.task";
|
|
11312
|
+
var WORKFLOW_SCORER_KIND = "braintrust.workflow.scorer";
|
|
11313
|
+
var WorkflowEvalMemoryStore = class {
|
|
10473
11314
|
values = /* @__PURE__ */ new Map();
|
|
11315
|
+
sets = /* @__PURE__ */ new Map();
|
|
10474
11316
|
async read(key) {
|
|
10475
11317
|
return this.values.get(key)?.slice();
|
|
10476
11318
|
}
|
|
@@ -10483,8 +11325,16 @@ var DurableEvalMemoryStore = class {
|
|
|
10483
11325
|
this.values.set(key, value.slice());
|
|
10484
11326
|
return { value: value.slice(), created: true };
|
|
10485
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
|
+
}
|
|
10486
11336
|
};
|
|
10487
|
-
var
|
|
11337
|
+
var WorkflowEvalRedisStore = class {
|
|
10488
11338
|
client;
|
|
10489
11339
|
keyPrefix;
|
|
10490
11340
|
ttlMs;
|
|
@@ -10493,14 +11343,16 @@ var DurableEvalRedisStore = class {
|
|
|
10493
11343
|
this.keyPrefix = options.keyPrefix ?? "braintrust-eval:";
|
|
10494
11344
|
this.ttlMs = options.ttlMs ?? 1e3 * 60 * 60 * 24 * 7;
|
|
10495
11345
|
if (!Number.isInteger(this.ttlMs) || this.ttlMs < 1) {
|
|
10496
|
-
throw new Error(
|
|
11346
|
+
throw new Error(
|
|
11347
|
+
"WorkflowEvalRedisStore ttlMs must be a positive integer"
|
|
11348
|
+
);
|
|
10497
11349
|
}
|
|
10498
11350
|
}
|
|
10499
11351
|
async read(key) {
|
|
10500
11352
|
const value = await this.client.get(`${this.keyPrefix}${key}`);
|
|
10501
11353
|
if (value == null) return void 0;
|
|
10502
11354
|
if (typeof value !== "string") {
|
|
10503
|
-
throw new Error("
|
|
11355
|
+
throw new Error("WorkflowEvalRedisStore expected GET to return a string");
|
|
10504
11356
|
}
|
|
10505
11357
|
return base64ToUint8Array(value);
|
|
10506
11358
|
}
|
|
@@ -10517,7 +11369,7 @@ var DurableEvalRedisStore = class {
|
|
|
10517
11369
|
await set.call(client, redisKey, encoded, { px: this.ttlMs });
|
|
10518
11370
|
} else {
|
|
10519
11371
|
throw new Error(
|
|
10520
|
-
"
|
|
11372
|
+
"WorkflowEvalRedisStore requires a node-redis, ioredis, or @upstash/redis client"
|
|
10521
11373
|
);
|
|
10522
11374
|
}
|
|
10523
11375
|
}
|
|
@@ -10535,49 +11387,73 @@ var DurableEvalRedisStore = class {
|
|
|
10535
11387
|
setOptions = [{ px: this.ttlMs, nx: true, get: true }];
|
|
10536
11388
|
} else {
|
|
10537
11389
|
throw new Error(
|
|
10538
|
-
"
|
|
11390
|
+
"WorkflowEvalRedisStore getOrSet requires a node-redis, ioredis, or @upstash/redis client"
|
|
10539
11391
|
);
|
|
10540
11392
|
}
|
|
10541
11393
|
const existing = await set.call(client, redisKey, encoded, ...setOptions);
|
|
10542
11394
|
if (existing === null) return { value: value.slice(), created: true };
|
|
10543
11395
|
if (typeof existing !== "string") {
|
|
10544
11396
|
throw new Error(
|
|
10545
|
-
"
|
|
11397
|
+
"WorkflowEvalRedisStore expected atomic SET to return a string or null"
|
|
10546
11398
|
);
|
|
10547
11399
|
}
|
|
10548
11400
|
return { value: base64ToUint8Array(existing), created: false };
|
|
10549
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
|
+
}
|
|
10550
11423
|
};
|
|
10551
|
-
var
|
|
11424
|
+
var WorkflowTask = class {
|
|
10552
11425
|
constructor(processor) {
|
|
10553
11426
|
this.processor = processor;
|
|
10554
11427
|
}
|
|
10555
11428
|
processor;
|
|
10556
|
-
kind =
|
|
11429
|
+
kind = WORKFLOW_TASK_KIND;
|
|
10557
11430
|
};
|
|
10558
|
-
var
|
|
11431
|
+
var WorkflowScorer = class {
|
|
10559
11432
|
constructor(processor) {
|
|
10560
11433
|
this.processor = processor;
|
|
10561
11434
|
this.name = processor.name;
|
|
10562
11435
|
}
|
|
10563
11436
|
processor;
|
|
10564
|
-
kind =
|
|
11437
|
+
kind = WORKFLOW_SCORER_KIND;
|
|
10565
11438
|
name;
|
|
10566
11439
|
};
|
|
10567
|
-
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
|
+
}
|
|
10568
11444
|
const definition = {
|
|
10569
11445
|
projectName,
|
|
10570
11446
|
evalName: evaluator.experimentName ?? projectName,
|
|
10571
11447
|
evaluator
|
|
10572
11448
|
};
|
|
10573
11449
|
return {
|
|
10574
|
-
start: (options = {}) =>
|
|
10575
|
-
status: (options) =>
|
|
10576
|
-
poll: (options) =>
|
|
10577
|
-
|
|
11450
|
+
start: (options = {}) => startWorkflowEval(definition, options),
|
|
11451
|
+
status: (options) => getWorkflowEvalStatus(definition, options),
|
|
11452
|
+
poll: (options) => pollWorkflowEval(definition, options),
|
|
11453
|
+
processSubmissionResult: (result) => processWorkflowSubmissionResult(definition, result)
|
|
10578
11454
|
};
|
|
10579
11455
|
}
|
|
10580
|
-
async function
|
|
11456
|
+
async function startWorkflowEval(definition, options) {
|
|
10581
11457
|
const store = definition.evaluator.store;
|
|
10582
11458
|
const runId = newId();
|
|
10583
11459
|
const key = runKey(definition.projectName, definition.evalName, runId);
|
|
@@ -10597,7 +11473,7 @@ async function startDurableEval(definition, options) {
|
|
|
10597
11473
|
update: true
|
|
10598
11474
|
}
|
|
10599
11475
|
);
|
|
10600
|
-
if (!
|
|
11476
|
+
if (!isWorkflowTask(definition.evaluator.task) && !(definition.evaluator.scores ?? []).some(isWorkflowScorer)) {
|
|
10601
11477
|
const result = await runEvaluator(
|
|
10602
11478
|
experiment,
|
|
10603
11479
|
{
|
|
@@ -10624,67 +11500,91 @@ async function startDurableEval(definition, options) {
|
|
|
10624
11500
|
parameters: assertJsonValue(parameters, "eval parameters"),
|
|
10625
11501
|
status: "completed",
|
|
10626
11502
|
summary: result.summary,
|
|
11503
|
+
caseCount: 0,
|
|
10627
11504
|
cases: [],
|
|
10628
|
-
|
|
11505
|
+
submissions: []
|
|
10629
11506
|
};
|
|
10630
11507
|
await experiment?.flush();
|
|
10631
11508
|
await writeRunRecord(store, key, state2);
|
|
10632
11509
|
return currentStatus(definition, state2);
|
|
10633
11510
|
}
|
|
11511
|
+
const cases = await materializeCases(definition, data, experiment);
|
|
10634
11512
|
const state = {
|
|
10635
11513
|
runId,
|
|
10636
11514
|
experimentName,
|
|
10637
11515
|
noSendLogs: options.noSendLogs ?? false,
|
|
10638
11516
|
parameters: assertJsonValue(parameters, "eval parameters"),
|
|
10639
11517
|
status: "running",
|
|
10640
|
-
|
|
10641
|
-
|
|
11518
|
+
caseCount: cases.length,
|
|
11519
|
+
cases,
|
|
11520
|
+
submissions: []
|
|
10642
11521
|
};
|
|
11522
|
+
await writeJson(
|
|
11523
|
+
store,
|
|
11524
|
+
`${key}/case-ids`,
|
|
11525
|
+
cases.map(({ id }) => id)
|
|
11526
|
+
);
|
|
10643
11527
|
await writeCaseBaseRecords(store, key, state.cases);
|
|
10644
11528
|
await writeRunRecord(store, key, state);
|
|
10645
|
-
return
|
|
11529
|
+
return advanceWorkflowEval(definition, state, store, key, experiment);
|
|
10646
11530
|
}
|
|
10647
|
-
async function
|
|
11531
|
+
async function getWorkflowEvalStatus(definition, options) {
|
|
10648
11532
|
const store = definition.evaluator.store;
|
|
10649
|
-
const
|
|
10650
|
-
definition,
|
|
10651
|
-
|
|
10652
|
-
|
|
11533
|
+
const key = runKey(
|
|
11534
|
+
definition.projectName,
|
|
11535
|
+
definition.evalName,
|
|
11536
|
+
options.runId
|
|
10653
11537
|
);
|
|
10654
|
-
|
|
11538
|
+
const state = await readJson(store, key);
|
|
11539
|
+
if (!state) throw new Error(`Workflow eval run ${options.runId} is missing`);
|
|
10655
11540
|
return currentStatus(definition, state);
|
|
10656
11541
|
}
|
|
10657
|
-
async function
|
|
10658
|
-
if (!result.
|
|
10659
|
-
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");
|
|
10660
11545
|
}
|
|
10661
11546
|
const store = definition.evaluator.store;
|
|
10662
11547
|
const key = runKey(definition.projectName, definition.evalName, result.runId);
|
|
10663
|
-
const
|
|
10664
|
-
if (!
|
|
10665
|
-
const
|
|
10666
|
-
|
|
10667
|
-
(
|
|
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)}`
|
|
10668
11553
|
) : void 0;
|
|
10669
|
-
if (
|
|
10670
|
-
throw new Error(
|
|
10671
|
-
|
|
10672
|
-
|
|
10673
|
-
|
|
10674
|
-
|
|
10675
|
-
|
|
10676
|
-
|
|
10677
|
-
|
|
10678
|
-
|
|
10679
|
-
|
|
10680
|
-
|
|
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)
|
|
11563
|
+
) : void 0;
|
|
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(
|
|
10681
11581
|
definition,
|
|
10682
|
-
await readRunState(definition, store, key),
|
|
11582
|
+
await readRunState(definition, store, key, [submission.itemId]),
|
|
10683
11583
|
store,
|
|
10684
11584
|
key
|
|
10685
11585
|
);
|
|
10686
11586
|
}
|
|
10687
|
-
async function
|
|
11587
|
+
async function pollWorkflowEval(definition, options) {
|
|
10688
11588
|
const store = definition.evaluator.store;
|
|
10689
11589
|
const key = runKey(
|
|
10690
11590
|
definition.projectName,
|
|
@@ -10692,39 +11592,53 @@ async function pollDurableEval(definition, options) {
|
|
|
10692
11592
|
options.runId
|
|
10693
11593
|
);
|
|
10694
11594
|
const state = await readRunState(definition, store, key);
|
|
10695
|
-
if (!state) throw new Error(`
|
|
10696
|
-
const
|
|
10697
|
-
if (
|
|
10698
|
-
return processorForStage(definition,
|
|
10699
|
-
});
|
|
10700
|
-
const
|
|
10701
|
-
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
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
|
+
});
|
|
10712
11611
|
if (result.status === "failed") throw asError(result.error);
|
|
10713
|
-
if (result.status
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
}
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
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));
|
|
10723
11635
|
}
|
|
10724
|
-
|
|
10725
|
-
|
|
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;
|
|
10726
11640
|
}
|
|
10727
|
-
async function
|
|
11641
|
+
async function openWorkflowExperiment(definition, state) {
|
|
10728
11642
|
const data = [];
|
|
10729
11643
|
return await _internalInitEvaluatorExperiment(
|
|
10730
11644
|
definition.projectName,
|
|
@@ -10737,45 +11651,49 @@ async function openDurableExperiment(definition, state) {
|
|
|
10737
11651
|
}
|
|
10738
11652
|
);
|
|
10739
11653
|
}
|
|
10740
|
-
async function
|
|
11654
|
+
async function advanceWorkflowEval(definition, state, store, key, existingExperiment) {
|
|
10741
11655
|
if (state.status === "completed") return currentStatus(definition, state);
|
|
10742
|
-
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);
|
|
10743
11658
|
await runTaskStage(definition, state, store, key, experiment);
|
|
10744
11659
|
await logCompletedTasks(definition, state, store, key, experiment);
|
|
10745
|
-
state = await readRunState(definition, store, key) ?? state;
|
|
10746
|
-
if (state.cases.some((record) => !record.taskComplete || !record.taskLogged)) {
|
|
10747
|
-
return currentStatus(definition, state);
|
|
10748
|
-
}
|
|
11660
|
+
state = await readRunState(definition, store, key, caseIds) ?? state;
|
|
10749
11661
|
await runScoreStages(definition, state, store, key, experiment);
|
|
10750
|
-
state = await readRunState(definition, store, key) ?? state;
|
|
11662
|
+
state = await readRunState(definition, store, key, caseIds) ?? state;
|
|
10751
11663
|
const scorerNames = resolveScorers(definition.evaluator.scores ?? []).map(
|
|
10752
11664
|
({ name }) => name
|
|
10753
11665
|
);
|
|
10754
11666
|
const classifierNames = (definition.evaluator.classifiers ?? []).map(
|
|
10755
11667
|
classifierName
|
|
10756
11668
|
);
|
|
10757
|
-
|
|
10758
|
-
(record) =>
|
|
10759
|
-
(
|
|
10760
|
-
|
|
10761
|
-
|
|
10762
|
-
|
|
10763
|
-
|
|
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) {
|
|
10764
11681
|
return currentStatus(definition, state);
|
|
10765
11682
|
}
|
|
10766
11683
|
if (!await claimAction(store, key, "finish")) {
|
|
10767
|
-
const latest = await
|
|
11684
|
+
const latest = await readJson(store, key);
|
|
10768
11685
|
return currentStatus(definition, latest ?? state);
|
|
10769
11686
|
}
|
|
11687
|
+
state = await readRunState(definition, store, key);
|
|
10770
11688
|
state.summary = await finishExperiment(definition, state, experiment);
|
|
10771
11689
|
state.status = "completed";
|
|
10772
11690
|
await writeRunRecord(store, key, state);
|
|
10773
11691
|
return currentStatus(definition, state);
|
|
10774
11692
|
}
|
|
10775
|
-
function currentStatus(definition, state) {
|
|
11693
|
+
async function currentStatus(definition, state) {
|
|
10776
11694
|
if (state.status === "completed") {
|
|
10777
11695
|
if (!state.summary) {
|
|
10778
|
-
throw new Error(`
|
|
11696
|
+
throw new Error(`Workflow eval run ${state.runId} has no saved summary`);
|
|
10779
11697
|
}
|
|
10780
11698
|
return {
|
|
10781
11699
|
status: "completed",
|
|
@@ -10784,11 +11702,20 @@ function currentStatus(definition, state) {
|
|
|
10784
11702
|
summary: state.summary
|
|
10785
11703
|
};
|
|
10786
11704
|
}
|
|
11705
|
+
const key = runKey(definition.projectName, definition.evalName, state.runId);
|
|
11706
|
+
const store = definition.evaluator.store;
|
|
10787
11707
|
const pending = { poll: 0, webhook: 0 };
|
|
10788
|
-
|
|
10789
|
-
|
|
10790
|
-
|
|
10791
|
-
|
|
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
|
+
);
|
|
10792
11719
|
return { status: "waiting", runId: state.runId, pending };
|
|
10793
11720
|
}
|
|
10794
11721
|
async function startCaseRoot(definition, state, record, experiment) {
|
|
@@ -10849,7 +11776,7 @@ async function logTaskResult(definition, state, record, experiment, task) {
|
|
|
10849
11776
|
expected: "expected" in datum ? datum.expected : void 0,
|
|
10850
11777
|
metadata: {
|
|
10851
11778
|
...record.metadata,
|
|
10852
|
-
|
|
11779
|
+
workflow_eval: {
|
|
10853
11780
|
run_id: state.runId,
|
|
10854
11781
|
case_id: record.caseId,
|
|
10855
11782
|
trial_index: record.trialIndex
|
|
@@ -10880,8 +11807,8 @@ async function logCompletedTasks(definition, state, store, key, experiment) {
|
|
|
10880
11807
|
}
|
|
10881
11808
|
}
|
|
10882
11809
|
async function runTaskStage(definition, state, store, key, experiment) {
|
|
10883
|
-
if (
|
|
10884
|
-
await
|
|
11810
|
+
if (isWorkflowTask(definition.evaluator.task)) {
|
|
11811
|
+
await ensureSubmissions(definition, state, store, key, "task");
|
|
10885
11812
|
return;
|
|
10886
11813
|
}
|
|
10887
11814
|
const task = definition.evaluator.task;
|
|
@@ -10907,8 +11834,9 @@ async function runScoreStages(definition, state, store, key, experiment) {
|
|
|
10907
11834
|
changed.clear();
|
|
10908
11835
|
};
|
|
10909
11836
|
for (const { name, scorer } of scorers) {
|
|
10910
|
-
if (
|
|
11837
|
+
if (isWorkflowScorer(scorer)) {
|
|
10911
11838
|
for (const record of state.cases) {
|
|
11839
|
+
if (!record.taskComplete || !record.taskLogged) continue;
|
|
10912
11840
|
if (Object.hasOwn(record.scores, name) && !Object.hasOwn(record.loggedScores, name)) {
|
|
10913
11841
|
if (!await claimAction(store, key, "score-log", record.id, name)) {
|
|
10914
11842
|
continue;
|
|
@@ -10924,10 +11852,11 @@ async function runScoreStages(definition, state, store, key, experiment) {
|
|
|
10924
11852
|
}
|
|
10925
11853
|
}
|
|
10926
11854
|
await persistChangedCases();
|
|
10927
|
-
await
|
|
11855
|
+
await ensureSubmissions(definition, state, store, key, "score", name);
|
|
10928
11856
|
continue;
|
|
10929
11857
|
}
|
|
10930
11858
|
for (const record of state.cases) {
|
|
11859
|
+
if (!record.taskComplete || !record.taskLogged) continue;
|
|
10931
11860
|
if (Object.hasOwn(record.loggedScores, name)) continue;
|
|
10932
11861
|
if (!await claimAction(store, key, "score", record.id, name)) continue;
|
|
10933
11862
|
await evaluateAndLogScore(
|
|
@@ -10944,6 +11873,7 @@ async function runScoreStages(definition, state, store, key, experiment) {
|
|
|
10944
11873
|
for (const [index, classifier] of (definition.evaluator.classifiers ?? []).entries()) {
|
|
10945
11874
|
const name = classifierName(classifier, index);
|
|
10946
11875
|
for (const record of state.cases) {
|
|
11876
|
+
if (!record.taskComplete || !record.taskLogged) continue;
|
|
10947
11877
|
if (Object.hasOwn(record.loggedClassifications, name)) continue;
|
|
10948
11878
|
if (!await claimAction(store, key, "classification", record.id, name)) {
|
|
10949
11879
|
continue;
|
|
@@ -10966,13 +11896,14 @@ function scorerArgs(record) {
|
|
|
10966
11896
|
return {
|
|
10967
11897
|
...datum,
|
|
10968
11898
|
metadata: record.metadata,
|
|
11899
|
+
tags: record.tags,
|
|
10969
11900
|
output: record.output
|
|
10970
11901
|
};
|
|
10971
11902
|
}
|
|
10972
11903
|
function resumeCaseRoot(definition, record, experiment) {
|
|
10973
11904
|
if (!experiment) return NOOP_SPAN;
|
|
10974
11905
|
if (!record.rootSpan) {
|
|
10975
|
-
throw new Error(`
|
|
11906
|
+
throw new Error(`Workflow eval case ${record.caseId} has no root span`);
|
|
10976
11907
|
}
|
|
10977
11908
|
return _internalResumeSpan({
|
|
10978
11909
|
exported: record.rootSpan,
|
|
@@ -11060,117 +11991,110 @@ async function evaluateAndLogClassification(definition, state, record, name, cla
|
|
|
11060
11991
|
root.end();
|
|
11061
11992
|
}
|
|
11062
11993
|
}
|
|
11063
|
-
async function
|
|
11994
|
+
async function ensureSubmissions(definition, state, store, key, kind, scorerName2) {
|
|
11064
11995
|
const processor = processorForStage(definition, kind, scorerName2);
|
|
11065
|
-
const plans =
|
|
11996
|
+
const plans = plannedSubmissions(
|
|
11066
11997
|
definition,
|
|
11067
11998
|
state.runId,
|
|
11068
11999
|
state.cases.map(({ id }) => id)
|
|
11069
12000
|
);
|
|
11070
12001
|
const casesById = new Map(state.cases.map((record) => [record.id, record]));
|
|
11071
|
-
|
|
11072
|
-
|
|
11073
|
-
if (
|
|
11074
|
-
|
|
11075
|
-
const
|
|
11076
|
-
|
|
11077
|
-
);
|
|
11078
|
-
|
|
11079
|
-
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;
|
|
11080
12010
|
const claim = await store.getOrSet(
|
|
11081
|
-
claimRecordKey(key, "
|
|
11082
|
-
encoder.encode(
|
|
11083
|
-
);
|
|
11084
|
-
if (!claim.created) continue;
|
|
11085
|
-
const context = { runId: state.runId, batchId };
|
|
11086
|
-
const items = records.map(
|
|
11087
|
-
(record) => kind === "task" ? taskBatchItem(record, state.parameters) : scorerBatchItem(record)
|
|
12011
|
+
claimRecordKey(key, "submission", submissionId),
|
|
12012
|
+
encoder.encode(submissionId)
|
|
11088
12013
|
);
|
|
12014
|
+
if (!claim.created) return;
|
|
12015
|
+
const context = { runId: state.runId, submissionId };
|
|
12016
|
+
const item = kind === "task" ? taskSubmissionItem(record, state.parameters) : scorerSubmissionItem(record);
|
|
11089
12017
|
const submissionData = assertJsonValue(
|
|
11090
|
-
await processor.submit(
|
|
11091
|
-
`submission data for
|
|
12018
|
+
await processor.submit(item, context),
|
|
12019
|
+
`submission data for submission ${submissionId}`
|
|
11092
12020
|
);
|
|
11093
12021
|
const externalId = processor.completion.mode === "webhook" ? processor.completion.getExternalId(submissionData, context) : void 0;
|
|
11094
12022
|
if (externalId !== void 0 && !externalId.trim()) {
|
|
11095
|
-
throw new Error(
|
|
12023
|
+
throw new Error(
|
|
12024
|
+
`Submission ${submissionId} produced an empty externalId`
|
|
12025
|
+
);
|
|
11096
12026
|
}
|
|
11097
|
-
const
|
|
11098
|
-
id:
|
|
12027
|
+
const submission = {
|
|
12028
|
+
id: submissionId,
|
|
11099
12029
|
kind,
|
|
11100
12030
|
scorerName: scorerName2,
|
|
11101
|
-
|
|
12031
|
+
itemId: record.id,
|
|
11102
12032
|
submissionData,
|
|
11103
12033
|
externalId,
|
|
11104
|
-
status: "submitted"
|
|
12034
|
+
status: "submitted",
|
|
12035
|
+
completionMode: processor.completion.mode
|
|
11105
12036
|
};
|
|
11106
|
-
state.
|
|
11107
|
-
await
|
|
11108
|
-
}
|
|
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");
|
|
11109
12049
|
}
|
|
11110
|
-
async function
|
|
11111
|
-
const processor = processorForStage(
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
|
|
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
|
+
);
|
|
11116
12062
|
}
|
|
11117
|
-
const
|
|
11118
|
-
|
|
11119
|
-
|
|
11120
|
-
|
|
11121
|
-
|
|
11122
|
-
|
|
11123
|
-
|
|
11124
|
-
|
|
11125
|
-
if (
|
|
11126
|
-
|
|
11127
|
-
|
|
11128
|
-
|
|
11129
|
-
const record = state.cases.find((candidate) => candidate.id === id);
|
|
11130
|
-
records.push(record);
|
|
11131
|
-
if (batch.kind === "task") {
|
|
11132
|
-
record.output = assertJsonValue(
|
|
11133
|
-
result.output,
|
|
11134
|
-
`task output for item ${id}`
|
|
11135
|
-
);
|
|
11136
|
-
if ("metadata" in result && result.metadata !== void 0) {
|
|
11137
|
-
record.metadata = assertJsonValue(
|
|
11138
|
-
{
|
|
11139
|
-
...record.metadata,
|
|
11140
|
-
...result.metadata
|
|
11141
|
-
},
|
|
11142
|
-
`metadata for ${id}`
|
|
11143
|
-
);
|
|
11144
|
-
}
|
|
11145
|
-
if ("tags" in result && result.tags !== void 0)
|
|
11146
|
-
record.tags = result.tags;
|
|
11147
|
-
record.taskComplete = true;
|
|
11148
|
-
} else {
|
|
11149
|
-
record.scores[batch.scorerName] = assertJsonValue(
|
|
11150
|
-
result.score,
|
|
11151
|
-
`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}`
|
|
11152
12075
|
);
|
|
11153
12076
|
}
|
|
11154
|
-
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
|
|
11158
|
-
|
|
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}`
|
|
11159
12083
|
);
|
|
11160
12084
|
}
|
|
11161
|
-
return
|
|
12085
|
+
return record;
|
|
11162
12086
|
}
|
|
11163
12087
|
function processorForStage(definition, kind, scorerName2) {
|
|
11164
12088
|
if (kind === "task") {
|
|
11165
|
-
if (!
|
|
11166
|
-
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");
|
|
11167
12091
|
}
|
|
11168
12092
|
return definition.evaluator.task.processor;
|
|
11169
12093
|
}
|
|
11170
12094
|
const scorer = resolveScorers(definition.evaluator.scores ?? []).find(
|
|
11171
12095
|
({ name }) => name === scorerName2
|
|
11172
12096
|
)?.scorer;
|
|
11173
|
-
if (!
|
|
12097
|
+
if (!isWorkflowScorer(scorer)) {
|
|
11174
12098
|
throw new Error(`Definition no longer contains scorer ${scorerName2}`);
|
|
11175
12099
|
}
|
|
11176
12100
|
return scorer.processor;
|
|
@@ -11192,15 +12116,15 @@ async function materializeCases(definition, data, experiment) {
|
|
|
11192
12116
|
const caseId = datum.id ?? datum.upsert_id ?? (evaluator.caseId ? await evaluator.caseId(datum) : void 0);
|
|
11193
12117
|
if (!caseId) {
|
|
11194
12118
|
throw new Error(
|
|
11195
|
-
"Every
|
|
12119
|
+
"Every workflow eval case requires id, upsert_id, or caseId"
|
|
11196
12120
|
);
|
|
11197
12121
|
}
|
|
11198
12122
|
if (seen.has(caseId))
|
|
11199
|
-
throw new Error(`Duplicate
|
|
12123
|
+
throw new Error(`Duplicate workflow eval case id: ${caseId}`);
|
|
11200
12124
|
seen.add(caseId);
|
|
11201
12125
|
const trialCount = datum.trialCount ?? evaluator.trialCount ?? 1;
|
|
11202
12126
|
if (!Number.isInteger(trialCount) || trialCount < 1) {
|
|
11203
|
-
throw new Error(`Invalid trialCount for
|
|
12127
|
+
throw new Error(`Invalid trialCount for workflow eval case ${caseId}`);
|
|
11204
12128
|
}
|
|
11205
12129
|
for (let trialIndex = 0; trialIndex < trialCount; trialIndex++) {
|
|
11206
12130
|
records.push({
|
|
@@ -11224,7 +12148,7 @@ async function materializeCases(definition, data, experiment) {
|
|
|
11224
12148
|
}
|
|
11225
12149
|
return records;
|
|
11226
12150
|
}
|
|
11227
|
-
function
|
|
12151
|
+
function taskSubmissionItem(record, parameters) {
|
|
11228
12152
|
const datum = record.datum;
|
|
11229
12153
|
return {
|
|
11230
12154
|
id: record.id,
|
|
@@ -11236,7 +12160,7 @@ function taskBatchItem(record, parameters) {
|
|
|
11236
12160
|
trialIndex: record.trialIndex
|
|
11237
12161
|
};
|
|
11238
12162
|
}
|
|
11239
|
-
function
|
|
12163
|
+
function scorerSubmissionItem(record) {
|
|
11240
12164
|
const datum = record.datum;
|
|
11241
12165
|
return {
|
|
11242
12166
|
id: record.id,
|
|
@@ -11307,12 +12231,12 @@ async function finishExperiment(definition, state, experiment) {
|
|
|
11307
12231
|
}
|
|
11308
12232
|
function resolveScorers(scorers) {
|
|
11309
12233
|
return scorers.map((scorer, index) => ({
|
|
11310
|
-
name:
|
|
12234
|
+
name: isWorkflowScorer(scorer) ? scorer.name : scorer.name || `scorer_${index}`,
|
|
11311
12235
|
scorer
|
|
11312
12236
|
}));
|
|
11313
12237
|
}
|
|
11314
12238
|
function runKey(projectName, evalName, runId) {
|
|
11315
|
-
return `
|
|
12239
|
+
return `workflow-eval/v1/runs/${contentVersion(encoder.encode(`${projectName}\0${evalName}\0${runId}`))}`;
|
|
11316
12240
|
}
|
|
11317
12241
|
function encodedKeyPart(value) {
|
|
11318
12242
|
return uint8ArrayToBase64(encoder.encode(value)).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
|
|
@@ -11321,8 +12245,8 @@ function caseRecordKey(key, caseId, kind, ...names) {
|
|
|
11321
12245
|
const suffix = names.map(encodedKeyPart).join("/");
|
|
11322
12246
|
return `${key}/cases/${encodedKeyPart(caseId)}/${kind}${suffix ? `/${suffix}` : ""}`;
|
|
11323
12247
|
}
|
|
11324
|
-
function
|
|
11325
|
-
return `${key}/
|
|
12248
|
+
function submissionRecordKey(key, submissionId) {
|
|
12249
|
+
return `${key}/submissions/${encodedKeyPart(submissionId)}`;
|
|
11326
12250
|
}
|
|
11327
12251
|
function claimRecordKey(key, kind, ...parts) {
|
|
11328
12252
|
const identity = stableStringify([kind, parts]);
|
|
@@ -11334,33 +12258,24 @@ async function claimAction(store, key, kind, ...parts) {
|
|
|
11334
12258
|
encoder.encode("claimed")
|
|
11335
12259
|
)).created;
|
|
11336
12260
|
}
|
|
11337
|
-
function
|
|
12261
|
+
function plannedSubmissions(definition, runId, caseIds) {
|
|
11338
12262
|
const stages = [];
|
|
11339
|
-
if (
|
|
12263
|
+
if (isWorkflowTask(definition.evaluator.task)) stages.push({ kind: "task" });
|
|
11340
12264
|
for (const { name, scorer } of resolveScorers(
|
|
11341
12265
|
definition.evaluator.scores ?? []
|
|
11342
12266
|
)) {
|
|
11343
|
-
if (
|
|
12267
|
+
if (isWorkflowScorer(scorer)) {
|
|
11344
12268
|
stages.push({ kind: "score", scorerName: name });
|
|
11345
12269
|
}
|
|
11346
12270
|
}
|
|
11347
12271
|
const plans = [];
|
|
11348
12272
|
for (const { kind, scorerName: scorerName2 } of stages) {
|
|
11349
|
-
const
|
|
11350
|
-
if (!Number.isInteger(batchSize) || batchSize < 1) {
|
|
11351
|
-
throw new Error(
|
|
11352
|
-
`Invalid batchSize for ${scorerName2 ?? "task"}: ${batchSize}`
|
|
11353
|
-
);
|
|
11354
|
-
}
|
|
11355
|
-
for (let offset = 0; offset < caseIds.length; offset += batchSize) {
|
|
11356
|
-
const itemIds = caseIds.slice(offset, offset + batchSize);
|
|
12273
|
+
for (const itemId of caseIds) {
|
|
11357
12274
|
plans.push({
|
|
11358
|
-
id: deterministicId(
|
|
11359
|
-
stableStringify([runId, kind, scorerName2, itemIds])
|
|
11360
|
-
),
|
|
12275
|
+
id: deterministicId(stableStringify([runId, kind, scorerName2, itemId])),
|
|
11361
12276
|
kind,
|
|
11362
12277
|
scorerName: scorerName2,
|
|
11363
|
-
|
|
12278
|
+
itemId
|
|
11364
12279
|
});
|
|
11365
12280
|
}
|
|
11366
12281
|
}
|
|
@@ -11420,7 +12335,7 @@ async function readCaseRecord(definition, store, key, id) {
|
|
|
11420
12335
|
}))
|
|
11421
12336
|
)
|
|
11422
12337
|
]);
|
|
11423
|
-
if (!base) throw new Error(`
|
|
12338
|
+
if (!base) throw new Error(`Workflow eval case ${id} is missing`);
|
|
11424
12339
|
const scores = /* @__PURE__ */ Object.create(null);
|
|
11425
12340
|
for (const { name, value } of scoreValues) {
|
|
11426
12341
|
if (value !== void 0) scores[name] = value;
|
|
@@ -11451,32 +12366,34 @@ async function readCaseRecord(definition, store, key, id) {
|
|
|
11451
12366
|
loggedClassifications
|
|
11452
12367
|
};
|
|
11453
12368
|
}
|
|
11454
|
-
async function readRunState(definition, store, key) {
|
|
12369
|
+
async function readRunState(definition, store, key, caseIds) {
|
|
11455
12370
|
const record = await readJson(store, key);
|
|
11456
12371
|
if (!record) return void 0;
|
|
11457
|
-
const
|
|
11458
|
-
|
|
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([
|
|
11459
12377
|
Promise.all(
|
|
11460
|
-
|
|
12378
|
+
selectedIds.map((id) => readCaseRecord(definition, store, key, id))
|
|
11461
12379
|
),
|
|
11462
12380
|
Promise.all(
|
|
11463
12381
|
plans.map(async ({ id }) => {
|
|
11464
|
-
return readJson(
|
|
12382
|
+
return readJson(
|
|
12383
|
+
store,
|
|
12384
|
+
submissionRecordKey(key, id)
|
|
12385
|
+
);
|
|
11465
12386
|
})
|
|
11466
12387
|
)
|
|
11467
12388
|
]);
|
|
11468
|
-
const
|
|
12389
|
+
const submissions = submissionRecords.filter(
|
|
11469
12390
|
(value) => value !== void 0
|
|
11470
12391
|
);
|
|
11471
|
-
|
|
11472
|
-
return { ...state, cases, batches };
|
|
12392
|
+
return { ...record, cases, submissions };
|
|
11473
12393
|
}
|
|
11474
12394
|
async function writeRunRecord(store, key, state) {
|
|
11475
|
-
const { cases,
|
|
11476
|
-
await writeJson(store, key,
|
|
11477
|
-
...record,
|
|
11478
|
-
caseIds: cases.map(({ id }) => id)
|
|
11479
|
-
});
|
|
12395
|
+
const { cases: _cases, submissions: _submissions, ...record } = state;
|
|
12396
|
+
await writeJson(store, key, record);
|
|
11480
12397
|
}
|
|
11481
12398
|
async function writeCaseBaseRecords(store, key, records) {
|
|
11482
12399
|
await Promise.all(
|
|
@@ -11548,11 +12465,25 @@ async function writeCaseRecords(store, key, records) {
|
|
|
11548
12465
|
}
|
|
11549
12466
|
await Promise.all(writes);
|
|
11550
12467
|
}
|
|
11551
|
-
async function
|
|
12468
|
+
async function writeSubmissionRecords(store, key, records) {
|
|
11552
12469
|
await Promise.all(
|
|
11553
|
-
records.map(
|
|
11554
|
-
(record
|
|
11555
|
-
|
|
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
|
+
})
|
|
11556
12487
|
);
|
|
11557
12488
|
}
|
|
11558
12489
|
function deterministicId(value) {
|
|
@@ -11597,17 +12528,11 @@ function assertJsonValue(value, label) {
|
|
|
11597
12528
|
throw new Error(`${label} must be JSON serializable`, { cause: error });
|
|
11598
12529
|
}
|
|
11599
12530
|
}
|
|
11600
|
-
function
|
|
11601
|
-
|
|
11602
|
-
throw new Error("Batch results must contain a string id");
|
|
11603
|
-
}
|
|
11604
|
-
return value.id;
|
|
11605
|
-
}
|
|
11606
|
-
function isBatchTask(value) {
|
|
11607
|
-
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;
|
|
11608
12533
|
}
|
|
11609
|
-
function
|
|
11610
|
-
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;
|
|
11611
12536
|
}
|
|
11612
12537
|
function asError(error) {
|
|
11613
12538
|
return error instanceof Error ? error : new Error(String(error));
|
|
@@ -12534,6 +13459,65 @@ var evaluatorDefinitionsSchema = z5.record(
|
|
|
12534
13459
|
evaluatorDefinitionSchema
|
|
12535
13460
|
);
|
|
12536
13461
|
|
|
13462
|
+
// src/wrappers/elevenlabs.ts
|
|
13463
|
+
var clients2 = /* @__PURE__ */ new WeakMap();
|
|
13464
|
+
function wrapElevenLabs(client) {
|
|
13465
|
+
if (!isObject(client) || !isObject(client.textToSpeech) || typeof client.textToSpeech.convert !== "function") {
|
|
13466
|
+
debugLogger.warn("Unsupported ElevenLabs client. Not wrapping.");
|
|
13467
|
+
return client;
|
|
13468
|
+
}
|
|
13469
|
+
const cached = clients2.get(client);
|
|
13470
|
+
if (cached) return cached;
|
|
13471
|
+
const sdk = client;
|
|
13472
|
+
const speech = new Proxy(sdk.textToSpeech, {
|
|
13473
|
+
get(target, prop, receiver) {
|
|
13474
|
+
switch (prop) {
|
|
13475
|
+
case "convert":
|
|
13476
|
+
case "stream":
|
|
13477
|
+
return (...args) => elevenLabsChannels[prop].invoke(target[prop], target, args, {});
|
|
13478
|
+
case "convertWithTimestamps":
|
|
13479
|
+
return (...args) => elevenLabsChannels.convertWithTimestamps.invoke(
|
|
13480
|
+
target.convertWithTimestamps,
|
|
13481
|
+
target,
|
|
13482
|
+
args,
|
|
13483
|
+
{}
|
|
13484
|
+
);
|
|
13485
|
+
case "streamWithTimestamps":
|
|
13486
|
+
return (...args) => elevenLabsChannels.streamWithTimestamps.invoke(
|
|
13487
|
+
target.streamWithTimestamps,
|
|
13488
|
+
target,
|
|
13489
|
+
args,
|
|
13490
|
+
{}
|
|
13491
|
+
);
|
|
13492
|
+
default:
|
|
13493
|
+
return Reflect.get(target, prop, receiver);
|
|
13494
|
+
}
|
|
13495
|
+
}
|
|
13496
|
+
});
|
|
13497
|
+
const transcription = new Proxy(sdk.speechToText, {
|
|
13498
|
+
get(target, prop, receiver) {
|
|
13499
|
+
if (prop === "convert")
|
|
13500
|
+
return (request, options) => elevenLabsChannels.transcribe.invoke(
|
|
13501
|
+
target.convert,
|
|
13502
|
+
target,
|
|
13503
|
+
[request, options],
|
|
13504
|
+
{}
|
|
13505
|
+
);
|
|
13506
|
+
return Reflect.get(target, prop, receiver);
|
|
13507
|
+
}
|
|
13508
|
+
});
|
|
13509
|
+
const proxy = new Proxy(sdk, {
|
|
13510
|
+
get(target, prop, receiver) {
|
|
13511
|
+
if (prop === "textToSpeech") return speech;
|
|
13512
|
+
if (prop === "speechToText") return transcription;
|
|
13513
|
+
return Reflect.get(target, prop, receiver);
|
|
13514
|
+
}
|
|
13515
|
+
});
|
|
13516
|
+
clients2.set(client, proxy);
|
|
13517
|
+
clients2.set(proxy, proxy);
|
|
13518
|
+
return proxy;
|
|
13519
|
+
}
|
|
13520
|
+
|
|
12537
13521
|
// src/node/index.ts
|
|
12538
13522
|
configureNode();
|
|
12539
13523
|
export {
|
|
@@ -12545,8 +13529,6 @@ export {
|
|
|
12545
13529
|
BRAINTRUST_PARENT_KEY,
|
|
12546
13530
|
BaseAttachment,
|
|
12547
13531
|
BaseExperiment,
|
|
12548
|
-
BatchScorer,
|
|
12549
|
-
BatchTask,
|
|
12550
13532
|
BraintrustLangChainCallbackHandler,
|
|
12551
13533
|
BraintrustMiddleware,
|
|
12552
13534
|
BraintrustObservabilityExporter,
|
|
@@ -12560,8 +13542,6 @@ export {
|
|
|
12560
13542
|
DEFAULT_MAX_REQUEST_SIZE,
|
|
12561
13543
|
Dataset,
|
|
12562
13544
|
DatasetPipeline,
|
|
12563
|
-
DurableEvalMemoryStore,
|
|
12564
|
-
DurableEvalRedisStore,
|
|
12565
13545
|
ERR_PERMALINK,
|
|
12566
13546
|
Eval,
|
|
12567
13547
|
EvalResultWithSummary,
|
|
@@ -12596,6 +13576,10 @@ export {
|
|
|
12596
13576
|
TestBackgroundLogger,
|
|
12597
13577
|
ToolBuilder,
|
|
12598
13578
|
UUIDGenerator,
|
|
13579
|
+
WorkflowEvalMemoryStore,
|
|
13580
|
+
WorkflowEvalRedisStore,
|
|
13581
|
+
WorkflowScorer,
|
|
13582
|
+
WorkflowTask,
|
|
12599
13583
|
X_CACHED_HEADER,
|
|
12600
13584
|
_exportsForTestingOnly,
|
|
12601
13585
|
_internalGetGlobalState,
|
|
@@ -12621,12 +13605,13 @@ export {
|
|
|
12621
13605
|
deepCopyEvent,
|
|
12622
13606
|
exports_exports as default,
|
|
12623
13607
|
defaultErrorScoreHandler,
|
|
12624
|
-
|
|
13608
|
+
defineWorkflowEval,
|
|
12625
13609
|
deserializePlainStringAsJSON,
|
|
12626
13610
|
devNullWritableStream,
|
|
12627
13611
|
evaluatorDefinitionSchema,
|
|
12628
13612
|
evaluatorDefinitionsSchema,
|
|
12629
13613
|
extractTraceContextFromHeaders,
|
|
13614
|
+
failOpenAIAgentsTrace,
|
|
12630
13615
|
flush,
|
|
12631
13616
|
getContextManager,
|
|
12632
13617
|
getIdGenerator,
|
|
@@ -12673,12 +13658,14 @@ export {
|
|
|
12673
13658
|
setFetch,
|
|
12674
13659
|
setMaskingFunction,
|
|
12675
13660
|
spanComponentsToObjectId,
|
|
13661
|
+
startOpenAIAgentsTrace,
|
|
12676
13662
|
startSpan,
|
|
12677
13663
|
summarize,
|
|
12678
13664
|
templateRegistry,
|
|
12679
13665
|
ToolFunctionDefinition as toolFunctionDefinitionSchema,
|
|
12680
13666
|
traceable,
|
|
12681
13667
|
traced,
|
|
13668
|
+
updateOpenAIAgentsTrace,
|
|
12682
13669
|
updateSpan,
|
|
12683
13670
|
uploadLogs3OverflowPayload,
|
|
12684
13671
|
utf8ByteLength,
|
|
@@ -12699,12 +13686,15 @@ export {
|
|
|
12699
13686
|
wrapCohere,
|
|
12700
13687
|
wrapCopilotClient,
|
|
12701
13688
|
wrapCursorSDK,
|
|
13689
|
+
wrapElevenLabs,
|
|
12702
13690
|
wrapGenkit,
|
|
12703
13691
|
wrapGoogleADK,
|
|
12704
13692
|
wrapGoogleGenAI,
|
|
13693
|
+
wrapGoogleGenerativeAI,
|
|
12705
13694
|
wrapGroq,
|
|
12706
13695
|
wrapHuggingFace,
|
|
12707
13696
|
wrapHuggingFaceTransformers,
|
|
13697
|
+
wrapLangGraphSDK,
|
|
12708
13698
|
wrapLangSmithClient,
|
|
12709
13699
|
wrapLangSmithRunTrees,
|
|
12710
13700
|
wrapLangSmithTraceable,
|