@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.browser.js
CHANGED
|
@@ -22177,6 +22177,7 @@ var ModelCatalog = class {
|
|
|
22177
22177
|
family: info.family,
|
|
22178
22178
|
version: info.version,
|
|
22179
22179
|
status: info.status,
|
|
22180
|
+
availability: info.availability,
|
|
22180
22181
|
active: info.active,
|
|
22181
22182
|
deprecation: info.deprecation
|
|
22182
22183
|
});
|
|
@@ -22264,6 +22265,168 @@ var ModelCatalog = class {
|
|
|
22264
22265
|
}
|
|
22265
22266
|
};
|
|
22266
22267
|
|
|
22268
|
+
// src/llm/providers/openai/moderations.ts
|
|
22269
|
+
var OPENAI_MODERATION_BASE_URL = "https://api.openai.com";
|
|
22270
|
+
var OPENAI_MODERATION_PATH = "/v1/moderations";
|
|
22271
|
+
var OPENAI_MODERATION_DEFAULT_MODEL = "omni-moderation-latest";
|
|
22272
|
+
var OpenAIModerationAdapter = class {
|
|
22273
|
+
apiKey;
|
|
22274
|
+
baseURL;
|
|
22275
|
+
constructor(config) {
|
|
22276
|
+
this.apiKey = config.apiKey;
|
|
22277
|
+
this.baseURL = config.baseURL ?? OPENAI_MODERATION_BASE_URL;
|
|
22278
|
+
}
|
|
22279
|
+
async moderate(input, model, fetch2) {
|
|
22280
|
+
const res = await fetch2({
|
|
22281
|
+
url: `${this.baseURL}${OPENAI_MODERATION_PATH}`,
|
|
22282
|
+
method: "POST",
|
|
22283
|
+
headers: { authorization: `Bearer ${this.apiKey}`, "content-type": "application/json" },
|
|
22284
|
+
body: { model, input },
|
|
22285
|
+
provider: "openai",
|
|
22286
|
+
model,
|
|
22287
|
+
responseType: "json"
|
|
22288
|
+
});
|
|
22289
|
+
if (res.status >= 400) {
|
|
22290
|
+
throw new Error(`OpenAI moderations failed (${res.status}): ${JSON.stringify(res.body)}`);
|
|
22291
|
+
}
|
|
22292
|
+
const data = res.body;
|
|
22293
|
+
return (data.results ?? []).map(parseRawResult);
|
|
22294
|
+
}
|
|
22295
|
+
};
|
|
22296
|
+
function parseRawResult(r) {
|
|
22297
|
+
return {
|
|
22298
|
+
flagged: r.flagged,
|
|
22299
|
+
categories: r.categories,
|
|
22300
|
+
categoryScores: r.category_scores,
|
|
22301
|
+
categoryAppliedInputTypes: r.category_applied_input_types
|
|
22302
|
+
};
|
|
22303
|
+
}
|
|
22304
|
+
|
|
22305
|
+
// src/llm/moderation/types.ts
|
|
22306
|
+
var MODERATION_DEFAULT_MODEL = "omni-moderation-latest";
|
|
22307
|
+
var MODERATION_DEFAULT_STRATEGY = "buffer";
|
|
22308
|
+
var MODERATION_DEFAULT_INTERVAL = 400;
|
|
22309
|
+
|
|
22310
|
+
// src/llm/moderation/runner.ts
|
|
22311
|
+
function resolveModerationMode(provider, mod) {
|
|
22312
|
+
if (mod.mode) return mod.mode;
|
|
22313
|
+
return provider === "openai" ? "native" : "emulate";
|
|
22314
|
+
}
|
|
22315
|
+
function moderationInputText(messages) {
|
|
22316
|
+
const lastUser = [...messages].reverse().find((m) => m.role === "user");
|
|
22317
|
+
if (!lastUser) return "";
|
|
22318
|
+
return typeof lastUser.content === "string" ? lastUser.content : contentText(lastUser.content);
|
|
22319
|
+
}
|
|
22320
|
+
function emptyResult() {
|
|
22321
|
+
return {
|
|
22322
|
+
flagged: false,
|
|
22323
|
+
categories: {},
|
|
22324
|
+
categoryScores: {}
|
|
22325
|
+
};
|
|
22326
|
+
}
|
|
22327
|
+
async function runModeration(text, cfg) {
|
|
22328
|
+
if (!text) return emptyResult();
|
|
22329
|
+
try {
|
|
22330
|
+
const adapter = new OpenAIModerationAdapter({ apiKey: cfg.apiKey });
|
|
22331
|
+
const results = await adapter.moderate(text, cfg.model, cfg.fetch);
|
|
22332
|
+
return results[0] ?? emptyResult();
|
|
22333
|
+
} catch (e) {
|
|
22334
|
+
return { error: e instanceof Error ? e.message : String(e) };
|
|
22335
|
+
}
|
|
22336
|
+
}
|
|
22337
|
+
function moderationModel(mod) {
|
|
22338
|
+
return mod.model ?? MODERATION_DEFAULT_MODEL;
|
|
22339
|
+
}
|
|
22340
|
+
function emitModerationZeroCost(hooks, model) {
|
|
22341
|
+
const entry = {
|
|
22342
|
+
id: crypto.randomUUID(),
|
|
22343
|
+
timestamp: Date.now(),
|
|
22344
|
+
provider: "openai",
|
|
22345
|
+
model,
|
|
22346
|
+
tokens: { input: 0, output: 0, cached: 0, cacheWrite: 0, reasoning: 0 },
|
|
22347
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0, total: 0, source: "calculated" },
|
|
22348
|
+
providerEvidence: { note: "free: moderations endpoint not billed" },
|
|
22349
|
+
tags: { provider: "openai", model, type: "moderation" }
|
|
22350
|
+
};
|
|
22351
|
+
hooks.emitSync("onCostEntry", { entry, runningTotal: 0 });
|
|
22352
|
+
}
|
|
22353
|
+
function outputEvent(result) {
|
|
22354
|
+
return { type: "moderation", phase: "output", result, source: "emulated" };
|
|
22355
|
+
}
|
|
22356
|
+
function wrapModeratedStream(raw, strategy, interval, moderate2) {
|
|
22357
|
+
const step = interval > 0 ? interval : MODERATION_DEFAULT_INTERVAL;
|
|
22358
|
+
if (strategy === "post") return wrapPost(raw, moderate2);
|
|
22359
|
+
if (strategy === "parallel") return wrapParallel(raw, step, moderate2);
|
|
22360
|
+
return wrapBuffer(raw, step, moderate2);
|
|
22361
|
+
}
|
|
22362
|
+
async function* wrapPost(raw, moderate2) {
|
|
22363
|
+
let acc = "";
|
|
22364
|
+
for await (const ev of raw) {
|
|
22365
|
+
if (ev.type === "text") acc += ev.text;
|
|
22366
|
+
yield ev;
|
|
22367
|
+
}
|
|
22368
|
+
if (acc) yield outputEvent(await moderate2(acc));
|
|
22369
|
+
}
|
|
22370
|
+
async function* wrapBuffer(raw, interval, moderate2) {
|
|
22371
|
+
let acc = "";
|
|
22372
|
+
let checkedAt = 0;
|
|
22373
|
+
let hold = [];
|
|
22374
|
+
for await (const ev of raw) {
|
|
22375
|
+
hold.push(ev);
|
|
22376
|
+
if (ev.type === "text") {
|
|
22377
|
+
acc += ev.text;
|
|
22378
|
+
if (acc.length - checkedAt >= interval || ev.text.includes("\n")) {
|
|
22379
|
+
checkedAt = acc.length;
|
|
22380
|
+
yield outputEvent(await moderate2(acc));
|
|
22381
|
+
for (const h of hold) yield h;
|
|
22382
|
+
hold = [];
|
|
22383
|
+
}
|
|
22384
|
+
}
|
|
22385
|
+
}
|
|
22386
|
+
if (acc.length > checkedAt) yield outputEvent(await moderate2(acc));
|
|
22387
|
+
for (const h of hold) yield h;
|
|
22388
|
+
}
|
|
22389
|
+
async function* wrapParallel(raw, interval, moderate2) {
|
|
22390
|
+
const iter = raw[Symbol.asyncIterator]();
|
|
22391
|
+
const pending = /* @__PURE__ */ new Set();
|
|
22392
|
+
let acc = "";
|
|
22393
|
+
let checkedAt = 0;
|
|
22394
|
+
let rawDone = false;
|
|
22395
|
+
let rawNext = iter.next();
|
|
22396
|
+
const schedule = (text) => {
|
|
22397
|
+
const p = moderate2(text).then((result) => {
|
|
22398
|
+
pending.delete(p);
|
|
22399
|
+
return { tag: "mod", event: outputEvent(result) };
|
|
22400
|
+
});
|
|
22401
|
+
pending.add(p);
|
|
22402
|
+
};
|
|
22403
|
+
while (!rawDone || pending.size > 0) {
|
|
22404
|
+
const racers = [];
|
|
22405
|
+
if (!rawDone) racers.push(rawNext.then((result) => ({ tag: "raw", result })));
|
|
22406
|
+
for (const p of pending) racers.push(p);
|
|
22407
|
+
const winner = await Promise.race(racers);
|
|
22408
|
+
if (winner.tag === "mod") {
|
|
22409
|
+
yield winner.event;
|
|
22410
|
+
continue;
|
|
22411
|
+
}
|
|
22412
|
+
if (winner.result.done) {
|
|
22413
|
+
rawDone = true;
|
|
22414
|
+
if (acc.length > checkedAt) schedule(acc);
|
|
22415
|
+
continue;
|
|
22416
|
+
}
|
|
22417
|
+
const ev = winner.result.value;
|
|
22418
|
+
yield ev;
|
|
22419
|
+
if (ev.type === "text") {
|
|
22420
|
+
acc += ev.text;
|
|
22421
|
+
if (acc.length - checkedAt >= interval) {
|
|
22422
|
+
checkedAt = acc.length;
|
|
22423
|
+
schedule(acc);
|
|
22424
|
+
}
|
|
22425
|
+
}
|
|
22426
|
+
rawNext = iter.next();
|
|
22427
|
+
}
|
|
22428
|
+
}
|
|
22429
|
+
|
|
22267
22430
|
// src/util/duration.ts
|
|
22268
22431
|
var UNIT_MS = {
|
|
22269
22432
|
s: 1e3,
|
|
@@ -22400,6 +22563,7 @@ var LLMClient = class {
|
|
|
22400
22563
|
mode;
|
|
22401
22564
|
batchable;
|
|
22402
22565
|
adapter;
|
|
22566
|
+
apiKey;
|
|
22403
22567
|
fetchFn;
|
|
22404
22568
|
fetchStreamFn;
|
|
22405
22569
|
priority;
|
|
@@ -22423,6 +22587,7 @@ var LLMClient = class {
|
|
|
22423
22587
|
this.provider = config.provider;
|
|
22424
22588
|
this.model = config.model;
|
|
22425
22589
|
this.system = config.system;
|
|
22590
|
+
this.apiKey = config.apiKey;
|
|
22426
22591
|
this.hooks = config.hooks ?? new HookBus();
|
|
22427
22592
|
this.fetchFn = config.fetch;
|
|
22428
22593
|
this.fetchStreamFn = config.fetchStream ?? null;
|
|
@@ -22476,6 +22641,34 @@ var LLMClient = class {
|
|
|
22476
22641
|
}
|
|
22477
22642
|
};
|
|
22478
22643
|
}
|
|
22644
|
+
// ─── Moderation helpers ───────────────────────────────────────────────
|
|
22645
|
+
/** Resolve the OpenAI key the emulated moderation path needs. Reuses the
|
|
22646
|
+
* client's own key when the provider is OpenAI; otherwise requires an explicit
|
|
22647
|
+
* one. Throws when none is resolvable (report-only feature, but the call still
|
|
22648
|
+
* needs a key to reach the moderations endpoint). */
|
|
22649
|
+
resolveModerationKey(mod) {
|
|
22650
|
+
const key = mod.apiKey ?? (this.provider === "openai" ? this.apiKey : void 0);
|
|
22651
|
+
if (!key) {
|
|
22652
|
+
throw new Error(
|
|
22653
|
+
"moderation: emulated moderation requires an OpenAI API key (the only public moderations endpoint). Pass moderation.apiKey, or use the OpenAI provider."
|
|
22654
|
+
);
|
|
22655
|
+
}
|
|
22656
|
+
return key;
|
|
22657
|
+
}
|
|
22658
|
+
moderationConfig(mod) {
|
|
22659
|
+
return {
|
|
22660
|
+
apiKey: this.resolveModerationKey(mod),
|
|
22661
|
+
model: moderationModel(mod),
|
|
22662
|
+
fetch: this.fetchFn
|
|
22663
|
+
};
|
|
22664
|
+
}
|
|
22665
|
+
/** Fold a moderation stream event into the accumulating report. */
|
|
22666
|
+
mergeModeration(prev, phase, result, source) {
|
|
22667
|
+
const next = prev && prev.source === source ? { ...prev } : { source };
|
|
22668
|
+
if (phase === "input") next.input = result;
|
|
22669
|
+
else next.output = result;
|
|
22670
|
+
return next;
|
|
22671
|
+
}
|
|
22479
22672
|
/** Submit a request. Returns the parsed CompletionResponse. */
|
|
22480
22673
|
async complete(input, options = {}) {
|
|
22481
22674
|
const rawMessages = normalizeInput(input);
|
|
@@ -22496,6 +22689,7 @@ var LLMClient = class {
|
|
|
22496
22689
|
thinking: options.thinking,
|
|
22497
22690
|
cache: options.cache,
|
|
22498
22691
|
serviceTier: options.serviceTier,
|
|
22692
|
+
moderation: options.moderation,
|
|
22499
22693
|
providerOptions: options.providerOptions,
|
|
22500
22694
|
audio: options.audio,
|
|
22501
22695
|
outputModalities: options.outputModalities,
|
|
@@ -22551,6 +22745,8 @@ var LLMClient = class {
|
|
|
22551
22745
|
await this.hooks.emit("onBeforeSubmit", submitCtx);
|
|
22552
22746
|
const inputChars = JSON.stringify(normalized.messages).length;
|
|
22553
22747
|
const estimatedInputTokens = Math.ceil(inputChars / 4);
|
|
22748
|
+
const mod = options.moderation;
|
|
22749
|
+
const moderationCfg = mod && resolveModerationMode(this.provider, mod) === "emulate" ? this.moderationConfig(mod) : void 0;
|
|
22554
22750
|
const start = performance.now();
|
|
22555
22751
|
let response;
|
|
22556
22752
|
if (submitCtx.intercepted && submitCtx.resultPromise) {
|
|
@@ -22576,6 +22772,22 @@ var LLMClient = class {
|
|
|
22576
22772
|
}
|
|
22577
22773
|
const latencyMs = performance.now() - start;
|
|
22578
22774
|
const result = this.adapter.parseResponse(response.body, latencyMs);
|
|
22775
|
+
if (mod && moderationCfg) {
|
|
22776
|
+
const cfg = moderationCfg;
|
|
22777
|
+
const doInput = mod.input ?? true;
|
|
22778
|
+
const doOutput = mod.output ?? true;
|
|
22779
|
+
const [inputEntry, outputEntry] = await Promise.all([
|
|
22780
|
+
doInput ? runModeration(moderationInputText(normalized.messages), cfg) : Promise.resolve(void 0),
|
|
22781
|
+
doOutput ? runModeration(result.text, cfg) : Promise.resolve(void 0)
|
|
22782
|
+
]);
|
|
22783
|
+
if (doInput) emitModerationZeroCost(this.hooks, cfg.model);
|
|
22784
|
+
if (doOutput) emitModerationZeroCost(this.hooks, cfg.model);
|
|
22785
|
+
result.moderation = {
|
|
22786
|
+
source: "emulated",
|
|
22787
|
+
...inputEntry ? { input: inputEntry } : {},
|
|
22788
|
+
...outputEntry ? { output: outputEntry } : {}
|
|
22789
|
+
};
|
|
22790
|
+
}
|
|
22579
22791
|
await this.hooks.emit("onCompletion", {
|
|
22580
22792
|
provider: this.provider,
|
|
22581
22793
|
model: this.model,
|
|
@@ -22623,6 +22835,7 @@ var LLMClient = class {
|
|
|
22623
22835
|
thinking: options.thinking,
|
|
22624
22836
|
cache: options.cache,
|
|
22625
22837
|
serviceTier: options.serviceTier,
|
|
22838
|
+
moderation: options.moderation,
|
|
22626
22839
|
providerOptions: options.providerOptions,
|
|
22627
22840
|
audio: options.audio,
|
|
22628
22841
|
outputModalities: options.outputModalities,
|
|
@@ -22666,29 +22879,65 @@ var LLMClient = class {
|
|
|
22666
22879
|
let thinking = "";
|
|
22667
22880
|
let usage = emptyUsage();
|
|
22668
22881
|
let finishReason = "stop";
|
|
22669
|
-
|
|
22670
|
-
|
|
22671
|
-
|
|
22672
|
-
|
|
22673
|
-
|
|
22674
|
-
|
|
22675
|
-
for (const
|
|
22676
|
-
|
|
22677
|
-
|
|
22678
|
-
|
|
22679
|
-
|
|
22680
|
-
|
|
22681
|
-
|
|
22682
|
-
|
|
22683
|
-
|
|
22684
|
-
|
|
22685
|
-
|
|
22686
|
-
|
|
22687
|
-
|
|
22688
|
-
|
|
22689
|
-
|
|
22690
|
-
|
|
22882
|
+
let moderationReport;
|
|
22883
|
+
const fetchStream = this.fetchStreamFn;
|
|
22884
|
+
const adapter = this.adapter;
|
|
22885
|
+
const queueName = this.queueName;
|
|
22886
|
+
const priority = this.priority;
|
|
22887
|
+
async function* rawEvents() {
|
|
22888
|
+
for await (const sseEvent of fetchStream(httpReq, {
|
|
22889
|
+
queueName,
|
|
22890
|
+
priority,
|
|
22891
|
+
ctx
|
|
22892
|
+
})) {
|
|
22893
|
+
for (const ev of adapter.parseStreamEvent(sseEvent)) yield ev;
|
|
22894
|
+
}
|
|
22895
|
+
}
|
|
22896
|
+
const mod = options.moderation;
|
|
22897
|
+
const emulate = !!mod && resolveModerationMode(this.provider, mod) === "emulate";
|
|
22898
|
+
let eventStream = rawEvents();
|
|
22899
|
+
if (mod && emulate && (mod.output ?? true)) {
|
|
22900
|
+
const cfg = this.moderationConfig(mod);
|
|
22901
|
+
const hooks = this.hooks;
|
|
22902
|
+
const strategy = mod.stream?.strategy ?? MODERATION_DEFAULT_STRATEGY;
|
|
22903
|
+
const interval = mod.stream?.interval ?? MODERATION_DEFAULT_INTERVAL;
|
|
22904
|
+
eventStream = wrapModeratedStream(eventStream, strategy, interval, async (t) => {
|
|
22905
|
+
const r = await runModeration(t, cfg);
|
|
22906
|
+
emitModerationZeroCost(hooks, cfg.model);
|
|
22907
|
+
return r;
|
|
22908
|
+
});
|
|
22909
|
+
}
|
|
22910
|
+
if (mod && emulate && (mod.input ?? true)) {
|
|
22911
|
+
const cfg = this.moderationConfig(mod);
|
|
22912
|
+
const inputEntry = await runModeration(moderationInputText(normalized.messages), cfg);
|
|
22913
|
+
emitModerationZeroCost(this.hooks, cfg.model);
|
|
22914
|
+
moderationReport = this.mergeModeration(moderationReport, "input", inputEntry, "emulated");
|
|
22915
|
+
yield { type: "moderation", phase: "input", result: inputEntry, source: "emulated" };
|
|
22916
|
+
}
|
|
22917
|
+
for await (const event of eventStream) {
|
|
22918
|
+
switch (event.type) {
|
|
22919
|
+
case "text":
|
|
22920
|
+
text += event.text;
|
|
22921
|
+
break;
|
|
22922
|
+
case "thinking":
|
|
22923
|
+
thinking += event.text;
|
|
22924
|
+
break;
|
|
22925
|
+
case "usage":
|
|
22926
|
+
usage = event.usage;
|
|
22927
|
+
break;
|
|
22928
|
+
case "done":
|
|
22929
|
+
finishReason = event.finishReason;
|
|
22930
|
+
break;
|
|
22931
|
+
case "moderation":
|
|
22932
|
+
moderationReport = this.mergeModeration(
|
|
22933
|
+
moderationReport,
|
|
22934
|
+
event.phase,
|
|
22935
|
+
event.result,
|
|
22936
|
+
event.source
|
|
22937
|
+
);
|
|
22938
|
+
break;
|
|
22691
22939
|
}
|
|
22940
|
+
yield event;
|
|
22692
22941
|
}
|
|
22693
22942
|
const inputChars = JSON.stringify(normalized.messages).length;
|
|
22694
22943
|
const response = {
|
|
@@ -22701,6 +22950,7 @@ var LLMClient = class {
|
|
|
22701
22950
|
toolCalls: [],
|
|
22702
22951
|
thinking: thinking || null,
|
|
22703
22952
|
media: [],
|
|
22953
|
+
...moderationReport ? { moderation: moderationReport } : {},
|
|
22704
22954
|
latencyMs: performance.now() - start,
|
|
22705
22955
|
raw: null
|
|
22706
22956
|
};
|
|
@@ -23009,6 +23259,9 @@ var AnthropicAdapter = class {
|
|
|
23009
23259
|
if (t.type === "web_search") {
|
|
23010
23260
|
return { type: "web_search_20250305", name: "web_search", max_uses: 5 };
|
|
23011
23261
|
}
|
|
23262
|
+
if (t.type === "code_interpreter") {
|
|
23263
|
+
return { type: "code_execution_20260521", name: "code_execution" };
|
|
23264
|
+
}
|
|
23012
23265
|
return null;
|
|
23013
23266
|
}
|
|
23014
23267
|
const tool = {
|
|
@@ -23052,7 +23305,10 @@ var AnthropicAdapter = class {
|
|
|
23052
23305
|
});
|
|
23053
23306
|
const headers = {};
|
|
23054
23307
|
if (hasFileRef) headers["anthropic-beta"] = "files-api-2025-04-14";
|
|
23055
|
-
|
|
23308
|
+
const usesCodeExec = req.tools?.some(
|
|
23309
|
+
(t) => !isFunctionTool(t) && t.type === "code_interpreter"
|
|
23310
|
+
);
|
|
23311
|
+
return { body, headers, ...usesCodeExec ? { path: "/v1/messages?beta=true" } : {} };
|
|
23056
23312
|
}
|
|
23057
23313
|
enableStreaming(providerReq, _req) {
|
|
23058
23314
|
providerReq.body.stream = true;
|
|
@@ -23119,6 +23375,7 @@ var AnthropicAdapter = class {
|
|
|
23119
23375
|
const content = [];
|
|
23120
23376
|
let thinking = null;
|
|
23121
23377
|
const toolCalls = [];
|
|
23378
|
+
const files = [];
|
|
23122
23379
|
for (const block of contentBlocks) {
|
|
23123
23380
|
if (block.type === "text") {
|
|
23124
23381
|
content.push({ type: "text", text: block.text });
|
|
@@ -23133,6 +23390,15 @@ var AnthropicAdapter = class {
|
|
|
23133
23390
|
};
|
|
23134
23391
|
content.push(tc);
|
|
23135
23392
|
toolCalls.push(tc);
|
|
23393
|
+
} else if (block.type === "bash_code_execution_tool_result" || block.type === "code_execution_tool_result") {
|
|
23394
|
+
const result = block.content;
|
|
23395
|
+
if (result && (result.type === "bash_code_execution_result" || result.type === "code_execution_result") && Array.isArray(result.content)) {
|
|
23396
|
+
for (const out of result.content) {
|
|
23397
|
+
if ((out.type === "bash_code_execution_output" || out.type === "code_execution_output") && typeof out.file_id === "string") {
|
|
23398
|
+
files.push({ id: out.file_id, source: "code_execution" });
|
|
23399
|
+
}
|
|
23400
|
+
}
|
|
23401
|
+
}
|
|
23136
23402
|
}
|
|
23137
23403
|
}
|
|
23138
23404
|
const finishReason = extractFinishReason(toolCalls.length > 0, r.stop_reason, {
|
|
@@ -23147,6 +23413,7 @@ var AnthropicAdapter = class {
|
|
|
23147
23413
|
text: content.filter((p) => p.type === "text").map((p) => p.text).join(""),
|
|
23148
23414
|
toolCalls,
|
|
23149
23415
|
media: [],
|
|
23416
|
+
...files.length ? { files } : {},
|
|
23150
23417
|
thinking,
|
|
23151
23418
|
latencyMs,
|
|
23152
23419
|
raw
|
|
@@ -23452,6 +23719,17 @@ function resolveVoice(provider, voice) {
|
|
|
23452
23719
|
return VOICE_ALIASES[provider]?.[voice] ?? voice;
|
|
23453
23720
|
}
|
|
23454
23721
|
|
|
23722
|
+
// src/llm/providers/google/tiers.ts
|
|
23723
|
+
var REQUEST = /* @__PURE__ */ new Set(["flex", "standard", "priority"]);
|
|
23724
|
+
function googleRequestTier(t) {
|
|
23725
|
+
if (!t) return void 0;
|
|
23726
|
+
return REQUEST.has(t) ? t : void 0;
|
|
23727
|
+
}
|
|
23728
|
+
function googleBilledTier(raw) {
|
|
23729
|
+
if (typeof raw !== "string" || !raw) return {};
|
|
23730
|
+
return { serviceTier: raw, pricingTier: raw.toLowerCase() };
|
|
23731
|
+
}
|
|
23732
|
+
|
|
23455
23733
|
// src/llm/providers/google/constants.ts
|
|
23456
23734
|
var GOOGLE_THINKING_LEVELS = {
|
|
23457
23735
|
low: "LOW",
|
|
@@ -23504,6 +23782,8 @@ var GoogleAdapter = class {
|
|
|
23504
23782
|
contents,
|
|
23505
23783
|
generationConfig: config
|
|
23506
23784
|
};
|
|
23785
|
+
const tier = googleRequestTier(req.serviceTier);
|
|
23786
|
+
if (tier) body.serviceTier = tier;
|
|
23507
23787
|
if (req.system) {
|
|
23508
23788
|
body.systemInstruction = { parts: [{ text: req.system }] };
|
|
23509
23789
|
}
|
|
@@ -23622,7 +23902,9 @@ var GoogleAdapter = class {
|
|
|
23622
23902
|
const content = [];
|
|
23623
23903
|
const toolCalls = [];
|
|
23624
23904
|
const media = [];
|
|
23905
|
+
const files = [];
|
|
23625
23906
|
let thinking = null;
|
|
23907
|
+
const hasCodeExec = parts.some((p) => p.executableCode || p.codeExecutionResult);
|
|
23626
23908
|
for (const part of parts) {
|
|
23627
23909
|
if (part.text !== void 0 && !part.thought) {
|
|
23628
23910
|
content.push({ type: "text", text: part.text });
|
|
@@ -23633,7 +23915,9 @@ var GoogleAdapter = class {
|
|
|
23633
23915
|
if (part.inlineData) {
|
|
23634
23916
|
const inline = part.inlineData;
|
|
23635
23917
|
const mime = inline.mimeType;
|
|
23636
|
-
if (
|
|
23918
|
+
if (hasCodeExec) {
|
|
23919
|
+
files.push({ data: inline.data, mimeType: mime, source: "code_execution" });
|
|
23920
|
+
} else if (mime.startsWith("image/")) {
|
|
23637
23921
|
const p = {
|
|
23638
23922
|
type: "image_output",
|
|
23639
23923
|
mediaId: "",
|
|
@@ -23694,6 +23978,7 @@ var GoogleAdapter = class {
|
|
|
23694
23978
|
toolCalls,
|
|
23695
23979
|
thinking,
|
|
23696
23980
|
media,
|
|
23981
|
+
...files.length ? { files } : {},
|
|
23697
23982
|
latencyMs,
|
|
23698
23983
|
raw
|
|
23699
23984
|
};
|
|
@@ -23762,7 +24047,9 @@ var GoogleAdapter = class {
|
|
|
23762
24047
|
totalTokens: u.totalTokenCount ?? input + output,
|
|
23763
24048
|
cachedTokens: u.cachedContentTokenCount ?? 0,
|
|
23764
24049
|
cacheWriteTokens: 0,
|
|
23765
|
-
reasoningTokens: u.thoughtsTokenCount ?? 0
|
|
24050
|
+
reasoningTokens: u.thoughtsTokenCount ?? 0,
|
|
24051
|
+
// Billed service tier (output-only `usageMetadata.serviceTier`).
|
|
24052
|
+
...googleBilledTier(u.serviceTier)
|
|
23766
24053
|
};
|
|
23767
24054
|
}
|
|
23768
24055
|
};
|
|
@@ -24637,8 +24924,48 @@ var OpenAIBatchAdapter = class {
|
|
|
24637
24924
|
}
|
|
24638
24925
|
};
|
|
24639
24926
|
|
|
24927
|
+
// src/llm/moderation/native.ts
|
|
24928
|
+
function buildNativeModeration(mod) {
|
|
24929
|
+
return { model: mod.model ?? MODERATION_DEFAULT_MODEL };
|
|
24930
|
+
}
|
|
24931
|
+
function parseNativeModeration(raw) {
|
|
24932
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
24933
|
+
const m = raw;
|
|
24934
|
+
const input = parseEntry(m.input);
|
|
24935
|
+
const output = parseEntry(m.output);
|
|
24936
|
+
if (!input && !output) return void 0;
|
|
24937
|
+
return {
|
|
24938
|
+
source: "native",
|
|
24939
|
+
...input ? { input } : {},
|
|
24940
|
+
...output ? { output } : {}
|
|
24941
|
+
};
|
|
24942
|
+
}
|
|
24943
|
+
function parseEntry(entry) {
|
|
24944
|
+
if (!entry || typeof entry !== "object") return void 0;
|
|
24945
|
+
const e = entry;
|
|
24946
|
+
if (e.type === "error") {
|
|
24947
|
+
return { error: String(e.message ?? e.code ?? "moderation error") };
|
|
24948
|
+
}
|
|
24949
|
+
if (e.type === "moderation_results" && Array.isArray(e.results)) {
|
|
24950
|
+
const first = e.results[0];
|
|
24951
|
+
return first ? toResult(first) : void 0;
|
|
24952
|
+
}
|
|
24953
|
+
if (e.type === "moderation_result" || e.categories) {
|
|
24954
|
+
return toResult(e);
|
|
24955
|
+
}
|
|
24956
|
+
return void 0;
|
|
24957
|
+
}
|
|
24958
|
+
function toResult(r) {
|
|
24959
|
+
return {
|
|
24960
|
+
flagged: Boolean(r.flagged),
|
|
24961
|
+
categories: r.categories ?? {},
|
|
24962
|
+
categoryScores: r.category_scores ?? {},
|
|
24963
|
+
categoryAppliedInputTypes: r.category_applied_input_types
|
|
24964
|
+
};
|
|
24965
|
+
}
|
|
24966
|
+
|
|
24640
24967
|
// src/llm/providers/openai/tiers.ts
|
|
24641
|
-
var
|
|
24968
|
+
var REQUEST2 = {
|
|
24642
24969
|
auto: "auto",
|
|
24643
24970
|
standard: "default",
|
|
24644
24971
|
priority: "priority",
|
|
@@ -24648,7 +24975,7 @@ var REQUEST = {
|
|
|
24648
24975
|
var KNOWN = /* @__PURE__ */ new Set(["auto", "default", "flex", "scale", "priority"]);
|
|
24649
24976
|
function openaiRequestTier(t) {
|
|
24650
24977
|
if (!t) return void 0;
|
|
24651
|
-
const mapped =
|
|
24978
|
+
const mapped = REQUEST2[t] ?? t;
|
|
24652
24979
|
return KNOWN.has(mapped) ? mapped : "auto";
|
|
24653
24980
|
}
|
|
24654
24981
|
function openaiBilledTier(raw) {
|
|
@@ -24707,6 +25034,9 @@ var OpenAIAdapter = class {
|
|
|
24707
25034
|
if (req.stop) body.stop = req.stop;
|
|
24708
25035
|
const tier = openaiRequestTier(req.serviceTier);
|
|
24709
25036
|
if (tier) body.service_tier = tier;
|
|
25037
|
+
if (req.moderation && req.moderation.mode !== "emulate") {
|
|
25038
|
+
body.moderation = buildNativeModeration(req.moderation);
|
|
25039
|
+
}
|
|
24710
25040
|
const hasAudioInput = req.messages.some(
|
|
24711
25041
|
(m) => Array.isArray(m.content) && m.content.some((p) => p.type === "audio")
|
|
24712
25042
|
);
|
|
@@ -24865,6 +25195,7 @@ var OpenAIAdapter = class {
|
|
|
24865
25195
|
{ tool_calls: "tool_use", length: "length", content_filter: "content_filter" }
|
|
24866
25196
|
);
|
|
24867
25197
|
const reasoningContent = message.reasoning_content ?? null;
|
|
25198
|
+
const moderation = parseNativeModeration(r.moderation);
|
|
24868
25199
|
return {
|
|
24869
25200
|
id: r.id,
|
|
24870
25201
|
model: r.model,
|
|
@@ -24875,12 +25206,22 @@ var OpenAIAdapter = class {
|
|
|
24875
25206
|
toolCalls,
|
|
24876
25207
|
media,
|
|
24877
25208
|
thinking: reasoningContent,
|
|
25209
|
+
...moderation ? { moderation } : {},
|
|
24878
25210
|
latencyMs,
|
|
24879
25211
|
raw
|
|
24880
25212
|
};
|
|
24881
25213
|
}
|
|
24882
25214
|
parseStreamEvent(event) {
|
|
24883
25215
|
const data = JSON.parse(event.data);
|
|
25216
|
+
if (data.moderation) {
|
|
25217
|
+
const report = parseNativeModeration(data.moderation);
|
|
25218
|
+
const out = [];
|
|
25219
|
+
if (report?.input)
|
|
25220
|
+
out.push({ type: "moderation", phase: "input", result: report.input, source: "native" });
|
|
25221
|
+
if (report?.output)
|
|
25222
|
+
out.push({ type: "moderation", phase: "output", result: report.output, source: "native" });
|
|
25223
|
+
if (out.length) return out;
|
|
25224
|
+
}
|
|
24884
25225
|
const choices = data.choices ?? [];
|
|
24885
25226
|
const choice = choices[0];
|
|
24886
25227
|
if (!choice) {
|
|
@@ -25481,6 +25822,9 @@ var OpenAIResponsesAdapter = class {
|
|
|
25481
25822
|
if (req.topP !== void 0) body.top_p = req.topP;
|
|
25482
25823
|
const tier = openaiRequestTier(req.serviceTier);
|
|
25483
25824
|
if (tier) body.service_tier = tier;
|
|
25825
|
+
if (req.moderation && req.moderation.mode !== "emulate") {
|
|
25826
|
+
body.moderation = buildNativeModeration(req.moderation);
|
|
25827
|
+
}
|
|
25484
25828
|
if (req.tools?.length) {
|
|
25485
25829
|
body.tools = req.tools.map((t) => {
|
|
25486
25830
|
if (isFunctionTool(t)) {
|
|
@@ -25519,7 +25863,9 @@ var OpenAIResponsesAdapter = class {
|
|
|
25519
25863
|
if (req.thinking && req.thinking.mode !== "off") {
|
|
25520
25864
|
body.reasoning = {
|
|
25521
25865
|
effort: req.thinking.effort ?? "medium",
|
|
25522
|
-
summary: "auto"
|
|
25866
|
+
summary: "auto",
|
|
25867
|
+
// Cross-turn reasoning persistence (gpt-5/o-series, Responses only).
|
|
25868
|
+
...req.thinking.context ? { context: req.thinking.context } : {}
|
|
25523
25869
|
};
|
|
25524
25870
|
}
|
|
25525
25871
|
return { body };
|
|
@@ -25611,6 +25957,7 @@ var OpenAIResponsesAdapter = class {
|
|
|
25611
25957
|
const content = [];
|
|
25612
25958
|
const toolCalls = [];
|
|
25613
25959
|
const media = [];
|
|
25960
|
+
const files = [];
|
|
25614
25961
|
let thinking = null;
|
|
25615
25962
|
let text = "";
|
|
25616
25963
|
for (const item of output) {
|
|
@@ -25622,6 +25969,22 @@ var OpenAIResponsesAdapter = class {
|
|
|
25622
25969
|
const t = c.text;
|
|
25623
25970
|
text += t;
|
|
25624
25971
|
content.push({ type: "text", text: t });
|
|
25972
|
+
for (const a of c.annotations ?? []) {
|
|
25973
|
+
if (a.type === "container_file_citation" && typeof a.file_id === "string") {
|
|
25974
|
+
files.push({
|
|
25975
|
+
id: a.file_id,
|
|
25976
|
+
...typeof a.filename === "string" ? { name: a.filename } : {},
|
|
25977
|
+
source: "code_execution"
|
|
25978
|
+
});
|
|
25979
|
+
}
|
|
25980
|
+
}
|
|
25981
|
+
}
|
|
25982
|
+
}
|
|
25983
|
+
}
|
|
25984
|
+
if (type === "code_interpreter_call") {
|
|
25985
|
+
for (const out of item.outputs ?? []) {
|
|
25986
|
+
if (out.type === "image" && typeof out.url === "string") {
|
|
25987
|
+
files.push({ url: out.url, source: "code_execution" });
|
|
25625
25988
|
}
|
|
25626
25989
|
}
|
|
25627
25990
|
}
|
|
@@ -25663,6 +26026,7 @@ var OpenAIResponsesAdapter = class {
|
|
|
25663
26026
|
text = r.output_text;
|
|
25664
26027
|
if (text && content.length === 0) content.push({ type: "text", text });
|
|
25665
26028
|
}
|
|
26029
|
+
const moderation = parseNativeModeration(r.moderation);
|
|
25666
26030
|
return {
|
|
25667
26031
|
id: r.id,
|
|
25668
26032
|
model: r.model ?? "",
|
|
@@ -25673,6 +26037,8 @@ var OpenAIResponsesAdapter = class {
|
|
|
25673
26037
|
toolCalls,
|
|
25674
26038
|
thinking,
|
|
25675
26039
|
media,
|
|
26040
|
+
...files.length ? { files } : {},
|
|
26041
|
+
...moderation ? { moderation } : {},
|
|
25676
26042
|
latencyMs,
|
|
25677
26043
|
raw
|
|
25678
26044
|
};
|
|
@@ -25727,6 +26093,11 @@ var OpenAIResponsesAdapter = class {
|
|
|
25727
26093
|
}
|
|
25728
26094
|
if (type === "response.completed") {
|
|
25729
26095
|
const response = data.response ?? data;
|
|
26096
|
+
const moderation = parseNativeModeration(response.moderation);
|
|
26097
|
+
if (moderation?.input)
|
|
26098
|
+
events.push({ type: "moderation", phase: "input", result: moderation.input, source: "native" });
|
|
26099
|
+
if (moderation?.output)
|
|
26100
|
+
events.push({ type: "moderation", phase: "output", result: moderation.output, source: "native" });
|
|
25730
26101
|
const usage = response.usage;
|
|
25731
26102
|
if (usage) events.push({ type: "usage", usage: this.parseUsage(usage) });
|
|
25732
26103
|
events.push({
|
|
@@ -27393,6 +27764,7 @@ var AgentLoop = class _AgentLoop {
|
|
|
27393
27764
|
_toolTimeout;
|
|
27394
27765
|
_maxSteps;
|
|
27395
27766
|
_guardrails;
|
|
27767
|
+
_toolInputGuardrails;
|
|
27396
27768
|
_policy;
|
|
27397
27769
|
_approve;
|
|
27398
27770
|
_checkpoint;
|
|
@@ -27420,6 +27792,7 @@ var AgentLoop = class _AgentLoop {
|
|
|
27420
27792
|
this._toolTimeout = config.toolTimeout ?? DEFAULT_TOOL_TIMEOUT_MS;
|
|
27421
27793
|
this._maxSteps = config.maxSteps !== void 0 && config.maxSteps > 0 ? config.maxSteps : DEFAULT_MAX_STEPS;
|
|
27422
27794
|
this._guardrails = config.guardrails ?? [];
|
|
27795
|
+
this._toolInputGuardrails = config.toolInputGuardrails ?? [];
|
|
27423
27796
|
this._policy = config.policy ?? null;
|
|
27424
27797
|
this._approve = config.approve ?? null;
|
|
27425
27798
|
this._checkpoint = config.checkpoint ?? null;
|
|
@@ -27638,6 +28011,10 @@ var AgentLoop = class _AgentLoop {
|
|
|
27638
28011
|
toolCalls: lastResponse?.toolCalls ?? [],
|
|
27639
28012
|
thinking: lastResponse?.thinking ?? null,
|
|
27640
28013
|
media: lastResponse?.media ?? [],
|
|
28014
|
+
// Propagate hosted-tool file outputs + inline-moderation result from the final
|
|
28015
|
+
// LLM response (e.g. code-execution files produced during the run).
|
|
28016
|
+
...lastResponse?.files ? { files: lastResponse.files } : {},
|
|
28017
|
+
...lastResponse?.moderation ? { moderation: lastResponse.moderation } : {},
|
|
27641
28018
|
latencyMs: performance.now() - startPerf,
|
|
27642
28019
|
raw: lastResponse?.raw ?? null
|
|
27643
28020
|
};
|
|
@@ -27832,6 +28209,8 @@ var AgentLoop = class _AgentLoop {
|
|
|
27832
28209
|
toolCalls: lastResponse?.toolCalls ?? [],
|
|
27833
28210
|
thinking: lastResponse?.thinking ?? null,
|
|
27834
28211
|
media: [],
|
|
28212
|
+
...lastResponse?.files ? { files: lastResponse.files } : {},
|
|
28213
|
+
...lastResponse?.moderation ? { moderation: lastResponse.moderation } : {},
|
|
27835
28214
|
latencyMs: performance.now() - startPerf,
|
|
27836
28215
|
raw: null
|
|
27837
28216
|
};
|
|
@@ -27918,6 +28297,18 @@ var AgentLoop = class _AgentLoop {
|
|
|
27918
28297
|
runTrace
|
|
27919
28298
|
);
|
|
27920
28299
|
if (!lookup.found) return lookup.errorResult;
|
|
28300
|
+
for (const g of this._toolInputGuardrails) {
|
|
28301
|
+
const decision = await g.check({
|
|
28302
|
+
toolName: tc.name,
|
|
28303
|
+
arguments: tc.arguments,
|
|
28304
|
+
callId: tc.id,
|
|
28305
|
+
step,
|
|
28306
|
+
trace: { sessionId: runTrace.sessionId, requestId: runTrace.requestId, callId: tc.id }
|
|
28307
|
+
});
|
|
28308
|
+
if (!decision.pass) {
|
|
28309
|
+
return this.buildDeniedResult(tc, decision.reason, reports);
|
|
28310
|
+
}
|
|
28311
|
+
}
|
|
27921
28312
|
if (this._policy !== null) {
|
|
27922
28313
|
const target = {
|
|
27923
28314
|
kind: "tool",
|
|
@@ -27934,7 +28325,7 @@ var AgentLoop = class _AgentLoop {
|
|
|
27934
28325
|
try {
|
|
27935
28326
|
const baseCtx = { step, callId: tc.id, metrics, trace: { sessionId: runTrace.sessionId, requestId: runTrace.requestId, callId: tc.id } };
|
|
27936
28327
|
const result = await executeWithTimeout(lookup.tool, tc, baseCtx, this._toolTimeout);
|
|
27937
|
-
return await this.buildSuccessResult(tc, result, runId, step, metrics, reports, toolStart, runTrace);
|
|
28328
|
+
return await this.buildSuccessResult(tc, result, runId, step, metrics, reports, toolStart, runTrace, lookup.tool, baseCtx);
|
|
27938
28329
|
} catch (e) {
|
|
27939
28330
|
return handleToolError(e, tc, this.hooks, runId, this.id, step, metrics, reports, toolStart, runTrace);
|
|
27940
28331
|
}
|
|
@@ -28025,7 +28416,7 @@ var AgentLoop = class _AgentLoop {
|
|
|
28025
28416
|
try {
|
|
28026
28417
|
const baseCtx = { step, callId: tc.id, metrics, trace: { sessionId: runTrace.sessionId, requestId: runTrace.requestId, callId: tc.id } };
|
|
28027
28418
|
const result = await executeWithTimeout(tool, tc, baseCtx, this._toolTimeout);
|
|
28028
|
-
return await this.buildSuccessResult(tc, result, runId, step, metrics, reports, toolStart, runTrace);
|
|
28419
|
+
return await this.buildSuccessResult(tc, result, runId, step, metrics, reports, toolStart, runTrace, tool, baseCtx);
|
|
28029
28420
|
} catch (e) {
|
|
28030
28421
|
return handleToolError(e, tc, this.hooks, runId, this.id, step, metrics, reports, toolStart, runTrace);
|
|
28031
28422
|
}
|
|
@@ -28037,9 +28428,16 @@ var AgentLoop = class _AgentLoop {
|
|
|
28037
28428
|
return this.buildDeniedResult(tc, denyMsg, reports);
|
|
28038
28429
|
}
|
|
28039
28430
|
/** Emit onToolCallComplete, push report, and return success content part. */
|
|
28040
|
-
async buildSuccessResult(tc, result, runId, step, metrics, reports, toolStart, runTrace) {
|
|
28431
|
+
async buildSuccessResult(tc, result, runId, step, metrics, reports, toolStart, runTrace, tool, context) {
|
|
28041
28432
|
const latencyMs = performance.now() - toolStart;
|
|
28042
28433
|
const resultStr = typeof result === "string" ? result : JSON.stringify(result);
|
|
28434
|
+
let customData;
|
|
28435
|
+
if (tool?.customDataExtractor && context) {
|
|
28436
|
+
try {
|
|
28437
|
+
customData = await tool.customDataExtractor(result, tc.arguments, context);
|
|
28438
|
+
} catch {
|
|
28439
|
+
}
|
|
28440
|
+
}
|
|
28043
28441
|
await this.hooks.emit("onToolCallComplete", {
|
|
28044
28442
|
runId,
|
|
28045
28443
|
agentId: this.id,
|
|
@@ -28061,7 +28459,8 @@ var AgentLoop = class _AgentLoop {
|
|
|
28061
28459
|
latencyMs,
|
|
28062
28460
|
skipped: false,
|
|
28063
28461
|
error: null,
|
|
28064
|
-
metrics: Object.fromEntries(metrics)
|
|
28462
|
+
metrics: Object.fromEntries(metrics),
|
|
28463
|
+
...customData !== void 0 ? { customData } : {}
|
|
28065
28464
|
});
|
|
28066
28465
|
return { type: "tool_result", id: tc.id, content: resultStr };
|
|
28067
28466
|
}
|
|
@@ -33606,43 +34005,6 @@ function handoff(name, description, agent, opts = {}) {
|
|
|
33606
34005
|
});
|
|
33607
34006
|
}
|
|
33608
34007
|
|
|
33609
|
-
// src/llm/providers/openai/moderations.ts
|
|
33610
|
-
var OPENAI_MODERATION_BASE_URL = "https://api.openai.com";
|
|
33611
|
-
var OPENAI_MODERATION_PATH = "/v1/moderations";
|
|
33612
|
-
var OPENAI_MODERATION_DEFAULT_MODEL = "omni-moderation-latest";
|
|
33613
|
-
var OpenAIModerationAdapter = class {
|
|
33614
|
-
apiKey;
|
|
33615
|
-
baseURL;
|
|
33616
|
-
constructor(config) {
|
|
33617
|
-
this.apiKey = config.apiKey;
|
|
33618
|
-
this.baseURL = config.baseURL ?? OPENAI_MODERATION_BASE_URL;
|
|
33619
|
-
}
|
|
33620
|
-
async moderate(input, model, fetch2) {
|
|
33621
|
-
const res = await fetch2({
|
|
33622
|
-
url: `${this.baseURL}${OPENAI_MODERATION_PATH}`,
|
|
33623
|
-
method: "POST",
|
|
33624
|
-
headers: { authorization: `Bearer ${this.apiKey}`, "content-type": "application/json" },
|
|
33625
|
-
body: { model, input },
|
|
33626
|
-
provider: "openai",
|
|
33627
|
-
model,
|
|
33628
|
-
responseType: "json"
|
|
33629
|
-
});
|
|
33630
|
-
if (res.status >= 400) {
|
|
33631
|
-
throw new Error(`OpenAI moderations failed (${res.status}): ${JSON.stringify(res.body)}`);
|
|
33632
|
-
}
|
|
33633
|
-
const data = res.body;
|
|
33634
|
-
return (data.results ?? []).map(parseRawResult);
|
|
33635
|
-
}
|
|
33636
|
-
};
|
|
33637
|
-
function parseRawResult(r) {
|
|
33638
|
-
return {
|
|
33639
|
-
flagged: r.flagged,
|
|
33640
|
-
categories: r.categories,
|
|
33641
|
-
categoryScores: r.category_scores,
|
|
33642
|
-
categoryAppliedInputTypes: r.category_applied_input_types
|
|
33643
|
-
};
|
|
33644
|
-
}
|
|
33645
|
-
|
|
33646
34008
|
// src/helpers/moderate.ts
|
|
33647
34009
|
var MODERATION_COST_NOTE = "free: moderations endpoint not billed";
|
|
33648
34010
|
var MODERATION_DEFAULT_PROVIDER = "openai";
|