@bitfab/sdk 0.54.12 → 0.54.14
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 +0 -19
- package/dist/autoTrace.cjs.map +1 -1
- package/dist/autoTrace.d.cts +1 -3
- package/dist/autoTrace.d.ts +1 -3
- package/dist/autoTrace.js +1 -5
- package/dist/{chunk-I5NJU64I.js → chunk-DXBYY5RS.js} +22 -16
- package/dist/chunk-DXBYY5RS.js.map +1 -0
- package/dist/{chunk-GZI455WP.js → chunk-KMSJJOT6.js} +21 -15
- package/dist/chunk-KMSJJOT6.js.map +1 -0
- package/dist/{chunk-EGWJYCNT.js → chunk-RCHSYWKI.js} +2 -19
- package/dist/chunk-RCHSYWKI.js.map +1 -0
- package/dist/{chunk-Q3X54UPA.js → chunk-RMJAAI6S.js} +37 -7
- package/dist/chunk-RMJAAI6S.js.map +1 -0
- package/dist/{chunk-XTUINMAL.js → chunk-ROQKK6YZ.js} +9 -3
- package/dist/chunk-ROQKK6YZ.js.map +1 -0
- package/dist/{chunk-JEFU6FTD.js → chunk-V2TWHXTK.js} +33 -60
- package/dist/chunk-V2TWHXTK.js.map +1 -0
- package/dist/{http-X4YOOM54.js → http-PNENM32G.js} +2 -2
- package/dist/{http-FJVBYZES.js → http-X5LJ4GM6.js} +2 -2
- package/dist/index.cjs +54 -83
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -14
- package/dist/index.d.ts +16 -14
- package/dist/index.js +4 -4
- package/dist/node.cjs +54 -83
- 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 +4 -4
- package/dist/{replay-IA5VRWHD.js → replay-BRLNXOAL.js} +3 -3
- package/dist/replayCli.js +2 -2
- package/dist/seedCli.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-EGWJYCNT.js.map +0 -1
- package/dist/chunk-GZI455WP.js.map +0 -1
- package/dist/chunk-I5NJU64I.js.map +0 -1
- package/dist/chunk-JEFU6FTD.js.map +0 -1
- package/dist/chunk-Q3X54UPA.js.map +0 -1
- package/dist/chunk-XTUINMAL.js.map +0 -1
- /package/dist/{http-FJVBYZES.js.map → http-PNENM32G.js.map} +0 -0
- /package/dist/{http-X4YOOM54.js.map → http-X5LJ4GM6.js.map} +0 -0
- /package/dist/{replay-IA5VRWHD.js.map → replay-BRLNXOAL.js.map} +0 -0
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
flushTraces,
|
|
7
7
|
parseRetryAfterMs,
|
|
8
8
|
serializePayloadBody
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-DXBYY5RS.js";
|
|
10
10
|
import "./chunk-VCRFFCLY.js";
|
|
11
11
|
export {
|
|
12
12
|
BitfabError,
|
|
@@ -17,4 +17,4 @@ export {
|
|
|
17
17
|
parseRetryAfterMs,
|
|
18
18
|
serializePayloadBody
|
|
19
19
|
};
|
|
20
|
-
//# sourceMappingURL=http-
|
|
20
|
+
//# sourceMappingURL=http-PNENM32G.js.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
flushTraces,
|
|
7
7
|
parseRetryAfterMs,
|
|
8
8
|
serializePayloadBody
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KMSJJOT6.js";
|
|
10
10
|
export {
|
|
11
11
|
BitfabError,
|
|
12
12
|
HttpClient,
|
|
@@ -16,4 +16,4 @@ export {
|
|
|
16
16
|
parseRetryAfterMs,
|
|
17
17
|
serializePayloadBody
|
|
18
18
|
};
|
|
19
|
-
//# sourceMappingURL=http-
|
|
19
|
+
//# sourceMappingURL=http-X5LJ4GM6.js.map
|
package/dist/index.cjs
CHANGED
|
@@ -42,7 +42,7 @@ var __version__, __packageName__;
|
|
|
42
42
|
var init_version_generated = __esm({
|
|
43
43
|
"src/version.generated.ts"() {
|
|
44
44
|
"use strict";
|
|
45
|
-
__version__ = "0.54.
|
|
45
|
+
__version__ = "0.54.14";
|
|
46
46
|
__packageName__ = "@bitfab/sdk";
|
|
47
47
|
}
|
|
48
48
|
});
|
|
@@ -1256,6 +1256,7 @@ var init_simulationPlan = __esm({
|
|
|
1256
1256
|
}
|
|
1257
1257
|
this.warnNeverLoaded();
|
|
1258
1258
|
this.warnDropped();
|
|
1259
|
+
return this.held.length === 0;
|
|
1259
1260
|
}
|
|
1260
1261
|
waitForFirstLoad(timeoutMs) {
|
|
1261
1262
|
const firstLoad = this.firstLoad();
|
|
@@ -2078,9 +2079,14 @@ __export(http_exports, {
|
|
|
2078
2079
|
});
|
|
2079
2080
|
async function releaseHeldExternalSpans(timeoutMs) {
|
|
2080
2081
|
const deadline = Date.now() + Math.max(timeoutMs, 0);
|
|
2082
|
+
let released = true;
|
|
2081
2083
|
for (const client of [...liveHttpClients]) {
|
|
2082
|
-
await client.releaseHeldExternalSpans?.(
|
|
2084
|
+
const result = await client.releaseHeldExternalSpans?.(
|
|
2085
|
+
Math.max(0, deadline - Date.now())
|
|
2086
|
+
);
|
|
2087
|
+
released = result !== false && released;
|
|
2083
2088
|
}
|
|
2089
|
+
return released;
|
|
2084
2090
|
}
|
|
2085
2091
|
function stopSimulationPlans() {
|
|
2086
2092
|
for (const client of [...liveHttpClients]) {
|
|
@@ -2097,14 +2103,15 @@ function awaitOnExit(promise) {
|
|
|
2097
2103
|
}
|
|
2098
2104
|
async function flushTraces(timeoutMs = 5e3) {
|
|
2099
2105
|
const deadline = Date.now() + Math.max(timeoutMs, 0);
|
|
2100
|
-
await releaseHeldExternalSpans(planWaitSliceMs(timeoutMs));
|
|
2106
|
+
const released = await releaseHeldExternalSpans(planWaitSliceMs(timeoutMs));
|
|
2101
2107
|
const requestsFlushed = await awaitPendingRequests(
|
|
2102
2108
|
Math.max(0, deadline - Date.now())
|
|
2103
2109
|
);
|
|
2110
|
+
const releasedAfterDeferred = await releaseHeldExternalSpans(0);
|
|
2104
2111
|
const transportsFlushed = await flushTraceTransports(
|
|
2105
2112
|
Math.max(0, deadline - Date.now())
|
|
2106
2113
|
);
|
|
2107
|
-
return requestsFlushed && transportsFlushed;
|
|
2114
|
+
return released && releasedAfterDeferred && requestsFlushed && transportsFlushed;
|
|
2108
2115
|
}
|
|
2109
2116
|
async function awaitPendingRequests(timeoutMs = DEFAULT_LIFECYCLE_TIMEOUT_MS2) {
|
|
2110
2117
|
await replayContextReady.catch(() => {
|
|
@@ -2514,13 +2521,17 @@ var init_http = __esm({
|
|
|
2514
2521
|
*/
|
|
2515
2522
|
async settleDeferredWork(timeoutMs = DEFAULT_LIFECYCLE_TIMEOUT_MS2) {
|
|
2516
2523
|
const deadline = Date.now() + Math.max(timeoutMs, 0);
|
|
2517
|
-
await this.releaseHeldExternalSpans?.(
|
|
2524
|
+
const released = await this.releaseHeldExternalSpans?.(
|
|
2525
|
+
planWaitSliceMs(timeoutMs)
|
|
2526
|
+
);
|
|
2518
2527
|
await replayContextReady.catch(() => {
|
|
2519
2528
|
});
|
|
2520
|
-
|
|
2529
|
+
const settled2 = await waitForPromises(
|
|
2521
2530
|
Array.from(this.deferredWork),
|
|
2522
2531
|
Math.max(0, deadline - Date.now())
|
|
2523
2532
|
);
|
|
2533
|
+
const releasedAfterDeferred = await this.releaseHeldExternalSpans?.(0);
|
|
2534
|
+
return released !== false && releasedAfterDeferred !== false && settled2;
|
|
2524
2535
|
}
|
|
2525
2536
|
/**
|
|
2526
2537
|
* Wait for spans queued by this client to be delivered, within one deadline.
|
|
@@ -2545,7 +2556,9 @@ var init_http = __esm({
|
|
|
2545
2556
|
}
|
|
2546
2557
|
const deadline = Date.now() + Math.max(timeoutMs, 0);
|
|
2547
2558
|
this.closing = (async () => {
|
|
2548
|
-
await this.releaseHeldExternalSpans?.(
|
|
2559
|
+
const released = await this.releaseHeldExternalSpans?.(
|
|
2560
|
+
planWaitSliceMs(timeoutMs)
|
|
2561
|
+
);
|
|
2549
2562
|
this.stopSimulationPlan?.();
|
|
2550
2563
|
this.externalSpanTransform = void 0;
|
|
2551
2564
|
this.externalTraceTransform = void 0;
|
|
@@ -2559,7 +2572,7 @@ var init_http = __esm({
|
|
|
2559
2572
|
const transport = this.traceTransport;
|
|
2560
2573
|
this.traceTransport = void 0;
|
|
2561
2574
|
const shutdownOk = await transport?.shutdown(Math.max(0, deadline - Date.now())) ?? true;
|
|
2562
|
-
return settled2 && shutdownOk;
|
|
2575
|
+
return released !== false && settled2 && shutdownOk;
|
|
2563
2576
|
})();
|
|
2564
2577
|
return this.closing;
|
|
2565
2578
|
}
|
|
@@ -2657,12 +2670,6 @@ var init_http = __esm({
|
|
|
2657
2670
|
async lookupFunction(name) {
|
|
2658
2671
|
return this.request("/api/sdk/functions/lookup", { name });
|
|
2659
2672
|
}
|
|
2660
|
-
async getAutoTracePolicy(traceFunctionKey, protocol) {
|
|
2661
|
-
return this.request("/api/sdk/auto-trace/policy", {
|
|
2662
|
-
traceFunctionKey,
|
|
2663
|
-
protocol
|
|
2664
|
-
});
|
|
2665
|
-
}
|
|
2666
2673
|
async getSimulationPlan() {
|
|
2667
2674
|
return this.get(
|
|
2668
2675
|
"/api/sdk/sim-plan",
|
|
@@ -3999,6 +4006,12 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
3999
4006
|
}
|
|
4000
4007
|
}
|
|
4001
4008
|
const attempts = resolveAttempts(options?.attempts);
|
|
4009
|
+
const maxConcurrency = options?.maxConcurrency ?? 10;
|
|
4010
|
+
if (!Number.isInteger(maxConcurrency) || maxConcurrency < 1) {
|
|
4011
|
+
throw new BitfabError(
|
|
4012
|
+
`maxConcurrency must be a positive integer (got ${maxConcurrency}).`
|
|
4013
|
+
);
|
|
4014
|
+
}
|
|
4002
4015
|
await replayContextReady;
|
|
4003
4016
|
let codeChangeDescription = options?.codeChangeDescription;
|
|
4004
4017
|
let codeChangeFiles = options?.codeChangeFiles;
|
|
@@ -4045,7 +4058,6 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4045
4058
|
}
|
|
4046
4059
|
}
|
|
4047
4060
|
const mockStrategy = options?.mock ?? "marked";
|
|
4048
|
-
const maxConcurrency = options?.maxConcurrency ?? 10;
|
|
4049
4061
|
const fullTestRunUrl = `${serviceUrl}${testRunUrl}`;
|
|
4050
4062
|
const resolvedOverrides = [
|
|
4051
4063
|
...normalizeMockOverrides(options?.mockOverride),
|
|
@@ -4142,6 +4154,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
|
|
|
4142
4154
|
originalDurationMs: item.originalDurationMs,
|
|
4143
4155
|
originalTokens: item.originalTokens,
|
|
4144
4156
|
originalModel: item.originalModel,
|
|
4157
|
+
ingestionType: item.ingestionType,
|
|
4145
4158
|
tokens: item.tokens,
|
|
4146
4159
|
model: item.model,
|
|
4147
4160
|
dbSnapshotRef: item.dbSnapshotRef,
|
|
@@ -5186,21 +5199,6 @@ function currentAutoTraceScope() {
|
|
|
5186
5199
|
initializeAutoTraceStorage();
|
|
5187
5200
|
return autoTraceState.storage?.getStore() ?? autoTraceState.browserScope;
|
|
5188
5201
|
}
|
|
5189
|
-
function __setBitfabAutoTraceCapturePolicy(client, traceFunctionKey, functionIds) {
|
|
5190
|
-
const policies = autoTraceState.capturePolicies.get(client) ?? /* @__PURE__ */ new Map();
|
|
5191
|
-
if (functionIds === void 0) {
|
|
5192
|
-
policies.delete(traceFunctionKey);
|
|
5193
|
-
if (policies.size === 0) {
|
|
5194
|
-
autoTraceState.capturePolicies.delete(client);
|
|
5195
|
-
}
|
|
5196
|
-
return;
|
|
5197
|
-
}
|
|
5198
|
-
policies.set(traceFunctionKey, new Set(functionIds));
|
|
5199
|
-
autoTraceState.capturePolicies.set(client, policies);
|
|
5200
|
-
}
|
|
5201
|
-
function getAutoTraceCapturePolicy(client, traceFunctionKey) {
|
|
5202
|
-
return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey);
|
|
5203
|
-
}
|
|
5204
5202
|
|
|
5205
5203
|
// src/optionalPeer.ts
|
|
5206
5204
|
function importOptionalPeer(specifierParts) {
|
|
@@ -5990,6 +5988,14 @@ var LabelsClient = class {
|
|
|
5990
5988
|
);
|
|
5991
5989
|
return response.labels;
|
|
5992
5990
|
}
|
|
5991
|
+
/** Withhold a verdict for a trace or replay attempt whose check did not run. */
|
|
5992
|
+
async skip(target, testRunId) {
|
|
5993
|
+
return this.save({ ...target, skip: true }, testRunId);
|
|
5994
|
+
}
|
|
5995
|
+
/** Clear a previous verdict for a trace, replay attempt, or assertion. */
|
|
5996
|
+
async archive(target, testRunId) {
|
|
5997
|
+
return this.save({ ...target, archive: true }, testRunId);
|
|
5998
|
+
}
|
|
5993
5999
|
async saveHuman(update) {
|
|
5994
6000
|
const [outcome] = await this.saveHumanAll([update]);
|
|
5995
6001
|
return outcome;
|
|
@@ -6908,6 +6914,15 @@ var BitfabLangGraphIntegration = class {
|
|
|
6908
6914
|
// src/client.ts
|
|
6909
6915
|
init_mockOverride();
|
|
6910
6916
|
|
|
6917
|
+
// src/streamFinalizationError.ts
|
|
6918
|
+
var StreamFinalizationError = class extends Error {
|
|
6919
|
+
constructor(message, output) {
|
|
6920
|
+
super(message);
|
|
6921
|
+
this.output = output;
|
|
6922
|
+
this.name = "StreamFinalizationError";
|
|
6923
|
+
}
|
|
6924
|
+
};
|
|
6925
|
+
|
|
6911
6926
|
// src/openaiAgentSdk.ts
|
|
6912
6927
|
var BitfabOpenAIAgentHandler = class {
|
|
6913
6928
|
constructor(config) {
|
|
@@ -6947,7 +6962,11 @@ var BitfabOpenAIAgentHandler = class {
|
|
|
6947
6962
|
if (isStreaming && res?.completed) {
|
|
6948
6963
|
try {
|
|
6949
6964
|
await res.completed;
|
|
6950
|
-
} catch {
|
|
6965
|
+
} catch (error) {
|
|
6966
|
+
throw new StreamFinalizationError(
|
|
6967
|
+
error instanceof Error ? error.message : String(error),
|
|
6968
|
+
res.finalOutput
|
|
6969
|
+
);
|
|
6951
6970
|
}
|
|
6952
6971
|
}
|
|
6953
6972
|
return res?.finalOutput;
|
|
@@ -7049,7 +7068,6 @@ function openAiAgentsParentSpanId(bitfabTraceId, enclosingSpanIds) {
|
|
|
7049
7068
|
}
|
|
7050
7069
|
|
|
7051
7070
|
// src/client.ts
|
|
7052
|
-
init_policyRefresh();
|
|
7053
7071
|
init_randomUuid();
|
|
7054
7072
|
init_replay();
|
|
7055
7073
|
|
|
@@ -7706,17 +7724,6 @@ function runWithSeedContext(ctx, fn) {
|
|
|
7706
7724
|
init_serialize();
|
|
7707
7725
|
init_simulationPlan();
|
|
7708
7726
|
init_spanOrigin();
|
|
7709
|
-
|
|
7710
|
-
// src/streamFinalizationError.ts
|
|
7711
|
-
var StreamFinalizationError = class extends Error {
|
|
7712
|
-
constructor(message, output) {
|
|
7713
|
-
super(message);
|
|
7714
|
-
this.output = output;
|
|
7715
|
-
this.name = "StreamFinalizationError";
|
|
7716
|
-
}
|
|
7717
|
-
};
|
|
7718
|
-
|
|
7719
|
-
// src/client.ts
|
|
7720
7727
|
init_traceMetadata();
|
|
7721
7728
|
|
|
7722
7729
|
// src/traces.ts
|
|
@@ -8633,8 +8640,6 @@ function readBooleanEnv(name) {
|
|
|
8633
8640
|
var DEFAULT_AUTO_TRACE_MAX_DEPTH = 30;
|
|
8634
8641
|
var DEFAULT_AUTO_TRACE_MAX_SPANS = 500;
|
|
8635
8642
|
var AUTO_TRACE_PROTOCOL = "ts-auto-v1";
|
|
8636
|
-
var AUTO_TRACE_POLICY_REFRESH_MS = 6e4;
|
|
8637
|
-
var AUTO_TRACE_POLICY_RETRY_MS = 1e4;
|
|
8638
8643
|
function spanOwnerName(receiver) {
|
|
8639
8644
|
if (typeof receiver === "function") {
|
|
8640
8645
|
return receiver.name !== "" ? receiver.name : void 0;
|
|
@@ -8667,7 +8672,6 @@ var Bitfab = class {
|
|
|
8667
8672
|
constructor(config) {
|
|
8668
8673
|
/** Gate the empty-key warning to fire at most once. */
|
|
8669
8674
|
this.apiKeyWarned = false;
|
|
8670
|
-
this.autoTracePolicyRefreshes = /* @__PURE__ */ new Map();
|
|
8671
8675
|
/**
|
|
8672
8676
|
* Mock overrides registered via {@link Bitfab.registerMockOverride}, applied
|
|
8673
8677
|
* to every `replay` on this client (after any per-call `mockOverride`). In
|
|
@@ -8716,12 +8720,12 @@ var Bitfab = class {
|
|
|
8716
8720
|
*
|
|
8717
8721
|
* Build instrumentation turns repository functions called beneath this
|
|
8718
8722
|
* method into nested spans that capture inputs, outputs, and errors by
|
|
8719
|
-
* default.
|
|
8720
|
-
*
|
|
8723
|
+
* default. Source exclusions and sim-plan capture-off decisions are explicit
|
|
8724
|
+
* opt-outs from that default.
|
|
8721
8725
|
* Without a compatible build transform, this still records the decorated
|
|
8722
8726
|
* method as a normal rich root span but cannot discover child calls.
|
|
8723
8727
|
*
|
|
8724
|
-
* @param traceFunctionKey - Groups traces and their capture
|
|
8728
|
+
* @param traceFunctionKey - Groups traces and their capture controls.
|
|
8725
8729
|
* @param options - Root presentation, subtree bounds, and exclusions.
|
|
8726
8730
|
* @experimental Automatic child-call instrumentation is experimental.
|
|
8727
8731
|
*/
|
|
@@ -8879,11 +8883,6 @@ var Bitfab = class {
|
|
|
8879
8883
|
traceFunctionKey,
|
|
8880
8884
|
spanOptions,
|
|
8881
8885
|
function(...args) {
|
|
8882
|
-
const capturePolicy = getAutoTraceCapturePolicy(
|
|
8883
|
-
self,
|
|
8884
|
-
traceFunctionKey
|
|
8885
|
-
);
|
|
8886
|
-
self.refreshAutoTraceCapturePolicy(traceFunctionKey);
|
|
8887
8886
|
self.simulationPlan.refresh();
|
|
8888
8887
|
let spansUsed = 0;
|
|
8889
8888
|
let truncated = false;
|
|
@@ -8963,7 +8962,7 @@ var Bitfab = class {
|
|
|
8963
8962
|
surface: "opt-out",
|
|
8964
8963
|
instrumentation: "trace",
|
|
8965
8964
|
functionId: definition.id,
|
|
8966
|
-
captureContent:
|
|
8965
|
+
captureContent: true,
|
|
8967
8966
|
autoTraceDefinition: definition,
|
|
8968
8967
|
...nodeConfiguration?.testRunId !== void 0 && {
|
|
8969
8968
|
testRunId: nodeConfiguration.testRunId
|
|
@@ -9062,34 +9061,6 @@ var Bitfab = class {
|
|
|
9062
9061
|
applySimulationPlan(payload, submit) {
|
|
9063
9062
|
this.simulationPlan.send(payload, rootTraceFunctionKeyOf(payload), submit);
|
|
9064
9063
|
}
|
|
9065
|
-
refreshAutoTraceCapturePolicy(traceFunctionKey) {
|
|
9066
|
-
const state2 = this.autoTracePolicyRefreshes.get(traceFunctionKey) ?? new PolicyRefresh();
|
|
9067
|
-
this.autoTracePolicyRefreshes.set(traceFunctionKey, state2);
|
|
9068
|
-
state2.run(
|
|
9069
|
-
() => this.httpClient.getAutoTracePolicy(
|
|
9070
|
-
traceFunctionKey,
|
|
9071
|
-
AUTO_TRACE_PROTOCOL
|
|
9072
|
-
),
|
|
9073
|
-
(policy) => {
|
|
9074
|
-
if (policy.protocol !== AUTO_TRACE_PROTOCOL) {
|
|
9075
|
-
state2.hold(AUTO_TRACE_POLICY_RETRY_MS);
|
|
9076
|
-
return;
|
|
9077
|
-
}
|
|
9078
|
-
const functionIds = Array.isArray(policy.functionIds) ? policy.functionIds.filter(
|
|
9079
|
-
(id) => typeof id === "string" && id.startsWith(`${AUTO_TRACE_PROTOCOL}:`)
|
|
9080
|
-
).slice(0, DEFAULT_AUTO_TRACE_MAX_SPANS) : [];
|
|
9081
|
-
__setBitfabAutoTraceCapturePolicy(
|
|
9082
|
-
this,
|
|
9083
|
-
traceFunctionKey,
|
|
9084
|
-
policy.revision === null ? void 0 : functionIds
|
|
9085
|
-
);
|
|
9086
|
-
state2.hold(AUTO_TRACE_POLICY_REFRESH_MS);
|
|
9087
|
-
},
|
|
9088
|
-
() => {
|
|
9089
|
-
state2.hold(AUTO_TRACE_POLICY_RETRY_MS);
|
|
9090
|
-
}
|
|
9091
|
-
);
|
|
9092
|
-
}
|
|
9093
9064
|
/**
|
|
9094
9065
|
* Flush and permanently close this client's tracing resources: its pending
|
|
9095
9066
|
* requests and the single span-transport worker shared by its decorators and
|