@bitfab/sdk 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-ETZUSSF6.js → chunk-5DNB7EN7.js} +1 -1
- package/dist/chunk-5DNB7EN7.js.map +1 -0
- package/dist/{chunk-IP2AYKT7.js → chunk-5IQ3KQLI.js} +29 -14
- package/dist/chunk-5IQ3KQLI.js.map +1 -0
- package/dist/{chunk-Y47DQCCK.js → chunk-AYSXJGAZ.js} +149 -41
- package/dist/chunk-AYSXJGAZ.js.map +1 -0
- package/dist/{chunk-E25HU4YZ.js → chunk-ERS4TBD6.js} +29 -14
- package/dist/chunk-ERS4TBD6.js.map +1 -0
- package/dist/{chunk-YGZA3H67.js → chunk-MK756TJL.js} +54 -38
- package/dist/chunk-MK756TJL.js.map +1 -0
- package/dist/{chunk-NNSJVCR3.js → chunk-ZC6TZ2IM.js} +18 -10
- package/dist/chunk-ZC6TZ2IM.js.map +1 -0
- package/dist/{http-PVE62D6W.js → http-JBKOOV7C.js} +4 -2
- package/dist/{http-6K4GQC4S.js → http-SMGYDRGR.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-6WA5GD4R.js → replay-OQN464ZF.js} +3 -3
- package/dist/replayCli.js +2 -2
- package/dist/seedCli.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-E25HU4YZ.js.map +0 -1
- package/dist/chunk-ETZUSSF6.js.map +0 -1
- package/dist/chunk-IP2AYKT7.js.map +0 -1
- package/dist/chunk-NNSJVCR3.js.map +0 -1
- package/dist/chunk-Y47DQCCK.js.map +0 -1
- package/dist/chunk-YGZA3H67.js.map +0 -1
- /package/dist/{http-6K4GQC4S.js.map → http-JBKOOV7C.js.map} +0 -0
- /package/dist/{http-PVE62D6W.js.map → http-SMGYDRGR.js.map} +0 -0
- /package/dist/{replay-6WA5GD4R.js.map → replay-OQN464ZF.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -42,7 +42,7 @@ var __version__, __packageName__;
|
|
|
42
42
|
var init_version_generated = __esm({
|
|
43
43
|
"src/version.generated.ts"() {
|
|
44
44
|
"use strict";
|
|
45
|
-
__version__ = "0.
|
|
45
|
+
__version__ = "0.59.1";
|
|
46
46
|
__packageName__ = "@bitfab/sdk";
|
|
47
47
|
}
|
|
48
48
|
});
|
|
@@ -2104,6 +2104,7 @@ __export(http_exports, {
|
|
|
2104
2104
|
HttpClient: () => HttpClient,
|
|
2105
2105
|
awaitOnExit: () => awaitOnExit,
|
|
2106
2106
|
awaitPendingRequests: () => awaitPendingRequests,
|
|
2107
|
+
experimentIdWireFields: () => experimentIdWireFields,
|
|
2107
2108
|
flushTraces: () => flushTraces,
|
|
2108
2109
|
parseRetryAfterMs: () => parseRetryAfterMs,
|
|
2109
2110
|
serializePayloadBody: () => serializePayloadBody
|
|
@@ -2272,6 +2273,9 @@ function warnDroppedExternalTrace(error) {
|
|
|
2272
2273
|
`a trace was dropped because the send step failed: ${describeError(error)}`
|
|
2273
2274
|
);
|
|
2274
2275
|
}
|
|
2276
|
+
function experimentIdWireFields(experimentId) {
|
|
2277
|
+
return { experimentId, testRunId: experimentId };
|
|
2278
|
+
}
|
|
2275
2279
|
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;
|
|
2276
2280
|
var init_http = __esm({
|
|
2277
2281
|
"src/http.ts"() {
|
|
@@ -2876,7 +2880,7 @@ var init_http = __esm({
|
|
|
2876
2880
|
}
|
|
2877
2881
|
/**
|
|
2878
2882
|
* Start a replay session by fetching historical traces.
|
|
2879
|
-
* Blocking call - creates
|
|
2883
|
+
* Blocking call - creates an experiment and returns lightweight item references.
|
|
2880
2884
|
*/
|
|
2881
2885
|
async startReplay(traceFunctionKey, limit, traceIds, name, codeChangeDescription, codeChangeFiles, includeDbBranchLease, experimentGroupId, datasetIds, graderIds, dbBranchSettings, attempts, includeOriginalMetadata, onlyWithAssertions, judgeAssertions) {
|
|
2882
2886
|
const payload = { traceFunctionKey };
|
|
@@ -2932,9 +2936,20 @@ var init_http = __esm({
|
|
|
2932
2936
|
payload.git = git;
|
|
2933
2937
|
}
|
|
2934
2938
|
const timeout = includeDbBranchLease ? REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS : 3e4;
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2939
|
+
const response = await this.request(
|
|
2940
|
+
"/api/sdk/replay/start",
|
|
2941
|
+
payload,
|
|
2942
|
+
{ timeout }
|
|
2943
|
+
);
|
|
2944
|
+
const { testRunId, testRunUrl, ...rest } = response;
|
|
2945
|
+
const experimentId = response.experimentId ?? testRunId;
|
|
2946
|
+
const experimentUrl = response.experimentUrl ?? testRunUrl;
|
|
2947
|
+
if (experimentId === void 0 || experimentUrl === void 0) {
|
|
2948
|
+
throw new BitfabError(
|
|
2949
|
+
"Replay start response is missing the experiment ID or URL."
|
|
2950
|
+
);
|
|
2951
|
+
}
|
|
2952
|
+
return { ...rest, experimentId, experimentUrl };
|
|
2938
2953
|
}
|
|
2939
2954
|
/**
|
|
2940
2955
|
* Fetch an external span by ID.
|
|
@@ -3031,21 +3046,21 @@ var init_http = __esm({
|
|
|
3031
3046
|
* has a final status AND at least that many persisted spans, which is what
|
|
3032
3047
|
* makes this a real barrier rather than a "the row exists" check.
|
|
3033
3048
|
*/
|
|
3034
|
-
async getReplayStatus(
|
|
3049
|
+
async getReplayStatus(experimentId, expectedSpanCounts) {
|
|
3035
3050
|
return this.request(
|
|
3036
3051
|
"/api/sdk/replay/status",
|
|
3037
|
-
{
|
|
3052
|
+
{ ...experimentIdWireFields(experimentId), expectedSpanCounts },
|
|
3038
3053
|
{ timeout: 3e4 }
|
|
3039
3054
|
);
|
|
3040
3055
|
}
|
|
3041
3056
|
/**
|
|
3042
|
-
* Mark a replay
|
|
3057
|
+
* Mark a replay experiment as completed.
|
|
3043
3058
|
* Blocking call.
|
|
3044
3059
|
*/
|
|
3045
|
-
async completeReplay(
|
|
3060
|
+
async completeReplay(experimentId) {
|
|
3046
3061
|
return this.request(
|
|
3047
3062
|
"/api/sdk/replay/complete",
|
|
3048
|
-
|
|
3063
|
+
experimentIdWireFields(experimentId),
|
|
3049
3064
|
{ timeout: REPLAY_COMPLETE_REQUEST_TIMEOUT_MS }
|
|
3050
3065
|
);
|
|
3051
3066
|
}
|
|
@@ -3067,11 +3082,11 @@ var init_http = __esm({
|
|
|
3067
3082
|
* snapshot + preview branch and polls operations to readiness, which
|
|
3068
3083
|
* can take seconds.
|
|
3069
3084
|
*/
|
|
3070
|
-
async resolveDbBranchLease(
|
|
3085
|
+
async resolveDbBranchLease(experimentId, traceId, dbBranchSettings, attempt) {
|
|
3071
3086
|
return this.request(
|
|
3072
3087
|
"/api/sdk/replay/resolveDbBranchLease",
|
|
3073
3088
|
{
|
|
3074
|
-
|
|
3089
|
+
...experimentIdWireFields(experimentId),
|
|
3075
3090
|
traceId,
|
|
3076
3091
|
dbBranchSettings,
|
|
3077
3092
|
...attempt !== void 0 && attempt > 0 ? { attempt } : {}
|
|
@@ -3660,7 +3675,7 @@ function replayJsonReplacer(_key, value) {
|
|
|
3660
3675
|
function serializeReplayResult(result) {
|
|
3661
3676
|
return JSON.stringify(result, replayJsonReplacer, 2);
|
|
3662
3677
|
}
|
|
3663
|
-
async function preserveReplayFailure(operation, items,
|
|
3678
|
+
async function preserveReplayFailure(operation, items, experimentId, experimentUrl) {
|
|
3664
3679
|
try {
|
|
3665
3680
|
return await operation();
|
|
3666
3681
|
} catch (cause) {
|
|
@@ -3670,8 +3685,8 @@ async function preserveReplayFailure(operation, items, testRunId, testRunUrl) {
|
|
|
3670
3685
|
throw new ReplayError(
|
|
3671
3686
|
errorMessage(cause),
|
|
3672
3687
|
items,
|
|
3673
|
-
|
|
3674
|
-
|
|
3688
|
+
experimentId,
|
|
3689
|
+
experimentUrl,
|
|
3675
3690
|
cause
|
|
3676
3691
|
);
|
|
3677
3692
|
}
|
|
@@ -3725,7 +3740,7 @@ function buildMockTree(rootNode) {
|
|
|
3725
3740
|
}
|
|
3726
3741
|
return { spans };
|
|
3727
3742
|
}
|
|
3728
|
-
async function processItem(httpClient, serverItem, fn,
|
|
3743
|
+
async function processItem(httpClient, serverItem, fn, experimentId, mockStrategy, resolvedOverrides, replayedTraceId, attempt, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
|
|
3729
3744
|
let lease = includeDbBranchLease ? serverItem.dbBranchLease : void 0;
|
|
3730
3745
|
let leaseError = includeDbBranchLease ? serverItem.dbBranchLeaseError : void 0;
|
|
3731
3746
|
let dbSnapshotRef = serverItem.dbSnapshotRef;
|
|
@@ -3745,7 +3760,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
3745
3760
|
let resolved2;
|
|
3746
3761
|
try {
|
|
3747
3762
|
resolved2 = await httpClient.resolveDbBranchLease(
|
|
3748
|
-
|
|
3763
|
+
experimentId,
|
|
3749
3764
|
originalTraceId,
|
|
3750
3765
|
dbBranchSettings,
|
|
3751
3766
|
attempt
|
|
@@ -3857,7 +3872,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
3857
3872
|
replayStarted = performance.now();
|
|
3858
3873
|
const maybePromise = runWithReplayContext(
|
|
3859
3874
|
{
|
|
3860
|
-
|
|
3875
|
+
experimentId,
|
|
3861
3876
|
traceId: replayedTraceId,
|
|
3862
3877
|
inputSourceSpanId: span.id,
|
|
3863
3878
|
inputSourceTraceId: span.externalTraceId,
|
|
@@ -3940,14 +3955,14 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
3940
3955
|
originalTraceOutline: null
|
|
3941
3956
|
};
|
|
3942
3957
|
}
|
|
3943
|
-
async function waitForReplayPersistence(httpClient,
|
|
3958
|
+
async function waitForReplayPersistence(httpClient, experimentId, replayedTraceIds) {
|
|
3944
3959
|
const deferredSettled = await httpClient.settleDeferredWork(
|
|
3945
3960
|
REPLAY_PERSISTENCE_TIMEOUT_MS
|
|
3946
3961
|
);
|
|
3947
3962
|
if (!deferredSettled) {
|
|
3948
3963
|
httpClient.takeTraceDeliveries(replayedTraceIds);
|
|
3949
3964
|
throw new BitfabError(
|
|
3950
|
-
`Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (
|
|
3965
|
+
`Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (experiment ${experimentId}).`
|
|
3951
3966
|
);
|
|
3952
3967
|
}
|
|
3953
3968
|
if (!httpClient.hasClosedDeliveries(replayedTraceIds)) {
|
|
@@ -3976,7 +3991,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
3976
3991
|
let missing = Object.keys(expectedSpanCounts).length;
|
|
3977
3992
|
while (true) {
|
|
3978
3993
|
const status = await httpClient.getReplayStatus(
|
|
3979
|
-
|
|
3994
|
+
experimentId,
|
|
3980
3995
|
expectedSpanCounts
|
|
3981
3996
|
);
|
|
3982
3997
|
const ready = status.traceIds ?? {};
|
|
@@ -3995,7 +4010,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
3995
4010
|
}
|
|
3996
4011
|
const cause = flushed ? "" : " Delivery was also not confirmed before the flush deadline, so the spans likely never reached the server.";
|
|
3997
4012
|
throw new BitfabError(
|
|
3998
|
-
`Replay traces were not fully persisted before the delivery deadline (
|
|
4013
|
+
`Replay traces were not fully persisted before the delivery deadline (experiment ${experimentId}, missing ${missing} of ${Object.keys(expectedSpanCounts).length} trace(s)).${cause}`
|
|
3999
4014
|
);
|
|
4000
4015
|
}
|
|
4001
4016
|
function sleepForReplayPersistence(ms) {
|
|
@@ -4062,8 +4077,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4062
4077
|
}
|
|
4063
4078
|
}
|
|
4064
4079
|
const {
|
|
4065
|
-
|
|
4066
|
-
|
|
4080
|
+
experimentId,
|
|
4081
|
+
experimentUrl,
|
|
4067
4082
|
items: serverItems
|
|
4068
4083
|
} = await httpClient.startReplay(
|
|
4069
4084
|
traceFunctionKey,
|
|
@@ -4096,7 +4111,14 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4096
4111
|
}
|
|
4097
4112
|
}
|
|
4098
4113
|
const mockStrategy = options?.mock ?? "marked";
|
|
4099
|
-
const
|
|
4114
|
+
const fullExperimentUrl = `${serviceUrl}${experimentUrl}`;
|
|
4115
|
+
try {
|
|
4116
|
+
options?.onExperimentStart?.({
|
|
4117
|
+
experimentId,
|
|
4118
|
+
experimentUrl: fullExperimentUrl
|
|
4119
|
+
});
|
|
4120
|
+
} catch {
|
|
4121
|
+
}
|
|
4100
4122
|
const resolvedOverrides = [
|
|
4101
4123
|
...normalizeMockOverrides(options?.mockOverride),
|
|
4102
4124
|
...registeredOverrides
|
|
@@ -4109,7 +4131,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4109
4131
|
httpClient,
|
|
4110
4132
|
serverItem,
|
|
4111
4133
|
fn,
|
|
4112
|
-
|
|
4134
|
+
experimentId,
|
|
4113
4135
|
mockStrategy,
|
|
4114
4136
|
resolvedOverrides,
|
|
4115
4137
|
replayedTraceIds[index],
|
|
@@ -4164,7 +4186,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4164
4186
|
}
|
|
4165
4187
|
try {
|
|
4166
4188
|
onItemFinish?.({
|
|
4167
|
-
|
|
4189
|
+
experimentId,
|
|
4190
|
+
testRunId: experimentId,
|
|
4168
4191
|
completed,
|
|
4169
4192
|
total,
|
|
4170
4193
|
succeeded,
|
|
@@ -4212,7 +4235,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4212
4235
|
try {
|
|
4213
4236
|
options.onItemStart?.({
|
|
4214
4237
|
type: "started",
|
|
4215
|
-
|
|
4238
|
+
experimentId,
|
|
4239
|
+
testRunId: experimentId,
|
|
4216
4240
|
started,
|
|
4217
4241
|
completed,
|
|
4218
4242
|
total,
|
|
@@ -4231,21 +4255,23 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4231
4255
|
} : void 0
|
|
4232
4256
|
);
|
|
4233
4257
|
if (options?.dryRun === true) {
|
|
4234
|
-
await httpClient.completeReplay(
|
|
4258
|
+
await httpClient.completeReplay(experimentId).catch(() => void 0);
|
|
4235
4259
|
const dryResult = {
|
|
4236
4260
|
items: resultItems,
|
|
4237
|
-
|
|
4238
|
-
|
|
4261
|
+
experimentId,
|
|
4262
|
+
experimentUrl: fullExperimentUrl,
|
|
4263
|
+
testRunId: experimentId,
|
|
4264
|
+
testRunUrl: fullExperimentUrl,
|
|
4239
4265
|
attempts
|
|
4240
4266
|
};
|
|
4241
4267
|
await writeReplayResultFile(dryResult);
|
|
4242
4268
|
return dryResult;
|
|
4243
4269
|
}
|
|
4244
4270
|
const deliveredTraceIds = await preserveReplayFailure(
|
|
4245
|
-
() => waitForReplayPersistence(httpClient,
|
|
4271
|
+
() => waitForReplayPersistence(httpClient, experimentId, replayedTraceIds),
|
|
4246
4272
|
resultItems,
|
|
4247
|
-
|
|
4248
|
-
|
|
4273
|
+
experimentId,
|
|
4274
|
+
fullExperimentUrl
|
|
4249
4275
|
);
|
|
4250
4276
|
for (let index = 0; index < resultItems.length; index += 1) {
|
|
4251
4277
|
const localId = replayedTraceIds[index];
|
|
@@ -4255,10 +4281,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4255
4281
|
}
|
|
4256
4282
|
}
|
|
4257
4283
|
const completeResult = await preserveReplayFailure(
|
|
4258
|
-
() => httpClient.completeReplay(
|
|
4284
|
+
() => httpClient.completeReplay(experimentId),
|
|
4259
4285
|
resultItems,
|
|
4260
|
-
|
|
4261
|
-
|
|
4286
|
+
experimentId,
|
|
4287
|
+
fullExperimentUrl
|
|
4262
4288
|
);
|
|
4263
4289
|
const serverTraceIds = completeResult.traceIds;
|
|
4264
4290
|
const replayTokens = completeResult.tokens;
|
|
@@ -4285,20 +4311,20 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4285
4311
|
if (completedCount > 0 && missing.length === completedCount) {
|
|
4286
4312
|
const serverCount = completeResult.traceCount !== void 0 ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.` : "";
|
|
4287
4313
|
const cause = new BitfabError(
|
|
4288
|
-
`Replay completed but the server has no persisted trace for any of the ${completedCount} completed item(s) (
|
|
4314
|
+
`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.`
|
|
4289
4315
|
);
|
|
4290
4316
|
throw new ReplayError(
|
|
4291
4317
|
cause.message,
|
|
4292
4318
|
resultItems,
|
|
4293
|
-
|
|
4294
|
-
|
|
4319
|
+
experimentId,
|
|
4320
|
+
fullExperimentUrl,
|
|
4295
4321
|
cause
|
|
4296
4322
|
);
|
|
4297
4323
|
}
|
|
4298
4324
|
if (missing.length > 0) {
|
|
4299
4325
|
try {
|
|
4300
4326
|
console.error(
|
|
4301
|
-
`Bitfab: server has no persisted trace for ${missing.length} of ${completedCount} completed replay item(s) (
|
|
4327
|
+
`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.`
|
|
4302
4328
|
);
|
|
4303
4329
|
} catch {
|
|
4304
4330
|
}
|
|
@@ -4306,8 +4332,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4306
4332
|
}
|
|
4307
4333
|
const result = {
|
|
4308
4334
|
items: resultItems,
|
|
4309
|
-
|
|
4310
|
-
|
|
4335
|
+
experimentId,
|
|
4336
|
+
experimentUrl: fullExperimentUrl,
|
|
4337
|
+
testRunId: experimentId,
|
|
4338
|
+
testRunUrl: fullExperimentUrl,
|
|
4311
4339
|
attempts
|
|
4312
4340
|
};
|
|
4313
4341
|
await writeReplayResultFile(result);
|
|
@@ -4315,7 +4343,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4315
4343
|
try {
|
|
4316
4344
|
options?.onProgress?.({
|
|
4317
4345
|
type: "complete",
|
|
4318
|
-
|
|
4346
|
+
experimentId,
|
|
4347
|
+
testRunId: experimentId,
|
|
4319
4348
|
completed: total,
|
|
4320
4349
|
total,
|
|
4321
4350
|
succeeded,
|
|
@@ -4365,13 +4394,15 @@ var init_replay = __esm({
|
|
|
4365
4394
|
MAX_REPLAY_ATTEMPTS = 100;
|
|
4366
4395
|
BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
|
|
4367
4396
|
ReplayError = class extends BitfabError {
|
|
4368
|
-
constructor(message, items,
|
|
4369
|
-
super(message,
|
|
4397
|
+
constructor(message, items, experimentId, experimentUrl, cause) {
|
|
4398
|
+
super(message, experimentUrl);
|
|
4370
4399
|
this.items = items;
|
|
4371
|
-
this.
|
|
4372
|
-
this.
|
|
4400
|
+
this.experimentId = experimentId;
|
|
4401
|
+
this.experimentUrl = experimentUrl;
|
|
4373
4402
|
this.cause = cause;
|
|
4374
4403
|
this.name = "ReplayError";
|
|
4404
|
+
this.testRunId = experimentId;
|
|
4405
|
+
this.testRunUrl = experimentUrl;
|
|
4375
4406
|
}
|
|
4376
4407
|
};
|
|
4377
4408
|
DbBranchReplayError = class extends BitfabError {
|
|
@@ -4390,6 +4421,8 @@ var init_replay = __esm({
|
|
|
4390
4421
|
var index_exports = {};
|
|
4391
4422
|
__export(index_exports, {
|
|
4392
4423
|
AssertionCategoriesClient: () => AssertionCategoriesClient,
|
|
4424
|
+
AssertionGenerationError: () => AssertionGenerationError,
|
|
4425
|
+
AssertionGenerationTimeoutError: () => AssertionGenerationTimeoutError,
|
|
4393
4426
|
BITFAB_PROGRESS_PREFIX: () => BITFAB_PROGRESS_PREFIX,
|
|
4394
4427
|
Bitfab: () => Bitfab,
|
|
4395
4428
|
BitfabClaudeAgentHandler: () => BitfabClaudeAgentHandler,
|
|
@@ -4405,6 +4438,8 @@ __export(index_exports, {
|
|
|
4405
4438
|
DEFAULT_SERVICE_URL: () => DEFAULT_SERVICE_URL,
|
|
4406
4439
|
DatasetsClient: () => DatasetsClient,
|
|
4407
4440
|
DbBranchReplayError: () => DbBranchReplayError,
|
|
4441
|
+
GraderRerunError: () => GraderRerunError,
|
|
4442
|
+
GraderRerunTimeoutError: () => GraderRerunTimeoutError,
|
|
4408
4443
|
GradersClient: () => GradersClient,
|
|
4409
4444
|
HttpClient: () => HttpClient,
|
|
4410
4445
|
LabelsClient: () => LabelsClient,
|
|
@@ -5832,11 +5867,39 @@ init_constants();
|
|
|
5832
5867
|
|
|
5833
5868
|
// src/datasets.ts
|
|
5834
5869
|
var DEFAULT_RERUN_TIMEOUT_MS = 9e4;
|
|
5835
|
-
var
|
|
5870
|
+
var RERUN_POLL_INTERVAL_MS = 1e3;
|
|
5836
5871
|
var TERMINAL_RERUN_STATUSES = /* @__PURE__ */ new Set([
|
|
5837
5872
|
"completed",
|
|
5838
5873
|
"errored"
|
|
5839
5874
|
]);
|
|
5875
|
+
var GraderRerunError = class extends Error {
|
|
5876
|
+
constructor(message, run) {
|
|
5877
|
+
super(message);
|
|
5878
|
+
this.run = run;
|
|
5879
|
+
this.name = "GraderRerunError";
|
|
5880
|
+
}
|
|
5881
|
+
};
|
|
5882
|
+
var GraderRerunTimeoutError = class extends GraderRerunError {
|
|
5883
|
+
constructor(datasetId, run, timeoutMs) {
|
|
5884
|
+
super(
|
|
5885
|
+
`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.`,
|
|
5886
|
+
run
|
|
5887
|
+
);
|
|
5888
|
+
this.name = "GraderRerunTimeoutError";
|
|
5889
|
+
}
|
|
5890
|
+
};
|
|
5891
|
+
function finishedRerun(datasetId, run, joinedExisting) {
|
|
5892
|
+
if (!TERMINAL_RERUN_STATUSES.has(run.status)) {
|
|
5893
|
+
return null;
|
|
5894
|
+
}
|
|
5895
|
+
if (run.status === "errored") {
|
|
5896
|
+
throw new GraderRerunError(
|
|
5897
|
+
`Grader re-run ${run.id} on dataset ${datasetId} errored: ${run.error ?? "no reason recorded"}`,
|
|
5898
|
+
run
|
|
5899
|
+
);
|
|
5900
|
+
}
|
|
5901
|
+
return { run, joinedExisting };
|
|
5902
|
+
}
|
|
5840
5903
|
function sleep(ms) {
|
|
5841
5904
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5842
5905
|
}
|
|
@@ -5936,28 +5999,25 @@ var DatasetsClient = class {
|
|
|
5936
5999
|
{ graderIds }
|
|
5937
6000
|
);
|
|
5938
6001
|
}
|
|
5939
|
-
/**
|
|
5940
|
-
* Re-run graders over every trace in the dataset. Defaults to every assigned
|
|
5941
|
-
* grader; an unassigned id is rejected. Waits for the run to finish (up to
|
|
5942
|
-
* `timeoutMs`, default 90s) unless `wait` is `false`, and returns the last
|
|
5943
|
-
* run state seen either way. A request matching an in-flight run joins it.
|
|
5944
|
-
*/
|
|
5945
6002
|
async rerunGraders(datasetId, options = {}) {
|
|
5946
6003
|
const started = await this.httpClient.request(
|
|
5947
6004
|
datasetPath(datasetId, "/rerunGraders"),
|
|
5948
6005
|
options.graderIds === void 0 ? {} : { graderIds: options.graderIds }
|
|
5949
6006
|
);
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
}
|
|
5953
|
-
const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS);
|
|
5954
|
-
const interval = options.pollIntervalMs ?? DEFAULT_RERUN_POLL_INTERVAL_MS;
|
|
6007
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS;
|
|
6008
|
+
const deadline = Date.now() + timeoutMs;
|
|
5955
6009
|
let run = started.run;
|
|
5956
|
-
while (
|
|
5957
|
-
|
|
6010
|
+
while (true) {
|
|
6011
|
+
const finished = finishedRerun(datasetId, run, started.joinedExisting);
|
|
6012
|
+
if (finished !== null) {
|
|
6013
|
+
return finished;
|
|
6014
|
+
}
|
|
6015
|
+
if (Date.now() >= deadline) {
|
|
6016
|
+
throw new GraderRerunTimeoutError(datasetId, run, timeoutMs);
|
|
6017
|
+
}
|
|
6018
|
+
await sleep(RERUN_POLL_INTERVAL_MS);
|
|
5958
6019
|
run = await this.getGraderRerun(datasetId, run.id) ?? run;
|
|
5959
6020
|
}
|
|
5960
|
-
return { run, joinedExisting: started.joinedExisting };
|
|
5961
6021
|
}
|
|
5962
6022
|
/**
|
|
5963
6023
|
* The dataset's active grader re-run, or the run named by `runId`. Returns
|
|
@@ -6028,6 +6088,7 @@ var GradersClient = class {
|
|
|
6028
6088
|
init_http();
|
|
6029
6089
|
|
|
6030
6090
|
// src/labels.ts
|
|
6091
|
+
init_http();
|
|
6031
6092
|
var LABELS_PATH = "/api/sdk/traces/labels";
|
|
6032
6093
|
var HUMAN_LABELS_PATH = "/api/sdk/traces/labels/human";
|
|
6033
6094
|
function labelEvidencePath(traceId, assertionId) {
|
|
@@ -6037,27 +6098,27 @@ var LabelsClient = class {
|
|
|
6037
6098
|
constructor(httpClient) {
|
|
6038
6099
|
this.httpClient = httpClient;
|
|
6039
6100
|
}
|
|
6040
|
-
async save(update,
|
|
6041
|
-
const [outcome] = await this.saveAll([update],
|
|
6101
|
+
async save(update, experimentId) {
|
|
6102
|
+
const [outcome] = await this.saveAll([update], experimentId);
|
|
6042
6103
|
return outcome;
|
|
6043
6104
|
}
|
|
6044
|
-
async saveAll(updates,
|
|
6105
|
+
async saveAll(updates, experimentId) {
|
|
6045
6106
|
const response = await this.httpClient.request(
|
|
6046
6107
|
LABELS_PATH,
|
|
6047
6108
|
{
|
|
6048
6109
|
labels: updates,
|
|
6049
|
-
...
|
|
6110
|
+
...experimentId === void 0 ? {} : experimentIdWireFields(experimentId)
|
|
6050
6111
|
}
|
|
6051
6112
|
);
|
|
6052
6113
|
return response.labels;
|
|
6053
6114
|
}
|
|
6054
6115
|
/** Withhold a verdict for a trace or replay attempt whose check did not run. */
|
|
6055
|
-
async skip(target,
|
|
6056
|
-
return this.save({ ...target, skip: true },
|
|
6116
|
+
async skip(target, experimentId) {
|
|
6117
|
+
return this.save({ ...target, skip: true }, experimentId);
|
|
6057
6118
|
}
|
|
6058
6119
|
/** Clear a previous verdict for a trace, replay attempt, or assertion. */
|
|
6059
|
-
async archive(target,
|
|
6060
|
-
return this.save({ ...target, archive: true },
|
|
6120
|
+
async archive(target, experimentId) {
|
|
6121
|
+
return this.save({ ...target, archive: true }, experimentId);
|
|
6061
6122
|
}
|
|
6062
6123
|
async saveHuman(update) {
|
|
6063
6124
|
const [outcome] = await this.saveHumanAll([update]);
|
|
@@ -7813,6 +7874,46 @@ init_traceMetadata();
|
|
|
7813
7874
|
// src/traces.ts
|
|
7814
7875
|
var ASSERTIONS_PATH = "/api/sdk/traces/assertions";
|
|
7815
7876
|
var SEARCH_PATH = "/api/sdk/traces/search";
|
|
7877
|
+
var DEFAULT_GENERATION_TIMEOUT_MS = 6e5;
|
|
7878
|
+
var GENERATION_POLL_INTERVAL_MS = 2e3;
|
|
7879
|
+
var AssertionGenerationError = class extends Error {
|
|
7880
|
+
constructor(message, traceId) {
|
|
7881
|
+
super(message);
|
|
7882
|
+
this.traceId = traceId;
|
|
7883
|
+
this.name = "AssertionGenerationError";
|
|
7884
|
+
}
|
|
7885
|
+
};
|
|
7886
|
+
var AssertionGenerationTimeoutError = class extends AssertionGenerationError {
|
|
7887
|
+
constructor(traceId, timeoutMs) {
|
|
7888
|
+
super(
|
|
7889
|
+
`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.`,
|
|
7890
|
+
traceId
|
|
7891
|
+
);
|
|
7892
|
+
this.name = "AssertionGenerationTimeoutError";
|
|
7893
|
+
}
|
|
7894
|
+
};
|
|
7895
|
+
function sleep2(ms) {
|
|
7896
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7897
|
+
}
|
|
7898
|
+
function isGenerationFinished(traceId, generation) {
|
|
7899
|
+
if (generation === null || generation.status === "running") {
|
|
7900
|
+
return false;
|
|
7901
|
+
}
|
|
7902
|
+
if (generation.status === "failed") {
|
|
7903
|
+
throw new AssertionGenerationError(
|
|
7904
|
+
`Assertion generation for trace ${traceId} failed: ${generation.error ?? "no reason recorded"}. Pass regenerate: true to try again.`,
|
|
7905
|
+
traceId
|
|
7906
|
+
);
|
|
7907
|
+
}
|
|
7908
|
+
return true;
|
|
7909
|
+
}
|
|
7910
|
+
function draftsInGenerationOrder(assertions, assertionIds) {
|
|
7911
|
+
const byId = new Map(assertions.map((assertion) => [assertion.id, assertion]));
|
|
7912
|
+
return assertionIds.flatMap((id) => {
|
|
7913
|
+
const assertion = byId.get(id);
|
|
7914
|
+
return assertion === void 0 ? [] : [assertion];
|
|
7915
|
+
});
|
|
7916
|
+
}
|
|
7816
7917
|
function traceAssertionsPath(traceId, suffix = "") {
|
|
7817
7918
|
return `/api/sdk/traces/${encodeURIComponent(traceId)}/assertions${suffix}`;
|
|
7818
7919
|
}
|
|
@@ -7844,6 +7945,34 @@ var TracesClient = class {
|
|
|
7844
7945
|
});
|
|
7845
7946
|
return response.assertions;
|
|
7846
7947
|
}
|
|
7948
|
+
async generateAssertions(traceId, options = {}) {
|
|
7949
|
+
const started = await this.httpClient.request(
|
|
7950
|
+
traceAssertionsPath(traceId, "/generate"),
|
|
7951
|
+
{
|
|
7952
|
+
...options.guidance === void 0 ? {} : { guidance: options.guidance },
|
|
7953
|
+
...options.categoryIds === void 0 ? {} : { categoryIds: options.categoryIds },
|
|
7954
|
+
...options.regenerate === void 0 ? {} : { regenerate: options.regenerate }
|
|
7955
|
+
}
|
|
7956
|
+
);
|
|
7957
|
+
if (isGenerationFinished(traceId, started.generation)) {
|
|
7958
|
+
return started.assertions;
|
|
7959
|
+
}
|
|
7960
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_GENERATION_TIMEOUT_MS;
|
|
7961
|
+
const deadline = Date.now() + timeoutMs;
|
|
7962
|
+
while (true) {
|
|
7963
|
+
if (Date.now() >= deadline) {
|
|
7964
|
+
throw new AssertionGenerationTimeoutError(traceId, timeoutMs);
|
|
7965
|
+
}
|
|
7966
|
+
await sleep2(GENERATION_POLL_INTERVAL_MS);
|
|
7967
|
+
const read2 = await this.getAssertions(traceId);
|
|
7968
|
+
if (isGenerationFinished(traceId, read2.generation)) {
|
|
7969
|
+
return draftsInGenerationOrder(
|
|
7970
|
+
read2.assertions,
|
|
7971
|
+
read2.generation.assertionIds
|
|
7972
|
+
);
|
|
7973
|
+
}
|
|
7974
|
+
}
|
|
7975
|
+
}
|
|
7847
7976
|
async archiveAssertions(params) {
|
|
7848
7977
|
const response = await this.httpClient.request(
|
|
7849
7978
|
traceAssertionsPath(params.traceId, "/archive"),
|
|
@@ -8347,6 +8476,15 @@ var BitfabVercelAiHandler = class {
|
|
|
8347
8476
|
|
|
8348
8477
|
// src/client.ts
|
|
8349
8478
|
init_warnOnce();
|
|
8479
|
+
function resolveSpanExperimentId(options) {
|
|
8480
|
+
const { experimentId, testRunId } = options;
|
|
8481
|
+
if (experimentId !== void 0 && testRunId !== void 0 && experimentId !== testRunId) {
|
|
8482
|
+
throw new BitfabError(
|
|
8483
|
+
`experimentId ("${experimentId}") and its deprecated alias testRunId ("${testRunId}") were both passed with different values. Pass only experimentId.`
|
|
8484
|
+
);
|
|
8485
|
+
}
|
|
8486
|
+
return experimentId ?? testRunId;
|
|
8487
|
+
}
|
|
8350
8488
|
var TRUNCATION_LIMIT_ORDER = [
|
|
8351
8489
|
"max_depth",
|
|
8352
8490
|
"max_captured_subtree_spans"
|
|
@@ -8936,13 +9074,12 @@ var Bitfab = class {
|
|
|
8936
9074
|
"bitfab.node({ capture: false }) cannot use mockOnReplay: true because an uncaptured node has no recorded output."
|
|
8937
9075
|
);
|
|
8938
9076
|
}
|
|
9077
|
+
const experimentId = resolveSpanExperimentId(options);
|
|
8939
9078
|
return {
|
|
8940
9079
|
capture,
|
|
8941
9080
|
type: options.type ?? "custom",
|
|
8942
9081
|
...options.name !== void 0 && { name: options.name },
|
|
8943
|
-
...
|
|
8944
|
-
testRunId: options.testRunId
|
|
8945
|
-
},
|
|
9082
|
+
...experimentId !== void 0 && { experimentId },
|
|
8946
9083
|
...options.mockOnReplay !== void 0 && {
|
|
8947
9084
|
mockOnReplay: options.mockOnReplay
|
|
8948
9085
|
},
|
|
@@ -9077,6 +9214,7 @@ var Bitfab = class {
|
|
|
9077
9214
|
return invokeWithoutNode();
|
|
9078
9215
|
}
|
|
9079
9216
|
const mockOnReplay = nodeConfiguration?.mockOnReplay ?? options.mockOnReplayDefault;
|
|
9217
|
+
const nodeExperimentId = nodeConfiguration === void 0 ? void 0 : resolveSpanExperimentId(nodeConfiguration);
|
|
9080
9218
|
const childOptions = {
|
|
9081
9219
|
name: spanName,
|
|
9082
9220
|
type: nodeConfiguration?.type ?? "function",
|
|
@@ -9087,8 +9225,8 @@ var Bitfab = class {
|
|
|
9087
9225
|
captureContent: true,
|
|
9088
9226
|
autoTraceDefinition: definition,
|
|
9089
9227
|
...declaredNode && { declaredNode },
|
|
9090
|
-
...
|
|
9091
|
-
|
|
9228
|
+
...nodeExperimentId !== void 0 && {
|
|
9229
|
+
experimentId: nodeExperimentId
|
|
9092
9230
|
},
|
|
9093
9231
|
...mockOnReplay !== void 0 && {
|
|
9094
9232
|
mockOnReplay
|
|
@@ -9749,6 +9887,7 @@ var Bitfab = class {
|
|
|
9749
9887
|
const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
|
|
9750
9888
|
const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
9751
9889
|
const self = this;
|
|
9890
|
+
const optionExperimentId = resolveSpanExperimentId(options);
|
|
9752
9891
|
const fnIsAsyncFunction = fn.constructor.name === "AsyncFunction";
|
|
9753
9892
|
const fnReturnsPromise = fnIsAsyncFunction || (() => {
|
|
9754
9893
|
try {
|
|
@@ -9851,7 +9990,7 @@ var Bitfab = class {
|
|
|
9851
9990
|
const inputs = args;
|
|
9852
9991
|
const startedAt = nowIsoTimestamp();
|
|
9853
9992
|
const replayCtxAtStart = getReplayContext();
|
|
9854
|
-
const
|
|
9993
|
+
const experimentId = replayCtxAtStart?.experimentId ?? optionExperimentId;
|
|
9855
9994
|
if (isRootSpan && !activeTraceStates.has(traceId)) {
|
|
9856
9995
|
const dbSnapshotRef = buildSnapshotRef(self.dbSnapshot, startedAt);
|
|
9857
9996
|
self.simulationPlan.refresh();
|
|
@@ -9860,7 +9999,7 @@ var Bitfab = class {
|
|
|
9860
9999
|
traceFunctionKey,
|
|
9861
10000
|
startedAt,
|
|
9862
10001
|
contexts: [],
|
|
9863
|
-
...
|
|
10002
|
+
...experimentId !== void 0 && { experimentId },
|
|
9864
10003
|
...replayCtxAtStart?.inputSourceTraceId && {
|
|
9865
10004
|
inputSourceTraceId: replayCtxAtStart.inputSourceTraceId
|
|
9866
10005
|
},
|
|
@@ -9906,7 +10045,7 @@ var Bitfab = class {
|
|
|
9906
10045
|
contexts: newContext.contexts,
|
|
9907
10046
|
prompt: newContext.prompt,
|
|
9908
10047
|
endedAt,
|
|
9909
|
-
...
|
|
10048
|
+
...experimentId !== void 0 && { experimentId },
|
|
9910
10049
|
...replayCtx?.inputSourceSpanId && {
|
|
9911
10050
|
inputSourceSpanId: replayCtx.inputSourceSpanId
|
|
9912
10051
|
}
|
|
@@ -9927,7 +10066,7 @@ var Bitfab = class {
|
|
|
9927
10066
|
name: traceState?.name,
|
|
9928
10067
|
metadata: callerTraceMetadata(traceId),
|
|
9929
10068
|
contexts: traceState?.contexts ?? [],
|
|
9930
|
-
|
|
10069
|
+
experimentId: traceState?.experimentId,
|
|
9931
10070
|
inputSourceTraceId: traceState?.inputSourceTraceId,
|
|
9932
10071
|
replayAttempt: traceState?.replayAttempt,
|
|
9933
10072
|
dbSnapshotRef: traceState?.dbSnapshotRef,
|
|
@@ -10398,7 +10537,7 @@ var Bitfab = class {
|
|
|
10398
10537
|
completed: true,
|
|
10399
10538
|
...params.dropped && { dropped: true },
|
|
10400
10539
|
...params.sessionId && { sessionId: params.sessionId },
|
|
10401
|
-
...params.
|
|
10540
|
+
...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId)
|
|
10402
10541
|
});
|
|
10403
10542
|
}
|
|
10404
10543
|
sendsSpanOnCompletion(context) {
|
|
@@ -10510,7 +10649,7 @@ var Bitfab = class {
|
|
|
10510
10649
|
},
|
|
10511
10650
|
...params.declaredNode === true && { [DECLARED_NODE_FIELD]: true },
|
|
10512
10651
|
rawSpan: externalSpan,
|
|
10513
|
-
...params.
|
|
10652
|
+
...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId),
|
|
10514
10653
|
...params.mocked && { mocked: true },
|
|
10515
10654
|
...params.mockTarget && { mockTarget: params.mockTarget },
|
|
10516
10655
|
...params.mockSource && { mockSource: params.mockSource }
|
|
@@ -11062,6 +11201,8 @@ function resolveTraceFunctionKey(registration) {
|
|
|
11062
11201
|
// Annotate the CommonJS export names for ESM import in node:
|
|
11063
11202
|
0 && (module.exports = {
|
|
11064
11203
|
AssertionCategoriesClient,
|
|
11204
|
+
AssertionGenerationError,
|
|
11205
|
+
AssertionGenerationTimeoutError,
|
|
11065
11206
|
BITFAB_PROGRESS_PREFIX,
|
|
11066
11207
|
Bitfab,
|
|
11067
11208
|
BitfabClaudeAgentHandler,
|
|
@@ -11077,6 +11218,8 @@ function resolveTraceFunctionKey(registration) {
|
|
|
11077
11218
|
DEFAULT_SERVICE_URL,
|
|
11078
11219
|
DatasetsClient,
|
|
11079
11220
|
DbBranchReplayError,
|
|
11221
|
+
GraderRerunError,
|
|
11222
|
+
GraderRerunTimeoutError,
|
|
11080
11223
|
GradersClient,
|
|
11081
11224
|
HttpClient,
|
|
11082
11225
|
LabelsClient,
|