@combycode/llm-sdk 1.0.0 → 1.2.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/CHANGELOG.md +68 -0
- package/README.md +1 -1
- package/dist/agent/guardrail-types.d.ts +25 -0
- package/dist/agent/loop-config.d.ts +5 -1
- package/dist/agent/loop.d.ts +1 -0
- package/dist/agent/types.d.ts +8 -0
- package/dist/index.browser.js +431 -69
- package/dist/index.d.ts +5 -4
- package/dist/index.js +431 -69
- package/dist/llm/client.d.ts +9 -0
- package/dist/llm/moderation/native.d.ts +18 -0
- package/dist/llm/moderation/runner.d.ts +33 -0
- package/dist/llm/moderation/types.d.ts +75 -0
- package/dist/llm/providers/google/tiers.d.ts +15 -0
- package/dist/llm/types/options.d.ts +5 -0
- package/dist/llm/types/request.d.ts +10 -0
- package/dist/llm/types/response.d.ts +26 -0
- package/dist/llm/types/stream.d.ts +10 -0
- package/dist/llm/types/tools.d.ts +21 -0
- package/dist/plugins/model-catalog/catalog.d.ts +3 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22104,6 +22104,7 @@ var ModelCatalog = class {
|
|
|
22104
22104
|
family: info.family,
|
|
22105
22105
|
version: info.version,
|
|
22106
22106
|
status: info.status,
|
|
22107
|
+
availability: info.availability,
|
|
22107
22108
|
active: info.active,
|
|
22108
22109
|
deprecation: info.deprecation
|
|
22109
22110
|
});
|
|
@@ -22191,6 +22192,168 @@ var ModelCatalog = class {
|
|
|
22191
22192
|
}
|
|
22192
22193
|
};
|
|
22193
22194
|
|
|
22195
|
+
// src/llm/providers/openai/moderations.ts
|
|
22196
|
+
var OPENAI_MODERATION_BASE_URL = "https://api.openai.com";
|
|
22197
|
+
var OPENAI_MODERATION_PATH = "/v1/moderations";
|
|
22198
|
+
var OPENAI_MODERATION_DEFAULT_MODEL = "omni-moderation-latest";
|
|
22199
|
+
var OpenAIModerationAdapter = class {
|
|
22200
|
+
apiKey;
|
|
22201
|
+
baseURL;
|
|
22202
|
+
constructor(config) {
|
|
22203
|
+
this.apiKey = config.apiKey;
|
|
22204
|
+
this.baseURL = config.baseURL ?? OPENAI_MODERATION_BASE_URL;
|
|
22205
|
+
}
|
|
22206
|
+
async moderate(input, model, fetch2) {
|
|
22207
|
+
const res = await fetch2({
|
|
22208
|
+
url: `${this.baseURL}${OPENAI_MODERATION_PATH}`,
|
|
22209
|
+
method: "POST",
|
|
22210
|
+
headers: { authorization: `Bearer ${this.apiKey}`, "content-type": "application/json" },
|
|
22211
|
+
body: { model, input },
|
|
22212
|
+
provider: "openai",
|
|
22213
|
+
model,
|
|
22214
|
+
responseType: "json"
|
|
22215
|
+
});
|
|
22216
|
+
if (res.status >= 400) {
|
|
22217
|
+
throw new Error(`OpenAI moderations failed (${res.status}): ${JSON.stringify(res.body)}`);
|
|
22218
|
+
}
|
|
22219
|
+
const data = res.body;
|
|
22220
|
+
return (data.results ?? []).map(parseRawResult);
|
|
22221
|
+
}
|
|
22222
|
+
};
|
|
22223
|
+
function parseRawResult(r) {
|
|
22224
|
+
return {
|
|
22225
|
+
flagged: r.flagged,
|
|
22226
|
+
categories: r.categories,
|
|
22227
|
+
categoryScores: r.category_scores,
|
|
22228
|
+
categoryAppliedInputTypes: r.category_applied_input_types
|
|
22229
|
+
};
|
|
22230
|
+
}
|
|
22231
|
+
|
|
22232
|
+
// src/llm/moderation/types.ts
|
|
22233
|
+
var MODERATION_DEFAULT_MODEL = "omni-moderation-latest";
|
|
22234
|
+
var MODERATION_DEFAULT_STRATEGY = "buffer";
|
|
22235
|
+
var MODERATION_DEFAULT_INTERVAL = 400;
|
|
22236
|
+
|
|
22237
|
+
// src/llm/moderation/runner.ts
|
|
22238
|
+
function resolveModerationMode(provider, mod) {
|
|
22239
|
+
if (mod.mode) return mod.mode;
|
|
22240
|
+
return provider === "openai" ? "native" : "emulate";
|
|
22241
|
+
}
|
|
22242
|
+
function moderationInputText(messages) {
|
|
22243
|
+
const lastUser = [...messages].reverse().find((m) => m.role === "user");
|
|
22244
|
+
if (!lastUser) return "";
|
|
22245
|
+
return typeof lastUser.content === "string" ? lastUser.content : contentText(lastUser.content);
|
|
22246
|
+
}
|
|
22247
|
+
function emptyResult() {
|
|
22248
|
+
return {
|
|
22249
|
+
flagged: false,
|
|
22250
|
+
categories: {},
|
|
22251
|
+
categoryScores: {}
|
|
22252
|
+
};
|
|
22253
|
+
}
|
|
22254
|
+
async function runModeration(text, cfg) {
|
|
22255
|
+
if (!text) return emptyResult();
|
|
22256
|
+
try {
|
|
22257
|
+
const adapter = new OpenAIModerationAdapter({ apiKey: cfg.apiKey });
|
|
22258
|
+
const results = await adapter.moderate(text, cfg.model, cfg.fetch);
|
|
22259
|
+
return results[0] ?? emptyResult();
|
|
22260
|
+
} catch (e) {
|
|
22261
|
+
return { error: e instanceof Error ? e.message : String(e) };
|
|
22262
|
+
}
|
|
22263
|
+
}
|
|
22264
|
+
function moderationModel(mod) {
|
|
22265
|
+
return mod.model ?? MODERATION_DEFAULT_MODEL;
|
|
22266
|
+
}
|
|
22267
|
+
function emitModerationZeroCost(hooks, model) {
|
|
22268
|
+
const entry = {
|
|
22269
|
+
id: crypto.randomUUID(),
|
|
22270
|
+
timestamp: Date.now(),
|
|
22271
|
+
provider: "openai",
|
|
22272
|
+
model,
|
|
22273
|
+
tokens: { input: 0, output: 0, cached: 0, cacheWrite: 0, reasoning: 0 },
|
|
22274
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0, total: 0, source: "calculated" },
|
|
22275
|
+
providerEvidence: { note: "free: moderations endpoint not billed" },
|
|
22276
|
+
tags: { provider: "openai", model, type: "moderation" }
|
|
22277
|
+
};
|
|
22278
|
+
hooks.emitSync("onCostEntry", { entry, runningTotal: 0 });
|
|
22279
|
+
}
|
|
22280
|
+
function outputEvent(result) {
|
|
22281
|
+
return { type: "moderation", phase: "output", result, source: "emulated" };
|
|
22282
|
+
}
|
|
22283
|
+
function wrapModeratedStream(raw, strategy, interval, moderate2) {
|
|
22284
|
+
const step = interval > 0 ? interval : MODERATION_DEFAULT_INTERVAL;
|
|
22285
|
+
if (strategy === "post") return wrapPost(raw, moderate2);
|
|
22286
|
+
if (strategy === "parallel") return wrapParallel(raw, step, moderate2);
|
|
22287
|
+
return wrapBuffer(raw, step, moderate2);
|
|
22288
|
+
}
|
|
22289
|
+
async function* wrapPost(raw, moderate2) {
|
|
22290
|
+
let acc = "";
|
|
22291
|
+
for await (const ev of raw) {
|
|
22292
|
+
if (ev.type === "text") acc += ev.text;
|
|
22293
|
+
yield ev;
|
|
22294
|
+
}
|
|
22295
|
+
if (acc) yield outputEvent(await moderate2(acc));
|
|
22296
|
+
}
|
|
22297
|
+
async function* wrapBuffer(raw, interval, moderate2) {
|
|
22298
|
+
let acc = "";
|
|
22299
|
+
let checkedAt = 0;
|
|
22300
|
+
let hold = [];
|
|
22301
|
+
for await (const ev of raw) {
|
|
22302
|
+
hold.push(ev);
|
|
22303
|
+
if (ev.type === "text") {
|
|
22304
|
+
acc += ev.text;
|
|
22305
|
+
if (acc.length - checkedAt >= interval || ev.text.includes("\n")) {
|
|
22306
|
+
checkedAt = acc.length;
|
|
22307
|
+
yield outputEvent(await moderate2(acc));
|
|
22308
|
+
for (const h of hold) yield h;
|
|
22309
|
+
hold = [];
|
|
22310
|
+
}
|
|
22311
|
+
}
|
|
22312
|
+
}
|
|
22313
|
+
if (acc.length > checkedAt) yield outputEvent(await moderate2(acc));
|
|
22314
|
+
for (const h of hold) yield h;
|
|
22315
|
+
}
|
|
22316
|
+
async function* wrapParallel(raw, interval, moderate2) {
|
|
22317
|
+
const iter = raw[Symbol.asyncIterator]();
|
|
22318
|
+
const pending = /* @__PURE__ */ new Set();
|
|
22319
|
+
let acc = "";
|
|
22320
|
+
let checkedAt = 0;
|
|
22321
|
+
let rawDone = false;
|
|
22322
|
+
let rawNext = iter.next();
|
|
22323
|
+
const schedule = (text) => {
|
|
22324
|
+
const p = moderate2(text).then((result) => {
|
|
22325
|
+
pending.delete(p);
|
|
22326
|
+
return { tag: "mod", event: outputEvent(result) };
|
|
22327
|
+
});
|
|
22328
|
+
pending.add(p);
|
|
22329
|
+
};
|
|
22330
|
+
while (!rawDone || pending.size > 0) {
|
|
22331
|
+
const racers = [];
|
|
22332
|
+
if (!rawDone) racers.push(rawNext.then((result) => ({ tag: "raw", result })));
|
|
22333
|
+
for (const p of pending) racers.push(p);
|
|
22334
|
+
const winner = await Promise.race(racers);
|
|
22335
|
+
if (winner.tag === "mod") {
|
|
22336
|
+
yield winner.event;
|
|
22337
|
+
continue;
|
|
22338
|
+
}
|
|
22339
|
+
if (winner.result.done) {
|
|
22340
|
+
rawDone = true;
|
|
22341
|
+
if (acc.length > checkedAt) schedule(acc);
|
|
22342
|
+
continue;
|
|
22343
|
+
}
|
|
22344
|
+
const ev = winner.result.value;
|
|
22345
|
+
yield ev;
|
|
22346
|
+
if (ev.type === "text") {
|
|
22347
|
+
acc += ev.text;
|
|
22348
|
+
if (acc.length - checkedAt >= interval) {
|
|
22349
|
+
checkedAt = acc.length;
|
|
22350
|
+
schedule(acc);
|
|
22351
|
+
}
|
|
22352
|
+
}
|
|
22353
|
+
rawNext = iter.next();
|
|
22354
|
+
}
|
|
22355
|
+
}
|
|
22356
|
+
|
|
22194
22357
|
// src/util/duration.ts
|
|
22195
22358
|
var UNIT_MS = {
|
|
22196
22359
|
s: 1e3,
|
|
@@ -22327,6 +22490,7 @@ var LLMClient = class {
|
|
|
22327
22490
|
mode;
|
|
22328
22491
|
batchable;
|
|
22329
22492
|
adapter;
|
|
22493
|
+
apiKey;
|
|
22330
22494
|
fetchFn;
|
|
22331
22495
|
fetchStreamFn;
|
|
22332
22496
|
priority;
|
|
@@ -22350,6 +22514,7 @@ var LLMClient = class {
|
|
|
22350
22514
|
this.provider = config.provider;
|
|
22351
22515
|
this.model = config.model;
|
|
22352
22516
|
this.system = config.system;
|
|
22517
|
+
this.apiKey = config.apiKey;
|
|
22353
22518
|
this.hooks = config.hooks ?? new HookBus();
|
|
22354
22519
|
this.fetchFn = config.fetch;
|
|
22355
22520
|
this.fetchStreamFn = config.fetchStream ?? null;
|
|
@@ -22403,6 +22568,34 @@ var LLMClient = class {
|
|
|
22403
22568
|
}
|
|
22404
22569
|
};
|
|
22405
22570
|
}
|
|
22571
|
+
// ─── Moderation helpers ───────────────────────────────────────────────
|
|
22572
|
+
/** Resolve the OpenAI key the emulated moderation path needs. Reuses the
|
|
22573
|
+
* client's own key when the provider is OpenAI; otherwise requires an explicit
|
|
22574
|
+
* one. Throws when none is resolvable (report-only feature, but the call still
|
|
22575
|
+
* needs a key to reach the moderations endpoint). */
|
|
22576
|
+
resolveModerationKey(mod) {
|
|
22577
|
+
const key = mod.apiKey ?? (this.provider === "openai" ? this.apiKey : void 0);
|
|
22578
|
+
if (!key) {
|
|
22579
|
+
throw new Error(
|
|
22580
|
+
"moderation: emulated moderation requires an OpenAI API key (the only public moderations endpoint). Pass moderation.apiKey, or use the OpenAI provider."
|
|
22581
|
+
);
|
|
22582
|
+
}
|
|
22583
|
+
return key;
|
|
22584
|
+
}
|
|
22585
|
+
moderationConfig(mod) {
|
|
22586
|
+
return {
|
|
22587
|
+
apiKey: this.resolveModerationKey(mod),
|
|
22588
|
+
model: moderationModel(mod),
|
|
22589
|
+
fetch: this.fetchFn
|
|
22590
|
+
};
|
|
22591
|
+
}
|
|
22592
|
+
/** Fold a moderation stream event into the accumulating report. */
|
|
22593
|
+
mergeModeration(prev, phase, result, source) {
|
|
22594
|
+
const next = prev && prev.source === source ? { ...prev } : { source };
|
|
22595
|
+
if (phase === "input") next.input = result;
|
|
22596
|
+
else next.output = result;
|
|
22597
|
+
return next;
|
|
22598
|
+
}
|
|
22406
22599
|
/** Submit a request. Returns the parsed CompletionResponse. */
|
|
22407
22600
|
async complete(input, options = {}) {
|
|
22408
22601
|
const rawMessages = normalizeInput(input);
|
|
@@ -22423,6 +22616,7 @@ var LLMClient = class {
|
|
|
22423
22616
|
thinking: options.thinking,
|
|
22424
22617
|
cache: options.cache,
|
|
22425
22618
|
serviceTier: options.serviceTier,
|
|
22619
|
+
moderation: options.moderation,
|
|
22426
22620
|
providerOptions: options.providerOptions,
|
|
22427
22621
|
audio: options.audio,
|
|
22428
22622
|
outputModalities: options.outputModalities,
|
|
@@ -22478,6 +22672,8 @@ var LLMClient = class {
|
|
|
22478
22672
|
await this.hooks.emit("onBeforeSubmit", submitCtx);
|
|
22479
22673
|
const inputChars = JSON.stringify(normalized.messages).length;
|
|
22480
22674
|
const estimatedInputTokens = Math.ceil(inputChars / 4);
|
|
22675
|
+
const mod = options.moderation;
|
|
22676
|
+
const moderationCfg = mod && resolveModerationMode(this.provider, mod) === "emulate" ? this.moderationConfig(mod) : void 0;
|
|
22481
22677
|
const start = performance.now();
|
|
22482
22678
|
let response;
|
|
22483
22679
|
if (submitCtx.intercepted && submitCtx.resultPromise) {
|
|
@@ -22503,6 +22699,22 @@ var LLMClient = class {
|
|
|
22503
22699
|
}
|
|
22504
22700
|
const latencyMs = performance.now() - start;
|
|
22505
22701
|
const result = this.adapter.parseResponse(response.body, latencyMs);
|
|
22702
|
+
if (mod && moderationCfg) {
|
|
22703
|
+
const cfg = moderationCfg;
|
|
22704
|
+
const doInput = mod.input ?? true;
|
|
22705
|
+
const doOutput = mod.output ?? true;
|
|
22706
|
+
const [inputEntry, outputEntry] = await Promise.all([
|
|
22707
|
+
doInput ? runModeration(moderationInputText(normalized.messages), cfg) : Promise.resolve(void 0),
|
|
22708
|
+
doOutput ? runModeration(result.text, cfg) : Promise.resolve(void 0)
|
|
22709
|
+
]);
|
|
22710
|
+
if (doInput) emitModerationZeroCost(this.hooks, cfg.model);
|
|
22711
|
+
if (doOutput) emitModerationZeroCost(this.hooks, cfg.model);
|
|
22712
|
+
result.moderation = {
|
|
22713
|
+
source: "emulated",
|
|
22714
|
+
...inputEntry ? { input: inputEntry } : {},
|
|
22715
|
+
...outputEntry ? { output: outputEntry } : {}
|
|
22716
|
+
};
|
|
22717
|
+
}
|
|
22506
22718
|
await this.hooks.emit("onCompletion", {
|
|
22507
22719
|
provider: this.provider,
|
|
22508
22720
|
model: this.model,
|
|
@@ -22550,6 +22762,7 @@ var LLMClient = class {
|
|
|
22550
22762
|
thinking: options.thinking,
|
|
22551
22763
|
cache: options.cache,
|
|
22552
22764
|
serviceTier: options.serviceTier,
|
|
22765
|
+
moderation: options.moderation,
|
|
22553
22766
|
providerOptions: options.providerOptions,
|
|
22554
22767
|
audio: options.audio,
|
|
22555
22768
|
outputModalities: options.outputModalities,
|
|
@@ -22593,29 +22806,65 @@ var LLMClient = class {
|
|
|
22593
22806
|
let thinking = "";
|
|
22594
22807
|
let usage = emptyUsage();
|
|
22595
22808
|
let finishReason = "stop";
|
|
22596
|
-
|
|
22597
|
-
|
|
22598
|
-
|
|
22599
|
-
|
|
22600
|
-
|
|
22601
|
-
|
|
22602
|
-
for (const
|
|
22603
|
-
|
|
22604
|
-
|
|
22605
|
-
|
|
22606
|
-
|
|
22607
|
-
|
|
22608
|
-
|
|
22609
|
-
|
|
22610
|
-
|
|
22611
|
-
|
|
22612
|
-
|
|
22613
|
-
|
|
22614
|
-
|
|
22615
|
-
|
|
22616
|
-
|
|
22617
|
-
|
|
22809
|
+
let moderationReport;
|
|
22810
|
+
const fetchStream = this.fetchStreamFn;
|
|
22811
|
+
const adapter = this.adapter;
|
|
22812
|
+
const queueName = this.queueName;
|
|
22813
|
+
const priority = this.priority;
|
|
22814
|
+
async function* rawEvents() {
|
|
22815
|
+
for await (const sseEvent of fetchStream(httpReq, {
|
|
22816
|
+
queueName,
|
|
22817
|
+
priority,
|
|
22818
|
+
ctx
|
|
22819
|
+
})) {
|
|
22820
|
+
for (const ev of adapter.parseStreamEvent(sseEvent)) yield ev;
|
|
22821
|
+
}
|
|
22822
|
+
}
|
|
22823
|
+
const mod = options.moderation;
|
|
22824
|
+
const emulate = !!mod && resolveModerationMode(this.provider, mod) === "emulate";
|
|
22825
|
+
let eventStream = rawEvents();
|
|
22826
|
+
if (mod && emulate && (mod.output ?? true)) {
|
|
22827
|
+
const cfg = this.moderationConfig(mod);
|
|
22828
|
+
const hooks = this.hooks;
|
|
22829
|
+
const strategy = mod.stream?.strategy ?? MODERATION_DEFAULT_STRATEGY;
|
|
22830
|
+
const interval = mod.stream?.interval ?? MODERATION_DEFAULT_INTERVAL;
|
|
22831
|
+
eventStream = wrapModeratedStream(eventStream, strategy, interval, async (t) => {
|
|
22832
|
+
const r = await runModeration(t, cfg);
|
|
22833
|
+
emitModerationZeroCost(hooks, cfg.model);
|
|
22834
|
+
return r;
|
|
22835
|
+
});
|
|
22836
|
+
}
|
|
22837
|
+
if (mod && emulate && (mod.input ?? true)) {
|
|
22838
|
+
const cfg = this.moderationConfig(mod);
|
|
22839
|
+
const inputEntry = await runModeration(moderationInputText(normalized.messages), cfg);
|
|
22840
|
+
emitModerationZeroCost(this.hooks, cfg.model);
|
|
22841
|
+
moderationReport = this.mergeModeration(moderationReport, "input", inputEntry, "emulated");
|
|
22842
|
+
yield { type: "moderation", phase: "input", result: inputEntry, source: "emulated" };
|
|
22843
|
+
}
|
|
22844
|
+
for await (const event of eventStream) {
|
|
22845
|
+
switch (event.type) {
|
|
22846
|
+
case "text":
|
|
22847
|
+
text += event.text;
|
|
22848
|
+
break;
|
|
22849
|
+
case "thinking":
|
|
22850
|
+
thinking += event.text;
|
|
22851
|
+
break;
|
|
22852
|
+
case "usage":
|
|
22853
|
+
usage = event.usage;
|
|
22854
|
+
break;
|
|
22855
|
+
case "done":
|
|
22856
|
+
finishReason = event.finishReason;
|
|
22857
|
+
break;
|
|
22858
|
+
case "moderation":
|
|
22859
|
+
moderationReport = this.mergeModeration(
|
|
22860
|
+
moderationReport,
|
|
22861
|
+
event.phase,
|
|
22862
|
+
event.result,
|
|
22863
|
+
event.source
|
|
22864
|
+
);
|
|
22865
|
+
break;
|
|
22618
22866
|
}
|
|
22867
|
+
yield event;
|
|
22619
22868
|
}
|
|
22620
22869
|
const inputChars = JSON.stringify(normalized.messages).length;
|
|
22621
22870
|
const response = {
|
|
@@ -22628,6 +22877,7 @@ var LLMClient = class {
|
|
|
22628
22877
|
toolCalls: [],
|
|
22629
22878
|
thinking: thinking || null,
|
|
22630
22879
|
media: [],
|
|
22880
|
+
...moderationReport ? { moderation: moderationReport } : {},
|
|
22631
22881
|
latencyMs: performance.now() - start,
|
|
22632
22882
|
raw: null
|
|
22633
22883
|
};
|
|
@@ -22936,6 +23186,9 @@ var AnthropicAdapter = class {
|
|
|
22936
23186
|
if (t.type === "web_search") {
|
|
22937
23187
|
return { type: "web_search_20250305", name: "web_search", max_uses: 5 };
|
|
22938
23188
|
}
|
|
23189
|
+
if (t.type === "code_interpreter") {
|
|
23190
|
+
return { type: "code_execution_20260521", name: "code_execution" };
|
|
23191
|
+
}
|
|
22939
23192
|
return null;
|
|
22940
23193
|
}
|
|
22941
23194
|
const tool = {
|
|
@@ -22979,7 +23232,10 @@ var AnthropicAdapter = class {
|
|
|
22979
23232
|
});
|
|
22980
23233
|
const headers = {};
|
|
22981
23234
|
if (hasFileRef) headers["anthropic-beta"] = "files-api-2025-04-14";
|
|
22982
|
-
|
|
23235
|
+
const usesCodeExec = req.tools?.some(
|
|
23236
|
+
(t) => !isFunctionTool(t) && t.type === "code_interpreter"
|
|
23237
|
+
);
|
|
23238
|
+
return { body, headers, ...usesCodeExec ? { path: "/v1/messages?beta=true" } : {} };
|
|
22983
23239
|
}
|
|
22984
23240
|
enableStreaming(providerReq, _req) {
|
|
22985
23241
|
providerReq.body.stream = true;
|
|
@@ -23046,6 +23302,7 @@ var AnthropicAdapter = class {
|
|
|
23046
23302
|
const content = [];
|
|
23047
23303
|
let thinking = null;
|
|
23048
23304
|
const toolCalls = [];
|
|
23305
|
+
const files = [];
|
|
23049
23306
|
for (const block of contentBlocks) {
|
|
23050
23307
|
if (block.type === "text") {
|
|
23051
23308
|
content.push({ type: "text", text: block.text });
|
|
@@ -23060,6 +23317,15 @@ var AnthropicAdapter = class {
|
|
|
23060
23317
|
};
|
|
23061
23318
|
content.push(tc);
|
|
23062
23319
|
toolCalls.push(tc);
|
|
23320
|
+
} else if (block.type === "bash_code_execution_tool_result" || block.type === "code_execution_tool_result") {
|
|
23321
|
+
const result = block.content;
|
|
23322
|
+
if (result && (result.type === "bash_code_execution_result" || result.type === "code_execution_result") && Array.isArray(result.content)) {
|
|
23323
|
+
for (const out of result.content) {
|
|
23324
|
+
if ((out.type === "bash_code_execution_output" || out.type === "code_execution_output") && typeof out.file_id === "string") {
|
|
23325
|
+
files.push({ id: out.file_id, source: "code_execution" });
|
|
23326
|
+
}
|
|
23327
|
+
}
|
|
23328
|
+
}
|
|
23063
23329
|
}
|
|
23064
23330
|
}
|
|
23065
23331
|
const finishReason = extractFinishReason(toolCalls.length > 0, r.stop_reason, {
|
|
@@ -23074,6 +23340,7 @@ var AnthropicAdapter = class {
|
|
|
23074
23340
|
text: content.filter((p) => p.type === "text").map((p) => p.text).join(""),
|
|
23075
23341
|
toolCalls,
|
|
23076
23342
|
media: [],
|
|
23343
|
+
...files.length ? { files } : {},
|
|
23077
23344
|
thinking,
|
|
23078
23345
|
latencyMs,
|
|
23079
23346
|
raw
|
|
@@ -23379,6 +23646,17 @@ function resolveVoice(provider, voice) {
|
|
|
23379
23646
|
return VOICE_ALIASES[provider]?.[voice] ?? voice;
|
|
23380
23647
|
}
|
|
23381
23648
|
|
|
23649
|
+
// src/llm/providers/google/tiers.ts
|
|
23650
|
+
var REQUEST = /* @__PURE__ */ new Set(["flex", "standard", "priority"]);
|
|
23651
|
+
function googleRequestTier(t) {
|
|
23652
|
+
if (!t) return void 0;
|
|
23653
|
+
return REQUEST.has(t) ? t : void 0;
|
|
23654
|
+
}
|
|
23655
|
+
function googleBilledTier(raw) {
|
|
23656
|
+
if (typeof raw !== "string" || !raw) return {};
|
|
23657
|
+
return { serviceTier: raw, pricingTier: raw.toLowerCase() };
|
|
23658
|
+
}
|
|
23659
|
+
|
|
23382
23660
|
// src/llm/providers/google/constants.ts
|
|
23383
23661
|
var GOOGLE_THINKING_LEVELS = {
|
|
23384
23662
|
low: "LOW",
|
|
@@ -23431,6 +23709,8 @@ var GoogleAdapter = class {
|
|
|
23431
23709
|
contents,
|
|
23432
23710
|
generationConfig: config
|
|
23433
23711
|
};
|
|
23712
|
+
const tier = googleRequestTier(req.serviceTier);
|
|
23713
|
+
if (tier) body.serviceTier = tier;
|
|
23434
23714
|
if (req.system) {
|
|
23435
23715
|
body.systemInstruction = { parts: [{ text: req.system }] };
|
|
23436
23716
|
}
|
|
@@ -23549,7 +23829,9 @@ var GoogleAdapter = class {
|
|
|
23549
23829
|
const content = [];
|
|
23550
23830
|
const toolCalls = [];
|
|
23551
23831
|
const media = [];
|
|
23832
|
+
const files = [];
|
|
23552
23833
|
let thinking = null;
|
|
23834
|
+
const hasCodeExec = parts.some((p) => p.executableCode || p.codeExecutionResult);
|
|
23553
23835
|
for (const part of parts) {
|
|
23554
23836
|
if (part.text !== void 0 && !part.thought) {
|
|
23555
23837
|
content.push({ type: "text", text: part.text });
|
|
@@ -23560,7 +23842,9 @@ var GoogleAdapter = class {
|
|
|
23560
23842
|
if (part.inlineData) {
|
|
23561
23843
|
const inline = part.inlineData;
|
|
23562
23844
|
const mime = inline.mimeType;
|
|
23563
|
-
if (
|
|
23845
|
+
if (hasCodeExec) {
|
|
23846
|
+
files.push({ data: inline.data, mimeType: mime, source: "code_execution" });
|
|
23847
|
+
} else if (mime.startsWith("image/")) {
|
|
23564
23848
|
const p = {
|
|
23565
23849
|
type: "image_output",
|
|
23566
23850
|
mediaId: "",
|
|
@@ -23621,6 +23905,7 @@ var GoogleAdapter = class {
|
|
|
23621
23905
|
toolCalls,
|
|
23622
23906
|
thinking,
|
|
23623
23907
|
media,
|
|
23908
|
+
...files.length ? { files } : {},
|
|
23624
23909
|
latencyMs,
|
|
23625
23910
|
raw
|
|
23626
23911
|
};
|
|
@@ -23689,7 +23974,9 @@ var GoogleAdapter = class {
|
|
|
23689
23974
|
totalTokens: u.totalTokenCount ?? input + output,
|
|
23690
23975
|
cachedTokens: u.cachedContentTokenCount ?? 0,
|
|
23691
23976
|
cacheWriteTokens: 0,
|
|
23692
|
-
reasoningTokens: u.thoughtsTokenCount ?? 0
|
|
23977
|
+
reasoningTokens: u.thoughtsTokenCount ?? 0,
|
|
23978
|
+
// Billed service tier (output-only `usageMetadata.serviceTier`).
|
|
23979
|
+
...googleBilledTier(u.serviceTier)
|
|
23693
23980
|
};
|
|
23694
23981
|
}
|
|
23695
23982
|
};
|
|
@@ -24564,8 +24851,48 @@ var OpenAIBatchAdapter = class {
|
|
|
24564
24851
|
}
|
|
24565
24852
|
};
|
|
24566
24853
|
|
|
24854
|
+
// src/llm/moderation/native.ts
|
|
24855
|
+
function buildNativeModeration(mod) {
|
|
24856
|
+
return { model: mod.model ?? MODERATION_DEFAULT_MODEL };
|
|
24857
|
+
}
|
|
24858
|
+
function parseNativeModeration(raw) {
|
|
24859
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
24860
|
+
const m = raw;
|
|
24861
|
+
const input = parseEntry(m.input);
|
|
24862
|
+
const output = parseEntry(m.output);
|
|
24863
|
+
if (!input && !output) return void 0;
|
|
24864
|
+
return {
|
|
24865
|
+
source: "native",
|
|
24866
|
+
...input ? { input } : {},
|
|
24867
|
+
...output ? { output } : {}
|
|
24868
|
+
};
|
|
24869
|
+
}
|
|
24870
|
+
function parseEntry(entry) {
|
|
24871
|
+
if (!entry || typeof entry !== "object") return void 0;
|
|
24872
|
+
const e = entry;
|
|
24873
|
+
if (e.type === "error") {
|
|
24874
|
+
return { error: String(e.message ?? e.code ?? "moderation error") };
|
|
24875
|
+
}
|
|
24876
|
+
if (e.type === "moderation_results" && Array.isArray(e.results)) {
|
|
24877
|
+
const first = e.results[0];
|
|
24878
|
+
return first ? toResult(first) : void 0;
|
|
24879
|
+
}
|
|
24880
|
+
if (e.type === "moderation_result" || e.categories) {
|
|
24881
|
+
return toResult(e);
|
|
24882
|
+
}
|
|
24883
|
+
return void 0;
|
|
24884
|
+
}
|
|
24885
|
+
function toResult(r) {
|
|
24886
|
+
return {
|
|
24887
|
+
flagged: Boolean(r.flagged),
|
|
24888
|
+
categories: r.categories ?? {},
|
|
24889
|
+
categoryScores: r.category_scores ?? {},
|
|
24890
|
+
categoryAppliedInputTypes: r.category_applied_input_types
|
|
24891
|
+
};
|
|
24892
|
+
}
|
|
24893
|
+
|
|
24567
24894
|
// src/llm/providers/openai/tiers.ts
|
|
24568
|
-
var
|
|
24895
|
+
var REQUEST2 = {
|
|
24569
24896
|
auto: "auto",
|
|
24570
24897
|
standard: "default",
|
|
24571
24898
|
priority: "priority",
|
|
@@ -24575,7 +24902,7 @@ var REQUEST = {
|
|
|
24575
24902
|
var KNOWN = /* @__PURE__ */ new Set(["auto", "default", "flex", "scale", "priority"]);
|
|
24576
24903
|
function openaiRequestTier(t) {
|
|
24577
24904
|
if (!t) return void 0;
|
|
24578
|
-
const mapped =
|
|
24905
|
+
const mapped = REQUEST2[t] ?? t;
|
|
24579
24906
|
return KNOWN.has(mapped) ? mapped : "auto";
|
|
24580
24907
|
}
|
|
24581
24908
|
function openaiBilledTier(raw) {
|
|
@@ -24634,6 +24961,9 @@ var OpenAIAdapter = class {
|
|
|
24634
24961
|
if (req.stop) body.stop = req.stop;
|
|
24635
24962
|
const tier = openaiRequestTier(req.serviceTier);
|
|
24636
24963
|
if (tier) body.service_tier = tier;
|
|
24964
|
+
if (req.moderation && req.moderation.mode !== "emulate") {
|
|
24965
|
+
body.moderation = buildNativeModeration(req.moderation);
|
|
24966
|
+
}
|
|
24637
24967
|
const hasAudioInput = req.messages.some(
|
|
24638
24968
|
(m) => Array.isArray(m.content) && m.content.some((p) => p.type === "audio")
|
|
24639
24969
|
);
|
|
@@ -24792,6 +25122,7 @@ var OpenAIAdapter = class {
|
|
|
24792
25122
|
{ tool_calls: "tool_use", length: "length", content_filter: "content_filter" }
|
|
24793
25123
|
);
|
|
24794
25124
|
const reasoningContent = message.reasoning_content ?? null;
|
|
25125
|
+
const moderation = parseNativeModeration(r.moderation);
|
|
24795
25126
|
return {
|
|
24796
25127
|
id: r.id,
|
|
24797
25128
|
model: r.model,
|
|
@@ -24802,12 +25133,22 @@ var OpenAIAdapter = class {
|
|
|
24802
25133
|
toolCalls,
|
|
24803
25134
|
media,
|
|
24804
25135
|
thinking: reasoningContent,
|
|
25136
|
+
...moderation ? { moderation } : {},
|
|
24805
25137
|
latencyMs,
|
|
24806
25138
|
raw
|
|
24807
25139
|
};
|
|
24808
25140
|
}
|
|
24809
25141
|
parseStreamEvent(event) {
|
|
24810
25142
|
const data = JSON.parse(event.data);
|
|
25143
|
+
if (data.moderation) {
|
|
25144
|
+
const report = parseNativeModeration(data.moderation);
|
|
25145
|
+
const out = [];
|
|
25146
|
+
if (report?.input)
|
|
25147
|
+
out.push({ type: "moderation", phase: "input", result: report.input, source: "native" });
|
|
25148
|
+
if (report?.output)
|
|
25149
|
+
out.push({ type: "moderation", phase: "output", result: report.output, source: "native" });
|
|
25150
|
+
if (out.length) return out;
|
|
25151
|
+
}
|
|
24811
25152
|
const choices = data.choices ?? [];
|
|
24812
25153
|
const choice = choices[0];
|
|
24813
25154
|
if (!choice) {
|
|
@@ -25408,6 +25749,9 @@ var OpenAIResponsesAdapter = class {
|
|
|
25408
25749
|
if (req.topP !== void 0) body.top_p = req.topP;
|
|
25409
25750
|
const tier = openaiRequestTier(req.serviceTier);
|
|
25410
25751
|
if (tier) body.service_tier = tier;
|
|
25752
|
+
if (req.moderation && req.moderation.mode !== "emulate") {
|
|
25753
|
+
body.moderation = buildNativeModeration(req.moderation);
|
|
25754
|
+
}
|
|
25411
25755
|
if (req.tools?.length) {
|
|
25412
25756
|
body.tools = req.tools.map((t) => {
|
|
25413
25757
|
if (isFunctionTool(t)) {
|
|
@@ -25446,7 +25790,9 @@ var OpenAIResponsesAdapter = class {
|
|
|
25446
25790
|
if (req.thinking && req.thinking.mode !== "off") {
|
|
25447
25791
|
body.reasoning = {
|
|
25448
25792
|
effort: req.thinking.effort ?? "medium",
|
|
25449
|
-
summary: "auto"
|
|
25793
|
+
summary: "auto",
|
|
25794
|
+
// Cross-turn reasoning persistence (gpt-5/o-series, Responses only).
|
|
25795
|
+
...req.thinking.context ? { context: req.thinking.context } : {}
|
|
25450
25796
|
};
|
|
25451
25797
|
}
|
|
25452
25798
|
return { body };
|
|
@@ -25538,6 +25884,7 @@ var OpenAIResponsesAdapter = class {
|
|
|
25538
25884
|
const content = [];
|
|
25539
25885
|
const toolCalls = [];
|
|
25540
25886
|
const media = [];
|
|
25887
|
+
const files = [];
|
|
25541
25888
|
let thinking = null;
|
|
25542
25889
|
let text = "";
|
|
25543
25890
|
for (const item of output) {
|
|
@@ -25549,6 +25896,22 @@ var OpenAIResponsesAdapter = class {
|
|
|
25549
25896
|
const t = c.text;
|
|
25550
25897
|
text += t;
|
|
25551
25898
|
content.push({ type: "text", text: t });
|
|
25899
|
+
for (const a of c.annotations ?? []) {
|
|
25900
|
+
if (a.type === "container_file_citation" && typeof a.file_id === "string") {
|
|
25901
|
+
files.push({
|
|
25902
|
+
id: a.file_id,
|
|
25903
|
+
...typeof a.filename === "string" ? { name: a.filename } : {},
|
|
25904
|
+
source: "code_execution"
|
|
25905
|
+
});
|
|
25906
|
+
}
|
|
25907
|
+
}
|
|
25908
|
+
}
|
|
25909
|
+
}
|
|
25910
|
+
}
|
|
25911
|
+
if (type === "code_interpreter_call") {
|
|
25912
|
+
for (const out of item.outputs ?? []) {
|
|
25913
|
+
if (out.type === "image" && typeof out.url === "string") {
|
|
25914
|
+
files.push({ url: out.url, source: "code_execution" });
|
|
25552
25915
|
}
|
|
25553
25916
|
}
|
|
25554
25917
|
}
|
|
@@ -25590,6 +25953,7 @@ var OpenAIResponsesAdapter = class {
|
|
|
25590
25953
|
text = r.output_text;
|
|
25591
25954
|
if (text && content.length === 0) content.push({ type: "text", text });
|
|
25592
25955
|
}
|
|
25956
|
+
const moderation = parseNativeModeration(r.moderation);
|
|
25593
25957
|
return {
|
|
25594
25958
|
id: r.id,
|
|
25595
25959
|
model: r.model ?? "",
|
|
@@ -25600,6 +25964,8 @@ var OpenAIResponsesAdapter = class {
|
|
|
25600
25964
|
toolCalls,
|
|
25601
25965
|
thinking,
|
|
25602
25966
|
media,
|
|
25967
|
+
...files.length ? { files } : {},
|
|
25968
|
+
...moderation ? { moderation } : {},
|
|
25603
25969
|
latencyMs,
|
|
25604
25970
|
raw
|
|
25605
25971
|
};
|
|
@@ -25654,6 +26020,11 @@ var OpenAIResponsesAdapter = class {
|
|
|
25654
26020
|
}
|
|
25655
26021
|
if (type === "response.completed") {
|
|
25656
26022
|
const response = data.response ?? data;
|
|
26023
|
+
const moderation = parseNativeModeration(response.moderation);
|
|
26024
|
+
if (moderation?.input)
|
|
26025
|
+
events.push({ type: "moderation", phase: "input", result: moderation.input, source: "native" });
|
|
26026
|
+
if (moderation?.output)
|
|
26027
|
+
events.push({ type: "moderation", phase: "output", result: moderation.output, source: "native" });
|
|
25657
26028
|
const usage = response.usage;
|
|
25658
26029
|
if (usage) events.push({ type: "usage", usage: this.parseUsage(usage) });
|
|
25659
26030
|
events.push({
|
|
@@ -27320,6 +27691,7 @@ var AgentLoop = class _AgentLoop {
|
|
|
27320
27691
|
_toolTimeout;
|
|
27321
27692
|
_maxSteps;
|
|
27322
27693
|
_guardrails;
|
|
27694
|
+
_toolInputGuardrails;
|
|
27323
27695
|
_policy;
|
|
27324
27696
|
_approve;
|
|
27325
27697
|
_checkpoint;
|
|
@@ -27347,6 +27719,7 @@ var AgentLoop = class _AgentLoop {
|
|
|
27347
27719
|
this._toolTimeout = config.toolTimeout ?? DEFAULT_TOOL_TIMEOUT_MS;
|
|
27348
27720
|
this._maxSteps = config.maxSteps !== void 0 && config.maxSteps > 0 ? config.maxSteps : DEFAULT_MAX_STEPS;
|
|
27349
27721
|
this._guardrails = config.guardrails ?? [];
|
|
27722
|
+
this._toolInputGuardrails = config.toolInputGuardrails ?? [];
|
|
27350
27723
|
this._policy = config.policy ?? null;
|
|
27351
27724
|
this._approve = config.approve ?? null;
|
|
27352
27725
|
this._checkpoint = config.checkpoint ?? null;
|
|
@@ -27565,6 +27938,10 @@ var AgentLoop = class _AgentLoop {
|
|
|
27565
27938
|
toolCalls: lastResponse?.toolCalls ?? [],
|
|
27566
27939
|
thinking: lastResponse?.thinking ?? null,
|
|
27567
27940
|
media: lastResponse?.media ?? [],
|
|
27941
|
+
// Propagate hosted-tool file outputs + inline-moderation result from the final
|
|
27942
|
+
// LLM response (e.g. code-execution files produced during the run).
|
|
27943
|
+
...lastResponse?.files ? { files: lastResponse.files } : {},
|
|
27944
|
+
...lastResponse?.moderation ? { moderation: lastResponse.moderation } : {},
|
|
27568
27945
|
latencyMs: performance.now() - startPerf,
|
|
27569
27946
|
raw: lastResponse?.raw ?? null
|
|
27570
27947
|
};
|
|
@@ -27759,6 +28136,8 @@ var AgentLoop = class _AgentLoop {
|
|
|
27759
28136
|
toolCalls: lastResponse?.toolCalls ?? [],
|
|
27760
28137
|
thinking: lastResponse?.thinking ?? null,
|
|
27761
28138
|
media: [],
|
|
28139
|
+
...lastResponse?.files ? { files: lastResponse.files } : {},
|
|
28140
|
+
...lastResponse?.moderation ? { moderation: lastResponse.moderation } : {},
|
|
27762
28141
|
latencyMs: performance.now() - startPerf,
|
|
27763
28142
|
raw: null
|
|
27764
28143
|
};
|
|
@@ -27845,6 +28224,18 @@ var AgentLoop = class _AgentLoop {
|
|
|
27845
28224
|
runTrace
|
|
27846
28225
|
);
|
|
27847
28226
|
if (!lookup.found) return lookup.errorResult;
|
|
28227
|
+
for (const g of this._toolInputGuardrails) {
|
|
28228
|
+
const decision = await g.check({
|
|
28229
|
+
toolName: tc.name,
|
|
28230
|
+
arguments: tc.arguments,
|
|
28231
|
+
callId: tc.id,
|
|
28232
|
+
step,
|
|
28233
|
+
trace: { sessionId: runTrace.sessionId, requestId: runTrace.requestId, callId: tc.id }
|
|
28234
|
+
});
|
|
28235
|
+
if (!decision.pass) {
|
|
28236
|
+
return this.buildDeniedResult(tc, decision.reason, reports);
|
|
28237
|
+
}
|
|
28238
|
+
}
|
|
27848
28239
|
if (this._policy !== null) {
|
|
27849
28240
|
const target = {
|
|
27850
28241
|
kind: "tool",
|
|
@@ -27861,7 +28252,7 @@ var AgentLoop = class _AgentLoop {
|
|
|
27861
28252
|
try {
|
|
27862
28253
|
const baseCtx = { step, callId: tc.id, metrics, trace: { sessionId: runTrace.sessionId, requestId: runTrace.requestId, callId: tc.id } };
|
|
27863
28254
|
const result = await executeWithTimeout(lookup.tool, tc, baseCtx, this._toolTimeout);
|
|
27864
|
-
return await this.buildSuccessResult(tc, result, runId, step, metrics, reports, toolStart, runTrace);
|
|
28255
|
+
return await this.buildSuccessResult(tc, result, runId, step, metrics, reports, toolStart, runTrace, lookup.tool, baseCtx);
|
|
27865
28256
|
} catch (e) {
|
|
27866
28257
|
return handleToolError(e, tc, this.hooks, runId, this.id, step, metrics, reports, toolStart, runTrace);
|
|
27867
28258
|
}
|
|
@@ -27952,7 +28343,7 @@ var AgentLoop = class _AgentLoop {
|
|
|
27952
28343
|
try {
|
|
27953
28344
|
const baseCtx = { step, callId: tc.id, metrics, trace: { sessionId: runTrace.sessionId, requestId: runTrace.requestId, callId: tc.id } };
|
|
27954
28345
|
const result = await executeWithTimeout(tool, tc, baseCtx, this._toolTimeout);
|
|
27955
|
-
return await this.buildSuccessResult(tc, result, runId, step, metrics, reports, toolStart, runTrace);
|
|
28346
|
+
return await this.buildSuccessResult(tc, result, runId, step, metrics, reports, toolStart, runTrace, tool, baseCtx);
|
|
27956
28347
|
} catch (e) {
|
|
27957
28348
|
return handleToolError(e, tc, this.hooks, runId, this.id, step, metrics, reports, toolStart, runTrace);
|
|
27958
28349
|
}
|
|
@@ -27964,9 +28355,16 @@ var AgentLoop = class _AgentLoop {
|
|
|
27964
28355
|
return this.buildDeniedResult(tc, denyMsg, reports);
|
|
27965
28356
|
}
|
|
27966
28357
|
/** Emit onToolCallComplete, push report, and return success content part. */
|
|
27967
|
-
async buildSuccessResult(tc, result, runId, step, metrics, reports, toolStart, runTrace) {
|
|
28358
|
+
async buildSuccessResult(tc, result, runId, step, metrics, reports, toolStart, runTrace, tool, context) {
|
|
27968
28359
|
const latencyMs = performance.now() - toolStart;
|
|
27969
28360
|
const resultStr = typeof result === "string" ? result : JSON.stringify(result);
|
|
28361
|
+
let customData;
|
|
28362
|
+
if (tool?.customDataExtractor && context) {
|
|
28363
|
+
try {
|
|
28364
|
+
customData = await tool.customDataExtractor(result, tc.arguments, context);
|
|
28365
|
+
} catch {
|
|
28366
|
+
}
|
|
28367
|
+
}
|
|
27970
28368
|
await this.hooks.emit("onToolCallComplete", {
|
|
27971
28369
|
runId,
|
|
27972
28370
|
agentId: this.id,
|
|
@@ -27988,7 +28386,8 @@ var AgentLoop = class _AgentLoop {
|
|
|
27988
28386
|
latencyMs,
|
|
27989
28387
|
skipped: false,
|
|
27990
28388
|
error: null,
|
|
27991
|
-
metrics: Object.fromEntries(metrics)
|
|
28389
|
+
metrics: Object.fromEntries(metrics),
|
|
28390
|
+
...customData !== void 0 ? { customData } : {}
|
|
27992
28391
|
});
|
|
27993
28392
|
return { type: "tool_result", id: tc.id, content: resultStr };
|
|
27994
28393
|
}
|
|
@@ -33533,43 +33932,6 @@ function handoff(name, description, agent, opts = {}) {
|
|
|
33533
33932
|
});
|
|
33534
33933
|
}
|
|
33535
33934
|
|
|
33536
|
-
// src/llm/providers/openai/moderations.ts
|
|
33537
|
-
var OPENAI_MODERATION_BASE_URL = "https://api.openai.com";
|
|
33538
|
-
var OPENAI_MODERATION_PATH = "/v1/moderations";
|
|
33539
|
-
var OPENAI_MODERATION_DEFAULT_MODEL = "omni-moderation-latest";
|
|
33540
|
-
var OpenAIModerationAdapter = class {
|
|
33541
|
-
apiKey;
|
|
33542
|
-
baseURL;
|
|
33543
|
-
constructor(config) {
|
|
33544
|
-
this.apiKey = config.apiKey;
|
|
33545
|
-
this.baseURL = config.baseURL ?? OPENAI_MODERATION_BASE_URL;
|
|
33546
|
-
}
|
|
33547
|
-
async moderate(input, model, fetch2) {
|
|
33548
|
-
const res = await fetch2({
|
|
33549
|
-
url: `${this.baseURL}${OPENAI_MODERATION_PATH}`,
|
|
33550
|
-
method: "POST",
|
|
33551
|
-
headers: { authorization: `Bearer ${this.apiKey}`, "content-type": "application/json" },
|
|
33552
|
-
body: { model, input },
|
|
33553
|
-
provider: "openai",
|
|
33554
|
-
model,
|
|
33555
|
-
responseType: "json"
|
|
33556
|
-
});
|
|
33557
|
-
if (res.status >= 400) {
|
|
33558
|
-
throw new Error(`OpenAI moderations failed (${res.status}): ${JSON.stringify(res.body)}`);
|
|
33559
|
-
}
|
|
33560
|
-
const data = res.body;
|
|
33561
|
-
return (data.results ?? []).map(parseRawResult);
|
|
33562
|
-
}
|
|
33563
|
-
};
|
|
33564
|
-
function parseRawResult(r) {
|
|
33565
|
-
return {
|
|
33566
|
-
flagged: r.flagged,
|
|
33567
|
-
categories: r.categories,
|
|
33568
|
-
categoryScores: r.category_scores,
|
|
33569
|
-
categoryAppliedInputTypes: r.category_applied_input_types
|
|
33570
|
-
};
|
|
33571
|
-
}
|
|
33572
|
-
|
|
33573
33935
|
// src/helpers/moderate.ts
|
|
33574
33936
|
var MODERATION_COST_NOTE = "free: moderations endpoint not billed";
|
|
33575
33937
|
var MODERATION_DEFAULT_PROVIDER = "openai";
|