bitfab 0.58.5 → 0.59.1
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/autoTrace.cjs.map +1 -1
- package/dist/autoTrace.d.cts +2 -0
- package/dist/autoTrace.d.ts +2 -0
- package/dist/autoTrace.js +1 -1
- package/dist/{chunk-TAEWAXPA.js → chunk-3D5EEY47.js} +54 -38
- package/dist/chunk-3D5EEY47.js.map +1 -0
- package/dist/{chunk-OTQA6MCF.js → chunk-4F46OBRG.js} +18 -10
- package/dist/chunk-4F46OBRG.js.map +1 -0
- package/dist/{chunk-ETZUSSF6.js → chunk-5DNB7EN7.js} +1 -1
- package/dist/chunk-5DNB7EN7.js.map +1 -0
- package/dist/{chunk-QIBFNIIF.js → chunk-5MN6WIMW.js} +29 -14
- package/dist/chunk-5MN6WIMW.js.map +1 -0
- package/dist/{chunk-7SPNHC33.js → chunk-GJCZABUC.js} +29 -14
- package/dist/chunk-GJCZABUC.js.map +1 -0
- package/dist/{chunk-UYAQRSCB.js → chunk-NVOQ7YMI.js} +149 -41
- package/dist/chunk-NVOQ7YMI.js.map +1 -0
- package/dist/{http-F6QV3YLY.js → http-2QEMP27E.js} +4 -2
- package/dist/{http-XDKEIZNV.js → http-OXKVRA3E.js} +4 -2
- package/dist/index.cjs +225 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +98 -43
- package/dist/index.d.ts +98 -43
- package/dist/index.js +12 -4
- package/dist/node.cjs +225 -82
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +12 -4
- package/dist/node.js.map +1 -1
- package/dist/{replay-WLJFWS6T.js → replay-WYPFFXSU.js} +3 -3
- package/dist/replayCli.js +2 -2
- package/dist/seedCli.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-7SPNHC33.js.map +0 -1
- package/dist/chunk-ETZUSSF6.js.map +0 -1
- package/dist/chunk-OTQA6MCF.js.map +0 -1
- package/dist/chunk-QIBFNIIF.js.map +0 -1
- package/dist/chunk-TAEWAXPA.js.map +0 -1
- package/dist/chunk-UYAQRSCB.js.map +0 -1
- /package/dist/{http-F6QV3YLY.js.map → http-2QEMP27E.js.map} +0 -0
- /package/dist/{http-XDKEIZNV.js.map → http-OXKVRA3E.js.map} +0 -0
- /package/dist/{replay-WLJFWS6T.js.map → replay-WYPFFXSU.js.map} +0 -0
package/dist/node.cjs
CHANGED
|
@@ -97,7 +97,7 @@ var __version__, __packageName__;
|
|
|
97
97
|
var init_version_generated = __esm({
|
|
98
98
|
"src/version.generated.ts"() {
|
|
99
99
|
"use strict";
|
|
100
|
-
__version__ = "0.
|
|
100
|
+
__version__ = "0.59.1";
|
|
101
101
|
__packageName__ = "bitfab";
|
|
102
102
|
}
|
|
103
103
|
});
|
|
@@ -2120,6 +2120,7 @@ __export(http_exports, {
|
|
|
2120
2120
|
HttpClient: () => HttpClient,
|
|
2121
2121
|
awaitOnExit: () => awaitOnExit,
|
|
2122
2122
|
awaitPendingRequests: () => awaitPendingRequests,
|
|
2123
|
+
experimentIdWireFields: () => experimentIdWireFields,
|
|
2123
2124
|
flushTraces: () => flushTraces,
|
|
2124
2125
|
parseRetryAfterMs: () => parseRetryAfterMs,
|
|
2125
2126
|
serializePayloadBody: () => serializePayloadBody
|
|
@@ -2288,6 +2289,9 @@ function warnDroppedExternalTrace(error) {
|
|
|
2288
2289
|
`a trace was dropped because the send step failed: ${describeError(error)}`
|
|
2289
2290
|
);
|
|
2290
2291
|
}
|
|
2292
|
+
function experimentIdWireFields(experimentId) {
|
|
2293
|
+
return { experimentId, testRunId: experimentId };
|
|
2294
|
+
}
|
|
2291
2295
|
var REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS, REPLAY_COMPLETE_REQUEST_TIMEOUT_MS, OTLP_TRACES_ENDPOINT, RETRYABLE_STATUSES, EXIT_FLUSH_TIMEOUT_MS, DEFAULT_LIFECYCLE_TIMEOUT_MS2, pendingTracePromises, liveHttpClients, carrierSeq, HttpClient;
|
|
2292
2296
|
var init_http = __esm({
|
|
2293
2297
|
"src/http.ts"() {
|
|
@@ -2892,7 +2896,7 @@ var init_http = __esm({
|
|
|
2892
2896
|
}
|
|
2893
2897
|
/**
|
|
2894
2898
|
* Start a replay session by fetching historical traces.
|
|
2895
|
-
* Blocking call - creates
|
|
2899
|
+
* Blocking call - creates an experiment and returns lightweight item references.
|
|
2896
2900
|
*/
|
|
2897
2901
|
async startReplay(traceFunctionKey, limit, traceIds, name, codeChangeDescription, codeChangeFiles, includeDbBranchLease, experimentGroupId, datasetIds, graderIds, dbBranchSettings, attempts, includeOriginalMetadata, onlyWithAssertions, judgeAssertions) {
|
|
2898
2902
|
const payload = { traceFunctionKey };
|
|
@@ -2948,9 +2952,20 @@ var init_http = __esm({
|
|
|
2948
2952
|
payload.git = git;
|
|
2949
2953
|
}
|
|
2950
2954
|
const timeout = includeDbBranchLease ? REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS : 3e4;
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2955
|
+
const response = await this.request(
|
|
2956
|
+
"/api/sdk/replay/start",
|
|
2957
|
+
payload,
|
|
2958
|
+
{ timeout }
|
|
2959
|
+
);
|
|
2960
|
+
const { testRunId, testRunUrl, ...rest } = response;
|
|
2961
|
+
const experimentId = response.experimentId ?? testRunId;
|
|
2962
|
+
const experimentUrl = response.experimentUrl ?? testRunUrl;
|
|
2963
|
+
if (experimentId === void 0 || experimentUrl === void 0) {
|
|
2964
|
+
throw new BitfabError(
|
|
2965
|
+
"Replay start response is missing the experiment ID or URL."
|
|
2966
|
+
);
|
|
2967
|
+
}
|
|
2968
|
+
return { ...rest, experimentId, experimentUrl };
|
|
2954
2969
|
}
|
|
2955
2970
|
/**
|
|
2956
2971
|
* Fetch an external span by ID.
|
|
@@ -3047,21 +3062,21 @@ var init_http = __esm({
|
|
|
3047
3062
|
* has a final status AND at least that many persisted spans, which is what
|
|
3048
3063
|
* makes this a real barrier rather than a "the row exists" check.
|
|
3049
3064
|
*/
|
|
3050
|
-
async getReplayStatus(
|
|
3065
|
+
async getReplayStatus(experimentId, expectedSpanCounts) {
|
|
3051
3066
|
return this.request(
|
|
3052
3067
|
"/api/sdk/replay/status",
|
|
3053
|
-
{
|
|
3068
|
+
{ ...experimentIdWireFields(experimentId), expectedSpanCounts },
|
|
3054
3069
|
{ timeout: 3e4 }
|
|
3055
3070
|
);
|
|
3056
3071
|
}
|
|
3057
3072
|
/**
|
|
3058
|
-
* Mark a replay
|
|
3073
|
+
* Mark a replay experiment as completed.
|
|
3059
3074
|
* Blocking call.
|
|
3060
3075
|
*/
|
|
3061
|
-
async completeReplay(
|
|
3076
|
+
async completeReplay(experimentId) {
|
|
3062
3077
|
return this.request(
|
|
3063
3078
|
"/api/sdk/replay/complete",
|
|
3064
|
-
|
|
3079
|
+
experimentIdWireFields(experimentId),
|
|
3065
3080
|
{ timeout: REPLAY_COMPLETE_REQUEST_TIMEOUT_MS }
|
|
3066
3081
|
);
|
|
3067
3082
|
}
|
|
@@ -3083,11 +3098,11 @@ var init_http = __esm({
|
|
|
3083
3098
|
* snapshot + preview branch and polls operations to readiness, which
|
|
3084
3099
|
* can take seconds.
|
|
3085
3100
|
*/
|
|
3086
|
-
async resolveDbBranchLease(
|
|
3101
|
+
async resolveDbBranchLease(experimentId, traceId, dbBranchSettings, attempt) {
|
|
3087
3102
|
return this.request(
|
|
3088
3103
|
"/api/sdk/replay/resolveDbBranchLease",
|
|
3089
3104
|
{
|
|
3090
|
-
|
|
3105
|
+
...experimentIdWireFields(experimentId),
|
|
3091
3106
|
traceId,
|
|
3092
3107
|
dbBranchSettings,
|
|
3093
3108
|
...attempt !== void 0 && attempt > 0 ? { attempt } : {}
|
|
@@ -3676,7 +3691,7 @@ function replayJsonReplacer(_key, value) {
|
|
|
3676
3691
|
function serializeReplayResult(result) {
|
|
3677
3692
|
return JSON.stringify(result, replayJsonReplacer, 2);
|
|
3678
3693
|
}
|
|
3679
|
-
async function preserveReplayFailure(operation, items,
|
|
3694
|
+
async function preserveReplayFailure(operation, items, experimentId, experimentUrl) {
|
|
3680
3695
|
try {
|
|
3681
3696
|
return await operation();
|
|
3682
3697
|
} catch (cause) {
|
|
@@ -3686,8 +3701,8 @@ async function preserveReplayFailure(operation, items, testRunId, testRunUrl) {
|
|
|
3686
3701
|
throw new ReplayError(
|
|
3687
3702
|
errorMessage(cause),
|
|
3688
3703
|
items,
|
|
3689
|
-
|
|
3690
|
-
|
|
3704
|
+
experimentId,
|
|
3705
|
+
experimentUrl,
|
|
3691
3706
|
cause
|
|
3692
3707
|
);
|
|
3693
3708
|
}
|
|
@@ -3741,7 +3756,7 @@ function buildMockTree(rootNode) {
|
|
|
3741
3756
|
}
|
|
3742
3757
|
return { spans };
|
|
3743
3758
|
}
|
|
3744
|
-
async function processItem(httpClient, serverItem, fn,
|
|
3759
|
+
async function processItem(httpClient, serverItem, fn, experimentId, mockStrategy, resolvedOverrides, replayedTraceId, attempt, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
|
|
3745
3760
|
let lease = includeDbBranchLease ? serverItem.dbBranchLease : void 0;
|
|
3746
3761
|
let leaseError = includeDbBranchLease ? serverItem.dbBranchLeaseError : void 0;
|
|
3747
3762
|
let dbSnapshotRef = serverItem.dbSnapshotRef;
|
|
@@ -3761,7 +3776,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
3761
3776
|
let resolved2;
|
|
3762
3777
|
try {
|
|
3763
3778
|
resolved2 = await httpClient.resolveDbBranchLease(
|
|
3764
|
-
|
|
3779
|
+
experimentId,
|
|
3765
3780
|
originalTraceId,
|
|
3766
3781
|
dbBranchSettings,
|
|
3767
3782
|
attempt
|
|
@@ -3873,7 +3888,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
3873
3888
|
replayStarted = performance.now();
|
|
3874
3889
|
const maybePromise = runWithReplayContext(
|
|
3875
3890
|
{
|
|
3876
|
-
|
|
3891
|
+
experimentId,
|
|
3877
3892
|
traceId: replayedTraceId,
|
|
3878
3893
|
inputSourceSpanId: span.id,
|
|
3879
3894
|
inputSourceTraceId: span.externalTraceId,
|
|
@@ -3956,14 +3971,14 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
3956
3971
|
originalTraceOutline: null
|
|
3957
3972
|
};
|
|
3958
3973
|
}
|
|
3959
|
-
async function waitForReplayPersistence(httpClient,
|
|
3974
|
+
async function waitForReplayPersistence(httpClient, experimentId, replayedTraceIds) {
|
|
3960
3975
|
const deferredSettled = await httpClient.settleDeferredWork(
|
|
3961
3976
|
REPLAY_PERSISTENCE_TIMEOUT_MS
|
|
3962
3977
|
);
|
|
3963
3978
|
if (!deferredSettled) {
|
|
3964
3979
|
httpClient.takeTraceDeliveries(replayedTraceIds);
|
|
3965
3980
|
throw new BitfabError(
|
|
3966
|
-
`Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (
|
|
3981
|
+
`Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (experiment ${experimentId}).`
|
|
3967
3982
|
);
|
|
3968
3983
|
}
|
|
3969
3984
|
if (!httpClient.hasClosedDeliveries(replayedTraceIds)) {
|
|
@@ -3992,7 +4007,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
3992
4007
|
let missing = Object.keys(expectedSpanCounts).length;
|
|
3993
4008
|
while (true) {
|
|
3994
4009
|
const status = await httpClient.getReplayStatus(
|
|
3995
|
-
|
|
4010
|
+
experimentId,
|
|
3996
4011
|
expectedSpanCounts
|
|
3997
4012
|
);
|
|
3998
4013
|
const ready = status.traceIds ?? {};
|
|
@@ -4011,7 +4026,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
4011
4026
|
}
|
|
4012
4027
|
const cause = flushed ? "" : " Delivery was also not confirmed before the flush deadline, so the spans likely never reached the server.";
|
|
4013
4028
|
throw new BitfabError(
|
|
4014
|
-
`Replay traces were not fully persisted before the delivery deadline (
|
|
4029
|
+
`Replay traces were not fully persisted before the delivery deadline (experiment ${experimentId}, missing ${missing} of ${Object.keys(expectedSpanCounts).length} trace(s)).${cause}`
|
|
4015
4030
|
);
|
|
4016
4031
|
}
|
|
4017
4032
|
function sleepForReplayPersistence(ms) {
|
|
@@ -4078,8 +4093,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4078
4093
|
}
|
|
4079
4094
|
}
|
|
4080
4095
|
const {
|
|
4081
|
-
|
|
4082
|
-
|
|
4096
|
+
experimentId,
|
|
4097
|
+
experimentUrl,
|
|
4083
4098
|
items: serverItems
|
|
4084
4099
|
} = await httpClient.startReplay(
|
|
4085
4100
|
traceFunctionKey,
|
|
@@ -4112,7 +4127,14 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4112
4127
|
}
|
|
4113
4128
|
}
|
|
4114
4129
|
const mockStrategy = options?.mock ?? "marked";
|
|
4115
|
-
const
|
|
4130
|
+
const fullExperimentUrl = `${serviceUrl}${experimentUrl}`;
|
|
4131
|
+
try {
|
|
4132
|
+
options?.onExperimentStart?.({
|
|
4133
|
+
experimentId,
|
|
4134
|
+
experimentUrl: fullExperimentUrl
|
|
4135
|
+
});
|
|
4136
|
+
} catch {
|
|
4137
|
+
}
|
|
4116
4138
|
const resolvedOverrides = [
|
|
4117
4139
|
...normalizeMockOverrides(options?.mockOverride),
|
|
4118
4140
|
...registeredOverrides
|
|
@@ -4125,7 +4147,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4125
4147
|
httpClient,
|
|
4126
4148
|
serverItem,
|
|
4127
4149
|
fn,
|
|
4128
|
-
|
|
4150
|
+
experimentId,
|
|
4129
4151
|
mockStrategy,
|
|
4130
4152
|
resolvedOverrides,
|
|
4131
4153
|
replayedTraceIds[index],
|
|
@@ -4180,7 +4202,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4180
4202
|
}
|
|
4181
4203
|
try {
|
|
4182
4204
|
onItemFinish?.({
|
|
4183
|
-
|
|
4205
|
+
experimentId,
|
|
4206
|
+
testRunId: experimentId,
|
|
4184
4207
|
completed,
|
|
4185
4208
|
total,
|
|
4186
4209
|
succeeded,
|
|
@@ -4228,7 +4251,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4228
4251
|
try {
|
|
4229
4252
|
options.onItemStart?.({
|
|
4230
4253
|
type: "started",
|
|
4231
|
-
|
|
4254
|
+
experimentId,
|
|
4255
|
+
testRunId: experimentId,
|
|
4232
4256
|
started,
|
|
4233
4257
|
completed,
|
|
4234
4258
|
total,
|
|
@@ -4247,21 +4271,23 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4247
4271
|
} : void 0
|
|
4248
4272
|
);
|
|
4249
4273
|
if (options?.dryRun === true) {
|
|
4250
|
-
await httpClient.completeReplay(
|
|
4274
|
+
await httpClient.completeReplay(experimentId).catch(() => void 0);
|
|
4251
4275
|
const dryResult = {
|
|
4252
4276
|
items: resultItems,
|
|
4253
|
-
|
|
4254
|
-
|
|
4277
|
+
experimentId,
|
|
4278
|
+
experimentUrl: fullExperimentUrl,
|
|
4279
|
+
testRunId: experimentId,
|
|
4280
|
+
testRunUrl: fullExperimentUrl,
|
|
4255
4281
|
attempts
|
|
4256
4282
|
};
|
|
4257
4283
|
await writeReplayResultFile(dryResult);
|
|
4258
4284
|
return dryResult;
|
|
4259
4285
|
}
|
|
4260
4286
|
const deliveredTraceIds = await preserveReplayFailure(
|
|
4261
|
-
() => waitForReplayPersistence(httpClient,
|
|
4287
|
+
() => waitForReplayPersistence(httpClient, experimentId, replayedTraceIds),
|
|
4262
4288
|
resultItems,
|
|
4263
|
-
|
|
4264
|
-
|
|
4289
|
+
experimentId,
|
|
4290
|
+
fullExperimentUrl
|
|
4265
4291
|
);
|
|
4266
4292
|
for (let index = 0; index < resultItems.length; index += 1) {
|
|
4267
4293
|
const localId = replayedTraceIds[index];
|
|
@@ -4271,10 +4297,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4271
4297
|
}
|
|
4272
4298
|
}
|
|
4273
4299
|
const completeResult = await preserveReplayFailure(
|
|
4274
|
-
() => httpClient.completeReplay(
|
|
4300
|
+
() => httpClient.completeReplay(experimentId),
|
|
4275
4301
|
resultItems,
|
|
4276
|
-
|
|
4277
|
-
|
|
4302
|
+
experimentId,
|
|
4303
|
+
fullExperimentUrl
|
|
4278
4304
|
);
|
|
4279
4305
|
const serverTraceIds = completeResult.traceIds;
|
|
4280
4306
|
const replayTokens = completeResult.tokens;
|
|
@@ -4301,20 +4327,20 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4301
4327
|
if (completedCount > 0 && missing.length === completedCount) {
|
|
4302
4328
|
const serverCount = completeResult.traceCount !== void 0 ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.` : "";
|
|
4303
4329
|
const cause = new BitfabError(
|
|
4304
|
-
`Replay completed but the server has no persisted trace for any of the ${completedCount} completed item(s) (
|
|
4330
|
+
`Replay completed but the server has no persisted trace for any of the ${completedCount} completed item(s) (experiment ${experimentId}).${serverCount} Trace uploads were awaited, so either the uploads failed (check for "Bitfab: Failed to create" errors above) or the replayed function is not wrapped with withSpan.`
|
|
4305
4331
|
);
|
|
4306
4332
|
throw new ReplayError(
|
|
4307
4333
|
cause.message,
|
|
4308
4334
|
resultItems,
|
|
4309
|
-
|
|
4310
|
-
|
|
4335
|
+
experimentId,
|
|
4336
|
+
fullExperimentUrl,
|
|
4311
4337
|
cause
|
|
4312
4338
|
);
|
|
4313
4339
|
}
|
|
4314
4340
|
if (missing.length > 0) {
|
|
4315
4341
|
try {
|
|
4316
4342
|
console.error(
|
|
4317
|
-
`Bitfab: server has no persisted trace for ${missing.length} of ${completedCount} completed replay item(s) (
|
|
4343
|
+
`Bitfab: server has no persisted trace for ${missing.length} of ${completedCount} completed replay item(s) (experiment ${experimentId}). Their replay token usage is unavailable and they cannot be labeled.`
|
|
4318
4344
|
);
|
|
4319
4345
|
} catch {
|
|
4320
4346
|
}
|
|
@@ -4322,8 +4348,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4322
4348
|
}
|
|
4323
4349
|
const result = {
|
|
4324
4350
|
items: resultItems,
|
|
4325
|
-
|
|
4326
|
-
|
|
4351
|
+
experimentId,
|
|
4352
|
+
experimentUrl: fullExperimentUrl,
|
|
4353
|
+
testRunId: experimentId,
|
|
4354
|
+
testRunUrl: fullExperimentUrl,
|
|
4327
4355
|
attempts
|
|
4328
4356
|
};
|
|
4329
4357
|
await writeReplayResultFile(result);
|
|
@@ -4331,7 +4359,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4331
4359
|
try {
|
|
4332
4360
|
options?.onProgress?.({
|
|
4333
4361
|
type: "complete",
|
|
4334
|
-
|
|
4362
|
+
experimentId,
|
|
4363
|
+
testRunId: experimentId,
|
|
4335
4364
|
completed: total,
|
|
4336
4365
|
total,
|
|
4337
4366
|
succeeded,
|
|
@@ -4381,13 +4410,15 @@ var init_replay = __esm({
|
|
|
4381
4410
|
MAX_REPLAY_ATTEMPTS = 100;
|
|
4382
4411
|
BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
|
|
4383
4412
|
ReplayError = class extends BitfabError {
|
|
4384
|
-
constructor(message, items,
|
|
4385
|
-
super(message,
|
|
4413
|
+
constructor(message, items, experimentId, experimentUrl, cause) {
|
|
4414
|
+
super(message, experimentUrl);
|
|
4386
4415
|
this.items = items;
|
|
4387
|
-
this.
|
|
4388
|
-
this.
|
|
4416
|
+
this.experimentId = experimentId;
|
|
4417
|
+
this.experimentUrl = experimentUrl;
|
|
4389
4418
|
this.cause = cause;
|
|
4390
4419
|
this.name = "ReplayError";
|
|
4420
|
+
this.testRunId = experimentId;
|
|
4421
|
+
this.testRunUrl = experimentUrl;
|
|
4391
4422
|
}
|
|
4392
4423
|
};
|
|
4393
4424
|
DbBranchReplayError = class extends BitfabError {
|
|
@@ -4406,6 +4437,8 @@ var init_replay = __esm({
|
|
|
4406
4437
|
var node_exports = {};
|
|
4407
4438
|
__export(node_exports, {
|
|
4408
4439
|
AssertionCategoriesClient: () => AssertionCategoriesClient,
|
|
4440
|
+
AssertionGenerationError: () => AssertionGenerationError,
|
|
4441
|
+
AssertionGenerationTimeoutError: () => AssertionGenerationTimeoutError,
|
|
4409
4442
|
BITFAB_PROGRESS_PREFIX: () => BITFAB_PROGRESS_PREFIX,
|
|
4410
4443
|
Bitfab: () => Bitfab,
|
|
4411
4444
|
BitfabClaudeAgentHandler: () => BitfabClaudeAgentHandler,
|
|
@@ -4421,6 +4454,8 @@ __export(node_exports, {
|
|
|
4421
4454
|
DEFAULT_SERVICE_URL: () => DEFAULT_SERVICE_URL,
|
|
4422
4455
|
DatasetsClient: () => DatasetsClient,
|
|
4423
4456
|
DbBranchReplayError: () => DbBranchReplayError,
|
|
4457
|
+
GraderRerunError: () => GraderRerunError,
|
|
4458
|
+
GraderRerunTimeoutError: () => GraderRerunTimeoutError,
|
|
4424
4459
|
GradersClient: () => GradersClient,
|
|
4425
4460
|
HttpClient: () => HttpClient,
|
|
4426
4461
|
LabelsClient: () => LabelsClient,
|
|
@@ -5855,11 +5890,39 @@ init_constants();
|
|
|
5855
5890
|
|
|
5856
5891
|
// src/datasets.ts
|
|
5857
5892
|
var DEFAULT_RERUN_TIMEOUT_MS = 9e4;
|
|
5858
|
-
var
|
|
5893
|
+
var RERUN_POLL_INTERVAL_MS = 1e3;
|
|
5859
5894
|
var TERMINAL_RERUN_STATUSES = /* @__PURE__ */ new Set([
|
|
5860
5895
|
"completed",
|
|
5861
5896
|
"errored"
|
|
5862
5897
|
]);
|
|
5898
|
+
var GraderRerunError = class extends Error {
|
|
5899
|
+
constructor(message, run) {
|
|
5900
|
+
super(message);
|
|
5901
|
+
this.run = run;
|
|
5902
|
+
this.name = "GraderRerunError";
|
|
5903
|
+
}
|
|
5904
|
+
};
|
|
5905
|
+
var GraderRerunTimeoutError = class extends GraderRerunError {
|
|
5906
|
+
constructor(datasetId, run, timeoutMs) {
|
|
5907
|
+
super(
|
|
5908
|
+
`Grader re-run ${run.id} on dataset ${datasetId} was still ${run.status} after ${timeoutMs}ms. It keeps running on Bitfab; read it later with getGraderRerun.`,
|
|
5909
|
+
run
|
|
5910
|
+
);
|
|
5911
|
+
this.name = "GraderRerunTimeoutError";
|
|
5912
|
+
}
|
|
5913
|
+
};
|
|
5914
|
+
function finishedRerun(datasetId, run, joinedExisting) {
|
|
5915
|
+
if (!TERMINAL_RERUN_STATUSES.has(run.status)) {
|
|
5916
|
+
return null;
|
|
5917
|
+
}
|
|
5918
|
+
if (run.status === "errored") {
|
|
5919
|
+
throw new GraderRerunError(
|
|
5920
|
+
`Grader re-run ${run.id} on dataset ${datasetId} errored: ${run.error ?? "no reason recorded"}`,
|
|
5921
|
+
run
|
|
5922
|
+
);
|
|
5923
|
+
}
|
|
5924
|
+
return { run, joinedExisting };
|
|
5925
|
+
}
|
|
5863
5926
|
function sleep(ms) {
|
|
5864
5927
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5865
5928
|
}
|
|
@@ -5959,28 +6022,25 @@ var DatasetsClient = class {
|
|
|
5959
6022
|
{ graderIds }
|
|
5960
6023
|
);
|
|
5961
6024
|
}
|
|
5962
|
-
/**
|
|
5963
|
-
* Re-run graders over every trace in the dataset. Defaults to every assigned
|
|
5964
|
-
* grader; an unassigned id is rejected. Waits for the run to finish (up to
|
|
5965
|
-
* `timeoutMs`, default 90s) unless `wait` is `false`, and returns the last
|
|
5966
|
-
* run state seen either way. A request matching an in-flight run joins it.
|
|
5967
|
-
*/
|
|
5968
6025
|
async rerunGraders(datasetId, options = {}) {
|
|
5969
6026
|
const started = await this.httpClient.request(
|
|
5970
6027
|
datasetPath(datasetId, "/rerunGraders"),
|
|
5971
6028
|
options.graderIds === void 0 ? {} : { graderIds: options.graderIds }
|
|
5972
6029
|
);
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
}
|
|
5976
|
-
const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS);
|
|
5977
|
-
const interval = options.pollIntervalMs ?? DEFAULT_RERUN_POLL_INTERVAL_MS;
|
|
6030
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS;
|
|
6031
|
+
const deadline = Date.now() + timeoutMs;
|
|
5978
6032
|
let run = started.run;
|
|
5979
|
-
while (
|
|
5980
|
-
|
|
6033
|
+
while (true) {
|
|
6034
|
+
const finished = finishedRerun(datasetId, run, started.joinedExisting);
|
|
6035
|
+
if (finished !== null) {
|
|
6036
|
+
return finished;
|
|
6037
|
+
}
|
|
6038
|
+
if (Date.now() >= deadline) {
|
|
6039
|
+
throw new GraderRerunTimeoutError(datasetId, run, timeoutMs);
|
|
6040
|
+
}
|
|
6041
|
+
await sleep(RERUN_POLL_INTERVAL_MS);
|
|
5981
6042
|
run = await this.getGraderRerun(datasetId, run.id) ?? run;
|
|
5982
6043
|
}
|
|
5983
|
-
return { run, joinedExisting: started.joinedExisting };
|
|
5984
6044
|
}
|
|
5985
6045
|
/**
|
|
5986
6046
|
* The dataset's active grader re-run, or the run named by `runId`. Returns
|
|
@@ -6051,6 +6111,7 @@ var GradersClient = class {
|
|
|
6051
6111
|
init_http();
|
|
6052
6112
|
|
|
6053
6113
|
// src/labels.ts
|
|
6114
|
+
init_http();
|
|
6054
6115
|
var LABELS_PATH = "/api/sdk/traces/labels";
|
|
6055
6116
|
var HUMAN_LABELS_PATH = "/api/sdk/traces/labels/human";
|
|
6056
6117
|
function labelEvidencePath(traceId, assertionId) {
|
|
@@ -6060,27 +6121,27 @@ var LabelsClient = class {
|
|
|
6060
6121
|
constructor(httpClient) {
|
|
6061
6122
|
this.httpClient = httpClient;
|
|
6062
6123
|
}
|
|
6063
|
-
async save(update,
|
|
6064
|
-
const [outcome] = await this.saveAll([update],
|
|
6124
|
+
async save(update, experimentId) {
|
|
6125
|
+
const [outcome] = await this.saveAll([update], experimentId);
|
|
6065
6126
|
return outcome;
|
|
6066
6127
|
}
|
|
6067
|
-
async saveAll(updates,
|
|
6128
|
+
async saveAll(updates, experimentId) {
|
|
6068
6129
|
const response = await this.httpClient.request(
|
|
6069
6130
|
LABELS_PATH,
|
|
6070
6131
|
{
|
|
6071
6132
|
labels: updates,
|
|
6072
|
-
...
|
|
6133
|
+
...experimentId === void 0 ? {} : experimentIdWireFields(experimentId)
|
|
6073
6134
|
}
|
|
6074
6135
|
);
|
|
6075
6136
|
return response.labels;
|
|
6076
6137
|
}
|
|
6077
6138
|
/** Withhold a verdict for a trace or replay attempt whose check did not run. */
|
|
6078
|
-
async skip(target,
|
|
6079
|
-
return this.save({ ...target, skip: true },
|
|
6139
|
+
async skip(target, experimentId) {
|
|
6140
|
+
return this.save({ ...target, skip: true }, experimentId);
|
|
6080
6141
|
}
|
|
6081
6142
|
/** Clear a previous verdict for a trace, replay attempt, or assertion. */
|
|
6082
|
-
async archive(target,
|
|
6083
|
-
return this.save({ ...target, archive: true },
|
|
6143
|
+
async archive(target, experimentId) {
|
|
6144
|
+
return this.save({ ...target, archive: true }, experimentId);
|
|
6084
6145
|
}
|
|
6085
6146
|
async saveHuman(update) {
|
|
6086
6147
|
const [outcome] = await this.saveHumanAll([update]);
|
|
@@ -7836,6 +7897,46 @@ init_traceMetadata();
|
|
|
7836
7897
|
// src/traces.ts
|
|
7837
7898
|
var ASSERTIONS_PATH = "/api/sdk/traces/assertions";
|
|
7838
7899
|
var SEARCH_PATH = "/api/sdk/traces/search";
|
|
7900
|
+
var DEFAULT_GENERATION_TIMEOUT_MS = 6e5;
|
|
7901
|
+
var GENERATION_POLL_INTERVAL_MS = 2e3;
|
|
7902
|
+
var AssertionGenerationError = class extends Error {
|
|
7903
|
+
constructor(message, traceId) {
|
|
7904
|
+
super(message);
|
|
7905
|
+
this.traceId = traceId;
|
|
7906
|
+
this.name = "AssertionGenerationError";
|
|
7907
|
+
}
|
|
7908
|
+
};
|
|
7909
|
+
var AssertionGenerationTimeoutError = class extends AssertionGenerationError {
|
|
7910
|
+
constructor(traceId, timeoutMs) {
|
|
7911
|
+
super(
|
|
7912
|
+
`Assertion generation for trace ${traceId} did not finish within ${timeoutMs}ms. Generation keeps running on Bitfab. Call getAssertions and read its generation field to check its status.`,
|
|
7913
|
+
traceId
|
|
7914
|
+
);
|
|
7915
|
+
this.name = "AssertionGenerationTimeoutError";
|
|
7916
|
+
}
|
|
7917
|
+
};
|
|
7918
|
+
function sleep2(ms) {
|
|
7919
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7920
|
+
}
|
|
7921
|
+
function isGenerationFinished(traceId, generation) {
|
|
7922
|
+
if (generation === null || generation.status === "running") {
|
|
7923
|
+
return false;
|
|
7924
|
+
}
|
|
7925
|
+
if (generation.status === "failed") {
|
|
7926
|
+
throw new AssertionGenerationError(
|
|
7927
|
+
`Assertion generation for trace ${traceId} failed: ${generation.error ?? "no reason recorded"}. Pass regenerate: true to try again.`,
|
|
7928
|
+
traceId
|
|
7929
|
+
);
|
|
7930
|
+
}
|
|
7931
|
+
return true;
|
|
7932
|
+
}
|
|
7933
|
+
function draftsInGenerationOrder(assertions, assertionIds) {
|
|
7934
|
+
const byId = new Map(assertions.map((assertion) => [assertion.id, assertion]));
|
|
7935
|
+
return assertionIds.flatMap((id) => {
|
|
7936
|
+
const assertion = byId.get(id);
|
|
7937
|
+
return assertion === void 0 ? [] : [assertion];
|
|
7938
|
+
});
|
|
7939
|
+
}
|
|
7839
7940
|
function traceAssertionsPath(traceId, suffix = "") {
|
|
7840
7941
|
return `/api/sdk/traces/${encodeURIComponent(traceId)}/assertions${suffix}`;
|
|
7841
7942
|
}
|
|
@@ -7867,6 +7968,34 @@ var TracesClient = class {
|
|
|
7867
7968
|
});
|
|
7868
7969
|
return response.assertions;
|
|
7869
7970
|
}
|
|
7971
|
+
async generateAssertions(traceId, options = {}) {
|
|
7972
|
+
const started = await this.httpClient.request(
|
|
7973
|
+
traceAssertionsPath(traceId, "/generate"),
|
|
7974
|
+
{
|
|
7975
|
+
...options.guidance === void 0 ? {} : { guidance: options.guidance },
|
|
7976
|
+
...options.categoryIds === void 0 ? {} : { categoryIds: options.categoryIds },
|
|
7977
|
+
...options.regenerate === void 0 ? {} : { regenerate: options.regenerate }
|
|
7978
|
+
}
|
|
7979
|
+
);
|
|
7980
|
+
if (isGenerationFinished(traceId, started.generation)) {
|
|
7981
|
+
return started.assertions;
|
|
7982
|
+
}
|
|
7983
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_GENERATION_TIMEOUT_MS;
|
|
7984
|
+
const deadline = Date.now() + timeoutMs;
|
|
7985
|
+
while (true) {
|
|
7986
|
+
if (Date.now() >= deadline) {
|
|
7987
|
+
throw new AssertionGenerationTimeoutError(traceId, timeoutMs);
|
|
7988
|
+
}
|
|
7989
|
+
await sleep2(GENERATION_POLL_INTERVAL_MS);
|
|
7990
|
+
const read2 = await this.getAssertions(traceId);
|
|
7991
|
+
if (isGenerationFinished(traceId, read2.generation)) {
|
|
7992
|
+
return draftsInGenerationOrder(
|
|
7993
|
+
read2.assertions,
|
|
7994
|
+
read2.generation.assertionIds
|
|
7995
|
+
);
|
|
7996
|
+
}
|
|
7997
|
+
}
|
|
7998
|
+
}
|
|
7870
7999
|
async archiveAssertions(params) {
|
|
7871
8000
|
const response = await this.httpClient.request(
|
|
7872
8001
|
traceAssertionsPath(params.traceId, "/archive"),
|
|
@@ -8370,6 +8499,15 @@ var BitfabVercelAiHandler = class {
|
|
|
8370
8499
|
|
|
8371
8500
|
// src/client.ts
|
|
8372
8501
|
init_warnOnce();
|
|
8502
|
+
function resolveSpanExperimentId(options) {
|
|
8503
|
+
const { experimentId, testRunId } = options;
|
|
8504
|
+
if (experimentId !== void 0 && testRunId !== void 0 && experimentId !== testRunId) {
|
|
8505
|
+
throw new BitfabError(
|
|
8506
|
+
`experimentId ("${experimentId}") and its deprecated alias testRunId ("${testRunId}") were both passed with different values. Pass only experimentId.`
|
|
8507
|
+
);
|
|
8508
|
+
}
|
|
8509
|
+
return experimentId ?? testRunId;
|
|
8510
|
+
}
|
|
8373
8511
|
var TRUNCATION_LIMIT_ORDER = [
|
|
8374
8512
|
"max_depth",
|
|
8375
8513
|
"max_captured_subtree_spans"
|
|
@@ -8959,13 +9097,12 @@ var Bitfab = class {
|
|
|
8959
9097
|
"bitfab.node({ capture: false }) cannot use mockOnReplay: true because an uncaptured node has no recorded output."
|
|
8960
9098
|
);
|
|
8961
9099
|
}
|
|
9100
|
+
const experimentId = resolveSpanExperimentId(options);
|
|
8962
9101
|
return {
|
|
8963
9102
|
capture,
|
|
8964
9103
|
type: options.type ?? "custom",
|
|
8965
9104
|
...options.name !== void 0 && { name: options.name },
|
|
8966
|
-
...
|
|
8967
|
-
testRunId: options.testRunId
|
|
8968
|
-
},
|
|
9105
|
+
...experimentId !== void 0 && { experimentId },
|
|
8969
9106
|
...options.mockOnReplay !== void 0 && {
|
|
8970
9107
|
mockOnReplay: options.mockOnReplay
|
|
8971
9108
|
},
|
|
@@ -9100,6 +9237,7 @@ var Bitfab = class {
|
|
|
9100
9237
|
return invokeWithoutNode();
|
|
9101
9238
|
}
|
|
9102
9239
|
const mockOnReplay = nodeConfiguration?.mockOnReplay ?? options.mockOnReplayDefault;
|
|
9240
|
+
const nodeExperimentId = nodeConfiguration === void 0 ? void 0 : resolveSpanExperimentId(nodeConfiguration);
|
|
9103
9241
|
const childOptions = {
|
|
9104
9242
|
name: spanName,
|
|
9105
9243
|
type: nodeConfiguration?.type ?? "function",
|
|
@@ -9110,8 +9248,8 @@ var Bitfab = class {
|
|
|
9110
9248
|
captureContent: true,
|
|
9111
9249
|
autoTraceDefinition: definition,
|
|
9112
9250
|
...declaredNode && { declaredNode },
|
|
9113
|
-
...
|
|
9114
|
-
|
|
9251
|
+
...nodeExperimentId !== void 0 && {
|
|
9252
|
+
experimentId: nodeExperimentId
|
|
9115
9253
|
},
|
|
9116
9254
|
...mockOnReplay !== void 0 && {
|
|
9117
9255
|
mockOnReplay
|
|
@@ -9772,6 +9910,7 @@ var Bitfab = class {
|
|
|
9772
9910
|
const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
|
|
9773
9911
|
const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
9774
9912
|
const self = this;
|
|
9913
|
+
const optionExperimentId = resolveSpanExperimentId(options);
|
|
9775
9914
|
const fnIsAsyncFunction = fn.constructor.name === "AsyncFunction";
|
|
9776
9915
|
const fnReturnsPromise = fnIsAsyncFunction || (() => {
|
|
9777
9916
|
try {
|
|
@@ -9874,7 +10013,7 @@ var Bitfab = class {
|
|
|
9874
10013
|
const inputs = args;
|
|
9875
10014
|
const startedAt = nowIsoTimestamp();
|
|
9876
10015
|
const replayCtxAtStart = getReplayContext();
|
|
9877
|
-
const
|
|
10016
|
+
const experimentId = replayCtxAtStart?.experimentId ?? optionExperimentId;
|
|
9878
10017
|
if (isRootSpan && !activeTraceStates.has(traceId)) {
|
|
9879
10018
|
const dbSnapshotRef = buildSnapshotRef(self.dbSnapshot, startedAt);
|
|
9880
10019
|
self.simulationPlan.refresh();
|
|
@@ -9883,7 +10022,7 @@ var Bitfab = class {
|
|
|
9883
10022
|
traceFunctionKey,
|
|
9884
10023
|
startedAt,
|
|
9885
10024
|
contexts: [],
|
|
9886
|
-
...
|
|
10025
|
+
...experimentId !== void 0 && { experimentId },
|
|
9887
10026
|
...replayCtxAtStart?.inputSourceTraceId && {
|
|
9888
10027
|
inputSourceTraceId: replayCtxAtStart.inputSourceTraceId
|
|
9889
10028
|
},
|
|
@@ -9929,7 +10068,7 @@ var Bitfab = class {
|
|
|
9929
10068
|
contexts: newContext.contexts,
|
|
9930
10069
|
prompt: newContext.prompt,
|
|
9931
10070
|
endedAt,
|
|
9932
|
-
...
|
|
10071
|
+
...experimentId !== void 0 && { experimentId },
|
|
9933
10072
|
...replayCtx?.inputSourceSpanId && {
|
|
9934
10073
|
inputSourceSpanId: replayCtx.inputSourceSpanId
|
|
9935
10074
|
}
|
|
@@ -9950,7 +10089,7 @@ var Bitfab = class {
|
|
|
9950
10089
|
name: traceState?.name,
|
|
9951
10090
|
metadata: callerTraceMetadata(traceId),
|
|
9952
10091
|
contexts: traceState?.contexts ?? [],
|
|
9953
|
-
|
|
10092
|
+
experimentId: traceState?.experimentId,
|
|
9954
10093
|
inputSourceTraceId: traceState?.inputSourceTraceId,
|
|
9955
10094
|
replayAttempt: traceState?.replayAttempt,
|
|
9956
10095
|
dbSnapshotRef: traceState?.dbSnapshotRef,
|
|
@@ -10421,7 +10560,7 @@ var Bitfab = class {
|
|
|
10421
10560
|
completed: true,
|
|
10422
10561
|
...params.dropped && { dropped: true },
|
|
10423
10562
|
...params.sessionId && { sessionId: params.sessionId },
|
|
10424
|
-
...params.
|
|
10563
|
+
...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId)
|
|
10425
10564
|
});
|
|
10426
10565
|
}
|
|
10427
10566
|
sendsSpanOnCompletion(context) {
|
|
@@ -10533,7 +10672,7 @@ var Bitfab = class {
|
|
|
10533
10672
|
},
|
|
10534
10673
|
...params.declaredNode === true && { [DECLARED_NODE_FIELD]: true },
|
|
10535
10674
|
rawSpan: externalSpan,
|
|
10536
|
-
...params.
|
|
10675
|
+
...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId),
|
|
10537
10676
|
...params.mocked && { mocked: true },
|
|
10538
10677
|
...params.mockTarget && { mockTarget: params.mockTarget },
|
|
10539
10678
|
...params.mockSource && { mockSource: params.mockSource }
|
|
@@ -11089,6 +11228,8 @@ assertAsyncStorageRegistered();
|
|
|
11089
11228
|
// Annotate the CommonJS export names for ESM import in node:
|
|
11090
11229
|
0 && (module.exports = {
|
|
11091
11230
|
AssertionCategoriesClient,
|
|
11231
|
+
AssertionGenerationError,
|
|
11232
|
+
AssertionGenerationTimeoutError,
|
|
11092
11233
|
BITFAB_PROGRESS_PREFIX,
|
|
11093
11234
|
Bitfab,
|
|
11094
11235
|
BitfabClaudeAgentHandler,
|
|
@@ -11104,6 +11245,8 @@ assertAsyncStorageRegistered();
|
|
|
11104
11245
|
DEFAULT_SERVICE_URL,
|
|
11105
11246
|
DatasetsClient,
|
|
11106
11247
|
DbBranchReplayError,
|
|
11248
|
+
GraderRerunError,
|
|
11249
|
+
GraderRerunTimeoutError,
|
|
11107
11250
|
GradersClient,
|
|
11108
11251
|
HttpClient,
|
|
11109
11252
|
LabelsClient,
|