@bitfab/sdk 0.38.10 → 0.40.0
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/{chunk-UE4GGPM6.js → chunk-5NT4YDCQ.js} +237 -9
- package/dist/chunk-5NT4YDCQ.js.map +1 -0
- package/dist/{chunk-BNOVHUQB.js → chunk-A22EYRSY.js} +29 -1103
- package/dist/chunk-A22EYRSY.js.map +1 -0
- package/dist/chunk-E2V4HFSM.js +1863 -0
- package/dist/chunk-E2V4HFSM.js.map +1 -0
- package/dist/chunk-EXT5FK54.js +1150 -0
- package/dist/chunk-EXT5FK54.js.map +1 -0
- package/dist/http-2OFIGQOK.js +20 -0
- package/dist/http-OZODCFFA.js +19 -0
- package/dist/http-OZODCFFA.js.map +1 -0
- package/dist/index.cjs +302 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +234 -4
- package/dist/index.d.ts +234 -4
- package/dist/index.js +14 -8
- package/dist/node.cjs +302 -7
- 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 +14 -8
- package/dist/node.js.map +1 -1
- package/dist/{replay-SMUBBMNK.js → replay-352POXG3.js} +3 -2
- package/dist/replay-352POXG3.js.map +1 -0
- package/dist/replayCli.js +132 -146
- package/dist/replayCli.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-BNOVHUQB.js.map +0 -1
- package/dist/chunk-UE4GGPM6.js.map +0 -1
- /package/dist/{replay-SMUBBMNK.js.map → http-2OFIGQOK.js.map} +0 -0
|
@@ -7,19 +7,21 @@ import {
|
|
|
7
7
|
runWithAutoTraceRootContext
|
|
8
8
|
} from "./chunk-ZUD7OFYB.js";
|
|
9
9
|
import {
|
|
10
|
-
BitfabError,
|
|
11
|
-
DEFAULT_SERVICE_URL,
|
|
12
|
-
HttpClient,
|
|
13
10
|
NO_MOCK_OVERRIDE,
|
|
14
11
|
deserializeValue,
|
|
15
|
-
getReplayContext,
|
|
16
12
|
randomUuid,
|
|
17
13
|
resolveMockValue,
|
|
18
14
|
serializeValue,
|
|
19
15
|
toJsonSafe,
|
|
20
|
-
toJsonSafeReport
|
|
16
|
+
toJsonSafeReport
|
|
17
|
+
} from "./chunk-EXT5FK54.js";
|
|
18
|
+
import {
|
|
19
|
+
BitfabError,
|
|
20
|
+
DEFAULT_SERVICE_URL,
|
|
21
|
+
HttpClient,
|
|
22
|
+
getReplayContext,
|
|
21
23
|
warnOnce
|
|
22
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-A22EYRSY.js";
|
|
23
25
|
import {
|
|
24
26
|
__privateAdd,
|
|
25
27
|
__privateGet,
|
|
@@ -947,6 +949,131 @@ async function runFunctionWithBaml(bamlSource, inputs, providers, envVars) {
|
|
|
947
949
|
};
|
|
948
950
|
}
|
|
949
951
|
|
|
952
|
+
// src/datasets.ts
|
|
953
|
+
var DEFAULT_RERUN_TIMEOUT_MS = 9e4;
|
|
954
|
+
var DEFAULT_RERUN_POLL_INTERVAL_MS = 1e3;
|
|
955
|
+
var TERMINAL_RERUN_STATUSES = /* @__PURE__ */ new Set([
|
|
956
|
+
"completed",
|
|
957
|
+
"errored"
|
|
958
|
+
]);
|
|
959
|
+
function sleep(ms) {
|
|
960
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
961
|
+
}
|
|
962
|
+
function datasetPath(datasetId, suffix = "") {
|
|
963
|
+
return `/api/sdk/datasets/${encodeURIComponent(datasetId)}${suffix}`;
|
|
964
|
+
}
|
|
965
|
+
var DatasetsClient = class {
|
|
966
|
+
constructor(httpClient) {
|
|
967
|
+
this.httpClient = httpClient;
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Create a dataset, or update the one already named this way under the same
|
|
971
|
+
* trace function. `created` reports which happened. An omitted description
|
|
972
|
+
* leaves an existing one untouched.
|
|
973
|
+
*/
|
|
974
|
+
async save(params) {
|
|
975
|
+
return this.httpClient.request("/api/sdk/datasets", {
|
|
976
|
+
traceFunctionKey: params.traceFunctionKey,
|
|
977
|
+
name: params.name,
|
|
978
|
+
...params.description === void 0 ? {} : { description: params.description }
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* List datasets, scoped to one trace function when `traceFunctionKey` is
|
|
983
|
+
* given and organization-wide otherwise.
|
|
984
|
+
*/
|
|
985
|
+
async list(params = {}) {
|
|
986
|
+
const query = params.traceFunctionKey === void 0 ? "" : `?traceFunctionKey=${encodeURIComponent(params.traceFunctionKey)}`;
|
|
987
|
+
const response = await this.httpClient.get(
|
|
988
|
+
`/api/sdk/datasets${query}`
|
|
989
|
+
);
|
|
990
|
+
return response.datasets;
|
|
991
|
+
}
|
|
992
|
+
/** Fetch one dataset by id. Rejects with a 404 `BitfabError` when it is not in this organization. */
|
|
993
|
+
async get(datasetId) {
|
|
994
|
+
const response = await this.httpClient.get(
|
|
995
|
+
datasetPath(datasetId)
|
|
996
|
+
);
|
|
997
|
+
return response.dataset;
|
|
998
|
+
}
|
|
999
|
+
/** The ids of every trace in the dataset, the same membership a replay with `datasetId` selects. */
|
|
1000
|
+
async listTraces(datasetId) {
|
|
1001
|
+
return this.httpClient.get(
|
|
1002
|
+
datasetPath(datasetId, "/traces")
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Add traces to the dataset (1 to 100 ids per call). Traces outside the
|
|
1007
|
+
* organization or under another trace function are reported in
|
|
1008
|
+
* `skippedTraceIds` rather than failing the call.
|
|
1009
|
+
*/
|
|
1010
|
+
async addTraces(datasetId, traceIds) {
|
|
1011
|
+
return this.httpClient.request(
|
|
1012
|
+
datasetPath(datasetId, "/traces"),
|
|
1013
|
+
{ traceIds }
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
/** Remove traces from the dataset. The traces themselves are never deleted. */
|
|
1017
|
+
async removeTraces(datasetId, traceIds) {
|
|
1018
|
+
return this.httpClient.request(
|
|
1019
|
+
datasetPath(datasetId, "/removeTraces"),
|
|
1020
|
+
{ traceIds }
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Assign graders to the dataset (1 to 100 ids per call). Graders outside the
|
|
1025
|
+
* organization or under another trace function are reported in
|
|
1026
|
+
* `skippedGraderIds` rather than failing the call.
|
|
1027
|
+
*/
|
|
1028
|
+
async addGraders(datasetId, graderIds) {
|
|
1029
|
+
return this.httpClient.request(
|
|
1030
|
+
datasetPath(datasetId, "/graders"),
|
|
1031
|
+
{ graderIds }
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1034
|
+
/** Unassign graders from the dataset. */
|
|
1035
|
+
async removeGraders(datasetId, graderIds) {
|
|
1036
|
+
return this.httpClient.request(
|
|
1037
|
+
datasetPath(datasetId, "/removeGraders"),
|
|
1038
|
+
{ graderIds }
|
|
1039
|
+
);
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Re-run graders over every trace in the dataset. Defaults to every assigned
|
|
1043
|
+
* grader; an unassigned id is rejected. Waits for the run to finish (up to
|
|
1044
|
+
* `timeoutMs`, default 90s) unless `wait` is `false`, and returns the last
|
|
1045
|
+
* run state seen either way. A request matching an in-flight run joins it.
|
|
1046
|
+
*/
|
|
1047
|
+
async rerunGraders(datasetId, options = {}) {
|
|
1048
|
+
const started = await this.httpClient.request(
|
|
1049
|
+
datasetPath(datasetId, "/rerunGraders"),
|
|
1050
|
+
options.graderIds === void 0 ? {} : { graderIds: options.graderIds }
|
|
1051
|
+
);
|
|
1052
|
+
if (options.wait === false) {
|
|
1053
|
+
return started;
|
|
1054
|
+
}
|
|
1055
|
+
const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_RERUN_TIMEOUT_MS);
|
|
1056
|
+
const interval = options.pollIntervalMs ?? DEFAULT_RERUN_POLL_INTERVAL_MS;
|
|
1057
|
+
let run = started.run;
|
|
1058
|
+
while (!TERMINAL_RERUN_STATUSES.has(run.status) && Date.now() < deadline) {
|
|
1059
|
+
await sleep(interval);
|
|
1060
|
+
run = await this.getGraderRerun(datasetId, run.id) ?? run;
|
|
1061
|
+
}
|
|
1062
|
+
return { run, joinedExisting: started.joinedExisting };
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* The dataset's active grader re-run, or the run named by `runId`. Returns
|
|
1066
|
+
* `null` when nothing is active or the run does not belong to this dataset.
|
|
1067
|
+
*/
|
|
1068
|
+
async getGraderRerun(datasetId, runId) {
|
|
1069
|
+
const query = runId === void 0 ? "" : `?runId=${encodeURIComponent(runId)}`;
|
|
1070
|
+
const response = await this.httpClient.get(
|
|
1071
|
+
datasetPath(datasetId, `/rerunGraders${query}`)
|
|
1072
|
+
);
|
|
1073
|
+
return response.run;
|
|
1074
|
+
}
|
|
1075
|
+
};
|
|
1076
|
+
|
|
950
1077
|
// src/dbSnapshot.ts
|
|
951
1078
|
var SUPPORTED_PROVIDERS = ["neon"];
|
|
952
1079
|
function validateDbSnapshotConfig(config) {
|
|
@@ -2658,6 +2785,7 @@ var Bitfab = class {
|
|
|
2658
2785
|
serviceUrl: this.serviceUrl,
|
|
2659
2786
|
timeout: this.timeout
|
|
2660
2787
|
});
|
|
2788
|
+
this.datasets = new DatasetsClient(this.httpClient);
|
|
2661
2789
|
}
|
|
2662
2790
|
/**
|
|
2663
2791
|
* Decorate a class method as an automatically expanded trace root.
|
|
@@ -3568,6 +3696,7 @@ var Bitfab = class {
|
|
|
3568
3696
|
inputSourceTraceId: traceState?.inputSourceTraceId,
|
|
3569
3697
|
dbSnapshotRef: traceState?.dbSnapshotRef,
|
|
3570
3698
|
dropped: traceState?.dropped,
|
|
3699
|
+
ingestionType: traceState?.ingestionType,
|
|
3571
3700
|
// Built AFTER the wrapped fn finished, so `accessed` reflects
|
|
3572
3701
|
// whether customer code obtained the branch URL during this
|
|
3573
3702
|
// item. Omitted entirely when no lease was attached, so the
|
|
@@ -3791,6 +3920,7 @@ var Bitfab = class {
|
|
|
3791
3920
|
Object.defineProperty(wrappedFn, "_bitfabTraceFunctionKey", {
|
|
3792
3921
|
value: traceFunctionKey
|
|
3793
3922
|
});
|
|
3923
|
+
Object.defineProperty(wrappedFn, "_bitfabWrappedFn", { value: fn });
|
|
3794
3924
|
return wrappedFn;
|
|
3795
3925
|
}
|
|
3796
3926
|
/**
|
|
@@ -3953,6 +4083,9 @@ var Bitfab = class {
|
|
|
3953
4083
|
if (params.dbSnapshotRef) {
|
|
3954
4084
|
rawTrace.db_snapshot_ref = params.dbSnapshotRef;
|
|
3955
4085
|
}
|
|
4086
|
+
if (params.ingestionType) {
|
|
4087
|
+
rawTrace.ingestion_type = params.ingestionType;
|
|
4088
|
+
}
|
|
3956
4089
|
if (params.dbSnapshotUsage) {
|
|
3957
4090
|
rawTrace.db_snapshot_usage = {
|
|
3958
4091
|
neon_branch_id: params.dbSnapshotUsage.neonBranchId,
|
|
@@ -4099,6 +4232,68 @@ var Bitfab = class {
|
|
|
4099
4232
|
clearMockOverrides() {
|
|
4100
4233
|
this.mockOverrides.length = 0;
|
|
4101
4234
|
}
|
|
4235
|
+
/**
|
|
4236
|
+
* Write a replayable trace from a case, without running anything.
|
|
4237
|
+
*
|
|
4238
|
+
* Use this to turn a corpus you already hold (a Braintrust dataset, a
|
|
4239
|
+
* spreadsheet, hand-written cases) into traces that {@link replay} can
|
|
4240
|
+
* select. The recorded root span carries `input` as its input and `expected`
|
|
4241
|
+
* as its output, so replay reports each item against the value you expected
|
|
4242
|
+
* rather than against a previous run.
|
|
4243
|
+
*
|
|
4244
|
+
* A seeded trace has no child spans and no database pin, so replay mocking
|
|
4245
|
+
* has nothing recorded to substitute and `dbBranch` refuses it. Pass
|
|
4246
|
+
* `mockOverride` at replay time for calls that must not run.
|
|
4247
|
+
*
|
|
4248
|
+
* @returns The trace ID, usable with `replay({ traceIds: [...] })`.
|
|
4249
|
+
*/
|
|
4250
|
+
seedTrace(traceFunctionKey, options) {
|
|
4251
|
+
const { input } = options;
|
|
4252
|
+
const fn = options.fn?._bitfabWrappedFn ?? options.fn;
|
|
4253
|
+
if (fn && input.length < fn.length) {
|
|
4254
|
+
throw new BitfabError(
|
|
4255
|
+
`Seeded case supplies ${input.length} argument(s) but ${fn.name === "" ? "the function" : fn.name} requires ${fn.length}. Fix the case, or omit fn to seed it anyway.`
|
|
4256
|
+
);
|
|
4257
|
+
}
|
|
4258
|
+
const traceId = randomUuid();
|
|
4259
|
+
const startedAt = nowIsoTimestamp();
|
|
4260
|
+
activeTraceStates.set(traceId, {
|
|
4261
|
+
traceId,
|
|
4262
|
+
startedAt,
|
|
4263
|
+
contexts: [],
|
|
4264
|
+
ingestionType: "seeded",
|
|
4265
|
+
...options.sessionId !== void 0 && { sessionId: options.sessionId },
|
|
4266
|
+
...options.metadata !== void 0 && { metadata: options.metadata }
|
|
4267
|
+
});
|
|
4268
|
+
try {
|
|
4269
|
+
this.sendWrapperSpan({
|
|
4270
|
+
traceFunctionKey,
|
|
4271
|
+
spanName: options.spanName ?? traceFunctionKey,
|
|
4272
|
+
traceId,
|
|
4273
|
+
spanId: randomUuid(),
|
|
4274
|
+
parentSpanId: null,
|
|
4275
|
+
inputs: input,
|
|
4276
|
+
result: options.expected,
|
|
4277
|
+
startedAt,
|
|
4278
|
+
endedAt: startedAt,
|
|
4279
|
+
spanType: options.spanType ?? "agent",
|
|
4280
|
+
captureContent: true
|
|
4281
|
+
});
|
|
4282
|
+
this.sendTraceCompletion({
|
|
4283
|
+
traceFunctionKey,
|
|
4284
|
+
traceId,
|
|
4285
|
+
startedAt,
|
|
4286
|
+
endedAt: startedAt,
|
|
4287
|
+
sessionId: options.sessionId,
|
|
4288
|
+
metadata: options.metadata,
|
|
4289
|
+
contexts: [],
|
|
4290
|
+
ingestionType: "seeded"
|
|
4291
|
+
});
|
|
4292
|
+
} finally {
|
|
4293
|
+
activeTraceStates.delete(traceId);
|
|
4294
|
+
}
|
|
4295
|
+
return traceId;
|
|
4296
|
+
}
|
|
4102
4297
|
async replay(traceFunctionKey, fn, options) {
|
|
4103
4298
|
const wrappedKey = fn._bitfabTraceFunctionKey;
|
|
4104
4299
|
let replayFn = fn;
|
|
@@ -4113,7 +4308,7 @@ var Bitfab = class {
|
|
|
4113
4308
|
`Function is wrapped with trace function key '${wrappedKey}' but replay was called with '${traceFunctionKey}'. Pass matching keys, or pass the unwrapped function to replay it under the explicit key.`
|
|
4114
4309
|
);
|
|
4115
4310
|
}
|
|
4116
|
-
const { replay: doReplay } = await import("./replay-
|
|
4311
|
+
const { replay: doReplay } = await import("./replay-352POXG3.js");
|
|
4117
4312
|
return doReplay(
|
|
4118
4313
|
this.httpClient,
|
|
4119
4314
|
this.serviceUrl,
|
|
@@ -4349,9 +4544,41 @@ var finalizers = {
|
|
|
4349
4544
|
function defineReplayRegistry(registry) {
|
|
4350
4545
|
return registry;
|
|
4351
4546
|
}
|
|
4547
|
+
async function seedFromRegistry(registry, pipeline, cases) {
|
|
4548
|
+
const registration = registry[pipeline];
|
|
4549
|
+
if (registration === void 0) {
|
|
4550
|
+
throw new BitfabError(
|
|
4551
|
+
`Unknown pipeline '${pipeline}'. Registered: ${Object.keys(registry).join(", ")}`
|
|
4552
|
+
);
|
|
4553
|
+
}
|
|
4554
|
+
const traceFunctionKey = resolveTraceFunctionKey(registration);
|
|
4555
|
+
const traceIds = cases.map(
|
|
4556
|
+
(seedCase) => registration.client.seedTrace(traceFunctionKey, {
|
|
4557
|
+
input: seedCase.input,
|
|
4558
|
+
expected: seedCase.expected,
|
|
4559
|
+
fn: registration.fn,
|
|
4560
|
+
metadata: seedCase.metadata,
|
|
4561
|
+
sessionId: seedCase.sessionId
|
|
4562
|
+
})
|
|
4563
|
+
);
|
|
4564
|
+
const { flushTraces: flushTraces2 } = await import("./http-2OFIGQOK.js");
|
|
4565
|
+
await flushTraces2(3e4);
|
|
4566
|
+
return { pipeline, traceFunctionKey, traceIds };
|
|
4567
|
+
}
|
|
4568
|
+
function resolveTraceFunctionKey(registration) {
|
|
4569
|
+
const wrappedKey = registration.fn._bitfabTraceFunctionKey;
|
|
4570
|
+
const key = registration.traceFunctionKey ?? wrappedKey;
|
|
4571
|
+
if (key === void 0) {
|
|
4572
|
+
throw new BitfabError(
|
|
4573
|
+
"Replay registry entry uses a plain function. Set traceFunctionKey to the key its production handler records."
|
|
4574
|
+
);
|
|
4575
|
+
}
|
|
4576
|
+
return key;
|
|
4577
|
+
}
|
|
4352
4578
|
|
|
4353
4579
|
export {
|
|
4354
4580
|
BitfabClaudeAgentHandler,
|
|
4581
|
+
DatasetsClient,
|
|
4355
4582
|
SUPPORTED_PROVIDERS,
|
|
4356
4583
|
BitfabLangGraphCallbackHandler,
|
|
4357
4584
|
BitfabLangGraphIntegration,
|
|
@@ -4364,6 +4591,7 @@ export {
|
|
|
4364
4591
|
Bitfab,
|
|
4365
4592
|
BitfabFunction,
|
|
4366
4593
|
finalizers,
|
|
4367
|
-
defineReplayRegistry
|
|
4594
|
+
defineReplayRegistry,
|
|
4595
|
+
seedFromRegistry
|
|
4368
4596
|
};
|
|
4369
|
-
//# sourceMappingURL=chunk-
|
|
4597
|
+
//# sourceMappingURL=chunk-5NT4YDCQ.js.map
|