@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/node.cjs
CHANGED
|
@@ -88,7 +88,7 @@ var __version__, __packageName__;
|
|
|
88
88
|
var init_version_generated = __esm({
|
|
89
89
|
"src/version.generated.ts"() {
|
|
90
90
|
"use strict";
|
|
91
|
-
__version__ = "0.
|
|
91
|
+
__version__ = "0.59.1";
|
|
92
92
|
__packageName__ = "@bitfab/sdk";
|
|
93
93
|
}
|
|
94
94
|
});
|
|
@@ -2111,6 +2111,7 @@ __export(http_exports, {
|
|
|
2111
2111
|
HttpClient: () => HttpClient,
|
|
2112
2112
|
awaitOnExit: () => awaitOnExit,
|
|
2113
2113
|
awaitPendingRequests: () => awaitPendingRequests,
|
|
2114
|
+
experimentIdWireFields: () => experimentIdWireFields,
|
|
2114
2115
|
flushTraces: () => flushTraces,
|
|
2115
2116
|
parseRetryAfterMs: () => parseRetryAfterMs,
|
|
2116
2117
|
serializePayloadBody: () => serializePayloadBody
|
|
@@ -2279,6 +2280,9 @@ function warnDroppedExternalTrace(error) {
|
|
|
2279
2280
|
`a trace was dropped because the send step failed: ${describeError(error)}`
|
|
2280
2281
|
);
|
|
2281
2282
|
}
|
|
2283
|
+
function experimentIdWireFields(experimentId) {
|
|
2284
|
+
return { experimentId, testRunId: experimentId };
|
|
2285
|
+
}
|
|
2282
2286
|
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;
|
|
2283
2287
|
var init_http = __esm({
|
|
2284
2288
|
"src/http.ts"() {
|
|
@@ -2883,7 +2887,7 @@ var init_http = __esm({
|
|
|
2883
2887
|
}
|
|
2884
2888
|
/**
|
|
2885
2889
|
* Start a replay session by fetching historical traces.
|
|
2886
|
-
* Blocking call - creates
|
|
2890
|
+
* Blocking call - creates an experiment and returns lightweight item references.
|
|
2887
2891
|
*/
|
|
2888
2892
|
async startReplay(traceFunctionKey, limit, traceIds, name, codeChangeDescription, codeChangeFiles, includeDbBranchLease, experimentGroupId, datasetIds, graderIds, dbBranchSettings, attempts, includeOriginalMetadata, onlyWithAssertions, judgeAssertions) {
|
|
2889
2893
|
const payload = { traceFunctionKey };
|
|
@@ -2939,9 +2943,20 @@ var init_http = __esm({
|
|
|
2939
2943
|
payload.git = git;
|
|
2940
2944
|
}
|
|
2941
2945
|
const timeout = includeDbBranchLease ? REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS : 3e4;
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2946
|
+
const response = await this.request(
|
|
2947
|
+
"/api/sdk/replay/start",
|
|
2948
|
+
payload,
|
|
2949
|
+
{ timeout }
|
|
2950
|
+
);
|
|
2951
|
+
const { testRunId, testRunUrl, ...rest } = response;
|
|
2952
|
+
const experimentId = response.experimentId ?? testRunId;
|
|
2953
|
+
const experimentUrl = response.experimentUrl ?? testRunUrl;
|
|
2954
|
+
if (experimentId === void 0 || experimentUrl === void 0) {
|
|
2955
|
+
throw new BitfabError(
|
|
2956
|
+
"Replay start response is missing the experiment ID or URL."
|
|
2957
|
+
);
|
|
2958
|
+
}
|
|
2959
|
+
return { ...rest, experimentId, experimentUrl };
|
|
2945
2960
|
}
|
|
2946
2961
|
/**
|
|
2947
2962
|
* Fetch an external span by ID.
|
|
@@ -3038,21 +3053,21 @@ var init_http = __esm({
|
|
|
3038
3053
|
* has a final status AND at least that many persisted spans, which is what
|
|
3039
3054
|
* makes this a real barrier rather than a "the row exists" check.
|
|
3040
3055
|
*/
|
|
3041
|
-
async getReplayStatus(
|
|
3056
|
+
async getReplayStatus(experimentId, expectedSpanCounts) {
|
|
3042
3057
|
return this.request(
|
|
3043
3058
|
"/api/sdk/replay/status",
|
|
3044
|
-
{
|
|
3059
|
+
{ ...experimentIdWireFields(experimentId), expectedSpanCounts },
|
|
3045
3060
|
{ timeout: 3e4 }
|
|
3046
3061
|
);
|
|
3047
3062
|
}
|
|
3048
3063
|
/**
|
|
3049
|
-
* Mark a replay
|
|
3064
|
+
* Mark a replay experiment as completed.
|
|
3050
3065
|
* Blocking call.
|
|
3051
3066
|
*/
|
|
3052
|
-
async completeReplay(
|
|
3067
|
+
async completeReplay(experimentId) {
|
|
3053
3068
|
return this.request(
|
|
3054
3069
|
"/api/sdk/replay/complete",
|
|
3055
|
-
|
|
3070
|
+
experimentIdWireFields(experimentId),
|
|
3056
3071
|
{ timeout: REPLAY_COMPLETE_REQUEST_TIMEOUT_MS }
|
|
3057
3072
|
);
|
|
3058
3073
|
}
|
|
@@ -3074,11 +3089,11 @@ var init_http = __esm({
|
|
|
3074
3089
|
* snapshot + preview branch and polls operations to readiness, which
|
|
3075
3090
|
* can take seconds.
|
|
3076
3091
|
*/
|
|
3077
|
-
async resolveDbBranchLease(
|
|
3092
|
+
async resolveDbBranchLease(experimentId, traceId, dbBranchSettings, attempt) {
|
|
3078
3093
|
return this.request(
|
|
3079
3094
|
"/api/sdk/replay/resolveDbBranchLease",
|
|
3080
3095
|
{
|
|
3081
|
-
|
|
3096
|
+
...experimentIdWireFields(experimentId),
|
|
3082
3097
|
traceId,
|
|
3083
3098
|
dbBranchSettings,
|
|
3084
3099
|
...attempt !== void 0 && attempt > 0 ? { attempt } : {}
|
|
@@ -3667,7 +3682,7 @@ function replayJsonReplacer(_key, value) {
|
|
|
3667
3682
|
function serializeReplayResult(result) {
|
|
3668
3683
|
return JSON.stringify(result, replayJsonReplacer, 2);
|
|
3669
3684
|
}
|
|
3670
|
-
async function preserveReplayFailure(operation, items,
|
|
3685
|
+
async function preserveReplayFailure(operation, items, experimentId, experimentUrl) {
|
|
3671
3686
|
try {
|
|
3672
3687
|
return await operation();
|
|
3673
3688
|
} catch (cause) {
|
|
@@ -3677,8 +3692,8 @@ async function preserveReplayFailure(operation, items, testRunId, testRunUrl) {
|
|
|
3677
3692
|
throw new ReplayError(
|
|
3678
3693
|
errorMessage(cause),
|
|
3679
3694
|
items,
|
|
3680
|
-
|
|
3681
|
-
|
|
3695
|
+
experimentId,
|
|
3696
|
+
experimentUrl,
|
|
3682
3697
|
cause
|
|
3683
3698
|
);
|
|
3684
3699
|
}
|
|
@@ -3732,7 +3747,7 @@ function buildMockTree(rootNode) {
|
|
|
3732
3747
|
}
|
|
3733
3748
|
return { spans };
|
|
3734
3749
|
}
|
|
3735
|
-
async function processItem(httpClient, serverItem, fn,
|
|
3750
|
+
async function processItem(httpClient, serverItem, fn, experimentId, mockStrategy, resolvedOverrides, replayedTraceId, attempt, includeDbBranchLease, dbBranchSettings, adaptInputs, dryRun) {
|
|
3736
3751
|
let lease = includeDbBranchLease ? serverItem.dbBranchLease : void 0;
|
|
3737
3752
|
let leaseError = includeDbBranchLease ? serverItem.dbBranchLeaseError : void 0;
|
|
3738
3753
|
let dbSnapshotRef = serverItem.dbSnapshotRef;
|
|
@@ -3752,7 +3767,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
3752
3767
|
let resolved2;
|
|
3753
3768
|
try {
|
|
3754
3769
|
resolved2 = await httpClient.resolveDbBranchLease(
|
|
3755
|
-
|
|
3770
|
+
experimentId,
|
|
3756
3771
|
originalTraceId,
|
|
3757
3772
|
dbBranchSettings,
|
|
3758
3773
|
attempt
|
|
@@ -3864,7 +3879,7 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
3864
3879
|
replayStarted = performance.now();
|
|
3865
3880
|
const maybePromise = runWithReplayContext(
|
|
3866
3881
|
{
|
|
3867
|
-
|
|
3882
|
+
experimentId,
|
|
3868
3883
|
traceId: replayedTraceId,
|
|
3869
3884
|
inputSourceSpanId: span.id,
|
|
3870
3885
|
inputSourceTraceId: span.externalTraceId,
|
|
@@ -3947,14 +3962,14 @@ async function processItem(httpClient, serverItem, fn, testRunId, mockStrategy,
|
|
|
3947
3962
|
originalTraceOutline: null
|
|
3948
3963
|
};
|
|
3949
3964
|
}
|
|
3950
|
-
async function waitForReplayPersistence(httpClient,
|
|
3965
|
+
async function waitForReplayPersistence(httpClient, experimentId, replayedTraceIds) {
|
|
3951
3966
|
const deferredSettled = await httpClient.settleDeferredWork(
|
|
3952
3967
|
REPLAY_PERSISTENCE_TIMEOUT_MS
|
|
3953
3968
|
);
|
|
3954
3969
|
if (!deferredSettled) {
|
|
3955
3970
|
httpClient.takeTraceDeliveries(replayedTraceIds);
|
|
3956
3971
|
throw new BitfabError(
|
|
3957
|
-
`Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (
|
|
3972
|
+
`Replay could not settle deferred span work before the deadline, so the expected span counts are incomplete (experiment ${experimentId}).`
|
|
3958
3973
|
);
|
|
3959
3974
|
}
|
|
3960
3975
|
if (!httpClient.hasClosedDeliveries(replayedTraceIds)) {
|
|
@@ -3983,7 +3998,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
3983
3998
|
let missing = Object.keys(expectedSpanCounts).length;
|
|
3984
3999
|
while (true) {
|
|
3985
4000
|
const status = await httpClient.getReplayStatus(
|
|
3986
|
-
|
|
4001
|
+
experimentId,
|
|
3987
4002
|
expectedSpanCounts
|
|
3988
4003
|
);
|
|
3989
4004
|
const ready = status.traceIds ?? {};
|
|
@@ -4002,7 +4017,7 @@ async function waitForReplayPersistence(httpClient, testRunId, replayedTraceIds)
|
|
|
4002
4017
|
}
|
|
4003
4018
|
const cause = flushed ? "" : " Delivery was also not confirmed before the flush deadline, so the spans likely never reached the server.";
|
|
4004
4019
|
throw new BitfabError(
|
|
4005
|
-
`Replay traces were not fully persisted before the delivery deadline (
|
|
4020
|
+
`Replay traces were not fully persisted before the delivery deadline (experiment ${experimentId}, missing ${missing} of ${Object.keys(expectedSpanCounts).length} trace(s)).${cause}`
|
|
4006
4021
|
);
|
|
4007
4022
|
}
|
|
4008
4023
|
function sleepForReplayPersistence(ms) {
|
|
@@ -4069,8 +4084,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4069
4084
|
}
|
|
4070
4085
|
}
|
|
4071
4086
|
const {
|
|
4072
|
-
|
|
4073
|
-
|
|
4087
|
+
experimentId,
|
|
4088
|
+
experimentUrl,
|
|
4074
4089
|
items: serverItems
|
|
4075
4090
|
} = await httpClient.startReplay(
|
|
4076
4091
|
traceFunctionKey,
|
|
@@ -4103,7 +4118,14 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4103
4118
|
}
|
|
4104
4119
|
}
|
|
4105
4120
|
const mockStrategy = options?.mock ?? "marked";
|
|
4106
|
-
const
|
|
4121
|
+
const fullExperimentUrl = `${serviceUrl}${experimentUrl}`;
|
|
4122
|
+
try {
|
|
4123
|
+
options?.onExperimentStart?.({
|
|
4124
|
+
experimentId,
|
|
4125
|
+
experimentUrl: fullExperimentUrl
|
|
4126
|
+
});
|
|
4127
|
+
} catch {
|
|
4128
|
+
}
|
|
4107
4129
|
const resolvedOverrides = [
|
|
4108
4130
|
...normalizeMockOverrides(options?.mockOverride),
|
|
4109
4131
|
...registeredOverrides
|
|
@@ -4116,7 +4138,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4116
4138
|
httpClient,
|
|
4117
4139
|
serverItem,
|
|
4118
4140
|
fn,
|
|
4119
|
-
|
|
4141
|
+
experimentId,
|
|
4120
4142
|
mockStrategy,
|
|
4121
4143
|
resolvedOverrides,
|
|
4122
4144
|
replayedTraceIds[index],
|
|
@@ -4171,7 +4193,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4171
4193
|
}
|
|
4172
4194
|
try {
|
|
4173
4195
|
onItemFinish?.({
|
|
4174
|
-
|
|
4196
|
+
experimentId,
|
|
4197
|
+
testRunId: experimentId,
|
|
4175
4198
|
completed,
|
|
4176
4199
|
total,
|
|
4177
4200
|
succeeded,
|
|
@@ -4219,7 +4242,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4219
4242
|
try {
|
|
4220
4243
|
options.onItemStart?.({
|
|
4221
4244
|
type: "started",
|
|
4222
|
-
|
|
4245
|
+
experimentId,
|
|
4246
|
+
testRunId: experimentId,
|
|
4223
4247
|
started,
|
|
4224
4248
|
completed,
|
|
4225
4249
|
total,
|
|
@@ -4238,21 +4262,23 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4238
4262
|
} : void 0
|
|
4239
4263
|
);
|
|
4240
4264
|
if (options?.dryRun === true) {
|
|
4241
|
-
await httpClient.completeReplay(
|
|
4265
|
+
await httpClient.completeReplay(experimentId).catch(() => void 0);
|
|
4242
4266
|
const dryResult = {
|
|
4243
4267
|
items: resultItems,
|
|
4244
|
-
|
|
4245
|
-
|
|
4268
|
+
experimentId,
|
|
4269
|
+
experimentUrl: fullExperimentUrl,
|
|
4270
|
+
testRunId: experimentId,
|
|
4271
|
+
testRunUrl: fullExperimentUrl,
|
|
4246
4272
|
attempts
|
|
4247
4273
|
};
|
|
4248
4274
|
await writeReplayResultFile(dryResult);
|
|
4249
4275
|
return dryResult;
|
|
4250
4276
|
}
|
|
4251
4277
|
const deliveredTraceIds = await preserveReplayFailure(
|
|
4252
|
-
() => waitForReplayPersistence(httpClient,
|
|
4278
|
+
() => waitForReplayPersistence(httpClient, experimentId, replayedTraceIds),
|
|
4253
4279
|
resultItems,
|
|
4254
|
-
|
|
4255
|
-
|
|
4280
|
+
experimentId,
|
|
4281
|
+
fullExperimentUrl
|
|
4256
4282
|
);
|
|
4257
4283
|
for (let index = 0; index < resultItems.length; index += 1) {
|
|
4258
4284
|
const localId = replayedTraceIds[index];
|
|
@@ -4262,10 +4288,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4262
4288
|
}
|
|
4263
4289
|
}
|
|
4264
4290
|
const completeResult = await preserveReplayFailure(
|
|
4265
|
-
() => httpClient.completeReplay(
|
|
4291
|
+
() => httpClient.completeReplay(experimentId),
|
|
4266
4292
|
resultItems,
|
|
4267
|
-
|
|
4268
|
-
|
|
4293
|
+
experimentId,
|
|
4294
|
+
fullExperimentUrl
|
|
4269
4295
|
);
|
|
4270
4296
|
const serverTraceIds = completeResult.traceIds;
|
|
4271
4297
|
const replayTokens = completeResult.tokens;
|
|
@@ -4292,20 +4318,20 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4292
4318
|
if (completedCount > 0 && missing.length === completedCount) {
|
|
4293
4319
|
const serverCount = completeResult.traceCount !== void 0 ? ` The server persisted ${completeResult.traceCount} trace(s) for this run.` : "";
|
|
4294
4320
|
const cause = new BitfabError(
|
|
4295
|
-
`Replay completed but the server has no persisted trace for any of the ${completedCount} completed item(s) (
|
|
4321
|
+
`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.`
|
|
4296
4322
|
);
|
|
4297
4323
|
throw new ReplayError(
|
|
4298
4324
|
cause.message,
|
|
4299
4325
|
resultItems,
|
|
4300
|
-
|
|
4301
|
-
|
|
4326
|
+
experimentId,
|
|
4327
|
+
fullExperimentUrl,
|
|
4302
4328
|
cause
|
|
4303
4329
|
);
|
|
4304
4330
|
}
|
|
4305
4331
|
if (missing.length > 0) {
|
|
4306
4332
|
try {
|
|
4307
4333
|
console.error(
|
|
4308
|
-
`Bitfab: server has no persisted trace for ${missing.length} of ${completedCount} completed replay item(s) (
|
|
4334
|
+
`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.`
|
|
4309
4335
|
);
|
|
4310
4336
|
} catch {
|
|
4311
4337
|
}
|
|
@@ -4313,8 +4339,10 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4313
4339
|
}
|
|
4314
4340
|
const result = {
|
|
4315
4341
|
items: resultItems,
|
|
4316
|
-
|
|
4317
|
-
|
|
4342
|
+
experimentId,
|
|
4343
|
+
experimentUrl: fullExperimentUrl,
|
|
4344
|
+
testRunId: experimentId,
|
|
4345
|
+
testRunUrl: fullExperimentUrl,
|
|
4318
4346
|
attempts
|
|
4319
4347
|
};
|
|
4320
4348
|
await writeReplayResultFile(result);
|
|
@@ -4322,7 +4350,8 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4322
4350
|
try {
|
|
4323
4351
|
options?.onProgress?.({
|
|
4324
4352
|
type: "complete",
|
|
4325
|
-
|
|
4353
|
+
experimentId,
|
|
4354
|
+
testRunId: experimentId,
|
|
4326
4355
|
completed: total,
|
|
4327
4356
|
total,
|
|
4328
4357
|
succeeded,
|
|
@@ -4372,13 +4401,15 @@ var init_replay = __esm({
|
|
|
4372
4401
|
MAX_REPLAY_ATTEMPTS = 100;
|
|
4373
4402
|
BITFAB_PROGRESS_PREFIX = "@@bitfab:progress ";
|
|
4374
4403
|
ReplayError = class extends BitfabError {
|
|
4375
|
-
constructor(message, items,
|
|
4376
|
-
super(message,
|
|
4404
|
+
constructor(message, items, experimentId, experimentUrl, cause) {
|
|
4405
|
+
super(message, experimentUrl);
|
|
4377
4406
|
this.items = items;
|
|
4378
|
-
this.
|
|
4379
|
-
this.
|
|
4407
|
+
this.experimentId = experimentId;
|
|
4408
|
+
this.experimentUrl = experimentUrl;
|
|
4380
4409
|
this.cause = cause;
|
|
4381
4410
|
this.name = "ReplayError";
|
|
4411
|
+
this.testRunId = experimentId;
|
|
4412
|
+
this.testRunUrl = experimentUrl;
|
|
4382
4413
|
}
|
|
4383
4414
|
};
|
|
4384
4415
|
DbBranchReplayError = class extends BitfabError {
|
|
@@ -4397,6 +4428,8 @@ var init_replay = __esm({
|
|
|
4397
4428
|
var node_exports = {};
|
|
4398
4429
|
__export(node_exports, {
|
|
4399
4430
|
AssertionCategoriesClient: () => AssertionCategoriesClient,
|
|
4431
|
+
AssertionGenerationError: () => AssertionGenerationError,
|
|
4432
|
+
AssertionGenerationTimeoutError: () => AssertionGenerationTimeoutError,
|
|
4400
4433
|
BITFAB_PROGRESS_PREFIX: () => BITFAB_PROGRESS_PREFIX,
|
|
4401
4434
|
Bitfab: () => Bitfab,
|
|
4402
4435
|
BitfabClaudeAgentHandler: () => BitfabClaudeAgentHandler,
|
|
@@ -4412,6 +4445,8 @@ __export(node_exports, {
|
|
|
4412
4445
|
DEFAULT_SERVICE_URL: () => DEFAULT_SERVICE_URL,
|
|
4413
4446
|
DatasetsClient: () => DatasetsClient,
|
|
4414
4447
|
DbBranchReplayError: () => DbBranchReplayError,
|
|
4448
|
+
GraderRerunError: () => GraderRerunError,
|
|
4449
|
+
GraderRerunTimeoutError: () => GraderRerunTimeoutError,
|
|
4415
4450
|
GradersClient: () => GradersClient,
|
|
4416
4451
|
HttpClient: () => HttpClient,
|
|
4417
4452
|
LabelsClient: () => LabelsClient,
|
|
@@ -5846,11 +5881,39 @@ init_constants();
|
|
|
5846
5881
|
|
|
5847
5882
|
// src/datasets.ts
|
|
5848
5883
|
var DEFAULT_RERUN_TIMEOUT_MS = 9e4;
|
|
5849
|
-
var
|
|
5884
|
+
var RERUN_POLL_INTERVAL_MS = 1e3;
|
|
5850
5885
|
var TERMINAL_RERUN_STATUSES = /* @__PURE__ */ new Set([
|
|
5851
5886
|
"completed",
|
|
5852
5887
|
"errored"
|
|
5853
5888
|
]);
|
|
5889
|
+
var GraderRerunError = class extends Error {
|
|
5890
|
+
constructor(message, run) {
|
|
5891
|
+
super(message);
|
|
5892
|
+
this.run = run;
|
|
5893
|
+
this.name = "GraderRerunError";
|
|
5894
|
+
}
|
|
5895
|
+
};
|
|
5896
|
+
var GraderRerunTimeoutError = class extends GraderRerunError {
|
|
5897
|
+
constructor(datasetId, run, timeoutMs) {
|
|
5898
|
+
super(
|
|
5899
|
+
`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.`,
|
|
5900
|
+
run
|
|
5901
|
+
);
|
|
5902
|
+
this.name = "GraderRerunTimeoutError";
|
|
5903
|
+
}
|
|
5904
|
+
};
|
|
5905
|
+
function finishedRerun(datasetId, run, joinedExisting) {
|
|
5906
|
+
if (!TERMINAL_RERUN_STATUSES.has(run.status)) {
|
|
5907
|
+
return null;
|
|
5908
|
+
}
|
|
5909
|
+
if (run.status === "errored") {
|
|
5910
|
+
throw new GraderRerunError(
|
|
5911
|
+
`Grader re-run ${run.id} on dataset ${datasetId} errored: ${run.error ?? "no reason recorded"}`,
|
|
5912
|
+
run
|
|
5913
|
+
);
|
|
5914
|
+
}
|
|
5915
|
+
return { run, joinedExisting };
|
|
5916
|
+
}
|
|
5854
5917
|
function sleep(ms) {
|
|
5855
5918
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5856
5919
|
}
|
|
@@ -5950,28 +6013,25 @@ var DatasetsClient = class {
|
|
|
5950
6013
|
{ graderIds }
|
|
5951
6014
|
);
|
|
5952
6015
|
}
|
|
5953
|
-
/**
|
|
5954
|
-
* Re-run graders over every trace in the dataset. Defaults to every assigned
|
|
5955
|
-
* grader; an unassigned id is rejected. Waits for the run to finish (up to
|
|
5956
|
-
* `timeoutMs`, default 90s) unless `wait` is `false`, and returns the last
|
|
5957
|
-
* run state seen either way. A request matching an in-flight run joins it.
|
|
5958
|
-
*/
|
|
5959
6016
|
async rerunGraders(datasetId, options = {}) {
|
|
5960
6017
|
const started = await this.httpClient.request(
|
|
5961
6018
|
datasetPath(datasetId, "/rerunGraders"),
|
|
5962
6019
|
options.graderIds === void 0 ? {} : { graderIds: options.graderIds }
|
|
5963
6020
|
);
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
}
|
|
5967
|
-
const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS);
|
|
5968
|
-
const interval = options.pollIntervalMs ?? DEFAULT_RERUN_POLL_INTERVAL_MS;
|
|
6021
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS;
|
|
6022
|
+
const deadline = Date.now() + timeoutMs;
|
|
5969
6023
|
let run = started.run;
|
|
5970
|
-
while (
|
|
5971
|
-
|
|
6024
|
+
while (true) {
|
|
6025
|
+
const finished = finishedRerun(datasetId, run, started.joinedExisting);
|
|
6026
|
+
if (finished !== null) {
|
|
6027
|
+
return finished;
|
|
6028
|
+
}
|
|
6029
|
+
if (Date.now() >= deadline) {
|
|
6030
|
+
throw new GraderRerunTimeoutError(datasetId, run, timeoutMs);
|
|
6031
|
+
}
|
|
6032
|
+
await sleep(RERUN_POLL_INTERVAL_MS);
|
|
5972
6033
|
run = await this.getGraderRerun(datasetId, run.id) ?? run;
|
|
5973
6034
|
}
|
|
5974
|
-
return { run, joinedExisting: started.joinedExisting };
|
|
5975
6035
|
}
|
|
5976
6036
|
/**
|
|
5977
6037
|
* The dataset's active grader re-run, or the run named by `runId`. Returns
|
|
@@ -6042,6 +6102,7 @@ var GradersClient = class {
|
|
|
6042
6102
|
init_http();
|
|
6043
6103
|
|
|
6044
6104
|
// src/labels.ts
|
|
6105
|
+
init_http();
|
|
6045
6106
|
var LABELS_PATH = "/api/sdk/traces/labels";
|
|
6046
6107
|
var HUMAN_LABELS_PATH = "/api/sdk/traces/labels/human";
|
|
6047
6108
|
function labelEvidencePath(traceId, assertionId) {
|
|
@@ -6051,27 +6112,27 @@ var LabelsClient = class {
|
|
|
6051
6112
|
constructor(httpClient) {
|
|
6052
6113
|
this.httpClient = httpClient;
|
|
6053
6114
|
}
|
|
6054
|
-
async save(update,
|
|
6055
|
-
const [outcome] = await this.saveAll([update],
|
|
6115
|
+
async save(update, experimentId) {
|
|
6116
|
+
const [outcome] = await this.saveAll([update], experimentId);
|
|
6056
6117
|
return outcome;
|
|
6057
6118
|
}
|
|
6058
|
-
async saveAll(updates,
|
|
6119
|
+
async saveAll(updates, experimentId) {
|
|
6059
6120
|
const response = await this.httpClient.request(
|
|
6060
6121
|
LABELS_PATH,
|
|
6061
6122
|
{
|
|
6062
6123
|
labels: updates,
|
|
6063
|
-
...
|
|
6124
|
+
...experimentId === void 0 ? {} : experimentIdWireFields(experimentId)
|
|
6064
6125
|
}
|
|
6065
6126
|
);
|
|
6066
6127
|
return response.labels;
|
|
6067
6128
|
}
|
|
6068
6129
|
/** Withhold a verdict for a trace or replay attempt whose check did not run. */
|
|
6069
|
-
async skip(target,
|
|
6070
|
-
return this.save({ ...target, skip: true },
|
|
6130
|
+
async skip(target, experimentId) {
|
|
6131
|
+
return this.save({ ...target, skip: true }, experimentId);
|
|
6071
6132
|
}
|
|
6072
6133
|
/** Clear a previous verdict for a trace, replay attempt, or assertion. */
|
|
6073
|
-
async archive(target,
|
|
6074
|
-
return this.save({ ...target, archive: true },
|
|
6134
|
+
async archive(target, experimentId) {
|
|
6135
|
+
return this.save({ ...target, archive: true }, experimentId);
|
|
6075
6136
|
}
|
|
6076
6137
|
async saveHuman(update) {
|
|
6077
6138
|
const [outcome] = await this.saveHumanAll([update]);
|
|
@@ -7827,6 +7888,46 @@ init_traceMetadata();
|
|
|
7827
7888
|
// src/traces.ts
|
|
7828
7889
|
var ASSERTIONS_PATH = "/api/sdk/traces/assertions";
|
|
7829
7890
|
var SEARCH_PATH = "/api/sdk/traces/search";
|
|
7891
|
+
var DEFAULT_GENERATION_TIMEOUT_MS = 6e5;
|
|
7892
|
+
var GENERATION_POLL_INTERVAL_MS = 2e3;
|
|
7893
|
+
var AssertionGenerationError = class extends Error {
|
|
7894
|
+
constructor(message, traceId) {
|
|
7895
|
+
super(message);
|
|
7896
|
+
this.traceId = traceId;
|
|
7897
|
+
this.name = "AssertionGenerationError";
|
|
7898
|
+
}
|
|
7899
|
+
};
|
|
7900
|
+
var AssertionGenerationTimeoutError = class extends AssertionGenerationError {
|
|
7901
|
+
constructor(traceId, timeoutMs) {
|
|
7902
|
+
super(
|
|
7903
|
+
`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.`,
|
|
7904
|
+
traceId
|
|
7905
|
+
);
|
|
7906
|
+
this.name = "AssertionGenerationTimeoutError";
|
|
7907
|
+
}
|
|
7908
|
+
};
|
|
7909
|
+
function sleep2(ms) {
|
|
7910
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7911
|
+
}
|
|
7912
|
+
function isGenerationFinished(traceId, generation) {
|
|
7913
|
+
if (generation === null || generation.status === "running") {
|
|
7914
|
+
return false;
|
|
7915
|
+
}
|
|
7916
|
+
if (generation.status === "failed") {
|
|
7917
|
+
throw new AssertionGenerationError(
|
|
7918
|
+
`Assertion generation for trace ${traceId} failed: ${generation.error ?? "no reason recorded"}. Pass regenerate: true to try again.`,
|
|
7919
|
+
traceId
|
|
7920
|
+
);
|
|
7921
|
+
}
|
|
7922
|
+
return true;
|
|
7923
|
+
}
|
|
7924
|
+
function draftsInGenerationOrder(assertions, assertionIds) {
|
|
7925
|
+
const byId = new Map(assertions.map((assertion) => [assertion.id, assertion]));
|
|
7926
|
+
return assertionIds.flatMap((id) => {
|
|
7927
|
+
const assertion = byId.get(id);
|
|
7928
|
+
return assertion === void 0 ? [] : [assertion];
|
|
7929
|
+
});
|
|
7930
|
+
}
|
|
7830
7931
|
function traceAssertionsPath(traceId, suffix = "") {
|
|
7831
7932
|
return `/api/sdk/traces/${encodeURIComponent(traceId)}/assertions${suffix}`;
|
|
7832
7933
|
}
|
|
@@ -7858,6 +7959,34 @@ var TracesClient = class {
|
|
|
7858
7959
|
});
|
|
7859
7960
|
return response.assertions;
|
|
7860
7961
|
}
|
|
7962
|
+
async generateAssertions(traceId, options = {}) {
|
|
7963
|
+
const started = await this.httpClient.request(
|
|
7964
|
+
traceAssertionsPath(traceId, "/generate"),
|
|
7965
|
+
{
|
|
7966
|
+
...options.guidance === void 0 ? {} : { guidance: options.guidance },
|
|
7967
|
+
...options.categoryIds === void 0 ? {} : { categoryIds: options.categoryIds },
|
|
7968
|
+
...options.regenerate === void 0 ? {} : { regenerate: options.regenerate }
|
|
7969
|
+
}
|
|
7970
|
+
);
|
|
7971
|
+
if (isGenerationFinished(traceId, started.generation)) {
|
|
7972
|
+
return started.assertions;
|
|
7973
|
+
}
|
|
7974
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_GENERATION_TIMEOUT_MS;
|
|
7975
|
+
const deadline = Date.now() + timeoutMs;
|
|
7976
|
+
while (true) {
|
|
7977
|
+
if (Date.now() >= deadline) {
|
|
7978
|
+
throw new AssertionGenerationTimeoutError(traceId, timeoutMs);
|
|
7979
|
+
}
|
|
7980
|
+
await sleep2(GENERATION_POLL_INTERVAL_MS);
|
|
7981
|
+
const read2 = await this.getAssertions(traceId);
|
|
7982
|
+
if (isGenerationFinished(traceId, read2.generation)) {
|
|
7983
|
+
return draftsInGenerationOrder(
|
|
7984
|
+
read2.assertions,
|
|
7985
|
+
read2.generation.assertionIds
|
|
7986
|
+
);
|
|
7987
|
+
}
|
|
7988
|
+
}
|
|
7989
|
+
}
|
|
7861
7990
|
async archiveAssertions(params) {
|
|
7862
7991
|
const response = await this.httpClient.request(
|
|
7863
7992
|
traceAssertionsPath(params.traceId, "/archive"),
|
|
@@ -8361,6 +8490,15 @@ var BitfabVercelAiHandler = class {
|
|
|
8361
8490
|
|
|
8362
8491
|
// src/client.ts
|
|
8363
8492
|
init_warnOnce();
|
|
8493
|
+
function resolveSpanExperimentId(options) {
|
|
8494
|
+
const { experimentId, testRunId } = options;
|
|
8495
|
+
if (experimentId !== void 0 && testRunId !== void 0 && experimentId !== testRunId) {
|
|
8496
|
+
throw new BitfabError(
|
|
8497
|
+
`experimentId ("${experimentId}") and its deprecated alias testRunId ("${testRunId}") were both passed with different values. Pass only experimentId.`
|
|
8498
|
+
);
|
|
8499
|
+
}
|
|
8500
|
+
return experimentId ?? testRunId;
|
|
8501
|
+
}
|
|
8364
8502
|
var TRUNCATION_LIMIT_ORDER = [
|
|
8365
8503
|
"max_depth",
|
|
8366
8504
|
"max_captured_subtree_spans"
|
|
@@ -8950,13 +9088,12 @@ var Bitfab = class {
|
|
|
8950
9088
|
"bitfab.node({ capture: false }) cannot use mockOnReplay: true because an uncaptured node has no recorded output."
|
|
8951
9089
|
);
|
|
8952
9090
|
}
|
|
9091
|
+
const experimentId = resolveSpanExperimentId(options);
|
|
8953
9092
|
return {
|
|
8954
9093
|
capture,
|
|
8955
9094
|
type: options.type ?? "custom",
|
|
8956
9095
|
...options.name !== void 0 && { name: options.name },
|
|
8957
|
-
...
|
|
8958
|
-
testRunId: options.testRunId
|
|
8959
|
-
},
|
|
9096
|
+
...experimentId !== void 0 && { experimentId },
|
|
8960
9097
|
...options.mockOnReplay !== void 0 && {
|
|
8961
9098
|
mockOnReplay: options.mockOnReplay
|
|
8962
9099
|
},
|
|
@@ -9091,6 +9228,7 @@ var Bitfab = class {
|
|
|
9091
9228
|
return invokeWithoutNode();
|
|
9092
9229
|
}
|
|
9093
9230
|
const mockOnReplay = nodeConfiguration?.mockOnReplay ?? options.mockOnReplayDefault;
|
|
9231
|
+
const nodeExperimentId = nodeConfiguration === void 0 ? void 0 : resolveSpanExperimentId(nodeConfiguration);
|
|
9094
9232
|
const childOptions = {
|
|
9095
9233
|
name: spanName,
|
|
9096
9234
|
type: nodeConfiguration?.type ?? "function",
|
|
@@ -9101,8 +9239,8 @@ var Bitfab = class {
|
|
|
9101
9239
|
captureContent: true,
|
|
9102
9240
|
autoTraceDefinition: definition,
|
|
9103
9241
|
...declaredNode && { declaredNode },
|
|
9104
|
-
...
|
|
9105
|
-
|
|
9242
|
+
...nodeExperimentId !== void 0 && {
|
|
9243
|
+
experimentId: nodeExperimentId
|
|
9106
9244
|
},
|
|
9107
9245
|
...mockOnReplay !== void 0 && {
|
|
9108
9246
|
mockOnReplay
|
|
@@ -9763,6 +9901,7 @@ var Bitfab = class {
|
|
|
9763
9901
|
const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
|
|
9764
9902
|
const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
9765
9903
|
const self = this;
|
|
9904
|
+
const optionExperimentId = resolveSpanExperimentId(options);
|
|
9766
9905
|
const fnIsAsyncFunction = fn.constructor.name === "AsyncFunction";
|
|
9767
9906
|
const fnReturnsPromise = fnIsAsyncFunction || (() => {
|
|
9768
9907
|
try {
|
|
@@ -9865,7 +10004,7 @@ var Bitfab = class {
|
|
|
9865
10004
|
const inputs = args;
|
|
9866
10005
|
const startedAt = nowIsoTimestamp();
|
|
9867
10006
|
const replayCtxAtStart = getReplayContext();
|
|
9868
|
-
const
|
|
10007
|
+
const experimentId = replayCtxAtStart?.experimentId ?? optionExperimentId;
|
|
9869
10008
|
if (isRootSpan && !activeTraceStates.has(traceId)) {
|
|
9870
10009
|
const dbSnapshotRef = buildSnapshotRef(self.dbSnapshot, startedAt);
|
|
9871
10010
|
self.simulationPlan.refresh();
|
|
@@ -9874,7 +10013,7 @@ var Bitfab = class {
|
|
|
9874
10013
|
traceFunctionKey,
|
|
9875
10014
|
startedAt,
|
|
9876
10015
|
contexts: [],
|
|
9877
|
-
...
|
|
10016
|
+
...experimentId !== void 0 && { experimentId },
|
|
9878
10017
|
...replayCtxAtStart?.inputSourceTraceId && {
|
|
9879
10018
|
inputSourceTraceId: replayCtxAtStart.inputSourceTraceId
|
|
9880
10019
|
},
|
|
@@ -9920,7 +10059,7 @@ var Bitfab = class {
|
|
|
9920
10059
|
contexts: newContext.contexts,
|
|
9921
10060
|
prompt: newContext.prompt,
|
|
9922
10061
|
endedAt,
|
|
9923
|
-
...
|
|
10062
|
+
...experimentId !== void 0 && { experimentId },
|
|
9924
10063
|
...replayCtx?.inputSourceSpanId && {
|
|
9925
10064
|
inputSourceSpanId: replayCtx.inputSourceSpanId
|
|
9926
10065
|
}
|
|
@@ -9941,7 +10080,7 @@ var Bitfab = class {
|
|
|
9941
10080
|
name: traceState?.name,
|
|
9942
10081
|
metadata: callerTraceMetadata(traceId),
|
|
9943
10082
|
contexts: traceState?.contexts ?? [],
|
|
9944
|
-
|
|
10083
|
+
experimentId: traceState?.experimentId,
|
|
9945
10084
|
inputSourceTraceId: traceState?.inputSourceTraceId,
|
|
9946
10085
|
replayAttempt: traceState?.replayAttempt,
|
|
9947
10086
|
dbSnapshotRef: traceState?.dbSnapshotRef,
|
|
@@ -10412,7 +10551,7 @@ var Bitfab = class {
|
|
|
10412
10551
|
completed: true,
|
|
10413
10552
|
...params.dropped && { dropped: true },
|
|
10414
10553
|
...params.sessionId && { sessionId: params.sessionId },
|
|
10415
|
-
...params.
|
|
10554
|
+
...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId)
|
|
10416
10555
|
});
|
|
10417
10556
|
}
|
|
10418
10557
|
sendsSpanOnCompletion(context) {
|
|
@@ -10524,7 +10663,7 @@ var Bitfab = class {
|
|
|
10524
10663
|
},
|
|
10525
10664
|
...params.declaredNode === true && { [DECLARED_NODE_FIELD]: true },
|
|
10526
10665
|
rawSpan: externalSpan,
|
|
10527
|
-
...params.
|
|
10666
|
+
...params.experimentId !== void 0 && experimentIdWireFields(params.experimentId),
|
|
10528
10667
|
...params.mocked && { mocked: true },
|
|
10529
10668
|
...params.mockTarget && { mockTarget: params.mockTarget },
|
|
10530
10669
|
...params.mockSource && { mockSource: params.mockSource }
|
|
@@ -11080,6 +11219,8 @@ assertAsyncStorageRegistered();
|
|
|
11080
11219
|
// Annotate the CommonJS export names for ESM import in node:
|
|
11081
11220
|
0 && (module.exports = {
|
|
11082
11221
|
AssertionCategoriesClient,
|
|
11222
|
+
AssertionGenerationError,
|
|
11223
|
+
AssertionGenerationTimeoutError,
|
|
11083
11224
|
BITFAB_PROGRESS_PREFIX,
|
|
11084
11225
|
Bitfab,
|
|
11085
11226
|
BitfabClaudeAgentHandler,
|
|
@@ -11095,6 +11236,8 @@ assertAsyncStorageRegistered();
|
|
|
11095
11236
|
DEFAULT_SERVICE_URL,
|
|
11096
11237
|
DatasetsClient,
|
|
11097
11238
|
DbBranchReplayError,
|
|
11239
|
+
GraderRerunError,
|
|
11240
|
+
GraderRerunTimeoutError,
|
|
11098
11241
|
GradersClient,
|
|
11099
11242
|
HttpClient,
|
|
11100
11243
|
LabelsClient,
|