@sema-agent/core
Version:
Stateless, task-oriented AI agent core
113 lines (112 loc) • 3.02 kB
JavaScript
import { isCredentialHeaderName } from "../core/secret-env.js";
export const OPENAI_RESERVED = new Set([
"model",
"messages",
"stream",
"stream_options",
"tools",
"temperature",
"max_tokens",
"stop",
"reasoning_effort",
"thinking",
"reasoning",
"enable_thinking",
"chat_template_kwargs",
]);
export const ANTHROPIC_RESERVED = new Set([
"model",
"messages",
"system",
"stream",
"tools",
"temperature",
"max_tokens",
"thinking",
"output_config",
"context_management",
]);
export const RESPONSES_RESERVED = new Set([
"model",
"input",
"stream",
"instructions",
"tools",
"temperature",
"max_output_tokens",
"reasoning",
"store",
"previous_response_id",
"conversation",
]);
const NO_KEYS = Object.freeze([]);
export function applyExtraBody(body, extraBody, reserved) {
if (!extraBody)
return { body, dropped: NO_KEYS };
const passthrough = {};
const dropped = [];
for (const [k, v] of Object.entries(extraBody)) {
if (reserved.has(k))
dropped.push(k);
else
passthrough[k] = v;
}
return { body: { ...passthrough, ...body }, dropped: dropped.length === 0 ? NO_KEYS : dropped };
}
export function lockHeader(headers, lowerName, value) {
for (const k of Object.keys(headers)) {
if (k !== lowerName && k.toLowerCase() === lowerName)
delete headers[k];
}
headers[lowerName] = value;
}
export function takeHeaderCasefold(headers, lowerName) {
for (const k of Object.keys(headers)) {
if (k.toLowerCase() === lowerName) {
const v = headers[k];
delete headers[k];
return v;
}
}
return undefined;
}
export function headerBagOnce(bag) {
return bag === undefined ? undefined : { ...bag };
}
export function mergeHeaders(...bags) {
const out = {};
const spellingByFold = new Map();
for (const bag of bags) {
if (!bag)
continue;
for (const [name, value] of Object.entries(bag)) {
const fold = name.toLowerCase();
if (isCredentialHeaderName(name)) {
out[name] = value;
continue;
}
const prior = spellingByFold.get(fold);
if (prior !== undefined && prior !== name)
delete out[prior];
spellingByFold.set(fold, name);
out[name] = value;
}
}
return out;
}
export const OUTPUT_CAP_KEYS = {
openai: ["max_tokens", "max_completion_tokens"],
anthropic: ["max_tokens"],
responses: ["max_output_tokens"],
};
export function effectiveOutputCap(body, keys) {
let smallest;
for (const key of keys) {
const raw = body[key];
if (typeof raw !== "number" || !Number.isFinite(raw) || raw <= 0)
continue;
if (smallest === undefined || raw < smallest)
smallest = raw;
}
return smallest;
}