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/index.cjs
CHANGED
|
@@ -51,7 +51,7 @@ var __version__, __packageName__;
|
|
|
51
51
|
var init_version_generated = __esm({
|
|
52
52
|
"src/version.generated.ts"() {
|
|
53
53
|
"use strict";
|
|
54
|
-
__version__ = "0.
|
|
54
|
+
__version__ = "0.59.1";
|
|
55
55
|
__packageName__ = "bitfab";
|
|
56
56
|
}
|
|
57
57
|
});
|
|
@@ -2113,6 +2113,7 @@ __export(http_exports, {
|
|
|
2113
2113
|
HttpClient: () => HttpClient,
|
|
2114
2114
|
awaitOnExit: () => awaitOnExit,
|
|
2115
2115
|
awaitPendingRequests: () => awaitPendingRequests,
|
|
2116
|
+
experimentIdWireFields: () => experimentIdWireFields,
|
|
2116
2117
|
flushTraces: () => flushTraces,
|
|
2117
2118
|
parseRetryAfterMs: () => parseRetryAfterMs,
|
|
2118
2119
|
serializePayloadBody: () => serializePayloadBody
|
|
@@ -2281,6 +2282,9 @@ function warnDroppedExternalTrace(error) {
|
|
|
2281
2282
|
`a trace was dropped because the send step failed: ${describeError(error)}`
|
|
2282
2283
|
);
|
|
2283
2284
|
}
|
|
2285
|
+
function experimentIdWireFields(experimentId) {
|
|
2286
|
+
return { experimentId, testRunId: experimentId };
|
|
2287
|
+
}
|
|
2284
2288
|
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;
|
|
2285
2289
|
var init_http = __esm({
|
|
2286
2290
|
"src/http.ts"() {
|
|
@@ -2885,7 +2889,7 @@ var init_http = __esm({
|
|
|
2885
2889
|
}
|
|
2886
2890
|
/**
|
|
2887
2891
|
* Start a replay session by fetching historical traces.
|
|
2888
|
-
* Blocking call - creates
|
|
2892
|
+
* Blocking call - creates an experiment and returns lightweight item references.
|
|
2889
2893
|
*/
|
|
2890
2894
|
async startReplay(traceFunctionKey, limit, traceIds, name, codeChangeDescription, codeChangeFiles, includeDbBranchLease, experimentGroupId, datasetIds, graderIds, dbBranchSettings, attempts, includeOriginalMetadata, onlyWithAssertions, judgeAssertions) {
|
|
2891
2895
|
const payload = { traceFunctionKey };
|
|
@@ -2941,9 +2945,20 @@ var init_http = __esm({
|
|
|
2941
2945
|
payload.git = git;
|
|
2942
2946
|
}
|
|
2943
2947
|
const timeout = includeDbBranchLease ? REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS : 3e4;
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2948
|
+
const response = await this.request(
|
|
2949
|
+
"/api/sdk/replay/start",
|
|
2950
|
+
payload,
|
|
2951
|
+
{ timeout }
|
|
2952
|
+
);
|
|
2953
|
+
const { testRunId, testRunUrl, ...rest } = response;
|
|
2954
|
+
const experimentId = response.experimentId ?? testRunId;
|
|
2955
|
+
const experimentUrl = response.experimentUrl ?? testRunUrl;
|
|
2956
|
+
if (experimentId === void 0 || experimentUrl === void 0) {
|
|
2957
|
+
throw new BitfabError(
|
|
2958
|
+
"Replay start response is missing the experiment ID or URL."
|
|
2959
|
+
);
|
|
2960
|
+
}
|
|
2961
|
+
return { ...rest, experimentId, experimentUrl };
|
|
2947
2962
|
}
|
|
2948
2963
|
/**
|
|
2949
2964
|
* Fetch an external span by ID.
|
|
@@ -3040,21 +3055,21 @@ var init_http = __esm({
|
|
|
3040
3055
|
* has a final status AND at least that many persisted spans, which is what
|
|
3041
3056
|
* makes this a real barrier rather than a "the row exists" check.
|
|
3042
3057
|
*/
|
|
3043
|
-
async getReplayStatus(
|
|
3058
|
+
async getReplayStatus(experimentId, expectedSpanCounts) {
|
|
3044
3059
|
return this.request(
|
|
3045
3060
|
"/api/sdk/replay/status",
|
|
3046
|
-
{
|
|
3061
|
+
{ ...experimentIdWireFields(experimentId), expectedSpanCounts },
|
|
3047
3062
|
{ timeout: 3e4 }
|
|
3048
3063
|
);
|
|
3049
3064
|
}
|
|
3050
3065
|
/**
|
|
3051
|
-
* Mark a replay
|
|
3066
|
+
* Mark a replay experiment as completed.
|
|
3052
3067
|
* Blocking call.
|
|
3053
3068
|
*/
|
|
3054
|
-
async completeReplay(
|
|
3069
|
+
async completeReplay(experimentId) {
|
|
3055
3070
|
return this.request(
|
|
3056
3071
|
"/api/sdk/replay/complete",
|
|
3057
|
-
|
|
3072
|
+
experimentIdWireFields(experimentId),
|
|
3058
3073
|
{ timeout: REPLAY_COMPLETE_REQUEST_TIMEOUT_MS }
|
|
3059
3074
|
);
|
|
3060
3075
|
}
|
|
@@ -3076,11 +3091,11 @@ var init_http = __esm({
|
|
|
3076
3091
|
* snapshot + preview branch and polls operations to readiness, which
|
|
3077
3092
|
* can take seconds.
|
|
3078
3093
|
*/
|
|
3079
|
-
async resolveDbBranchLease(
|
|
3094
|
+
async resolveDbBranchLease(experimentId, traceId, dbBranchSettings, attempt) {
|
|
3080
3095
|
return this.request(
|
|
3081
3096
|
"/api/sdk/replay/resolveDbBranchLease",
|
|
3082
3097
|
{
|
|
3083
|
-
|
|
3098
|
+
...experimentIdWireFields(experimentId),
|
|
3084
3099
|
traceId,
|
|
3085
3100
|
dbBranchSettings,
|
|
3086
3101
|
...attempt !== void 0 && attempt > 0 ? { attempt } : {}
|
|
@@ -3669,7 +3684,7 @@ function replayJsonReplacer(_key, value) {
|
|
|
3669
3684
|
function serializeReplayResult(result) {
|
|
3670
3685
|
return JSON.stringify(result, replayJsonReplacer, 2);
|
|
3671
3686
|
}
|
|
3672
|
-
async function preserveReplayFailure(operation, items,
|
|
3687
|
+
async function preserveReplayFailure(operation, items, experimentId, experimentUrl) {
|
|
3673
3688
|
try {
|
|
3674
3689
|
return await operation();
|
|
3675
3690
|
} catch (cause) {
|
|
@@ -3679,8 +3694,8 @@ async function preserveReplayFailure(operation, items, testRunId, testRunUrl) {
|
|
|
3679
3694
|
throw new ReplayError(
|
|
3680
3695
|
errorMessage(cause),
|
|
3681
3696
|
items,
|
|
3682
|
-
|
|
3683
|
-
|
|
3697
|
+
experimentId,
|
|
3698
|
+
experimentUrl,
|
|
3684
3699
|
cause
|
|
3685
3700
|
);
|
|
3686
3701
|
}
|
|
@@ -3734,7 +3749,7 @@ function buildMockTree(rootNode) {
|
|
|
3734
3749
|
}
|
|
3735
3750
|
return { spans };
|
|
3736
3751
|
}
|
|
3737
|
-
async function processItem(httpClient, serverItem, fn,
|
|
3752
|
+
async function processItem(httpClient, serverItem, fn, experimentId, mockStrategy, resolvedOverrides, replayedTraceId, attempt, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
|
|
3738
3753
|
let lease = includeDbBranchLease ? serverItem.dbBranchLease : void 0;
|
|
3739
3754
|
let leaseError = includeDbBranchLease ? serverItem.dbBranchLeaseError : void 0;
|
|
3740
3755
|
let dbSnapshotRef = serverItem.dbSnapshotRef;
|
|
@@ -3754,7 +3769,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
3754
3769
|
let resolved2;
|
|
3755
3770
|
try {
|
|
3756
3771
|
resolved2 = await httpClient.resolveDbBranchLease(
|
|
3757
|
-
|
|
3772
|
+
experimentId,
|
|
3758
3773
|
originalTraceId,
|
|
3759
3774
|
dbBranchSettings,
|
|
3760
3775
|
attempt
|
|
@@ -3866,7 +3881,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
3866
3881
|
replayStarted = performance.now();
|
|
3867
3882
|
const maybePromise = runWithReplayContext(
|
|
3868
3883
|
{
|
|
3869
|
-
|
|
3884
|
+
experimentId,
|
|
3870
3885
|
traceId: replayedTraceId,
|
|
3871
3886
|
inputSourceSpanId: span.id,
|
|
3872
3887
|
inputSourceTraceId: span.externalTraceId,
|
|
@@ -3949,14 +3964,14 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
3949
3964
|
originalTraceOutline: null
|
|
3950
3965
|
};
|
|
3951
3966
|
}
|
|
3952
|
-
async function waitForReplayPersistence(httpClient,
|
|
3967
|
+
async function waitForReplayPersistence(httpClient, experimentId, replayedTraceIds) {
|
|
3953
3968
|
const deferredSettled = await httpClient.settleDeferredWork(
|
|
3954
3969
|
REPLAY_PERSISTENCE_TIMEOUT_MS
|
|
3955
3970
|
);
|
|
3956
3971
|
if (!deferredSettled) {
|
|
3957
3972
|
httpClient.takeTraceDeliveries(replayedTraceIds);
|
|
3958
3973
|
throw new BitfabError(
|
|
3959
|
-
`Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (
|
|
3974
|
+
`Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (experiment ${experimentId}).`
|
|
3960
3975
|
);
|
|
3961
3976
|
}
|
|
3962
3977
|
if (!httpClient.hasClosedDeliveries(replayedTraceIds)) {
|
|
@@ -3985,7 +4000,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
3985
4000
|
let missing = Object.keys(expectedSpanCounts).length;
|
|
3986
4001
|
while (true) {
|
|
3987
4002
|
const status = await httpClient.getReplayStatus(
|
|
3988
|
-
|
|
4003
|
+
experimentId,
|
|
3989
4004
|
expectedSpanCounts
|
|
3990
4005
|
);
|
|
3991
4006
|
const ready = status.traceIds ?? {};
|
|
@@ -4004,7 +4019,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
4004
4019
|
}
|
|
4005
4020
|
const cause = flushed ? "" : " Delivery was also not confirmed before the flush deadline, so the spans likely never reached the server.";
|
|
4006
4021
|
throw new BitfabError(
|
|
4007
|
-
`Replay traces were not fully persisted before the delivery deadline (
|
|
4022
|
+
`Replay traces were not fully persisted before the delivery deadline (experiment ${experimentId}, missing ${missing} of ${Object.keys(expectedSpanCounts).length} trace(s)).${cause}`
|
|
4008
4023
|
);
|
|
4009
4024
|
}
|
|
4010
4025
|
function sleepForReplayPersistence(ms) {
|
|
@@ -4071,8 +4086,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4071
4086
|
}
|
|
4072
4087
|
}
|
|
4073
4088
|
const {
|
|
4074
|
-
|
|
4075
|
-
|
|
4089
|
+
experimentId,
|
|
4090
|
+
experimentUrl,
|
|
4076
4091
|
items: serverItems
|
|
4077
4092
|
} = await httpClient.startReplay(
|
|
4078
4093
|
traceFunctionKey,
|
|
@@ -4105,7 +4120,14 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4105
4120
|
}
|
|
4106
4121
|
}
|
|
4107
4122
|
const mockStrategy = options?.mock ?? "marked";
|
|
4108
|
-
const
|
|
4123
|
+
const fullExperimentUrl = `${serviceUrl}${experimentUrl}`;
|
|
4124
|
+
try {
|
|
4125
|
+
options?.onExperimentStart?.({
|
|
4126
|
+
experimentId,
|
|
4127
|
+
experimentUrl: fullExperimentUrl
|
|
4128
|
+
});
|
|
4129
|
+
} catch {
|
|
4130
|
+
}
|
|
4109
4131
|
const resolvedOverrides = [
|
|
4110
4132
|
...normalizeMockOverrides(options?.mockOverride),
|
|
4111
4133
|
...registeredOverrides
|
|
@@ -4118,7 +4140,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4118
4140
|
httpClient,
|
|
4119
4141
|
serverItem,
|
|
4120
4142
|
fn,
|
|
4121
|
-
|
|
4143
|
+
experimentId,
|
|
4122
4144
|
mockStrategy,
|
|
4123
4145
|
resolvedOverrides,
|
|
4124
4146
|
replayedTraceIds[index],
|
|
@@ -4173,7 +4195,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4173
4195
|
}
|
|
4174
4196
|
try {
|
|
4175
4197
|
onItemFinish?.({
|
|
4176
|
-
|
|
4198
|
+
experimentId,
|
|
4199
|
+
testRunId: experimentId,
|
|
4177
4200
|
completed,
|
|
4178
4201
|
total,
|
|
4179
4202
|
succeeded,
|
|
@@ -4221,7 +4244,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4221
4244
|
try {
|
|
4222
4245
|
options.onItemStart?.({
|
|
4223
4246
|
type: "started",
|
|
4224
|
-
|
|
4247
|
+
experimentId,
|
|
4248
|
+
testRunId: experimentId,
|
|
4225
4249
|
started,
|
|
4226
4250
|
completed,
|
|
4227
4251
|
total,
|
|
@@ -4240,21 +4264,23 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4240
4264
|
} : void 0
|
|
4241
4265
|
);
|
|
4242
4266
|
if (options?.dryRun === true) {
|
|
4243
|
-
await httpClient.completeReplay(
|
|
4267
|
+
await httpClient.completeReplay(experimentId).catch(() => void 0);
|
|
4244
4268
|
const dryResult = {
|
|
4245
4269
|
items: resultItems,
|
|
4246
|
-
|
|
4247
|
-
|
|
4270
|
+
experimentId,
|
|
4271
|
+
experimentUrl: fullExperimentUrl,
|
|
4272
|
+
testRunId: experimentId,
|
|
4273
|
+
testRunUrl: fullExperimentUrl,
|
|
4248
4274
|
attempts
|
|
4249
4275
|
};
|
|
4250
4276
|
await writeReplayResultFile(dryResult);
|
|
4251
4277
|
return dryResult;
|
|
4252
4278
|
}
|
|
4253
4279
|
const deliveredTraceIds = await preserveReplayFailure(
|
|
4254
|
-
() => waitForReplayPersistence(httpClient,
|
|
4280
|
+
() => waitForReplayPersistence(httpClient, experimentId, replayedTraceIds),
|
|
4255
4281
|
resultItems,
|
|
4256
|
-
|
|
4257
|
-
|
|
4282
|
+
experimentId,
|
|
4283
|
+
fullExperimentUrl
|
|
4258
4284
|
);
|
|
4259
4285
|
for (let index = 0; index < resultItems.length; index += 1) {
|
|
4260
4286
|
const localId = replayedTraceIds[index];
|
|
@@ -4264,10 +4290,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4264
4290
|
}
|
|
4265
4291
|
}
|
|
4266
4292
|
const completeResult = await preserveReplayFailure(
|
|
4267
|
-
() => httpClient.completeReplay(
|
|
4293
|
+
() => httpClient.completeReplay(experimentId),
|
|
4268
4294
|
resultItems,
|
|
4269
|
-
|
|
4270
|
-
|
|
4295
|
+
experimentId,
|
|
4296
|
+
fullExperimentUrl
|
|
4271
4297
|
);
|
|
4272
4298
|
const serverTraceIds = completeResult.traceIds;
|
|
4273
4299
|
const replayTokens = completeResult.tokens;
|
|
@@ -4294,20 +4320,20 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4294
4320
|
if (completedCount > 0 && missing.length === completedCount) {
|
|
4295
4321
|
const serverCount = completeResult.traceCount !== void 0 ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.` : "";
|
|
4296
4322
|
const cause = new BitfabError(
|
|
4297
|
-
`Replay completed but the server has no persisted trace for any of the ${completedCount} completed item(s) (
|
|
4323
|
+
`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.`
|
|
4298
4324
|
);
|
|
4299
4325
|
throw new ReplayError(
|
|
4300
4326
|
cause.message,
|
|
4301
4327
|
resultItems,
|
|
4302
|
-
|
|
4303
|
-
|
|
4328
|
+
experimentId,
|
|
4329
|
+
fullExperimentUrl,
|
|
4304
4330
|
cause
|
|
4305
4331
|
);
|
|
4306
4332
|
}
|
|
4307
4333
|
if (missing.length > 0) {
|
|
4308
4334
|
try {
|
|
4309
4335
|
console.error(
|
|
4310
|
-
`Bitfab: server has no persisted trace for ${missing.length} of ${completedCount} completed replay item(s) (
|
|
4336
|
+
`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.`
|
|
4311
4337
|
);
|
|
4312
4338
|
} catch {
|
|
4313
4339
|
}
|
|
@@ -4315,8 +4341,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4315
4341
|
}
|
|
4316
4342
|
const result = {
|
|
4317
4343
|
items: resultItems,
|
|
4318
|
-
|
|
4319
|
-
|
|
4344
|
+
experimentId,
|
|
4345
|
+
experimentUrl: fullExperimentUrl,
|
|
4346
|
+
testRunId: experimentId,
|
|
4347
|
+
testRunUrl: fullExperimentUrl,
|
|
4320
4348
|
attempts
|
|
4321
4349
|
};
|
|
4322
4350
|
await writeReplayResultFile(result);
|
|
@@ -4324,7 +4352,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4324
4352
|
try {
|
|
4325
4353
|
options?.onProgress?.({
|
|
4326
4354
|
type: "complete",
|
|
4327
|
-
|
|
4355
|
+
experimentId,
|
|
4356
|
+
testRunId: experimentId,
|
|
4328
4357
|
completed: total,
|
|
4329
4358
|
total,
|
|
4330
4359
|
succeeded,
|
|
@@ -4374,13 +4403,15 @@ var init_replay = __esm({
|
|
|
4374
4403
|
MAX_REPLAY_ATTEMPTS = 100;
|
|
4375
4404
|
BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
|
|
4376
4405
|
ReplayError = class extends BitfabError {
|
|
4377
|
-
constructor(message, items,
|
|
4378
|
-
super(message,
|
|
4406
|
+
constructor(message, items, experimentId, experimentUrl, cause) {
|
|
4407
|
+
super(message, experimentUrl);
|
|
4379
4408
|
this.items = items;
|
|
4380
|
-
this.
|
|
4381
|
-
this.
|
|
4409
|
+
this.experimentId = experimentId;
|
|
4410
|
+
this.experimentUrl = experimentUrl;
|
|
4382
4411
|
this.cause = cause;
|
|
4383
4412
|
this.name = "ReplayError";
|
|
4413
|
+
this.testRunId = experimentId;
|
|
4414
|
+
this.testRunUrl = experimentUrl;
|
|
4384
4415
|
}
|
|
4385
4416
|
};
|
|
4386
4417
|
DbBranchReplayError = class extends BitfabError {
|
|
@@ -4399,6 +4430,8 @@ var init_replay = __esm({
|
|
|
4399
4430
|
var index_exports = {};
|
|
4400
4431
|
__export(index_exports, {
|
|
4401
4432
|
AssertionCategoriesClient: () => AssertionCategoriesClient,
|
|
4433
|
+
AssertionGenerationError: () => AssertionGenerationError,
|
|
4434
|
+
AssertionGenerationTimeoutError: () => AssertionGenerationTimeoutError,
|
|
4402
4435
|
BITFAB_PROGRESS_PREFIX: () => BITFAB_PROGRESS_PREFIX,
|
|
4403
4436
|
Bitfab: () => Bitfab,
|
|
4404
4437
|
BitfabClaudeAgentHandler: () => BitfabClaudeAgentHandler,
|
|
@@ -4414,6 +4447,8 @@ __export(index_exports, {
|
|
|
4414
4447
|
DEFAULT_SERVICE_URL: () => DEFAULT_SERVICE_URL,
|
|
4415
4448
|
DatasetsClient: () => DatasetsClient,
|
|
4416
4449
|
DbBranchReplayError: () => DbBranchReplayError,
|
|
4450
|
+
GraderRerunError: () => GraderRerunError,
|
|
4451
|
+
GraderRerunTimeoutError: () => GraderRerunTimeoutError,
|
|
4417
4452
|
GradersClient: () => GradersClient,
|
|
4418
4453
|
HttpClient: () => HttpClient,
|
|
4419
4454
|
LabelsClient: () => LabelsClient,
|
|
@@ -5841,11 +5876,39 @@ init_constants();
|
|
|
5841
5876
|
|
|
5842
5877
|
// src/datasets.ts
|
|
5843
5878
|
var DEFAULT_RERUN_TIMEOUT_MS = 9e4;
|
|
5844
|
-
var
|
|
5879
|
+
var RERUN_POLL_INTERVAL_MS = 1e3;
|
|
5845
5880
|
var TERMINAL_RERUN_STATUSES = /* @__PURE__ */ new Set([
|
|
5846
5881
|
"completed",
|
|
5847
5882
|
"errored"
|
|
5848
5883
|
]);
|
|
5884
|
+
var GraderRerunError = class extends Error {
|
|
5885
|
+
constructor(message, run) {
|
|
5886
|
+
super(message);
|
|
5887
|
+
this.run = run;
|
|
5888
|
+
this.name = "GraderRerunError";
|
|
5889
|
+
}
|
|
5890
|
+
};
|
|
5891
|
+
var GraderRerunTimeoutError = class extends GraderRerunError {
|
|
5892
|
+
constructor(datasetId, run, timeoutMs) {
|
|
5893
|
+
super(
|
|
5894
|
+
`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.`,
|
|
5895
|
+
run
|
|
5896
|
+
);
|
|
5897
|
+
this.name = "GraderRerunTimeoutError";
|
|
5898
|
+
}
|
|
5899
|
+
};
|
|
5900
|
+
function finishedRerun(datasetId, run, joinedExisting) {
|
|
5901
|
+
if (!TERMINAL_RERUN_STATUSES.has(run.status)) {
|
|
5902
|
+
return null;
|
|
5903
|
+
}
|
|
5904
|
+
if (run.status === "errored") {
|
|
5905
|
+
throw new GraderRerunError(
|
|
5906
|
+
`Grader re-run ${run.id} on dataset ${datasetId} errored: ${run.error ?? "no reason recorded"}`,
|
|
5907
|
+
run
|
|
5908
|
+
);
|
|
5909
|
+
}
|
|
5910
|
+
return { run, joinedExisting };
|
|
5911
|
+
}
|
|
5849
5912
|
function sleep(ms) {
|
|
5850
5913
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5851
5914
|
}
|
|
@@ -5945,28 +6008,25 @@ var DatasetsClient = class {
|
|
|
5945
6008
|
{ graderIds }
|
|
5946
6009
|
);
|
|
5947
6010
|
}
|
|
5948
|
-
/**
|
|
5949
|
-
* Re-run graders over every trace in the dataset. Defaults to every assigned
|
|
5950
|
-
* grader; an unassigned id is rejected. Waits for the run to finish (up to
|
|
5951
|
-
* `timeoutMs`, default 90s) unless `wait` is `false`, and returns the last
|
|
5952
|
-
* run state seen either way. A request matching an in-flight run joins it.
|
|
5953
|
-
*/
|
|
5954
6011
|
async rerunGraders(datasetId, options = {}) {
|
|
5955
6012
|
const started = await this.httpClient.request(
|
|
5956
6013
|
datasetPath(datasetId, "/rerunGraders"),
|
|
5957
6014
|
options.graderIds === void 0 ? {} : { graderIds: options.graderIds }
|
|
5958
6015
|
);
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
}
|
|
5962
|
-
const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS);
|
|
5963
|
-
const interval = options.pollIntervalMs ?? DEFAULT_RERUN_POLL_INTERVAL_MS;
|
|
6016
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS;
|
|
6017
|
+
const deadline = Date.now() + timeoutMs;
|
|
5964
6018
|
let run = started.run;
|
|
5965
|
-
while (
|
|
5966
|
-
|
|
6019
|
+
while (true) {
|
|
6020
|
+
const finished = finishedRerun(datasetId, run, started.joinedExisting);
|
|
6021
|
+
if (finished !== null) {
|
|
6022
|
+
return finished;
|
|
6023
|
+
}
|
|
6024
|
+
if (Date.now() >= deadline) {
|
|
6025
|
+
throw new GraderRerunTimeoutError(datasetId, run, timeoutMs);
|
|
6026
|
+
}
|
|
6027
|
+
await sleep(RERUN_POLL_INTERVAL_MS);
|
|
5967
6028
|
run = await this.getGraderRerun(datasetId, run.id) ?? run;
|
|
5968
6029
|
}
|
|
5969
|
-
return { run, joinedExisting: started.joinedExisting };
|
|
5970
6030
|
}
|
|
5971
6031
|
/**
|
|
5972
6032
|
* The dataset's active grader re-run, or the run named by `runId`. Returns
|
|
@@ -6037,6 +6097,7 @@ var GradersClient = class {
|
|
|
6037
6097
|
init_http();
|
|
6038
6098
|
|
|
6039
6099
|
// src/labels.ts
|
|
6100
|
+
init_http();
|
|
6040
6101
|
var LABELS_PATH = "/api/sdk/traces/labels";
|
|
6041
6102
|
var HUMAN_LABELS_PATH = "/api/sdk/traces/labels/human";
|
|
6042
6103
|
function labelEvidencePath(traceId, assertionId) {
|
|
@@ -6046,27 +6107,27 @@ var LabelsClient = class {
|
|
|
6046
6107
|
constructor(httpClient) {
|
|
6047
6108
|
this.httpClient = httpClient;
|
|
6048
6109
|
}
|
|
6049
|
-
async save(update,
|
|
6050
|
-
const [outcome] = await this.saveAll([update],
|
|
6110
|
+
async save(update, experimentId) {
|
|
6111
|
+
const [outcome] = await this.saveAll([update], experimentId);
|
|
6051
6112
|
return outcome;
|
|
6052
6113
|
}
|
|
6053
|
-
async saveAll(updates,
|
|
6114
|
+
async saveAll(updates, experimentId) {
|
|
6054
6115
|
const response = await this.httpClient.request(
|
|
6055
6116
|
LABELS_PATH,
|
|
6056
6117
|
{
|
|
6057
6118
|
labels: updates,
|
|
6058
|
-
...
|
|
6119
|
+
...experimentId === void 0 ? {} : experimentIdWireFields(experimentId)
|
|
6059
6120
|
}
|
|
6060
6121
|
);
|
|
6061
6122
|
return response.labels;
|
|
6062
6123
|
}
|
|
6063
6124
|
/** Withhold a verdict for a trace or replay attempt whose check did not run. */
|
|
6064
|
-
async skip(target,
|
|
6065
|
-
return this.save({ ...target, skip: true },
|
|
6125
|
+
async skip(target, experimentId) {
|
|
6126
|
+
return this.save({ ...target, skip: true }, experimentId);
|
|
6066
6127
|
}
|
|
6067
6128
|
/** Clear a previous verdict for a trace, replay attempt, or assertion. */
|
|
6068
|
-
async archive(target,
|
|
6069
|
-
return this.save({ ...target, archive: true },
|
|
6129
|
+
async archive(target, experimentId) {
|
|
6130
|
+
return this.save({ ...target, archive: true }, experimentId);
|
|
6070
6131
|
}
|
|
6071
6132
|
async saveHuman(update) {
|
|
6072
6133
|
const [outcome] = await this.saveHumanAll([update]);
|
|
@@ -7822,6 +7883,46 @@ init_traceMetadata();
|
|
|
7822
7883
|
// src/traces.ts
|
|
7823
7884
|
var ASSERTIONS_PATH = "/api/sdk/traces/assertions";
|
|
7824
7885
|
var SEARCH_PATH = "/api/sdk/traces/search";
|
|
7886
|
+
var DEFAULT_GENERATION_TIMEOUT_MS = 6e5;
|
|
7887
|
+
var GENERATION_POLL_INTERVAL_MS = 2e3;
|
|
7888
|
+
var AssertionGenerationError = class extends Error {
|
|
7889
|
+
constructor(message, traceId) {
|
|
7890
|
+
super(message);
|
|
7891
|
+
this.traceId = traceId;
|
|
7892
|
+
this.name = "AssertionGenerationError";
|
|
7893
|
+
}
|
|
7894
|
+
};
|
|
7895
|
+
var AssertionGenerationTimeoutError = class extends AssertionGenerationError {
|
|
7896
|
+
constructor(traceId, timeoutMs) {
|
|
7897
|
+
super(
|
|
7898
|
+
`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.`,
|
|
7899
|
+
traceId
|
|
7900
|
+
);
|
|
7901
|
+
this.name = "AssertionGenerationTimeoutError";
|
|
7902
|
+
}
|
|
7903
|
+
};
|
|
7904
|
+
function sleep2(ms) {
|
|
7905
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7906
|
+
}
|
|
7907
|
+
function isGenerationFinished(traceId, generation) {
|
|
7908
|
+
if (generation === null || generation.status === "running") {
|
|
7909
|
+
return false;
|
|
7910
|
+
}
|
|
7911
|
+
if (generation.status === "failed") {
|
|
7912
|
+
throw new AssertionGenerationError(
|
|
7913
|
+
`Assertion generation for trace ${traceId} failed: ${generation.error ?? "no reason recorded"}. Pass regenerate: true to try again.`,
|
|
7914
|
+
traceId
|
|
7915
|
+
);
|
|
7916
|
+
}
|
|
7917
|
+
return true;
|
|
7918
|
+
}
|
|
7919
|
+
function draftsInGenerationOrder(assertions, assertionIds) {
|
|
7920
|
+
const byId = new Map(assertions.map((assertion) => [assertion.id, assertion]));
|
|
7921
|
+
return assertionIds.flatMap((id) => {
|
|
7922
|
+
const assertion = byId.get(id);
|
|
7923
|
+
return assertion === void 0 ? [] : [assertion];
|
|
7924
|
+
});
|
|
7925
|
+
}
|
|
7825
7926
|
function traceAssertionsPath(traceId, suffix = "") {
|
|
7826
7927
|
return `/api/sdk/traces/${encodeURIComponent(traceId)}/assertions${suffix}`;
|
|
7827
7928
|
}
|
|
@@ -7853,6 +7954,34 @@ var TracesClient = class {
|
|
|
7853
7954
|
});
|
|
7854
7955
|
return response.assertions;
|
|
7855
7956
|
}
|
|
7957
|
+
async generateAssertions(traceId, options = {}) {
|
|
7958
|
+
const started = await this.httpClient.request(
|
|
7959
|
+
traceAssertionsPath(traceId, "/generate"),
|
|
7960
|
+
{
|
|
7961
|
+
...options.guidance === void 0 ? {} : { guidance: options.guidance },
|
|
7962
|
+
...options.categoryIds === void 0 ? {} : { categoryIds: options.categoryIds },
|
|
7963
|
+
...options.regenerate === void 0 ? {} : { regenerate: options.regenerate }
|
|
7964
|
+
}
|
|
7965
|
+
);
|
|
7966
|
+
if (isGenerationFinished(traceId, started.generation)) {
|
|
7967
|
+
return started.assertions;
|
|
7968
|
+
}
|
|
7969
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_GENERATION_TIMEOUT_MS;
|
|
7970
|
+
const deadline = Date.now() + timeoutMs;
|
|
7971
|
+
while (true) {
|
|
7972
|
+
if (Date.now() >= deadline) {
|
|
7973
|
+
throw new AssertionGenerationTimeoutError(traceId, timeoutMs);
|
|
7974
|
+
}
|
|
7975
|
+
await sleep2(GENERATION_POLL_INTERVAL_MS);
|
|
7976
|
+
const read2 = await this.getAssertions(traceId);
|
|
7977
|
+
if (isGenerationFinished(traceId, read2.generation)) {
|
|
7978
|
+
return draftsInGenerationOrder(
|
|
7979
|
+
read2.assertions,
|
|
7980
|
+
read2.generation.assertionIds
|
|
7981
|
+
);
|
|
7982
|
+
}
|
|
7983
|
+
}
|
|
7984
|
+
}
|
|
7856
7985
|
async archiveAssertions(params) {
|
|
7857
7986
|
const response = await this.httpClient.request(
|
|
7858
7987
|
traceAssertionsPath(params.traceId, "/archive"),
|
|
@@ -8356,6 +8485,15 @@ var BitfabVercelAiHandler = class {
|
|
|
8356
8485
|
|
|
8357
8486
|
// src/client.ts
|
|
8358
8487
|
init_warnOnce();
|
|
8488
|
+
function resolveSpanExperimentId(options) {
|
|
8489
|
+
const { experimentId, testRunId } = options;
|
|
8490
|
+
if (experimentId !== void 0 && testRunId !== void 0 && experimentId !== testRunId) {
|
|
8491
|
+
throw new BitfabError(
|
|
8492
|
+
`experimentId ("${experimentId}") and its deprecated alias testRunId ("${testRunId}") were both passed with different values. Pass only experimentId.`
|
|
8493
|
+
);
|
|
8494
|
+
}
|
|
8495
|
+
return experimentId ?? testRunId;
|
|
8496
|
+
}
|
|
8359
8497
|
var TRUNCATION_LIMIT_ORDER = [
|
|
8360
8498
|
"max_depth",
|
|
8361
8499
|
"max_captured_subtree_spans"
|
|
@@ -8945,13 +9083,12 @@ var Bitfab = class {
|
|
|
8945
9083
|
"bitfab.node({ capture: false }) cannot use mockOnReplay: true because an uncaptured node has no recorded output."
|
|
8946
9084
|
);
|
|
8947
9085
|
}
|
|
9086
|
+
const experimentId = resolveSpanExperimentId(options);
|
|
8948
9087
|
return {
|
|
8949
9088
|
capture,
|
|
8950
9089
|
type: options.type ?? "custom",
|
|
8951
9090
|
...options.name !== void 0 && { name: options.name },
|
|
8952
|
-
...
|
|
8953
|
-
testRunId: options.testRunId
|
|
8954
|
-
},
|
|
9091
|
+
...experimentId !== void 0 && { experimentId },
|
|
8955
9092
|
...options.mockOnReplay !== void 0 && {
|
|
8956
9093
|
mockOnReplay: options.mockOnReplay
|
|
8957
9094
|
},
|
|
@@ -9086,6 +9223,7 @@ var Bitfab = class {
|
|
|
9086
9223
|
return invokeWithoutNode();
|
|
9087
9224
|
}
|
|
9088
9225
|
const mockOnReplay = nodeConfiguration?.mockOnReplay ?? options.mockOnReplayDefault;
|
|
9226
|
+
const nodeExperimentId = nodeConfiguration === void 0 ? void 0 : resolveSpanExperimentId(nodeConfiguration);
|
|
9089
9227
|
const childOptions = {
|
|
9090
9228
|
name: spanName,
|
|
9091
9229
|
type: nodeConfiguration?.type ?? "function",
|
|
@@ -9096,8 +9234,8 @@ var Bitfab = class {
|
|
|
9096
9234
|
captureContent: true,
|
|
9097
9235
|
autoTraceDefinition: definition,
|
|
9098
9236
|
...declaredNode && { declaredNode },
|
|
9099
|
-
...
|
|
9100
|
-
|
|
9237
|
+
...nodeExperimentId !== void 0 && {
|
|
9238
|
+
experimentId: nodeExperimentId
|
|
9101
9239
|
},
|
|
9102
9240
|
...mockOnReplay !== void 0 && {
|
|
9103
9241
|
mockOnReplay
|
|
@@ -9758,6 +9896,7 @@ var Bitfab = class {
|
|
|
9758
9896
|
const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
|
|
9759
9897
|
const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
9760
9898
|
const self = this;
|
|
9899
|
+
const optionExperimentId = resolveSpanExperimentId(options);
|
|
9761
9900
|
const fnIsAsyncFunction = fn.constructor.name === "AsyncFunction";
|
|
9762
9901
|
const fnReturnsPromise = fnIsAsyncFunction || (() => {
|
|
9763
9902
|
try {
|
|
@@ -9860,7 +9999,7 @@ var Bitfab = class {
|
|
|
9860
9999
|
const inputs = args;
|
|
9861
10000
|
const startedAt = nowIsoTimestamp();
|
|
9862
10001
|
const replayCtxAtStart = getReplayContext();
|
|
9863
|
-
const
|
|
10002
|
+
const experimentId = replayCtxAtStart?.experimentId ?? optionExperimentId;
|
|
9864
10003
|
if (isRootSpan && !activeTraceStates.has(traceId)) {
|
|
9865
10004
|
const dbSnapshotRef = buildSnapshotRef(self.dbSnapshot, startedAt);
|
|
9866
10005
|
self.simulationPlan.refresh();
|
|
@@ -9869,7 +10008,7 @@ var Bitfab = class {
|
|
|
9869
10008
|
traceFunctionKey,
|
|
9870
10009
|
startedAt,
|
|
9871
10010
|
contexts: [],
|
|
9872
|
-
...
|
|
10011
|
+
...experimentId !== void 0 && { experimentId },
|
|
9873
10012
|
...replayCtxAtStart?.inputSourceTraceId && {
|
|
9874
10013
|
inputSourceTraceId: replayCtxAtStart.inputSourceTraceId
|
|
9875
10014
|
},
|
|
@@ -9915,7 +10054,7 @@ var Bitfab = class {
|
|
|
9915
10054
|
contexts: newContext.contexts,
|
|
9916
10055
|
prompt: newContext.prompt,
|
|
9917
10056
|
endedAt,
|
|
9918
|
-
...
|
|
10057
|
+
...experimentId !== void 0 && { experimentId },
|
|
9919
10058
|
...replayCtx?.inputSourceSpanId && {
|
|
9920
10059
|
inputSourceSpanId: replayCtx.inputSourceSpanId
|
|
9921
10060
|
}
|
|
@@ -9936,7 +10075,7 @@ var Bitfab = class {
|
|
|
9936
10075
|
name: traceState?.name,
|
|
9937
10076
|
metadata: callerTraceMetadata(traceId),
|
|
9938
10077
|
contexts: traceState?.contexts ?? [],
|
|
9939
|
-
|
|
10078
|
+
experimentId: traceState?.experimentId,
|
|
9940
10079
|
inputSourceTraceId: traceState?.inputSourceTraceId,
|
|
9941
10080
|
replayAttempt: traceState?.replayAttempt,
|
|
9942
10081
|
dbSnapshotRef: traceState?.dbSnapshotRef,
|
|
@@ -10407,7 +10546,7 @@ var Bitfab = class {
|
|
|
10407
10546
|
completed: true,
|
|
10408
10547
|
...params.dropped && { dropped: true },
|
|
10409
10548
|
...params.sessionId && { sessionId: params.sessionId },
|
|
10410
|
-
...params.
|
|
10549
|
+
...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId)
|
|
10411
10550
|
});
|
|
10412
10551
|
}
|
|
10413
10552
|
sendsSpanOnCompletion(context) {
|
|
@@ -10519,7 +10658,7 @@ var Bitfab = class {
|
|
|
10519
10658
|
},
|
|
10520
10659
|
...params.declaredNode === true && { [DECLARED_NODE_FIELD]: true },
|
|
10521
10660
|
rawSpan: externalSpan,
|
|
10522
|
-
...params.
|
|
10661
|
+
...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId),
|
|
10523
10662
|
...params.mocked && { mocked: true },
|
|
10524
10663
|
...params.mockTarget && { mockTarget: params.mockTarget },
|
|
10525
10664
|
...params.mockSource && { mockSource: params.mockSource }
|
|
@@ -11071,6 +11210,8 @@ function resolveTraceFunctionKey(registration) {
|
|
|
11071
11210
|
// Annotate the CommonJS export names for ESM import in node:
|
|
11072
11211
|
0 && (module.exports = {
|
|
11073
11212
|
AssertionCategoriesClient,
|
|
11213
|
+
AssertionGenerationError,
|
|
11214
|
+
AssertionGenerationTimeoutError,
|
|
11074
11215
|
BITFAB_PROGRESS_PREFIX,
|
|
11075
11216
|
Bitfab,
|
|
11076
11217
|
BitfabClaudeAgentHandler,
|
|
@@ -11086,6 +11227,8 @@ function resolveTraceFunctionKey(registration) {
|
|
|
11086
11227
|
DEFAULT_SERVICE_URL,
|
|
11087
11228
|
DatasetsClient,
|
|
11088
11229
|
DbBranchReplayError,
|
|
11230
|
+
GraderRerunError,
|
|
11231
|
+
GraderRerunTimeoutError,
|
|
11089
11232
|
GradersClient,
|
|
11090
11233
|
HttpClient,
|
|
11091
11234
|
LabelsClient,
|