braintrust 0.0.166 → 0.0.168
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.d.mts +184 -41
- package/dist/browser.d.ts +184 -41
- package/dist/browser.js +348 -101
- package/dist/browser.mjs +349 -103
- package/dist/cli.js +397 -85
- package/dist/index.d.mts +186 -44
- package/dist/index.d.ts +186 -44
- package/dist/index.js +369 -105
- package/dist/index.mjs +370 -107
- package/package.json +7 -2
- package/typedoc.json +1 -0
package/dist/browser.js
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/browser.ts
|
|
31
31
|
var browser_exports = {};
|
|
32
32
|
__export(browser_exports, {
|
|
33
|
+
Attachment: () => Attachment,
|
|
33
34
|
BraintrustState: () => BraintrustState,
|
|
34
35
|
BraintrustStream: () => BraintrustStream,
|
|
35
36
|
Dataset: () => Dataset,
|
|
@@ -43,6 +44,7 @@ __export(browser_exports, {
|
|
|
43
44
|
ReadonlyExperiment: () => ReadonlyExperiment,
|
|
44
45
|
SpanImpl: () => SpanImpl,
|
|
45
46
|
X_CACHED_HEADER: () => X_CACHED_HEADER,
|
|
47
|
+
_exportsForTestingOnly: () => _exportsForTestingOnly,
|
|
46
48
|
_internalGetGlobalState: () => _internalGetGlobalState,
|
|
47
49
|
_internalSetInitialState: () => _internalSetInitialState,
|
|
48
50
|
braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
|
|
@@ -446,6 +448,9 @@ var NoopSpan = class {
|
|
|
446
448
|
async export() {
|
|
447
449
|
return "";
|
|
448
450
|
}
|
|
451
|
+
async permalink() {
|
|
452
|
+
return "";
|
|
453
|
+
}
|
|
449
454
|
async flush() {
|
|
450
455
|
}
|
|
451
456
|
close(args) {
|
|
@@ -587,11 +592,11 @@ var BraintrustState = class _BraintrustState {
|
|
|
587
592
|
state.loginReplaceApiConn(state.apiConn());
|
|
588
593
|
return state;
|
|
589
594
|
}
|
|
590
|
-
setFetch(
|
|
591
|
-
this.loginParams.fetch =
|
|
592
|
-
this.fetch =
|
|
593
|
-
this._apiConn?.setFetch(
|
|
594
|
-
this._appConn?.setFetch(
|
|
595
|
+
setFetch(fetch2) {
|
|
596
|
+
this.loginParams.fetch = fetch2;
|
|
597
|
+
this.fetch = fetch2;
|
|
598
|
+
this._apiConn?.setFetch(fetch2);
|
|
599
|
+
this._appConn?.setFetch(fetch2);
|
|
595
600
|
}
|
|
596
601
|
async login(loginParams) {
|
|
597
602
|
if (this.apiUrl && !loginParams.forceLogin) {
|
|
@@ -680,15 +685,15 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
680
685
|
token;
|
|
681
686
|
headers;
|
|
682
687
|
fetch;
|
|
683
|
-
constructor(base_url,
|
|
688
|
+
constructor(base_url, fetch2) {
|
|
684
689
|
this.base_url = base_url;
|
|
685
690
|
this.token = null;
|
|
686
691
|
this.headers = {};
|
|
687
692
|
this._reset();
|
|
688
|
-
this.fetch =
|
|
693
|
+
this.fetch = fetch2;
|
|
689
694
|
}
|
|
690
|
-
setFetch(
|
|
691
|
-
this.fetch =
|
|
695
|
+
setFetch(fetch2) {
|
|
696
|
+
this.fetch = fetch2;
|
|
692
697
|
}
|
|
693
698
|
async ping() {
|
|
694
699
|
try {
|
|
@@ -724,12 +729,14 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
724
729
|
([k, v]) => v !== void 0 ? typeof v === "string" ? [[k, v]] : v.map((x) => [k, x]) : []
|
|
725
730
|
) : []
|
|
726
731
|
).toString();
|
|
732
|
+
const this_fetch = this.fetch;
|
|
733
|
+
const this_headers = this.headers;
|
|
727
734
|
return await checkResponse(
|
|
728
735
|
// Using toString() here makes it work with isomorphic fetch
|
|
729
|
-
await
|
|
736
|
+
await this_fetch(url.toString(), {
|
|
730
737
|
headers: {
|
|
731
738
|
Accept: "application/json",
|
|
732
|
-
...
|
|
739
|
+
...this_headers,
|
|
733
740
|
...headers
|
|
734
741
|
},
|
|
735
742
|
keepalive: true,
|
|
@@ -739,13 +746,16 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
739
746
|
}
|
|
740
747
|
async post(path, params, config) {
|
|
741
748
|
const { headers, ...rest } = config || {};
|
|
749
|
+
const this_fetch = this.fetch;
|
|
750
|
+
const this_base_url = this.base_url;
|
|
751
|
+
const this_headers = this.headers;
|
|
742
752
|
return await checkResponse(
|
|
743
|
-
await
|
|
753
|
+
await this_fetch((0, import_core._urljoin)(this_base_url, path), {
|
|
744
754
|
method: "POST",
|
|
745
755
|
headers: {
|
|
746
756
|
Accept: "application/json",
|
|
747
757
|
"Content-Type": "application/json",
|
|
748
|
-
...
|
|
758
|
+
...this_headers,
|
|
749
759
|
...headers
|
|
750
760
|
},
|
|
751
761
|
body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
|
|
@@ -778,6 +788,167 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
778
788
|
return await resp.json();
|
|
779
789
|
}
|
|
780
790
|
};
|
|
791
|
+
var Attachment = class {
|
|
792
|
+
/**
|
|
793
|
+
* The object that replaces this `Attachment` at upload time.
|
|
794
|
+
*/
|
|
795
|
+
reference;
|
|
796
|
+
uploader;
|
|
797
|
+
data;
|
|
798
|
+
state;
|
|
799
|
+
// For debug logging only.
|
|
800
|
+
dataDebugString;
|
|
801
|
+
/**
|
|
802
|
+
* Construct an attachment.
|
|
803
|
+
*
|
|
804
|
+
* @param data A string representing the path of the file on disk, or a
|
|
805
|
+
* `Blob`/`ArrayBuffer` with the file's contents. The caller is responsible
|
|
806
|
+
* for ensuring the file/blob/buffer is not modified until upload is complete.
|
|
807
|
+
*
|
|
808
|
+
* @param filename The desired name of the file in Braintrust after uploading.
|
|
809
|
+
* This parameter is for visualization purposes only and has no effect on
|
|
810
|
+
* attachment storage.
|
|
811
|
+
*
|
|
812
|
+
* @param contentType The MIME type of the file.
|
|
813
|
+
*
|
|
814
|
+
* @param state (Optional) For internal use.
|
|
815
|
+
*/
|
|
816
|
+
constructor({ data, filename, contentType, state }) {
|
|
817
|
+
this.reference = {
|
|
818
|
+
type: import_typespecs2.BRAINTRUST_ATTACHMENT,
|
|
819
|
+
filename,
|
|
820
|
+
content_type: contentType,
|
|
821
|
+
key: newId()
|
|
822
|
+
};
|
|
823
|
+
this.state = state;
|
|
824
|
+
this.dataDebugString = typeof data === "string" ? data : "<in-memory data>";
|
|
825
|
+
this.data = this.initData(data);
|
|
826
|
+
this.uploader = this.initUploader();
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* On first access, (1) reads the attachment from disk if needed, (2)
|
|
830
|
+
* authenticates with the data plane to request a signed URL, (3) uploads to
|
|
831
|
+
* object store, and (4) updates the attachment.
|
|
832
|
+
*
|
|
833
|
+
* @returns The attachment status.
|
|
834
|
+
*/
|
|
835
|
+
async upload() {
|
|
836
|
+
return await this.uploader.get();
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* A human-readable description for logging and debugging.
|
|
840
|
+
*
|
|
841
|
+
* @returns The debug object. The return type is not stable and may change in
|
|
842
|
+
* a future release.
|
|
843
|
+
*/
|
|
844
|
+
debugInfo() {
|
|
845
|
+
return {
|
|
846
|
+
inputData: this.dataDebugString,
|
|
847
|
+
reference: this.reference,
|
|
848
|
+
state: this.state
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
initUploader() {
|
|
852
|
+
const doUpload = async (conn, orgId) => {
|
|
853
|
+
const requestParams = {
|
|
854
|
+
key: this.reference.key,
|
|
855
|
+
filename: this.reference.filename,
|
|
856
|
+
content_type: this.reference.content_type,
|
|
857
|
+
org_id: orgId
|
|
858
|
+
};
|
|
859
|
+
const [metadataPromiseResult, dataPromiseResult] = await Promise.allSettled([
|
|
860
|
+
conn.post("/attachment", requestParams),
|
|
861
|
+
this.data.get()
|
|
862
|
+
]);
|
|
863
|
+
if (metadataPromiseResult.status === "rejected") {
|
|
864
|
+
const errorStr = JSON.stringify(metadataPromiseResult.reason);
|
|
865
|
+
throw new Error(
|
|
866
|
+
`Failed to request signed URL from API server: ${errorStr}`
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
if (dataPromiseResult.status === "rejected") {
|
|
870
|
+
const errorStr = JSON.stringify(dataPromiseResult.reason);
|
|
871
|
+
throw new Error(`Failed to read file: ${errorStr}`);
|
|
872
|
+
}
|
|
873
|
+
const metadataResponse = metadataPromiseResult.value;
|
|
874
|
+
const data = dataPromiseResult.value;
|
|
875
|
+
let signedUrl;
|
|
876
|
+
let headers;
|
|
877
|
+
try {
|
|
878
|
+
({ signedUrl, headers } = import_zod2.z.object({
|
|
879
|
+
signedUrl: import_zod2.z.string().url(),
|
|
880
|
+
headers: import_zod2.z.record(import_zod2.z.string())
|
|
881
|
+
}).parse(await metadataResponse.json()));
|
|
882
|
+
} catch (error) {
|
|
883
|
+
if (error instanceof import_zod2.ZodError) {
|
|
884
|
+
const errorStr = JSON.stringify(error.flatten());
|
|
885
|
+
throw new Error(`Invalid response from API server: ${errorStr}`);
|
|
886
|
+
}
|
|
887
|
+
throw error;
|
|
888
|
+
}
|
|
889
|
+
let objectStoreResponse;
|
|
890
|
+
try {
|
|
891
|
+
objectStoreResponse = await checkResponse(
|
|
892
|
+
await fetch(signedUrl, {
|
|
893
|
+
method: "PUT",
|
|
894
|
+
headers,
|
|
895
|
+
body: data
|
|
896
|
+
})
|
|
897
|
+
);
|
|
898
|
+
} catch (error) {
|
|
899
|
+
if (error instanceof FailedHTTPResponse) {
|
|
900
|
+
throw new Error(
|
|
901
|
+
`Failed to upload attachment to object store: ${error.status} ${error.text} ${error.data}`
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
throw error;
|
|
905
|
+
}
|
|
906
|
+
return { signedUrl, metadataResponse, objectStoreResponse };
|
|
907
|
+
};
|
|
908
|
+
const errorWrapper = async () => {
|
|
909
|
+
const status = { upload_status: "done" };
|
|
910
|
+
const state = this.state ?? _globalState;
|
|
911
|
+
await state.login({});
|
|
912
|
+
const conn = state.apiConn();
|
|
913
|
+
const orgId = state.orgId ?? "";
|
|
914
|
+
try {
|
|
915
|
+
await doUpload(conn, orgId);
|
|
916
|
+
} catch (error) {
|
|
917
|
+
status.upload_status = "error";
|
|
918
|
+
status.error_message = error instanceof Error ? error.message : JSON.stringify(error);
|
|
919
|
+
}
|
|
920
|
+
const requestParams = {
|
|
921
|
+
key: this.reference.key,
|
|
922
|
+
org_id: orgId,
|
|
923
|
+
status
|
|
924
|
+
};
|
|
925
|
+
const statusResponse = await conn.post(
|
|
926
|
+
"/attachment/status",
|
|
927
|
+
requestParams
|
|
928
|
+
);
|
|
929
|
+
if (!statusResponse.ok) {
|
|
930
|
+
const errorStr = JSON.stringify(statusResponse);
|
|
931
|
+
throw new Error(`Couldn't log attachment status: ${errorStr}`);
|
|
932
|
+
}
|
|
933
|
+
return status;
|
|
934
|
+
};
|
|
935
|
+
return new LazyValue(errorWrapper);
|
|
936
|
+
}
|
|
937
|
+
initData(data) {
|
|
938
|
+
if (typeof data === "string") {
|
|
939
|
+
const readFile = isomorph_default.readFile;
|
|
940
|
+
if (!readFile) {
|
|
941
|
+
throw new Error(
|
|
942
|
+
`This platform does not support reading the filesystem. Construct the Attachment
|
|
943
|
+
with a Blob/ArrayBuffer, or run the program on Node.js.`
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
return new LazyValue(async () => new Blob([await readFile(data)]));
|
|
947
|
+
} else {
|
|
948
|
+
return new LazyValue(async () => new Blob([data]));
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
};
|
|
781
952
|
function logFeedbackImpl(state, parentObjectType, parentObjectId, {
|
|
782
953
|
id,
|
|
783
954
|
expected,
|
|
@@ -802,7 +973,7 @@ function logFeedbackImpl(state, parentObjectType, parentObjectId, {
|
|
|
802
973
|
expected,
|
|
803
974
|
tags
|
|
804
975
|
});
|
|
805
|
-
let { metadata, ...updateEvent } = validatedEvent;
|
|
976
|
+
let { metadata, ...updateEvent } = deepCopyEvent(validatedEvent);
|
|
806
977
|
updateEvent = Object.fromEntries(
|
|
807
978
|
Object.entries(updateEvent).filter(([_, v]) => !isEmpty(v))
|
|
808
979
|
);
|
|
@@ -851,10 +1022,12 @@ function updateSpanImpl({
|
|
|
851
1022
|
id,
|
|
852
1023
|
event
|
|
853
1024
|
}) {
|
|
854
|
-
const updateEvent =
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
1025
|
+
const updateEvent = deepCopyEvent(
|
|
1026
|
+
validateAndSanitizeExperimentLogPartialArgs({
|
|
1027
|
+
id,
|
|
1028
|
+
...event
|
|
1029
|
+
})
|
|
1030
|
+
);
|
|
858
1031
|
const parentIds = async () => new import_core.SpanComponentsV3({
|
|
859
1032
|
object_type: parentObjectType,
|
|
860
1033
|
object_id: await parentObjectId.get()
|
|
@@ -1055,7 +1228,7 @@ var Logger = class {
|
|
|
1055
1228
|
* @param event.id: (Optional) a unique identifier for the event. If you don't provide one, BrainTrust will generate one for you.
|
|
1056
1229
|
* @param options Additional logging options
|
|
1057
1230
|
* @param options.allowConcurrentWithSpans in rare cases where you need to log at the top level separately from spans on the logger elsewhere, set this to true.
|
|
1058
|
-
*
|
|
1231
|
+
* @returns The `id` of the logged event.
|
|
1059
1232
|
*/
|
|
1060
1233
|
log(event, options) {
|
|
1061
1234
|
if (this.calledStartSpan && !options?.allowConcurrentWithSpans) {
|
|
@@ -1078,7 +1251,7 @@ var Logger = class {
|
|
|
1078
1251
|
/**
|
|
1079
1252
|
* Create a new toplevel span underneath the logger. The name defaults to "root".
|
|
1080
1253
|
*
|
|
1081
|
-
* See
|
|
1254
|
+
* See {@link Span.traced} for full details.
|
|
1082
1255
|
*/
|
|
1083
1256
|
traced(callback, args) {
|
|
1084
1257
|
const { setCurrent, ...argsRest } = args ?? {};
|
|
@@ -1112,7 +1285,7 @@ var Logger = class {
|
|
|
1112
1285
|
* where you cannot use callbacks. However, spans started with `startSpan` will not be marked as the "current span",
|
|
1113
1286
|
* so `currentSpan()` and `traced()` will be no-ops. If you want to mark a span as current, use `traced` instead.
|
|
1114
1287
|
*
|
|
1115
|
-
* See
|
|
1288
|
+
* See {@link traced} for full details.
|
|
1116
1289
|
*/
|
|
1117
1290
|
startSpan(args) {
|
|
1118
1291
|
this.calledStartSpan = true;
|
|
@@ -1152,7 +1325,7 @@ var Logger = class {
|
|
|
1152
1325
|
* Update a span in the experiment using its id. It is important that you only update a span once the original span has been fully written and flushed,
|
|
1153
1326
|
* since otherwise updates to the span may conflict with the original span.
|
|
1154
1327
|
*
|
|
1155
|
-
* @param event The event data to update the span with. Must include `id`. See
|
|
1328
|
+
* @param event The event data to update the span with. Must include `id`. See {@link Experiment.log} for a full list of valid fields.
|
|
1156
1329
|
*/
|
|
1157
1330
|
updateSpan(event) {
|
|
1158
1331
|
const { id, ...eventRest } = event;
|
|
@@ -1168,7 +1341,9 @@ var Logger = class {
|
|
|
1168
1341
|
});
|
|
1169
1342
|
}
|
|
1170
1343
|
/**
|
|
1171
|
-
* Return a serialized representation of the logger that can be used to start subspans in other places.
|
|
1344
|
+
* Return a serialized representation of the logger that can be used to start subspans in other places.
|
|
1345
|
+
*
|
|
1346
|
+
* See {@link Span.startSpan} for more details.
|
|
1172
1347
|
*/
|
|
1173
1348
|
async export() {
|
|
1174
1349
|
return new import_core.SpanComponentsV3({
|
|
@@ -1208,6 +1383,7 @@ var BackgroundLogger = class _BackgroundLogger {
|
|
|
1208
1383
|
activeFlush = Promise.resolve();
|
|
1209
1384
|
activeFlushResolved = true;
|
|
1210
1385
|
activeFlushError = void 0;
|
|
1386
|
+
onFlushError;
|
|
1211
1387
|
syncFlush = false;
|
|
1212
1388
|
// 6 MB for the AWS lambda gateway (from our own testing).
|
|
1213
1389
|
maxRequestSize = 6 * 1024 * 1024;
|
|
@@ -1271,6 +1447,7 @@ var BackgroundLogger = class _BackgroundLogger {
|
|
|
1271
1447
|
await this.flush();
|
|
1272
1448
|
});
|
|
1273
1449
|
}
|
|
1450
|
+
this.onFlushError = opts.onFlushError;
|
|
1274
1451
|
}
|
|
1275
1452
|
log(items) {
|
|
1276
1453
|
const [addedItems, droppedItems] = (() => {
|
|
@@ -1302,14 +1479,16 @@ var BackgroundLogger = class _BackgroundLogger {
|
|
|
1302
1479
|
if (this.activeFlushError) {
|
|
1303
1480
|
const err = this.activeFlushError;
|
|
1304
1481
|
this.activeFlushError = void 0;
|
|
1305
|
-
|
|
1482
|
+
if (this.syncFlush) {
|
|
1483
|
+
throw err;
|
|
1484
|
+
}
|
|
1306
1485
|
}
|
|
1307
1486
|
}
|
|
1308
1487
|
async flushOnce(args) {
|
|
1309
1488
|
const batchSize = args?.batchSize ?? this.defaultBatchSize;
|
|
1310
1489
|
const wrappedItems = this.items;
|
|
1311
1490
|
this.items = [];
|
|
1312
|
-
const allItems = await this.unwrapLazyValues(wrappedItems);
|
|
1491
|
+
const [allItems, attachments] = await this.unwrapLazyValues(wrappedItems);
|
|
1313
1492
|
if (allItems.length === 0) {
|
|
1314
1493
|
return;
|
|
1315
1494
|
}
|
|
@@ -1341,6 +1520,23 @@ var BackgroundLogger = class _BackgroundLogger {
|
|
|
1341
1520
|
);
|
|
1342
1521
|
}
|
|
1343
1522
|
}
|
|
1523
|
+
const attachmentErrors = [];
|
|
1524
|
+
for (const attachment of attachments) {
|
|
1525
|
+
try {
|
|
1526
|
+
const result = await attachment.upload();
|
|
1527
|
+
if (result.upload_status === "error" && result.error_message) {
|
|
1528
|
+
attachmentErrors.push(new Error(result.error_message));
|
|
1529
|
+
}
|
|
1530
|
+
} catch (error) {
|
|
1531
|
+
attachmentErrors.push(error);
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
if (attachmentErrors.length > 0) {
|
|
1535
|
+
throw new AggregateError(
|
|
1536
|
+
attachmentErrors,
|
|
1537
|
+
`Encountered the following errors while uploading attachments:`
|
|
1538
|
+
);
|
|
1539
|
+
}
|
|
1344
1540
|
if (this.items.length > 0) {
|
|
1345
1541
|
await this.flushOnce(args);
|
|
1346
1542
|
}
|
|
@@ -1348,8 +1544,10 @@ var BackgroundLogger = class _BackgroundLogger {
|
|
|
1348
1544
|
async unwrapLazyValues(wrappedItems) {
|
|
1349
1545
|
for (let i = 0; i < this.numTries; ++i) {
|
|
1350
1546
|
try {
|
|
1351
|
-
const
|
|
1352
|
-
|
|
1547
|
+
const items = await Promise.all(wrappedItems.map((x) => x.get()));
|
|
1548
|
+
const attachments = [];
|
|
1549
|
+
items.forEach((item) => extractAttachments(item, attachments));
|
|
1550
|
+
return [(0, import_core.mergeRowBatch)(items), attachments];
|
|
1353
1551
|
} catch (e) {
|
|
1354
1552
|
let errmsg = "Encountered error when constructing records to flush";
|
|
1355
1553
|
const isRetrying = i + 1 < this.numTries;
|
|
@@ -1357,7 +1555,10 @@ var BackgroundLogger = class _BackgroundLogger {
|
|
|
1357
1555
|
errmsg += ". Retrying";
|
|
1358
1556
|
}
|
|
1359
1557
|
console.warn(errmsg);
|
|
1360
|
-
if (!isRetrying
|
|
1558
|
+
if (!isRetrying) {
|
|
1559
|
+
console.warn(
|
|
1560
|
+
`Failed to construct log records to flush after ${this.numTries} attempts. Dropping batch`
|
|
1561
|
+
);
|
|
1361
1562
|
throw e;
|
|
1362
1563
|
} else {
|
|
1363
1564
|
console.warn(e);
|
|
@@ -1365,10 +1566,7 @@ var BackgroundLogger = class _BackgroundLogger {
|
|
|
1365
1566
|
}
|
|
1366
1567
|
}
|
|
1367
1568
|
}
|
|
1368
|
-
|
|
1369
|
-
`Failed to construct log records to flush after ${this.numTries} attempts. Dropping batch`
|
|
1370
|
-
);
|
|
1371
|
-
return [];
|
|
1569
|
+
throw new Error("Impossible");
|
|
1372
1570
|
}
|
|
1373
1571
|
async submitLogsRequest(items) {
|
|
1374
1572
|
const conn = await this.apiConn.get();
|
|
@@ -1384,16 +1582,14 @@ var BackgroundLogger = class _BackgroundLogger {
|
|
|
1384
1582
|
let error = void 0;
|
|
1385
1583
|
try {
|
|
1386
1584
|
await conn.post_json("logs3", dataStr);
|
|
1387
|
-
} catch
|
|
1585
|
+
} catch {
|
|
1388
1586
|
try {
|
|
1389
1587
|
const legacyDataS = (0, import_core.constructJsonArray)(
|
|
1390
|
-
items.map(
|
|
1391
|
-
(r) => JSON.stringify((0, import_core.makeLegacyEvent)(JSON.parse(r)))
|
|
1392
|
-
)
|
|
1588
|
+
items.map((r) => JSON.stringify((0, import_core.makeLegacyEvent)(JSON.parse(r))))
|
|
1393
1589
|
);
|
|
1394
1590
|
await conn.post_json("logs", legacyDataS);
|
|
1395
|
-
} catch (
|
|
1396
|
-
error =
|
|
1591
|
+
} catch (e) {
|
|
1592
|
+
error = e;
|
|
1397
1593
|
}
|
|
1398
1594
|
}
|
|
1399
1595
|
if (error === void 0) {
|
|
@@ -1417,7 +1613,10 @@ Error: ${errorText}`;
|
|
|
1417
1613
|
});
|
|
1418
1614
|
this.logFailedPayloadsDir();
|
|
1419
1615
|
}
|
|
1420
|
-
if (!isRetrying
|
|
1616
|
+
if (!isRetrying) {
|
|
1617
|
+
console.warn(
|
|
1618
|
+
`log request failed after ${this.numTries} retries. Dropping batch`
|
|
1619
|
+
);
|
|
1421
1620
|
throw new Error(errMsg);
|
|
1422
1621
|
} else {
|
|
1423
1622
|
console.warn(errMsg);
|
|
@@ -1426,10 +1625,6 @@ Error: ${errorText}`;
|
|
|
1426
1625
|
}
|
|
1427
1626
|
}
|
|
1428
1627
|
}
|
|
1429
|
-
console.warn(
|
|
1430
|
-
`log request failed after ${this.numTries} retries. Dropping batch`
|
|
1431
|
-
);
|
|
1432
|
-
return;
|
|
1433
1628
|
}
|
|
1434
1629
|
registerDroppedItemCount(numItems) {
|
|
1435
1630
|
if (numItems <= 0) {
|
|
@@ -1457,15 +1652,17 @@ Error: ${errorText}`;
|
|
|
1457
1652
|
return;
|
|
1458
1653
|
}
|
|
1459
1654
|
try {
|
|
1460
|
-
const allItems = await this.unwrapLazyValues(wrappedItems);
|
|
1655
|
+
const [allItems, allAttachments] = await this.unwrapLazyValues(wrappedItems);
|
|
1461
1656
|
const dataStr = constructLogs3Data(
|
|
1462
1657
|
allItems.map((x) => JSON.stringify(x))
|
|
1463
1658
|
);
|
|
1659
|
+
const attachmentStr = JSON.stringify(
|
|
1660
|
+
allAttachments.map((a) => a.debugInfo())
|
|
1661
|
+
);
|
|
1662
|
+
const payload = `{"data": ${dataStr}, "attachments": ${attachmentStr}}
|
|
1663
|
+
`;
|
|
1464
1664
|
for (const payloadDir of publishPayloadsDir) {
|
|
1465
|
-
await _BackgroundLogger.writePayloadToDir({
|
|
1466
|
-
payloadDir,
|
|
1467
|
-
payload: dataStr
|
|
1468
|
-
});
|
|
1665
|
+
await _BackgroundLogger.writePayloadToDir({ payloadDir, payload });
|
|
1469
1666
|
}
|
|
1470
1667
|
} catch (e) {
|
|
1471
1668
|
console.error(e);
|
|
@@ -1504,6 +1701,13 @@ Error: ${errorText}`;
|
|
|
1504
1701
|
try {
|
|
1505
1702
|
await this.flushOnce();
|
|
1506
1703
|
} catch (err) {
|
|
1704
|
+
if (err instanceof AggregateError) {
|
|
1705
|
+
for (const e of err.errors) {
|
|
1706
|
+
this.onFlushError?.(e);
|
|
1707
|
+
}
|
|
1708
|
+
} else {
|
|
1709
|
+
this.onFlushError?.(err);
|
|
1710
|
+
}
|
|
1507
1711
|
this.activeFlushError = err;
|
|
1508
1712
|
} finally {
|
|
1509
1713
|
this.activeFlushResolved = true;
|
|
@@ -1546,7 +1750,7 @@ function init(projectOrOptions, optionalOptions) {
|
|
|
1546
1750
|
apiKey,
|
|
1547
1751
|
orgName,
|
|
1548
1752
|
forceLogin,
|
|
1549
|
-
fetch,
|
|
1753
|
+
fetch: fetch2,
|
|
1550
1754
|
metadata,
|
|
1551
1755
|
gitMetadataSettings,
|
|
1552
1756
|
projectId,
|
|
@@ -1564,7 +1768,7 @@ function init(projectOrOptions, optionalOptions) {
|
|
|
1564
1768
|
}
|
|
1565
1769
|
const lazyMetadata2 = new LazyValue(
|
|
1566
1770
|
async () => {
|
|
1567
|
-
await state.login({ apiKey, appUrl, orgName, fetch, forceLogin });
|
|
1771
|
+
await state.login({ apiKey, appUrl, orgName, fetch: fetch2, forceLogin });
|
|
1568
1772
|
const args = {
|
|
1569
1773
|
project_name: project,
|
|
1570
1774
|
project_id: projectId,
|
|
@@ -1735,7 +1939,7 @@ function initDataset(projectOrOptions, optionalOptions) {
|
|
|
1735
1939
|
appUrl,
|
|
1736
1940
|
apiKey,
|
|
1737
1941
|
orgName,
|
|
1738
|
-
fetch,
|
|
1942
|
+
fetch: fetch2,
|
|
1739
1943
|
forceLogin,
|
|
1740
1944
|
projectId,
|
|
1741
1945
|
metadata,
|
|
@@ -1749,7 +1953,7 @@ function initDataset(projectOrOptions, optionalOptions) {
|
|
|
1749
1953
|
orgName,
|
|
1750
1954
|
apiKey,
|
|
1751
1955
|
appUrl,
|
|
1752
|
-
fetch,
|
|
1956
|
+
fetch: fetch2,
|
|
1753
1957
|
forceLogin
|
|
1754
1958
|
});
|
|
1755
1959
|
const args = {
|
|
@@ -1831,7 +2035,7 @@ function initLogger(options = {}) {
|
|
|
1831
2035
|
apiKey,
|
|
1832
2036
|
orgName,
|
|
1833
2037
|
forceLogin,
|
|
1834
|
-
fetch,
|
|
2038
|
+
fetch: fetch2,
|
|
1835
2039
|
state: stateArg
|
|
1836
2040
|
} = options || {};
|
|
1837
2041
|
const computeMetadataArgs = {
|
|
@@ -1846,7 +2050,7 @@ function initLogger(options = {}) {
|
|
|
1846
2050
|
apiKey,
|
|
1847
2051
|
appUrl,
|
|
1848
2052
|
forceLogin,
|
|
1849
|
-
fetch
|
|
2053
|
+
fetch: fetch2
|
|
1850
2054
|
});
|
|
1851
2055
|
return computeLoggerMetadata(state, computeMetadataArgs);
|
|
1852
2056
|
}
|
|
@@ -1870,7 +2074,7 @@ async function loadPrompt({
|
|
|
1870
2074
|
appUrl,
|
|
1871
2075
|
apiKey,
|
|
1872
2076
|
orgName,
|
|
1873
|
-
fetch,
|
|
2077
|
+
fetch: fetch2,
|
|
1874
2078
|
forceLogin,
|
|
1875
2079
|
state: stateArg
|
|
1876
2080
|
}) {
|
|
@@ -1885,7 +2089,7 @@ async function loadPrompt({
|
|
|
1885
2089
|
orgName,
|
|
1886
2090
|
apiKey,
|
|
1887
2091
|
appUrl,
|
|
1888
|
-
fetch,
|
|
2092
|
+
fetch: fetch2,
|
|
1889
2093
|
forceLogin
|
|
1890
2094
|
});
|
|
1891
2095
|
const args = {
|
|
@@ -1936,7 +2140,7 @@ async function loginToState(options = {}) {
|
|
|
1936
2140
|
appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
|
|
1937
2141
|
apiKey = isomorph_default.getEnv("BRAINTRUST_API_KEY"),
|
|
1938
2142
|
orgName = isomorph_default.getEnv("BRAINTRUST_ORG_NAME"),
|
|
1939
|
-
fetch = globalThis.fetch
|
|
2143
|
+
fetch: fetch2 = globalThis.fetch
|
|
1940
2144
|
} = options || {};
|
|
1941
2145
|
const appPublicUrl = isomorph_default.getEnv("BRAINTRUST_APP_PUBLIC_URL") || appUrl;
|
|
1942
2146
|
const state = new BraintrustState(options);
|
|
@@ -1946,7 +2150,7 @@ async function loginToState(options = {}) {
|
|
|
1946
2150
|
let conn = null;
|
|
1947
2151
|
if (apiKey !== void 0) {
|
|
1948
2152
|
const resp = await checkResponse(
|
|
1949
|
-
await
|
|
2153
|
+
await fetch2((0, import_core._urljoin)(state.appUrl, `/api/apikey/login`), {
|
|
1950
2154
|
method: "POST",
|
|
1951
2155
|
headers: {
|
|
1952
2156
|
"Content-Type": "application/json",
|
|
@@ -2114,8 +2318,8 @@ async function flush(options) {
|
|
|
2114
2318
|
const state = options?.state ?? _globalState;
|
|
2115
2319
|
return await state.bgLogger().flush();
|
|
2116
2320
|
}
|
|
2117
|
-
function setFetch(
|
|
2118
|
-
_globalState.setFetch(
|
|
2321
|
+
function setFetch(fetch2) {
|
|
2322
|
+
_globalState.setFetch(fetch2);
|
|
2119
2323
|
}
|
|
2120
2324
|
function startSpanAndIsLogger(args) {
|
|
2121
2325
|
const state = args?.state ?? _globalState;
|
|
@@ -2243,6 +2447,47 @@ function validateAndSanitizeExperimentLogPartialArgs(event) {
|
|
|
2243
2447
|
return { ...event };
|
|
2244
2448
|
}
|
|
2245
2449
|
}
|
|
2450
|
+
function deepCopyEvent(event) {
|
|
2451
|
+
const attachments = [];
|
|
2452
|
+
const IDENTIFIER = "_bt_internal_saved_attachment";
|
|
2453
|
+
const savedAttachmentSchema = import_zod2.z.strictObject({ [IDENTIFIER]: import_zod2.z.number() });
|
|
2454
|
+
const serialized = JSON.stringify(event, (_k, v) => {
|
|
2455
|
+
if (v instanceof SpanImpl || v instanceof NoopSpan) {
|
|
2456
|
+
return `<span>`;
|
|
2457
|
+
} else if (v instanceof Experiment) {
|
|
2458
|
+
return `<experiment>`;
|
|
2459
|
+
} else if (v instanceof Dataset) {
|
|
2460
|
+
return `<dataset>`;
|
|
2461
|
+
} else if (v instanceof Logger) {
|
|
2462
|
+
return `<logger>`;
|
|
2463
|
+
} else if (v instanceof Attachment) {
|
|
2464
|
+
const idx = attachments.push(v);
|
|
2465
|
+
return { [IDENTIFIER]: idx - 1 };
|
|
2466
|
+
}
|
|
2467
|
+
return v;
|
|
2468
|
+
});
|
|
2469
|
+
const x = JSON.parse(serialized, (_k, v) => {
|
|
2470
|
+
const parsedAttachment = savedAttachmentSchema.safeParse(v);
|
|
2471
|
+
if (parsedAttachment.success) {
|
|
2472
|
+
return attachments[parsedAttachment.data[IDENTIFIER]];
|
|
2473
|
+
}
|
|
2474
|
+
return v;
|
|
2475
|
+
});
|
|
2476
|
+
return x;
|
|
2477
|
+
}
|
|
2478
|
+
function extractAttachments(event, attachments) {
|
|
2479
|
+
for (const [key, value] of Object.entries(event)) {
|
|
2480
|
+
if (value instanceof Attachment) {
|
|
2481
|
+
attachments.push(value);
|
|
2482
|
+
event[key] = value.reference;
|
|
2483
|
+
continue;
|
|
2484
|
+
}
|
|
2485
|
+
if (!(value instanceof Object)) {
|
|
2486
|
+
continue;
|
|
2487
|
+
}
|
|
2488
|
+
extractAttachments(value, attachments);
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2246
2491
|
function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
|
|
2247
2492
|
if ("input" in event && !isEmpty(event.input) && "inputs" in event && !isEmpty(event.inputs) || !("input" in event) && !("inputs" in event)) {
|
|
2248
2493
|
throw new Error(
|
|
@@ -2373,10 +2618,9 @@ var Experiment = class extends ObjectFetcher {
|
|
|
2373
2618
|
* @param event.metrics: (Optional) a dictionary of metrics to log. The following keys are populated automatically: "start", "end".
|
|
2374
2619
|
* @param event.id: (Optional) a unique identifier for the event. If you don't provide one, BrainTrust will generate one for you.
|
|
2375
2620
|
* @param event.dataset_record_id: (Optional) the id of the dataset record that this event is associated with. This field is required if and only if the experiment is associated with a dataset.
|
|
2376
|
-
* @param event.inputs: (Deprecated) the same as `input` (will be removed in a future version).
|
|
2377
2621
|
* @param options Additional logging options
|
|
2378
2622
|
* @param options.allowConcurrentWithSpans in rare cases where you need to log at the top level separately from spans on the experiment elsewhere, set this to true.
|
|
2379
|
-
*
|
|
2623
|
+
* @returns The `id` of the logged event.
|
|
2380
2624
|
*/
|
|
2381
2625
|
log(event, options) {
|
|
2382
2626
|
if (this.calledStartSpan && !options?.allowConcurrentWithSpans) {
|
|
@@ -2392,7 +2636,7 @@ var Experiment = class extends ObjectFetcher {
|
|
|
2392
2636
|
/**
|
|
2393
2637
|
* Create a new toplevel span underneath the experiment. The name defaults to "root".
|
|
2394
2638
|
*
|
|
2395
|
-
* See
|
|
2639
|
+
* See {@link Span.traced} for full details.
|
|
2396
2640
|
*/
|
|
2397
2641
|
traced(callback, args) {
|
|
2398
2642
|
const { setCurrent, ...argsRest } = args ?? {};
|
|
@@ -2418,7 +2662,7 @@ var Experiment = class extends ObjectFetcher {
|
|
|
2418
2662
|
* where you cannot use callbacks. However, spans started with `startSpan` will not be marked as the "current span",
|
|
2419
2663
|
* so `currentSpan()` and `traced()` will be no-ops. If you want to mark a span as current, use `traced` instead.
|
|
2420
2664
|
*
|
|
2421
|
-
* See
|
|
2665
|
+
* See {@link traced} for full details.
|
|
2422
2666
|
*/
|
|
2423
2667
|
startSpan(args) {
|
|
2424
2668
|
this.calledStartSpan = true;
|
|
@@ -2530,7 +2774,7 @@ var Experiment = class extends ObjectFetcher {
|
|
|
2530
2774
|
* Update a span in the experiment using its id. It is important that you only update a span once the original span has been fully written and flushed,
|
|
2531
2775
|
* since otherwise updates to the span may conflict with the original span.
|
|
2532
2776
|
*
|
|
2533
|
-
* @param event The event data to update the span with. Must include `id`. See
|
|
2777
|
+
* @param event The event data to update the span with. Must include `id`. See {@link Experiment.log} for a full list of valid fields.
|
|
2534
2778
|
*/
|
|
2535
2779
|
updateSpan(event) {
|
|
2536
2780
|
const { id, ...eventRest } = event;
|
|
@@ -2546,7 +2790,9 @@ var Experiment = class extends ObjectFetcher {
|
|
|
2546
2790
|
});
|
|
2547
2791
|
}
|
|
2548
2792
|
/**
|
|
2549
|
-
* Return a serialized representation of the experiment that can be used to start subspans in other places.
|
|
2793
|
+
* Return a serialized representation of the experiment that can be used to start subspans in other places.
|
|
2794
|
+
*
|
|
2795
|
+
* See {@link Span.startSpan} for more details.
|
|
2550
2796
|
*/
|
|
2551
2797
|
async export() {
|
|
2552
2798
|
return new import_core.SpanComponentsV3({
|
|
@@ -2561,7 +2807,7 @@ var Experiment = class extends ObjectFetcher {
|
|
|
2561
2807
|
return await this.state.bgLogger().flush();
|
|
2562
2808
|
}
|
|
2563
2809
|
/**
|
|
2564
|
-
* This function is deprecated. You can simply remove it from your code.
|
|
2810
|
+
* @deprecated This function is deprecated. You can simply remove it from your code.
|
|
2565
2811
|
*/
|
|
2566
2812
|
async close() {
|
|
2567
2813
|
console.warn(
|
|
@@ -2703,27 +2949,14 @@ var SpanImpl = class _SpanImpl {
|
|
|
2703
2949
|
event,
|
|
2704
2950
|
internalData
|
|
2705
2951
|
});
|
|
2706
|
-
|
|
2952
|
+
const partialRecord = deepCopyEvent({
|
|
2707
2953
|
id: this.id,
|
|
2708
2954
|
span_id: this.spanId,
|
|
2709
2955
|
root_span_id: this.rootSpanId,
|
|
2710
2956
|
span_parents: this.spanParents,
|
|
2711
2957
|
...serializableInternalData,
|
|
2712
2958
|
[import_core.IS_MERGE_FIELD]: this.isMerge
|
|
2713
|
-
};
|
|
2714
|
-
const serializedPartialRecord = JSON.stringify(partialRecord, (_k, v) => {
|
|
2715
|
-
if (v instanceof _SpanImpl) {
|
|
2716
|
-
return `<span>`;
|
|
2717
|
-
} else if (v instanceof Experiment) {
|
|
2718
|
-
return `<experiment>`;
|
|
2719
|
-
} else if (v instanceof Dataset) {
|
|
2720
|
-
return `<dataset>`;
|
|
2721
|
-
} else if (v instanceof Logger) {
|
|
2722
|
-
return `<logger>`;
|
|
2723
|
-
}
|
|
2724
|
-
return v;
|
|
2725
2959
|
});
|
|
2726
|
-
partialRecord = JSON.parse(serializedPartialRecord);
|
|
2727
2960
|
if (partialRecord.metrics?.end) {
|
|
2728
2961
|
this.loggedEndTime = partialRecord.metrics?.end;
|
|
2729
2962
|
}
|
|
@@ -2809,6 +3042,11 @@ var SpanImpl = class _SpanImpl {
|
|
|
2809
3042
|
propagated_event: this.propagatedEvent
|
|
2810
3043
|
}).toStr();
|
|
2811
3044
|
}
|
|
3045
|
+
async permalink() {
|
|
3046
|
+
return await permalink(await this.export(), {
|
|
3047
|
+
state: this.state
|
|
3048
|
+
});
|
|
3049
|
+
}
|
|
2812
3050
|
async flush() {
|
|
2813
3051
|
return await this.state.bgLogger().flush();
|
|
2814
3052
|
}
|
|
@@ -2958,15 +3196,17 @@ var Dataset = class extends ObjectFetcher {
|
|
|
2958
3196
|
}) {
|
|
2959
3197
|
this.validateEvent({ metadata, expected, output, tags });
|
|
2960
3198
|
const rowId = id || (0, import_uuid.v4)();
|
|
2961
|
-
const args = this.createArgs(
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
3199
|
+
const args = this.createArgs(
|
|
3200
|
+
deepCopyEvent({
|
|
3201
|
+
id: rowId,
|
|
3202
|
+
input,
|
|
3203
|
+
expected,
|
|
3204
|
+
metadata,
|
|
3205
|
+
tags,
|
|
3206
|
+
output,
|
|
3207
|
+
isMerge: false
|
|
3208
|
+
})
|
|
3209
|
+
);
|
|
2970
3210
|
this.state.bgLogger().log([args]);
|
|
2971
3211
|
return rowId;
|
|
2972
3212
|
}
|
|
@@ -2991,14 +3231,16 @@ var Dataset = class extends ObjectFetcher {
|
|
|
2991
3231
|
id
|
|
2992
3232
|
}) {
|
|
2993
3233
|
this.validateEvent({ metadata, expected, tags });
|
|
2994
|
-
const args = this.createArgs(
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3234
|
+
const args = this.createArgs(
|
|
3235
|
+
deepCopyEvent({
|
|
3236
|
+
id,
|
|
3237
|
+
input,
|
|
3238
|
+
expected,
|
|
3239
|
+
metadata,
|
|
3240
|
+
tags,
|
|
3241
|
+
isMerge: true
|
|
3242
|
+
})
|
|
3243
|
+
);
|
|
3002
3244
|
this.state.bgLogger().log([args]);
|
|
3003
3245
|
return id;
|
|
3004
3246
|
}
|
|
@@ -3053,7 +3295,7 @@ var Dataset = class extends ObjectFetcher {
|
|
|
3053
3295
|
return await this.state.bgLogger().flush();
|
|
3054
3296
|
}
|
|
3055
3297
|
/**
|
|
3056
|
-
* This function is deprecated. You can simply remove it from your code.
|
|
3298
|
+
* @deprecated This function is deprecated. You can simply remove it from your code.
|
|
3057
3299
|
*/
|
|
3058
3300
|
async close() {
|
|
3059
3301
|
console.warn(
|
|
@@ -3217,6 +3459,7 @@ var Prompt = class {
|
|
|
3217
3459
|
return this.parsedPromptData;
|
|
3218
3460
|
}
|
|
3219
3461
|
};
|
|
3462
|
+
var _exportsForTestingOnly = { extractAttachments, deepCopyEvent };
|
|
3220
3463
|
|
|
3221
3464
|
// src/browser-config.ts
|
|
3222
3465
|
var browserConfigured = false;
|
|
@@ -3243,6 +3486,7 @@ function configureBrowser() {
|
|
|
3243
3486
|
// src/exports-browser.ts
|
|
3244
3487
|
var exports_browser_exports = {};
|
|
3245
3488
|
__export(exports_browser_exports, {
|
|
3489
|
+
Attachment: () => Attachment,
|
|
3246
3490
|
BraintrustState: () => BraintrustState,
|
|
3247
3491
|
BraintrustStream: () => BraintrustStream,
|
|
3248
3492
|
Dataset: () => Dataset,
|
|
@@ -3256,6 +3500,7 @@ __export(exports_browser_exports, {
|
|
|
3256
3500
|
ReadonlyExperiment: () => ReadonlyExperiment,
|
|
3257
3501
|
SpanImpl: () => SpanImpl,
|
|
3258
3502
|
X_CACHED_HEADER: () => X_CACHED_HEADER,
|
|
3503
|
+
_exportsForTestingOnly: () => _exportsForTestingOnly,
|
|
3259
3504
|
_internalGetGlobalState: () => _internalGetGlobalState,
|
|
3260
3505
|
_internalSetInitialState: () => _internalSetInitialState,
|
|
3261
3506
|
braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
|
|
@@ -3304,7 +3549,7 @@ async function invoke(args) {
|
|
|
3304
3549
|
apiKey,
|
|
3305
3550
|
appUrl,
|
|
3306
3551
|
forceLogin,
|
|
3307
|
-
fetch,
|
|
3552
|
+
fetch: fetch2,
|
|
3308
3553
|
input,
|
|
3309
3554
|
messages,
|
|
3310
3555
|
parent: parentArg,
|
|
@@ -3320,7 +3565,7 @@ async function invoke(args) {
|
|
|
3320
3565
|
apiKey,
|
|
3321
3566
|
appUrl,
|
|
3322
3567
|
forceLogin,
|
|
3323
|
-
fetch
|
|
3568
|
+
fetch: fetch2
|
|
3324
3569
|
});
|
|
3325
3570
|
const parent = parentArg ? typeof parentArg === "string" ? parentArg : await parentArg.export() : await getSpanParentObject().export();
|
|
3326
3571
|
const functionId = import_typespecs3.functionIdSchema.safeParse({
|
|
@@ -3748,6 +3993,7 @@ configureBrowser();
|
|
|
3748
3993
|
var browser_default = exports_browser_exports;
|
|
3749
3994
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3750
3995
|
0 && (module.exports = {
|
|
3996
|
+
Attachment,
|
|
3751
3997
|
BraintrustState,
|
|
3752
3998
|
BraintrustStream,
|
|
3753
3999
|
Dataset,
|
|
@@ -3761,6 +4007,7 @@ var browser_default = exports_browser_exports;
|
|
|
3761
4007
|
ReadonlyExperiment,
|
|
3762
4008
|
SpanImpl,
|
|
3763
4009
|
X_CACHED_HEADER,
|
|
4010
|
+
_exportsForTestingOnly,
|
|
3764
4011
|
_internalGetGlobalState,
|
|
3765
4012
|
_internalSetInitialState,
|
|
3766
4013
|
braintrustStreamChunkSchema,
|