bitfab-cli 0.2.472 → 0.2.473
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/index.js +130 -102
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28929,7 +28929,7 @@ var dateOnlyStringSchema = external_exports.string().regex(DATE_PATTERN, "Must b
|
|
|
28929
28929
|
const date5 = parseDateOnly(value);
|
|
28930
28930
|
return date5.getFullYear() === year && date5.getMonth() === month - 1 && date5.getDate() === day;
|
|
28931
28931
|
}, "Must be a valid calendar date");
|
|
28932
|
-
var
|
|
28932
|
+
var GET_TRACE_VERDICTS_MAX_IDS = 100;
|
|
28933
28933
|
var GET_TRACES_DEFAULT_SPAN_LIMIT = 50;
|
|
28934
28934
|
var SPAN_READ_MAX_RESPONSE_CHARS = 32e3;
|
|
28935
28935
|
var GET_TRACES_MAX_SPAN_LIMIT = 200;
|
|
@@ -28953,10 +28953,10 @@ var spanFieldSchema = external_exports.enum([
|
|
|
28953
28953
|
var GET_TRACE_ASSERTIONS_MAX_IDS = 100;
|
|
28954
28954
|
var MAX_ASSERTIONS_PER_REQUEST = 50;
|
|
28955
28955
|
var MAX_ASSIGNEE_EMAIL_LENGTH = 320;
|
|
28956
|
-
var
|
|
28957
|
-
var
|
|
28958
|
-
var
|
|
28959
|
-
var
|
|
28956
|
+
var GET_GRADER_VERDICTS_MAX_IDS = 100;
|
|
28957
|
+
var DEFAULT_GRADER_VERDICT_LIMIT = 50;
|
|
28958
|
+
var MAX_GRADER_VERDICT_LIMIT = 200;
|
|
28959
|
+
var SAVE_GRADER_VERDICTS_MAX_ENTRIES = 200;
|
|
28960
28960
|
function parseJsonString(val) {
|
|
28961
28961
|
if (typeof val !== "string") {
|
|
28962
28962
|
return val;
|
|
@@ -29070,19 +29070,21 @@ var searchTraces = {
|
|
|
29070
29070
|
]))).optional().describe("Filter by up to 10 caller metadata key/value pairs. Matches exact values case-insensitively; all pairs must match."),
|
|
29071
29071
|
name: external_exports.string().trim().min(1).max(256).transform((value) => value.toLowerCase()).optional().describe("Filter by the trace's name, the title set by setName or seedTrace. Matches the name's words in order, so 'Order ABC' also matches 'Order ABC 123', and it matches whole words rather than inside a word. Case-insensitive. Use nameContains to match inside a word or on a partial word."),
|
|
29072
29072
|
nameContains: external_exports.string().trim().min(3).max(256).transform((value) => value.toLowerCase()).optional().describe("Filter by any part of the trace's name, including inside a word, matched case-insensitively. Needs at least 3 characters. Use name instead to match whole words in order."),
|
|
29073
|
-
|
|
29074
|
-
|
|
29075
|
-
|
|
29076
|
-
|
|
29073
|
+
verdictSource: external_exports.enum(["human", "agent"]).optional().describe('Filter by who gave the verdict: "human" for verdicts a person gave, "agent" for verdicts an agent gave. Omit to include any source. This filters on authorship only; for trust, use the separate `validated` parameter.'),
|
|
29074
|
+
labelSource: external_exports.enum(["human", "agent"]).optional().meta({ deprecated: true }).describe("Deprecated: the old name for verdictSource. Ignored when verdictSource is also sent."),
|
|
29075
|
+
validated: external_exports.preprocess(parseJsonString, external_exports.boolean()).optional().describe('If true, only return traces with a validated verdict: one a person gave, or one an agent gave that a person has approved (`approvedAt` is set). Use this when you want verdicts someone has reviewed. Combine with `verdictSource: "agent"` to get only approved agent verdicts (leaving out the ones a person gave). Omit (or pass false) to include unapproved verdicts too.'),
|
|
29076
|
+
verdictResult: external_exports.preprocess(parseJsonString, external_exports.boolean()).optional().describe("Filter by verdict: true for passing verdicts, false for failing verdicts"),
|
|
29077
|
+
labelResult: external_exports.preprocess(parseJsonString, external_exports.boolean()).optional().meta({ deprecated: true }).describe("Deprecated: the old name for verdictResult. Ignored when verdictResult is also sent."),
|
|
29078
|
+
includeReplays: external_exports.preprocess(parseJsonString, external_exports.boolean()).optional().describe("Include replayed traces (traces from experiments) in results. Defaults to false because replays have new inputs, not the original production inputs, so they're not useful when selecting traces to judge or when sampling real user behavior. Set to true only when you specifically want to inspect replay results."),
|
|
29077
29079
|
experimentId: external_exports.uuid().optional().describe("Filter to traces from a specific experiment ID. Automatically sets includeReplays to true."),
|
|
29078
|
-
datasetId: external_exports.uuid().optional().describe("Filter to traces belonging to a specific dataset. Combine with other filters (status,
|
|
29080
|
+
datasetId: external_exports.uuid().optional().describe("Filter to traces belonging to a specific dataset. Combine with other filters (status, verdictResult, etc.) to narrow within the dataset."),
|
|
29079
29081
|
hasDbSnapshot: external_exports.preprocess(parseJsonString, external_exports.boolean()).optional().describe("Filter by whether the trace captured a database snapshot reference. true returns only traces that can be replayed against a pinned historical DB branch (the 'Snapshot captured' traces); false returns only traces with no snapshot. Omit to include both.")
|
|
29080
29082
|
}
|
|
29081
29083
|
};
|
|
29082
29084
|
var getTraces = {
|
|
29083
29085
|
name: "get_traces",
|
|
29084
29086
|
title: "Get Traces",
|
|
29085
|
-
description: `Read one or more traces by ID. Includes inputs, outputs, status, environment tag, trace-level duration (ms), token usage (in/out/cached/total), and model (when available). Use these to compare latency and cost between a trace and its replay. Returns span details (input, output, reasoning, content, context, errors) plus per-span duration, tokens, time-to-first-token, and model when available. Use \`scope: "summary"\` when scanning many traces to keep the response small; \`scope: "full"\` when you need the complete untruncated detail of a few traces. Spans come back one page at a time (${GET_TRACES_DEFAULT_SPAN_LIMIT} per trace by default) and the whole response is capped in size, so it always fits in context. When a trace has more spans than one page, the response lists every span name and span type with its count and says which spanOffset reads the next page: narrow with spanNames (only spans with those names), spanTypes (only spans of those types, e.g. ["llm"] for the model calls) and spanFields (only those fields) rather than paging through thousands of spans, and fetch any one truncated field in full with get_span_field. To load only
|
|
29087
|
+
description: `Read one or more traces by ID. Includes inputs, outputs, status, environment tag, trace-level duration (ms), token usage (in/out/cached/total), and model (when available). Use these to compare latency and cost between a trace and its replay. Returns span details (input, output, reasoning, content, context, errors) plus per-span duration, tokens, time-to-first-token, and model when available. Use \`scope: "summary"\` when scanning many traces to keep the response small; \`scope: "full"\` when you need the complete untruncated detail of a few traces. Spans come back one page at a time (${GET_TRACES_DEFAULT_SPAN_LIMIT} per trace by default) and the whole response is capped in size, so it always fits in context. When a trace has more spans than one page, the response lists every span name and span type with its count and says which spanOffset reads the next page: narrow with spanNames (only spans with those names), spanTypes (only spans of those types, e.g. ["llm"] for the model calls) and spanFields (only those fields) rather than paging through thousands of spans, and fetch any one truncated field in full with get_span_field. To load only verdicts + annotations for many traces at once (no span content), use get_trace_verdicts instead.`,
|
|
29086
29088
|
inputSchema: {
|
|
29087
29089
|
traceIds: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.uuid()).min(1).max(10)).describe("Trace IDs to read (1-10)"),
|
|
29088
29090
|
scope: external_exports.enum(["summary", "full"]).optional().default("summary").describe('Level of span detail. "summary" (default) renders the same span structure as full but caps each span (its fields share a ~1500-char budget) and each trace-level field (~2000 chars), and leaves out any span field over 10k chars, printing its size instead (name it in spanFields to preview it anyway, or read it in full with get_span_field): prefer it when scanning or identifying candidate traces. "full" renders every field untruncated up to 10k chars each, with no per-span ceiling, until the response size cap: use it when you need complete detail on a handful of spans, ideally narrowed with spanNames.'),
|
|
@@ -29093,18 +29095,18 @@ var getTraces = {
|
|
|
29093
29095
|
spanFields: external_exports.preprocess(parseJsonString, external_exports.array(spanFieldSchema).max(6)).optional().describe("Only show these span fields (input, output, reasoning, content, errors, contexts). Omit to show all of them, with fields over 10k chars left out in summary scope. A field named here is previewed even when it is large. Pass [] to list spans with only their name, ID, duration, tokens, and model, which is the cheapest way to see a large trace's shape.")
|
|
29094
29096
|
}
|
|
29095
29097
|
};
|
|
29096
|
-
var
|
|
29097
|
-
name: "
|
|
29098
|
-
title: "Get Trace
|
|
29099
|
-
description: `Read just the
|
|
29098
|
+
var getTraceVerdicts = {
|
|
29099
|
+
name: "get_trace_verdicts",
|
|
29100
|
+
title: "Get Trace Verdicts",
|
|
29101
|
+
description: `Read just the verdicts for one or more traces by ID: returns each trace's pass/fail verdict, its annotation (the reviewer's reasoning), its saved { spanId, text } evidence, and whether the verdict is human-validated (a person gave or approved it). Per-assertion verdicts follow on indented lines, one per assertion, keyed by the assertionId the write used, each with its own verdict, annotation, evidence, confidence, and author, so a verdict written per assertion reads back per assertion rather than as a tally. A verdict reads ABSTAINED when the judge could not find the evidence the assertion needed: it counts as a fail in the passed/failed tally and the trace's verdict, and the tally also says how many of the fails were abstentions, so you can tell judge coverage from the agent's behavior. No span content, inputs, or outputs are loaded, so the response is small and one call accepts up to ${GET_TRACE_VERDICTS_MAX_IDS} IDs. Use this to load a whole dataset's verdicts into context in a single call (e.g. when building or confirming a dataset). When you need a trace's actual inputs/outputs/spans, use get_traces instead. This returns verdicts on runs that already happened; for what a trace SHOULD do on its next replay, use get_trace_assertions.`,
|
|
29100
29102
|
inputSchema: {
|
|
29101
|
-
traceIds: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.uuid()).min(1).max(
|
|
29103
|
+
traceIds: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.uuid()).min(1).max(GET_TRACE_VERDICTS_MAX_IDS)).describe(`Trace IDs to read verdicts for (1-${GET_TRACE_VERDICTS_MAX_IDS})`)
|
|
29102
29104
|
}
|
|
29103
29105
|
};
|
|
29104
|
-
var
|
|
29105
|
-
name: "
|
|
29106
|
-
title: "Generate
|
|
29107
|
-
description: "Suggest span-by-span evidence that could support a
|
|
29106
|
+
var generateVerdictEvidence = {
|
|
29107
|
+
name: "generate_verdict_evidence",
|
|
29108
|
+
title: "Generate Verdict Evidence",
|
|
29109
|
+
description: "Suggest span-by-span evidence that could support a verdict on one assertion on a specific evaluated trace. Pass the original or replay trace being judged; an inherited assertion is checked against that replay's spans. The service narrows the selected trace to spans relevant to the assertion, then returns evidence items with traceId, assertionId, spanId, text, spanName, signature-only parameters (names and runtime types, never values), spanType, and isMocked. Use get_trace_assertions to obtain assertion IDs. Saved `{ spanId, text }` evidence is read with get_trace_verdicts instead.",
|
|
29108
29110
|
inputSchema: {
|
|
29109
29111
|
traceId: external_exports.uuid().describe("The original or replay trace whose spans should be evaluated."),
|
|
29110
29112
|
assertionId: external_exports.uuid().describe("The assertion the evidence would support.")
|
|
@@ -29132,45 +29134,53 @@ var getSpan = {
|
|
|
29132
29134
|
offset: external_exports.preprocess(parseJsonString, external_exports.number().int().min(0)).optional().describe("Character position in the span's output to start reading from (default 0). Pass the offset a previous response gave to read the next part of a long output.")
|
|
29133
29135
|
}
|
|
29134
29136
|
};
|
|
29135
|
-
var
|
|
29137
|
+
var verdictEvidenceShape = external_exports.preprocess(parseJsonString, external_exports.array(external_exports.object({
|
|
29136
29138
|
spanId: external_exports.uuid(),
|
|
29137
29139
|
text: external_exports.string().trim().min(1).max(1e4)
|
|
29138
29140
|
})).min(1).max(50));
|
|
29139
|
-
var
|
|
29140
|
-
|
|
29141
|
-
|
|
29142
|
-
|
|
29141
|
+
var confidenceShape = external_exports.enum(["VeryLow", "Low", "Medium", "High", "VeryHigh"]);
|
|
29142
|
+
var MAX_VERDICTS_PER_REQUEST = 200;
|
|
29143
|
+
var agentVerdictEntryShape = external_exports.object({
|
|
29144
|
+
traceId: external_exports.uuid().optional().describe("The trace ID to update. Provide this OR originalTraceId, not both."),
|
|
29145
|
+
assertionId: external_exports.uuid().optional().describe("The assertion this verdict scores, taken from the `[ID: ...]` get_trace_assertions prints. Required unless `archive` is true: verdicts are never written directly on a trace. A replay may name an assertion it inherited from the original trace it was replayed from."),
|
|
29146
|
+
originalTraceId: external_exports.uuid().optional().describe("For replay verdicts: the original trace ID the replay item was replayed from (the replay item's originalTraceId). The server resolves it to the replay trace via lineage, so you never need a server replay trace id. Requires the top-level experimentId. Provide this OR traceId, not both."),
|
|
29147
|
+
sourceTraceId: external_exports.uuid().optional().meta({ deprecated: true }).describe("Deprecated alias for originalTraceId. Prefer originalTraceId; accepted for back-compat."),
|
|
29148
|
+
attempt: external_exports.number().int().min(0).optional().describe("For replay verdicts on an experiment that ran each trace more than once: which attempt of originalTraceId this verdict is for (0-based, the replay item's attempt). Defaults to 0, so single-attempt callers never need it."),
|
|
29149
|
+
verdict: external_exports.enum(["pass", "fail", "abstained"]).optional().describe('"pass" or "fail" for your judgment of the assertion. "abstained" when the evidence does not show the part of the run this assertion checks, so there was nothing to judge: it counts as a FAIL in every pass rate but is stored and shown as an abstention, apart from a fail. Required unless `archive` or `skip` is true.'),
|
|
29150
|
+
label: external_exports.boolean().optional().meta({ deprecated: true }).describe('Deprecated: the old spelling of verdict. true is "pass", false is "fail". Refused when verdict is also sent.'),
|
|
29151
|
+
abstain: external_exports.boolean().optional().meta({ deprecated: true }).describe('Deprecated: the old spelling of verdict "abstained".'),
|
|
29152
|
+
archive: external_exports.boolean().optional().describe("If true, archive the existing agent verdict on this assertion and ignore verdict/annotation/skip/confidence. Default false."),
|
|
29153
|
+
skip: external_exports.boolean().optional().describe("If true, record an explicit skip (cannot judge) and ignore verdict/confidence. Pass `annotation` alongside it to record why the verdict was withheld. Default false."),
|
|
29154
|
+
annotation: external_exports.string().min(1).optional().describe('Your reasoning, shown to the human reviewer beside the verdict. Required for a "pass" or "fail" verdict. Optional alongside `skip: true`, where it says why the verdict was withheld, and alongside verdict "abstained", where it says what the evidence would have had to show.'),
|
|
29155
|
+
confidence: confidenceShape.optional().describe('How confident you are in this verdict: VeryLow / Low / Medium / High / VeryHigh. Shown beside the verdict; low-confidence verdicts are put first for human review. Optional; only meaningful with a "pass" or "fail" verdict.'),
|
|
29156
|
+
evidence: verdictEvidenceShape.nullable().optional().describe("Span-by-span evidence for this verdict. Omit it to preserve existing evidence. Pass null to clear existing evidence.")
|
|
29157
|
+
});
|
|
29158
|
+
var saveAgentVerdicts = {
|
|
29159
|
+
name: "save_agent_verdicts",
|
|
29160
|
+
title: "Save Agent Verdicts",
|
|
29161
|
+
description: 'Set, skip, abstain on, or archive the agent\'s pass/fail verdict on one or more of a trace\'s approved assertions (`verdictSource="agent"`). Every verdict, skip, and abstention scores ONE assertion and must carry its `assertionId` (the `[ID: ...]` get_trace_assertions prints). Verdicts are only ever written on assertions, never directly on a trace: a trace with no approved assertions gets no verdict, so add assertions first (save_trace_assertions) or report your judgment in the conversation. Use this AFTER you have read the traces with get_traces and decided yourself whether each one looks like a pass, a fail, or genuinely cannot be judged. To set a verdict, pass `verdict` ("pass" or "fail") and `annotation` (your reasoning, shown to the human reviewer beside the verdict). Add `evidence` as `{ spanId, text }` entries to ground that reasoning in spans on the evaluated trace. Optionally pass `confidence` (`VeryLow|Low|Medium|High|VeryHigh`) to record how confident you are, shown beside the verdict so reviewers can look at low-confidence verdicts first. To explicitly skip an assertion you cannot decide on (instead of leaving it with no verdict), pass `skip: true` and omit verdict. That records an explicit skip so coverage checks know you intentionally did not judge it, and `annotation` still applies: pass it to say why the verdict was withheld (the check never ran, the tape was punctured, the run never terminated), which is the only place a reader learns that. A skip with no annotation clears the note the previous verdict carried, so a stale reason never sits under a withheld verdict. When you read the trace and the evidence does not show the part of the run the assertion checks at all (the message it sent, the call it made, the answer it gave), so nothing can confirm or deny the assertion, pass `verdict: "abstained"`. That is counted as a FAIL in every pass rate, since anything short of an evidenced pass is a fail, but it is stored and shown as an abstention so a reader sees judge coverage rather than the agent\'s behavior; `annotation` says what the evidence would have had to show. Abstaining is not a skip: a skip is for a check that never ran, an abstention is for a check that ran and found nothing to judge. To clear a previously-set agent verdict (e.g., you changed your mind or judged the wrong trace), pass `archive: true` and omit verdict/annotation; an archive may omit `assertionId` to clear an old whole-trace agent verdict. A verdict counts as soon as it is written; there is no approval step, and a person can override it with their own verdict. Archiving is non-destructive: the row is hidden from all reads but kept for audit, and you can immediately judge the assertion again from scratch. For replay results, key each verdict by the replay item\'s `originalTraceId` (the original trace it was replayed from; `sourceTraceId` is accepted as a deprecated alias) plus the top-level `experimentId` instead of a `traceId`: the server resolves it to the replay trace via lineage, so you never need a server-generated replay trace id. When the experiment ran each trace more than once, also pass the item\'s `attempt` so each attempt gets its own verdict. Returns an agent-readable summary with one parseable effective verdict line per entry you sent (so a trace scored on several assertions gets one line per assertion), keyed by the id you supplied (`originalTraceId` for replay verdicts, otherwise `traceId`), so command callers can verify persistence. Before judging a replay, call get_trace_assertions on the original trace ids: an assertion says what the user asked this specific case to do, so the verdict is measured against that rather than a guess. When an assertion\'s target cannot be found on the trace you are judging, the check never ran, so pass `skip: true` for that assertion rather than recording a FAIL. Send one entry per assertion, all in the same call. get_trace_verdicts reads these back one line per assertion, keyed by the same assertionId, so a per-assertion write is verifiable per assertion. The old `labels` array, with `label` (true or false) and `abstain` on each entry, is still accepted.',
|
|
29143
29162
|
inputSchema: {
|
|
29144
|
-
experimentId: external_exports.uuid().optional().describe("The experiment ID. Required when any
|
|
29145
|
-
|
|
29146
|
-
|
|
29147
|
-
|
|
29148
|
-
|
|
29149
|
-
|
|
29150
|
-
|
|
29151
|
-
|
|
29152
|
-
|
|
29153
|
-
|
|
29154
|
-
|
|
29155
|
-
|
|
29156
|
-
|
|
29157
|
-
|
|
29158
|
-
|
|
29159
|
-
|
|
29160
|
-
|
|
29161
|
-
|
|
29162
|
-
name: "save_human_labels",
|
|
29163
|
-
title: "Save Human Labels",
|
|
29164
|
-
description: "Record one or more human-authored pass/fail verdicts that are VALIDATED immediately (`labelSource=\"human\"`) on one or more of a trace's approved assertions. Unlike save_agent_labels (the agent's own verdicts), labels set here join the validated dataset the instant they are written and satisfy `search_traces` with `validated: true`. Pass `label` (true=PASS, false=FAIL), `annotation` (the reasoning behind the verdict), and optionally `evidence` as `{ spanId, text }` entries grounded in the evaluated trace. Optionally pass `confidence` (`VeryLow|Low|Medium|High|VeryHigh`). USE ONLY when a human has explicitly decided the verdict, for example saving a known production bug as a test case. This records a verdict on a run that already happened; to record what a trace should do on its next replay, use save_trace_assertions. Do NOT use this for the agent's own first-pass guesses; use save_agent_labels for those. Every entry must carry the `assertionId` of the ONE assertion the human judged (the `[ID: ...]` get_trace_assertions prints), one entry per assertion: labels are never written directly on a trace, so a trace with no approved assertions needs assertions first (save_trace_assertions). get_trace_labels reads these back one line per assertion, keyed by the same assertionId, so a per-assertion write is verifiable per assertion.",
|
|
29163
|
+
experimentId: external_exports.uuid().optional().describe("The experiment ID. Required when any verdict targets a trace by originalTraceId (replay verdicts); ignored otherwise."),
|
|
29164
|
+
verdicts: external_exports.preprocess(parseJsonString, external_exports.array(agentVerdictEntryShape).min(1).max(MAX_VERDICTS_PER_REQUEST)).optional().describe(`One entry per approved assertion, each carrying its assertionId; an archive entry may omit it (1-${MAX_VERDICTS_PER_REQUEST}). Required unless the deprecated labels is sent.`),
|
|
29165
|
+
labels: external_exports.preprocess(parseJsonString, external_exports.array(agentVerdictEntryShape).min(1).max(MAX_VERDICTS_PER_REQUEST)).optional().meta({ deprecated: true }).describe("Deprecated: the old name for verdicts. Refused when verdicts is also sent.")
|
|
29166
|
+
}
|
|
29167
|
+
};
|
|
29168
|
+
var humanVerdictEntryShape = external_exports.object({
|
|
29169
|
+
traceId: external_exports.uuid().describe("The trace ID the verdict is on"),
|
|
29170
|
+
assertionId: external_exports.uuid().describe("The assertion this verdict scores, taken from the `[ID: ...]` get_trace_assertions prints. Required: verdicts are never written directly on a trace."),
|
|
29171
|
+
verdict: external_exports.enum(["pass", "fail"]).optional().describe('"pass" or "fail". Required unless the deprecated label is sent. A person never abstains.'),
|
|
29172
|
+
label: external_exports.boolean().optional().meta({ deprecated: true }).describe('Deprecated: the old spelling of verdict. true is "pass", false is "fail". Refused when verdict is also sent.'),
|
|
29173
|
+
annotation: external_exports.string().min(1).describe("The reasoning behind the verdict. Required."),
|
|
29174
|
+
confidence: confidenceShape.optional().describe("How confident the verdict is: VeryLow / Low / Medium / High / VeryHigh. Optional."),
|
|
29175
|
+
evidence: verdictEvidenceShape.nullable().optional().describe("Span-by-span evidence for this verdict. Omit it to preserve existing evidence. Pass null to clear existing evidence.")
|
|
29176
|
+
});
|
|
29177
|
+
var saveHumanVerdicts = {
|
|
29178
|
+
name: "save_human_verdicts",
|
|
29179
|
+
title: "Save Human Verdicts",
|
|
29180
|
+
description: 'Record one or more pass/fail verdicts a person gave, which are VALIDATED immediately (`verdictSource="human"`), on one or more of a trace\'s approved assertions. Unlike save_agent_verdicts (the agent\'s own verdicts), verdicts set here join the validated dataset the instant they are written and satisfy `search_traces` with `validated: true`. Pass `verdict` ("pass" or "fail"), `annotation` (the reasoning behind the verdict), and optionally `evidence` as `{ spanId, text }` entries grounded in the evaluated trace. Optionally pass `confidence` (`VeryLow|Low|Medium|High|VeryHigh`). USE ONLY when a person has explicitly decided the verdict, for example saving a known production bug as a test case. This records a verdict on a run that already happened; to record what a trace should do on its next replay, use save_trace_assertions. Do NOT use this for the agent\'s own first-pass guesses; use save_agent_verdicts for those. Every entry must carry the `assertionId` of the ONE assertion the person judged (the `[ID: ...]` get_trace_assertions prints), one entry per assertion: verdicts are never written directly on a trace, so a trace with no approved assertions needs assertions first (save_trace_assertions). get_trace_verdicts reads these back one line per assertion, keyed by the same assertionId, so a per-assertion write is verifiable per assertion. The old `labels` array, with `label` (true or false) on each entry, is still accepted.',
|
|
29165
29181
|
inputSchema: {
|
|
29166
|
-
|
|
29167
|
-
|
|
29168
|
-
assertionId: external_exports.uuid().describe("The assertion this verdict scores, taken from the `[ID: ...]` get_trace_assertions prints. Required: labels are never written directly on a trace."),
|
|
29169
|
-
label: external_exports.boolean().describe("true for PASS, false for FAIL. Required."),
|
|
29170
|
-
annotation: external_exports.string().min(1).describe("The reasoning behind the verdict. Required."),
|
|
29171
|
-
confidence: external_exports.enum(["VeryLow", "Low", "Medium", "High", "VeryHigh"]).optional().describe("How confident the verdict is: VeryLow / Low / Medium / High / VeryHigh. Optional."),
|
|
29172
|
-
evidence: labelEvidenceShape.nullable().optional().describe("Span-by-span evidence for this verdict. Omit it to preserve existing evidence. Pass null to clear existing evidence.")
|
|
29173
|
-
})).min(1).max(200)).describe("One entry per approved assertion, each carrying its assertionId (1-200)")
|
|
29182
|
+
verdicts: external_exports.preprocess(parseJsonString, external_exports.array(humanVerdictEntryShape).min(1).max(MAX_VERDICTS_PER_REQUEST)).optional().describe(`One entry per approved assertion, each carrying its assertionId (1-${MAX_VERDICTS_PER_REQUEST}). Required unless the deprecated labels is sent.`),
|
|
29183
|
+
labels: external_exports.preprocess(parseJsonString, external_exports.array(humanVerdictEntryShape).min(1).max(MAX_VERDICTS_PER_REQUEST)).optional().meta({ deprecated: true }).describe("Deprecated: the old name for verdicts. Refused when verdicts is also sent.")
|
|
29174
29184
|
}
|
|
29175
29185
|
};
|
|
29176
29186
|
var assertionTargetShape = external_exports.discriminatedUnion("kind", [
|
|
@@ -29237,6 +29247,10 @@ var saveAssertionCategory = deprecatedAlias(saveCategory, "save_assertion_catego
|
|
|
29237
29247
|
var listAssertionCategories = deprecatedAlias(listCategories, "list_assertion_categories", "List Assertion Categories");
|
|
29238
29248
|
var getAssertionCategory = deprecatedAlias(getCategory, "get_assertion_category", "Get Assertion Category");
|
|
29239
29249
|
var deleteAssertionCategory = deprecatedAlias(deleteCategory, "delete_assertion_category", "Delete Assertion Category");
|
|
29250
|
+
var getTraceLabels = deprecatedAlias(getTraceVerdicts, "get_trace_labels", "Get Trace Labels");
|
|
29251
|
+
var generateLabelEvidence = deprecatedAlias(generateVerdictEvidence, "generate_label_evidence", "Generate Label Evidence");
|
|
29252
|
+
var saveAgentLabels = deprecatedAlias(saveAgentVerdicts, "save_agent_labels", "Save Agent Labels");
|
|
29253
|
+
var saveHumanLabels = deprecatedAlias(saveHumanVerdicts, "save_human_labels", "Save Human Labels");
|
|
29240
29254
|
var generateTraceAssertions = {
|
|
29241
29255
|
name: "generate_trace_assertions",
|
|
29242
29256
|
title: "Generate Trace Assertions",
|
|
@@ -29251,7 +29265,7 @@ var generateTraceAssertions = {
|
|
|
29251
29265
|
var saveTraceAssertions = {
|
|
29252
29266
|
name: "save_trace_assertions",
|
|
29253
29267
|
title: "Save Trace Assertions",
|
|
29254
|
-
description: `Record what SHOULD happen when this trace is replayed. Bitfab stores two kinds of
|
|
29268
|
+
description: `Record what SHOULD happen when this trace is replayed. Bitfab stores two kinds of record on a trace. A VERDICT says how a run that already happened turned out, and that is save_agent_verdicts / save_human_verdicts. An ASSERTION, which is what this tool writes, says what a correct run looks like for THIS specific input, carries no pass/fail of its own, and is checked against a later replay once a reviewer approves it. A trace holds any number of assertions, and each verdict is recorded on one of them. Call it when the user describes the right answer for a particular case, for example "this booking should have picked the 6am flight, not the 9am". This is not a verdict on a run that already happened, which is save_agent_verdicts, and it is not a check that applies to every trace of a function, which is save_grader. Pass \`assertion\` plus optional \`passCriteria\` / \`failCriteria\`, the same trio save_grader takes, so an assertion that proves out across many traces can later be promoted into a grader with no rewriting. \`humanNote\` stores people-only context on the assertion; preserve and return it, but never use it to judge whether a replay passed. \`assigneeEmail\` names the member who should review it, which routes the assertion to that person without deciding anything, so it never changes the approval state. Pass an entry's \`id\` to edit an existing assertion, or omit it to add a new one, so two callers adding different assertions to one trace never overwrite each other. What this tool writes is saved awaiting review, so nothing checks it yet; a reviewer approves it, in Bitfab or with \`approvalState\` on a later call here, and from then on every replay of the trace is judged against it. \`approvalState\` decides an assertion that already exists, so deciding one is \`{ id, approvalState }\` with nothing else: an omitted \`assertion\` keeps the current wording. It is refused on a new assertion, so the call that invents a claim is never the call that puts it into force. One decision covers the assertion and the category it is filed under, so set \`category_id\` and \`approvalState\` in the same entry when you are deciding both; recategorizing on a later call without deciding returns it to not reviewed, since the approval covered the old category. What it gates is whether replays check the assertion at all, so decide from the assertion and the spans it cites rather than from memory of having written it. Rewording an assertion, or changing its criteria, target, or category, returns it to not reviewed unless the same call says otherwise. Call get_trace_assertions first to find the assertion to edit and to avoid creating a duplicate, and read them back before judging a replay, where it lists the approved ones by default. Pass it \`approvalStates: ["pending"]\` to read back drafts awaiting review, including the ones you just wrote. Each assertion with new text is checked against the trace and rewritten when it breaks the writing rules, unless \`guidedRewrite\` is false, so read the response for what was saved and for any claim to save separately. Up to ${MAX_ASSERTIONS_PER_REQUEST} per call.`,
|
|
29255
29269
|
inputSchema: {
|
|
29256
29270
|
traceId: external_exports.uuid().describe("The ORIGINAL trace to attach assertions to. A replay trace id is refused, and the error names the original to retry with, because a replay reads its original's assertions automatically."),
|
|
29257
29271
|
assertions: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.object({
|
|
@@ -29274,7 +29288,7 @@ var saveTraceAssertions = {
|
|
|
29274
29288
|
var getTraceAssertions = {
|
|
29275
29289
|
name: "get_trace_assertions",
|
|
29276
29290
|
title: "Get Trace Assertions",
|
|
29277
|
-
description: `Read what SHOULD happen when one or more traces are replayed: each trace's assertions, their review state, their pass/fail criteria, people-only human note, who is assigned to review each one, and what part of the evaluated trace each one checks. By default only assertions a person has approved are returned, because only those are checked on a replay; a trace whose assertions are all still awaiting review reads the same as one with none. Pass \`approvalStates\` to read other review states: \`["pending"]\` for the assertions still awaiting review, including the drafts generate_trace_assertions saved, so a batch of them can be reviewed and then decided with save_trace_assertions \`approvalState\`; add \`"rejected"\` to see the ones turned down. Judge a replay only against the approved ones. To find assertions without knowing which traces carry them, such as every draft awaiting review on a function, use list_trace_assertions. Each trace also reports its assertion generation, if one ran: running, completed with how many drafts it saved for review, or failed with the reason. Categorized assertions include category_id and the category's id, title, and description. A human note is returned so it can be read and edited, but it is never assessment evidence: judge only from the assertion, pass/fail criteria, and evaluated trace. Call this before judging a replay so the verdict is measured against what the user actually asked for rather than a guess, and before save_trace_assertions to find the assertion to edit or to avoid creating a duplicate. No span content is loaded, so one call accepts up to ${GET_TRACE_ASSERTIONS_MAX_IDS} ids. Accepts original trace ids and replay trace ids alike: a replay with no assertions of its own reads its original's, and the response says which original they came from. An assertion whose target cannot be found on the trace being evaluated is errored, never passed, so record it with
|
|
29291
|
+
description: `Read what SHOULD happen when one or more traces are replayed: each trace's assertions, their review state, their pass/fail criteria, people-only human note, who is assigned to review each one, and what part of the evaluated trace each one checks. By default only assertions a person has approved are returned, because only those are checked on a replay; a trace whose assertions are all still awaiting review reads the same as one with none. Pass \`approvalStates\` to read other review states: \`["pending"]\` for the assertions still awaiting review, including the drafts generate_trace_assertions saved, so a batch of them can be reviewed and then decided with save_trace_assertions \`approvalState\`; add \`"rejected"\` to see the ones turned down. Judge a replay only against the approved ones. To find assertions without knowing which traces carry them, such as every draft awaiting review on a function, use list_trace_assertions. Each trace also reports its assertion generation, if one ran: running, completed with how many drafts it saved for review, or failed with the reason. Categorized assertions include category_id and the category's id, title, and description. A human note is returned so it can be read and edited, but it is never assessment evidence: judge only from the assertion, pass/fail criteria, and evaluated trace. Call this before judging a replay so the verdict is measured against what the user actually asked for rather than a guess, and before save_trace_assertions to find the assertion to edit or to avoid creating a duplicate. No span content is loaded, so one call accepts up to ${GET_TRACE_ASSERTIONS_MAX_IDS} ids. Accepts original trace ids and replay trace ids alike: a replay with no assertions of its own reads its original's, and the response says which original they came from. An assertion whose target cannot be found on the trace being evaluated is errored, never passed, so record it with save_agent_verdicts \`skip\` rather than a FAIL.`,
|
|
29278
29292
|
inputSchema: {
|
|
29279
29293
|
traceIds: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.uuid()).min(1).max(GET_TRACE_ASSERTIONS_MAX_IDS)).describe(`Original trace IDs to read assertions for (1-${GET_TRACE_ASSERTIONS_MAX_IDS})`),
|
|
29280
29294
|
approvalStates: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.enum(["pending", "approved", "rejected"])).min(1).max(3)).optional().describe('Review states to include: "approved" (checked on every replay), "pending" (awaiting review, including generated drafts), "rejected" (turned down, never checked). Defaults to ["approved"], which is what a replay is judged against. Pass ["pending"] to review drafts, or all three to see everything.')
|
|
@@ -29304,7 +29318,7 @@ var archiveTraceAssertions = {
|
|
|
29304
29318
|
var saveGrader = {
|
|
29305
29319
|
name: "save_grader",
|
|
29306
29320
|
title: "Save Grader",
|
|
29307
|
-
description: `Create or edit a grader: a pass/fail check that describes what must hold for a traced function (e.g. 'The reply never invents order numbers'). Call when the user asks to add, define, update, rename, archive, or restore a grader or check for a traced function. By default the grader is an LLM-as-judge that Bitfab runs; pass external: true when the user evaluates traces themselves. To create, pass traceFunctionKey + name + evaluationFocus. To edit, pass graderId (from list_graders) plus only the fields to change; saving with the name of an existing grader on the same function updates that grader instead of creating a duplicate. Set status to "archived" to retire a grader; any later save that omits status (or sets "active") restores it. On edit, pass an empty string for passCriteria/failCriteria to clear them. After a successful create or update, present the returned grader definition to the user, including its evaluation focus and any pass/fail criteria; do not respond with only a generic success confirmation. Graders are definitions only for now: nothing auto-evaluates them on new traces yet, so do not promise live grading. Call list_graders first to find ids and avoid duplicates. An external grader is one the user runs themselves (their own eval harness, CI, a human review queue): Bitfab never runs it, and its verdicts are posted with
|
|
29321
|
+
description: `Create or edit a grader: a pass/fail check that describes what must hold for a traced function (e.g. 'The reply never invents order numbers'). Call when the user asks to add, define, update, rename, archive, or restore a grader or check for a traced function. By default the grader is an LLM-as-judge that Bitfab runs; pass external: true when the user evaluates traces themselves. To create, pass traceFunctionKey + name + evaluationFocus. To edit, pass graderId (from list_graders) plus only the fields to change; saving with the name of an existing grader on the same function updates that grader instead of creating a duplicate. Set status to "archived" to retire a grader; any later save that omits status (or sets "active") restores it. On edit, pass an empty string for passCriteria/failCriteria to clear them. After a successful create or update, present the returned grader definition to the user, including its evaluation focus and any pass/fail criteria; do not respond with only a generic success confirmation. Graders are definitions only for now: nothing auto-evaluates them on new traces yet, so do not promise live grading. Call list_graders first to find ids and avoid duplicates. An external grader is one the user runs themselves (their own eval harness, CI, a human review queue): Bitfab never runs it, and its verdicts are posted with save_grader_verdicts. A grader's external setting is fixed at creation and cannot be changed on edit, and external graders take no model.`,
|
|
29308
29322
|
inputSchema: {
|
|
29309
29323
|
graderId: external_exports.uuid().optional().describe("Id of an existing grader to edit (from list_graders or a previous save). Omit to create a new grader (or update-by-name)."),
|
|
29310
29324
|
traceFunctionKey: external_exports.string().min(1).optional().describe("The traced function the grader applies to. Required when graderId is omitted; ignored when it is set."),
|
|
@@ -29312,19 +29326,15 @@ var saveGrader = {
|
|
|
29312
29326
|
evaluationFocus: external_exports.string().min(1).optional().describe("What this grader evaluates: the property a trace of this function must satisfy, written as a concrete, checkable statement. Required when creating; on edit, omit to keep the current value."),
|
|
29313
29327
|
passCriteria: external_exports.string().optional().describe("Optional: what a PASSING trace looks like. On edit, omit to keep the stored value; pass an empty string to clear it."),
|
|
29314
29328
|
failCriteria: external_exports.string().optional().describe("Optional: what a FAILING trace looks like. On edit, omit to keep the stored value; pass an empty string to clear it."),
|
|
29315
|
-
// The MCP surface exposes only the two grader statuses this tool owns.
|
|
29316
|
-
// Keep the enum in sync with bitfab-web's save_grader route schema.
|
|
29317
29329
|
status: external_exports.enum(["active", "archived"]).optional().describe(`The grader's status: "active" (the default for a create or edit) or "archived" to retire it (hidden from list_graders by default). Omit on edit to keep it active / restore an archived grader.`),
|
|
29318
|
-
// Keep the enum in sync with bitfab-web's save_grader route schema
|
|
29319
|
-
// (GRADER_MODEL_SLUGS in graderModels.ts).
|
|
29320
29330
|
model: external_exports.enum(["gemini-2-5-flash", "sol", "terra", "opus-4-8", "gemini-3-1-pro"]).optional().describe("Optional: the judge model this grader runs on. One of: gemini-2-5-flash, sol, terra, opus-4-8, gemini-3-1-pro. Omit to keep the current value (defaults to gemini-2-5-flash)."),
|
|
29321
|
-
external: external_exports.boolean().optional().describe("Create an external grader: Bitfab never runs it, and its verdicts arrive through
|
|
29331
|
+
external: external_exports.boolean().optional().describe("Create an external grader: Bitfab never runs it, and its verdicts arrive through save_grader_verdicts. Only honored when creating; on edit it must match the grader or be omitted.")
|
|
29322
29332
|
}
|
|
29323
29333
|
};
|
|
29324
29334
|
var listGraders = {
|
|
29325
29335
|
name: "list_graders",
|
|
29326
29336
|
title: "List Graders",
|
|
29327
|
-
description: "List the graders for a traced function: LLM-as-judge graders Bitfab runs, and external graders (marked 'Runs: externally') whose verdicts the user posts with
|
|
29337
|
+
description: "List the graders for a traced function: LLM-as-judge graders Bitfab runs, and external graders (marked 'Runs: externally') whose verdicts the user posts with save_grader_verdicts. Each comes with id, name, status, evaluation focus, and pass/fail criteria. Call before save_grader to find the grader to edit or to avoid creating a duplicate. Results are newest-first and paginated. Archived graders are hidden unless includeArchived is true.",
|
|
29328
29338
|
inputSchema: {
|
|
29329
29339
|
traceFunctionKey: external_exports.string().min(1).describe("The trace function key to list graders for"),
|
|
29330
29340
|
includeArchived: external_exports.preprocess(parseJsonString, external_exports.boolean()).optional().describe("Include archived graders (default false)"),
|
|
@@ -29336,11 +29346,11 @@ var listGraders = {
|
|
|
29336
29346
|
var saveDataset = {
|
|
29337
29347
|
name: "save_dataset",
|
|
29338
29348
|
title: "Save Dataset",
|
|
29339
|
-
description: "Create or edit a
|
|
29349
|
+
description: "Create or edit a dataset for a traced function. Datasets are named buckets of traces (e.g. 'Hallucination failures', 'Edge cases for grader X') that humans review and that experiments replay against. To create, pass traceFunctionKey, a short human-readable name, and an optional description. Saving with the name of an existing dataset on the same trace function updates that dataset instead of creating a duplicate, so re-running a flow is safe; pass a new description to change it, or omit it to leave the current one. To rename a dataset or change its description in place, pass its datasetId with a new name and/or description; its id, traces, and graders are kept, and a name already used by another dataset on the same trace function is refused. Pass golden: true to mark the dataset as golden, a trusted reference set to replay and grade changes against (golden datasets are listed first, for the whole organization, in the Bitfab app and in list_datasets), or golden: false to unmark it; omit golden to leave it as it is. This works on create, on a save by name, and with datasetId. Returns the dataset id; use it with add_traces_to_dataset to populate. Call list_datasets first when you need to see what already exists.",
|
|
29340
29350
|
inputSchema: {
|
|
29341
29351
|
datasetId: external_exports.uuid().optional().describe("Existing dataset id (from list_datasets) to rename or redescribe in place. Omit to create a dataset or save one by name."),
|
|
29342
29352
|
traceFunctionKey: external_exports.string().min(1).optional().describe("The trace function key the dataset is scoped to (must match traces you'll add). Required without datasetId."),
|
|
29343
|
-
name: external_exports.string().min(1).optional().describe("Short human-readable name shown in the
|
|
29353
|
+
name: external_exports.string().min(1).optional().describe("Short human-readable name shown in the Bitfab app (e.g. 'Hallucination failures'). Required without datasetId. With datasetId, the new name; omit to keep the current one."),
|
|
29344
29354
|
description: external_exports.string().optional().describe("Optional longer description of what's in the dataset. With datasetId, omit to keep the current one or pass an empty string to clear it."),
|
|
29345
29355
|
golden: external_exports.boolean().optional().describe("true marks the dataset as golden, false unmarks it. Omit to leave it as it is.")
|
|
29346
29356
|
}
|
|
@@ -29392,7 +29402,7 @@ var removeGradersFromDataset = {
|
|
|
29392
29402
|
var rerunGradersOnDataset = {
|
|
29393
29403
|
name: "rerun_graders_on_dataset",
|
|
29394
29404
|
title: "Re-run Graders on Dataset",
|
|
29395
|
-
description: "Re-score every trace in a dataset with its attached graders, overwriting their previous verdicts. This is how you grade traces that were added before a grader existed, or re-score everything after editing a grader's criteria: attaching a grader does not itself grade anything. Omit graderIds to re-run every grader attached to the dataset, or pass a subset; ids that are not attached are rejected rather than silently skipped. Waits up to 90 seconds for the run to finish and reports how many traces were graded; if it is still running, call again with the same arguments to check progress (it reports the running job rather than starting a second one). Read the resulting verdicts with
|
|
29405
|
+
description: "Re-score every trace in a dataset with its attached graders, overwriting their previous verdicts. This is how you grade traces that were added before a grader existed, or re-score everything after editing a grader's criteria: attaching a grader does not itself grade anything. Omit graderIds to re-run every grader attached to the dataset, or pass a subset; ids that are not attached are rejected rather than silently skipped. Waits up to 90 seconds for the run to finish and reports how many traces were graded; if it is still running, call again with the same arguments to check progress (it reports the running job rather than starting a second one). Read the resulting verdicts with get_grader_verdicts.",
|
|
29396
29406
|
inputSchema: {
|
|
29397
29407
|
datasetId: external_exports.uuid().describe("The dataset id (from save_dataset or list_datasets)"),
|
|
29398
29408
|
graderIds: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.uuid()).min(1).max(100)).optional().describe("Grader ids to re-run (1-100). Omit to re-run every grader attached to the dataset.")
|
|
@@ -29401,7 +29411,7 @@ var rerunGradersOnDataset = {
|
|
|
29401
29411
|
var rerunGradersOnExperiment = {
|
|
29402
29412
|
name: "rerun_graders_on_experiment",
|
|
29403
29413
|
title: "Re-run Graders on Experiment",
|
|
29404
|
-
description: "Re-score an experiment's completed replay traces with its attached graders, overwriting their previous verdicts. Use this after attaching a grader to an already-completed experiment (which persists the assignment but does not grade the existing traces) or after editing a grader's criteria. Only the replays belonging to this experiment are graded, never the originals they were compared against. Omit graderIds to re-run every grader attached to the experiment, or pass a subset; ids that are not attached are rejected. Waits up to 90 seconds and reports how many traces were graded; if it is still running, call again with the same arguments to check progress. Read the resulting verdicts with
|
|
29414
|
+
description: "Re-score an experiment's completed replay traces with its attached graders, overwriting their previous verdicts. Use this after attaching a grader to an already-completed experiment (which persists the assignment but does not grade the existing traces) or after editing a grader's criteria. Only the replays belonging to this experiment are graded, never the originals they were compared against. Omit graderIds to re-run every grader attached to the experiment, or pass a subset; ids that are not attached are rejected. Waits up to 90 seconds and reports how many traces were graded; if it is still running, call again with the same arguments to check progress. Read the resulting verdicts with get_grader_verdicts.",
|
|
29405
29415
|
inputSchema: {
|
|
29406
29416
|
experimentId: external_exports.uuid().describe("The experiment ID, from list_experiments"),
|
|
29407
29417
|
graderIds: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.uuid()).min(1).max(100)).optional().describe("Grader ids to re-run (1-100). Omit to re-run every grader attached to the experiment.")
|
|
@@ -29457,7 +29467,7 @@ var listExperiments = {
|
|
|
29457
29467
|
var listExperimentTraces = {
|
|
29458
29468
|
name: "list_experiment_traces",
|
|
29459
29469
|
title: "List Experiment Traces",
|
|
29460
|
-
description: "Get individual trace results for an experiment, including each replay trace's verdict (fixed, regressed, still-passing, still-failing, original-
|
|
29470
|
+
description: "Get individual trace results for an experiment, including each replay trace's verdict (fixed, regressed, still-passing, still-failing, original-no-verdict (the original has no verdict), replay-no-verdict (the replay has no verdict yet), capture-incomplete, unpaired, skipped) by comparing against the original trace's verdict, plus the replay's duration and token usage (input, output, cached, total) for the replay and the paired original so you can reason about latency, cost, and cache-read deltas. Use after list_experiments to drill into a specific experiment's results.",
|
|
29461
29471
|
inputSchema: {
|
|
29462
29472
|
experimentId: external_exports.uuid().describe("The experiment ID to get traces for")
|
|
29463
29473
|
}
|
|
@@ -29544,31 +29554,36 @@ var getExperiment = {
|
|
|
29544
29554
|
experimentId: external_exports.uuid().describe("The experiment ID, from list_experiments")
|
|
29545
29555
|
}
|
|
29546
29556
|
};
|
|
29547
|
-
var
|
|
29548
|
-
name: "
|
|
29549
|
-
title: "Get Grader
|
|
29550
|
-
description: `Read the INDIVIDUAL verdicts each grader recorded, one row per grader per trace, with the grader's reason, its failure diagnostic, the confidence, and whether the verdict came from a
|
|
29557
|
+
var getGraderVerdicts = {
|
|
29558
|
+
name: "get_grader_verdicts",
|
|
29559
|
+
title: "Get Grader Verdicts",
|
|
29560
|
+
description: `Read the INDIVIDUAL verdicts each grader recorded, one row per grader per trace, with the grader's reason, its failure diagnostic, the confidence, and whether the verdict came from a person, a grader Bitfab ran, or an external grader whose verdict was posted from outside Bitfab with save_grader_verdicts. This is the per-grader breakdown that get_trace_verdicts does not show: that tool returns one grader-agnostic verdict per trace, so use it for a dataset's overall pass/fail and use this one to see WHICH check failed and why. Pass traceIds to see every grader's verdict on those traces, graderId to see that grader's most recent verdicts across traces (newest first, use it to diagnose a grader that is misfiring), or both to narrow to one grader on specific traces. Call list_graders first if you need grader ids.`,
|
|
29551
29561
|
inputSchema: {
|
|
29552
|
-
traceIds: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.uuid()).min(1).max(
|
|
29562
|
+
traceIds: external_exports.preprocess(parseJsonString, external_exports.array(external_exports.uuid()).min(1).max(GET_GRADER_VERDICTS_MAX_IDS)).optional().describe(`Trace IDs to read grader verdicts for (1-${GET_GRADER_VERDICTS_MAX_IDS}). Omit to read by grader instead.`),
|
|
29553
29563
|
graderId: external_exports.uuid().optional().describe("Restrict to one grader (from list_graders). On its own, returns that grader's most recent verdicts across all traces."),
|
|
29554
|
-
limit: external_exports.preprocess(parseJsonString, external_exports.number().int().min(1).max(
|
|
29555
|
-
}
|
|
29556
|
-
};
|
|
29557
|
-
var
|
|
29558
|
-
|
|
29559
|
-
|
|
29560
|
-
|
|
29564
|
+
limit: external_exports.preprocess(parseJsonString, external_exports.number().int().min(1).max(MAX_GRADER_VERDICT_LIMIT)).optional().describe(`Max verdicts to return when reading by grader alone (default ${DEFAULT_GRADER_VERDICT_LIMIT}, max ${MAX_GRADER_VERDICT_LIMIT}). Ignored when traceIds is given.`)
|
|
29565
|
+
}
|
|
29566
|
+
};
|
|
29567
|
+
var graderVerdictEntryShape = external_exports.object({
|
|
29568
|
+
graderId: external_exports.uuid().describe("The external grader that produced this verdict (from list_graders or save_grader)."),
|
|
29569
|
+
traceId: external_exports.uuid().describe("The trace the verdict is about."),
|
|
29570
|
+
verdict: external_exports.enum(["pass", "fail"]).optional().describe('"pass" or "fail". Required unless the deprecated label is sent.'),
|
|
29571
|
+
label: external_exports.boolean().optional().meta({ deprecated: true }).describe('Deprecated: the old spelling of verdict. true is "pass", false is "fail". Refused when verdict is also sent.'),
|
|
29572
|
+
reason: external_exports.string().min(1).optional().describe("Why the grader reached this verdict. Optional."),
|
|
29573
|
+
failureDiagnostic: external_exports.string().min(1).optional().describe("For a FAIL: what went wrong in the trace, in a form someone fixing it can act on. Optional."),
|
|
29574
|
+
confidence: confidenceShape.optional().describe("How confident the grader is: VeryLow / Low / Medium / High / VeryHigh. Optional.")
|
|
29575
|
+
});
|
|
29576
|
+
var saveGraderVerdicts = {
|
|
29577
|
+
name: "save_grader_verdicts",
|
|
29578
|
+
title: "Save Grader Verdicts",
|
|
29579
|
+
description: `Record verdicts for EXTERNAL graders: graders created with save_grader external: true, which Bitfab never runs because the user evaluates traces somewhere else (their own eval harness, CI, a review queue). Each entry is one grader's pass/fail on one trace, written as that grader's own verdict, so it shows up everywhere Bitfab-run grader verdicts do: get_grader_verdicts, dataset and experiment pass rates, and the trace's grader panel. Saving again for the same grader and trace replaces the earlier verdict. Rejects every grader that is not external: Bitfab runs its own graders, and a person's verdict on a trace belongs in save_human_verdicts. Up to ${SAVE_GRADER_VERDICTS_MAX_ENTRIES} entries per call; the whole call is rejected if any entry is invalid. The old \`labels\` array, with \`label\` (true or false) on each entry, is still accepted.`,
|
|
29561
29580
|
inputSchema: {
|
|
29562
|
-
|
|
29563
|
-
|
|
29564
|
-
traceId: external_exports.uuid().describe("The trace the verdict is about."),
|
|
29565
|
-
label: external_exports.boolean().describe("true for PASS, false for FAIL. Required."),
|
|
29566
|
-
reason: external_exports.string().min(1).optional().describe("Why the grader reached this verdict. Optional."),
|
|
29567
|
-
failureDiagnostic: external_exports.string().min(1).optional().describe("For a FAIL: what went wrong in the trace, in a form someone fixing it can act on. Optional."),
|
|
29568
|
-
confidence: external_exports.enum(["VeryLow", "Low", "Medium", "High", "VeryHigh"]).optional().describe("How confident the grader is: VeryLow / Low / Medium / High / VeryHigh. Optional.")
|
|
29569
|
-
})).min(1).max(SAVE_GRADER_LABELS_MAX_ENTRIES)).describe(`One entry per grader per trace (1-${SAVE_GRADER_LABELS_MAX_ENTRIES}).`)
|
|
29581
|
+
verdicts: external_exports.preprocess(parseJsonString, external_exports.array(graderVerdictEntryShape).min(1).max(SAVE_GRADER_VERDICTS_MAX_ENTRIES)).optional().describe(`One entry per grader per trace (1-${SAVE_GRADER_VERDICTS_MAX_ENTRIES}). Required unless the deprecated labels is sent.`),
|
|
29582
|
+
labels: external_exports.preprocess(parseJsonString, external_exports.array(graderVerdictEntryShape).min(1).max(SAVE_GRADER_VERDICTS_MAX_ENTRIES)).optional().meta({ deprecated: true }).describe("Deprecated: the old name for verdicts. Refused when verdicts is also sent.")
|
|
29570
29583
|
}
|
|
29571
29584
|
};
|
|
29585
|
+
var getGraderLabels = deprecatedAlias(getGraderVerdicts, "get_grader_labels", "Get Grader Labels");
|
|
29586
|
+
var saveGraderLabels = deprecatedAlias(saveGraderVerdicts, "save_grader_labels", "Save Grader Labels");
|
|
29572
29587
|
var getSimPlan = {
|
|
29573
29588
|
name: "get_sim_plan",
|
|
29574
29589
|
title: "Get Sim Plan",
|
|
@@ -29668,6 +29683,8 @@ var generateScenarioAssertions = {
|
|
|
29668
29683
|
}
|
|
29669
29684
|
};
|
|
29670
29685
|
var ALL_TOOL_CONTRACTS = [
|
|
29686
|
+
getGraderVerdicts,
|
|
29687
|
+
saveGraderVerdicts,
|
|
29671
29688
|
getGraderLabels,
|
|
29672
29689
|
saveGraderLabels,
|
|
29673
29690
|
getExperiment,
|
|
@@ -29682,10 +29699,14 @@ var ALL_TOOL_CONTRACTS = [
|
|
|
29682
29699
|
listTraceFunctions,
|
|
29683
29700
|
searchTraces,
|
|
29684
29701
|
getTraces,
|
|
29702
|
+
getTraceVerdicts,
|
|
29703
|
+
generateVerdictEvidence,
|
|
29685
29704
|
getTraceLabels,
|
|
29686
29705
|
generateLabelEvidence,
|
|
29687
29706
|
getSpanField,
|
|
29688
29707
|
getSpan,
|
|
29708
|
+
saveAgentVerdicts,
|
|
29709
|
+
saveHumanVerdicts,
|
|
29689
29710
|
saveAgentLabels,
|
|
29690
29711
|
saveHumanLabels,
|
|
29691
29712
|
saveCategory,
|
|
@@ -30175,12 +30196,18 @@ function createBitfabToolHandlers(platform2, getConfig2, pluginVersion) {
|
|
|
30175
30196
|
function proxyToolCall(toolName, args) {
|
|
30176
30197
|
return proxy.toolCall(getConfig2(), toolName, withLegacyExperimentKeys(args));
|
|
30177
30198
|
}
|
|
30178
|
-
|
|
30179
|
-
|
|
30180
|
-
|
|
30181
|
-
|
|
30182
|
-
|
|
30183
|
-
|
|
30199
|
+
function withLegacySourceTraceId(entries) {
|
|
30200
|
+
return entries?.map((entry) => entry.originalTraceId !== void 0 && entry.sourceTraceId === void 0 ? { ...entry, sourceTraceId: entry.originalTraceId } : entry);
|
|
30201
|
+
}
|
|
30202
|
+
function handleSaveAgentVerdictsAs(toolName) {
|
|
30203
|
+
return async (args) => {
|
|
30204
|
+
const { experimentId, verdicts, labels } = args;
|
|
30205
|
+
return proxyToolCall(toolName, {
|
|
30206
|
+
experimentId,
|
|
30207
|
+
verdicts: withLegacySourceTraceId(verdicts),
|
|
30208
|
+
labels: withLegacySourceTraceId(labels)
|
|
30209
|
+
});
|
|
30210
|
+
};
|
|
30184
30211
|
}
|
|
30185
30212
|
async function handleSaveExperiment(args) {
|
|
30186
30213
|
const { experimentId, name, notes, experimentGroupId } = args;
|
|
@@ -30230,7 +30257,8 @@ function createBitfabToolHandlers(platform2, getConfig2, pluginVersion) {
|
|
|
30230
30257
|
return proxyToolCall("save_scenario", { ...rest, ...read });
|
|
30231
30258
|
}
|
|
30232
30259
|
const specialHandlers = {
|
|
30233
|
-
[
|
|
30260
|
+
[saveAgentVerdicts.name]: handleSaveAgentVerdictsAs(saveAgentVerdicts.name),
|
|
30261
|
+
[saveAgentLabels.name]: handleSaveAgentVerdictsAs(saveAgentLabels.name),
|
|
30234
30262
|
[saveExperiment.name]: handleSaveExperiment,
|
|
30235
30263
|
[saveExperimentGroup.name]: handleSaveExperimentGroup,
|
|
30236
30264
|
[saveScenario.name]: handleSaveScenario
|
|
@@ -31098,10 +31126,10 @@ var semver2 = __toESM(require_semver2(), 1);
|
|
|
31098
31126
|
|
|
31099
31127
|
// ../bitfab-plugin-lib/dist/bakedSdkVersions.js
|
|
31100
31128
|
var BAKED_SDK_VERSIONS = {
|
|
31101
|
-
typescript: "0.
|
|
31102
|
-
python: "0.
|
|
31103
|
-
ruby: "0.
|
|
31104
|
-
go: "0.
|
|
31129
|
+
typescript: "0.66.0",
|
|
31130
|
+
python: "0.66.0",
|
|
31131
|
+
ruby: "0.66.0",
|
|
31132
|
+
go: "0.66.0"
|
|
31105
31133
|
};
|
|
31106
31134
|
|
|
31107
31135
|
// ../bitfab-plugin-lib/dist/installedSdk.js
|
|
@@ -33851,7 +33879,7 @@ var assistantFlow = Flow.parse({
|
|
|
33851
33879
|
id: "assistant",
|
|
33852
33880
|
title: "Bitfab Assistant (retired)",
|
|
33853
33881
|
frontmatter: {
|
|
33854
|
-
description: "Retired. Only use when the user explicitly types the bitfab assistant command by name; it tells them the assistant has been retired. Never use it for requests about traces, datasets, labels, replays, experiments, or improving a traced function: handle those directly with the Bitfab MCP tools"
|
|
33882
|
+
description: "Retired. Only use when the user explicitly types the bitfab assistant command by name; it tells them the assistant has been retired. Never use it for requests about traces, datasets, labels, verdicts, replays, experiments, or improving a traced function: handle those directly with the Bitfab MCP tools"
|
|
33855
33883
|
},
|
|
33856
33884
|
entries: {
|
|
33857
33885
|
default: "retired/explain"
|
|
@@ -34279,7 +34307,7 @@ var setupFlow = Flow.parse({
|
|
|
34279
34307
|
id: "setup",
|
|
34280
34308
|
title: "Bitfab Setup",
|
|
34281
34309
|
frontmatter: {
|
|
34282
|
-
description: "Set up and maintain Bitfab tracing, replay registries, and cloud replay. Use for instrumenting AI/LLM code, adding observability or evaluation, tracing another workflow, changing captured inputs/outputs, re-instrumenting a function, moving side effects across trace boundaries, inspecting missing traces, explaining Bitfab, login, organization switching, session-log consent, database snapshots, templates, or read-only repo instrumentation recommendations (analyze-repo). Also use for 'setup cloud', 'set up cloud replay', or 'replay on GitHub'. Re-enter this skill for each additional function to instrument, even after earlier setup. Do not use for improving output quality, pass rates, labeling, or experiments (the agent does those directly with the Bitfab MCP tools), or upgrading SDK/plugin versions (use bitfab:update)",
|
|
34310
|
+
description: "Set up and maintain Bitfab tracing, replay registries, and cloud replay. Use for instrumenting AI/LLM code, adding observability or evaluation, tracing another workflow, changing captured inputs/outputs, re-instrumenting a function, moving side effects across trace boundaries, inspecting missing traces, explaining Bitfab, login, organization switching, session-log consent, database snapshots, templates, or read-only repo instrumentation recommendations (analyze-repo). Also use for 'setup cloud', 'set up cloud replay', or 'replay on GitHub'. Re-enter this skill for each additional function to instrument, even after earlier setup. Do not use for improving output quality, pass rates, verdicts (labeling), or experiments (the agent does those directly with the Bitfab MCP tools), or upgrading SDK/plugin versions (use bitfab:update)",
|
|
34283
34311
|
argumentHint: {
|
|
34284
34312
|
deriveFromModes: true,
|
|
34285
34313
|
suffix: "[what to do]"
|
|
@@ -36601,7 +36629,7 @@ Finding out what happened:
|
|
|
36601
36629
|
|
|
36602
36630
|
Writing down what should happen:
|
|
36603
36631
|
- An assertion says what should happen when one trace is replayed. Draft them from what the trace did with ${generateTraceAssertions.name}, or write them with ${saveTraceAssertions.name}. They wait for review until approved. Retire one with ${archiveTraceAssertions.name}.
|
|
36604
|
-
- A verdict says whether a run passed one assertion. Read a trace's assertions with ${getTraceAssertions.name}, then record your verdicts with ${
|
|
36632
|
+
- A verdict says whether a run passed one assertion. Read a trace's assertions with ${getTraceAssertions.name}, then record your verdicts with ${saveAgentVerdicts.name}. Use ${saveHumanVerdicts.name} only when the user gives the verdict.
|
|
36605
36633
|
- A grader is a pass/fail check for every trace of a function. Create one with ${saveGrader.name}.
|
|
36606
36634
|
- A scenario describes the situation one run was in. Read it with ${getScenario.name} and build it with ${saveScenario.name}.
|
|
36607
36635
|
|
package/package.json
CHANGED