zen: add safety identifier

This commit is contained in:
Frank
2026-03-30 16:28:37 -04:00
parent e3e1e9af50
commit 054f4be185
5 changed files with 33 additions and 26 deletions

View File

@@ -139,19 +139,16 @@ export async function handler(
const startTimestamp = Date.now() const startTimestamp = Date.now()
const reqUrl = providerInfo.modifyUrl(providerInfo.api, isStream) const reqUrl = providerInfo.modifyUrl(providerInfo.api, isStream)
const reqBody = JSON.stringify( const reqBody = JSON.stringify(
providerInfo.modifyBody( providerInfo.modifyBody({
{ ...createBodyConverter(opts.format, providerInfo.format)(body),
...createBodyConverter(opts.format, providerInfo.format)(body), model: providerInfo.model,
model: providerInfo.model, ...(providerInfo.payloadModifier ?? {}),
...(providerInfo.payloadModifier ?? {}), ...Object.fromEntries(
...Object.fromEntries( Object.entries(providerInfo.payloadMappings ?? {})
Object.entries(providerInfo.payloadMappings ?? {}) .map(([k, v]) => [k, input.request.headers.get(v)])
.map(([k, v]) => [k, input.request.headers.get(v)]) .filter(([_k, v]) => !!v),
.filter(([_k, v]) => !!v), ),
), }),
},
authInfo?.workspaceID,
),
) )
logger.debug("REQUEST URL: " + reqUrl) logger.debug("REQUEST URL: " + reqUrl)
logger.debug("REQUEST: " + reqBody.substring(0, 300) + "...") logger.debug("REQUEST: " + reqBody.substring(0, 300) + "...")
@@ -470,15 +467,17 @@ export async function handler(
...(() => { ...(() => {
const providerProps = zenData.providers[modelProvider.id] const providerProps = zenData.providers[modelProvider.id]
const format = providerProps.format const format = providerProps.format
const providerModel = modelProvider.model const opts = {
if (format === "anthropic") return anthropicHelper({ reqModel, providerModel })
if (format === "google") return googleHelper({ reqModel, providerModel })
if (format === "openai") return openaiHelper({ reqModel, providerModel })
return oaCompatHelper({
reqModel, reqModel,
providerModel, providerModel: modelProvider.model,
adjustCacheUsage: providerProps.adjustCacheUsage, adjustCacheUsage: providerProps.adjustCacheUsage,
}) safetyIdentifier: ip,
workspaceID: authInfo?.workspaceID,
}
if (format === "anthropic") return anthropicHelper(opts)
if (format === "google") return googleHelper(opts)
if (format === "openai") return openaiHelper(opts)
return oaCompatHelper(opts)
})(), })(),
} }
} }

View File

@@ -21,17 +21,18 @@ type Usage = {
} }
} }
export const oaCompatHelper: ProviderHelper = ({ adjustCacheUsage }) => ({ export const oaCompatHelper: ProviderHelper = ({ adjustCacheUsage, safetyIdentifier }) => ({
format: "oa-compat", format: "oa-compat",
modifyUrl: (providerApi: string) => providerApi + "/chat/completions", modifyUrl: (providerApi: string) => providerApi + "/chat/completions",
modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => { modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => {
headers.set("authorization", `Bearer ${apiKey}`) headers.set("authorization", `Bearer ${apiKey}`)
headers.set("x-session-affinity", headers.get("x-opencode-session") ?? "") headers.set("x-session-affinity", headers.get("x-opencode-session") ?? "")
}, },
modifyBody: (body: Record<string, any>) => { modifyBody: (body: Record<string, any>, workspaceID?: string) => {
return { return {
...body, ...body,
...(body.stream ? { stream_options: { include_usage: true } } : {}), ...(body.stream ? { stream_options: { include_usage: true } } : {}),
...(safetyIdentifier ? { safety_identifier: safetyIdentifier } : {}),
} }
}, },
createBinaryStreamDecoder: () => undefined, createBinaryStreamDecoder: () => undefined,

View File

@@ -12,13 +12,13 @@ type Usage = {
total_tokens?: number total_tokens?: number
} }
export const openaiHelper: ProviderHelper = () => ({ export const openaiHelper: ProviderHelper = ({ workspaceID }) => ({
format: "openai", format: "openai",
modifyUrl: (providerApi: string) => providerApi + "/responses", modifyUrl: (providerApi: string) => providerApi + "/responses",
modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => { modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => {
headers.set("authorization", `Bearer ${apiKey}`) headers.set("authorization", `Bearer ${apiKey}`)
}, },
modifyBody: (body: Record<string, any>, workspaceID?: string) => ({ modifyBody: (body: Record<string, any>) => ({
...body, ...body,
...(workspaceID ? { safety_identifier: workspaceID } : {}), ...(workspaceID ? { safety_identifier: workspaceID } : {}),
}), }),

View File

@@ -33,11 +33,17 @@ export type UsageInfo = {
cacheWrite1hTokens?: number cacheWrite1hTokens?: number
} }
export type ProviderHelper = (input: { reqModel: string; providerModel: string; adjustCacheUsage?: boolean }) => { export type ProviderHelper = (input: {
reqModel: string
providerModel: string
adjustCacheUsage?: boolean
safetyIdentifier?: string
workspaceID?: string
}) => {
format: ZenData.Format format: ZenData.Format
modifyUrl: (providerApi: string, isStream?: boolean) => string modifyUrl: (providerApi: string, isStream?: boolean) => string
modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => void modifyHeaders: (headers: Headers, body: Record<string, any>, apiKey: string) => void
modifyBody: (body: Record<string, any>, workspaceID?: string) => Record<string, any> modifyBody: (body: Record<string, any>) => Record<string, any>
createBinaryStreamDecoder: () => ((chunk: Uint8Array) => Uint8Array | undefined) | undefined createBinaryStreamDecoder: () => ((chunk: Uint8Array) => Uint8Array | undefined) | undefined
streamSeparator: string streamSeparator: string
createUsageParser: () => { createUsageParser: () => {

View File

@@ -49,6 +49,7 @@ export namespace ZenData {
payloadModifier: z.record(z.string(), z.any()).optional(), payloadModifier: z.record(z.string(), z.any()).optional(),
payloadMappings: z.record(z.string(), z.string()).optional(), payloadMappings: z.record(z.string(), z.string()).optional(),
adjustCacheUsage: z.boolean().optional(), adjustCacheUsage: z.boolean().optional(),
safetyIdentifier: z.boolean().optional(),
}) })
const ModelsSchema = z.object({ const ModelsSchema = z.object({