refactor(media): normalize inbound media type defaults (#16228)

This commit is contained in:
Peter Steinberger
2026-02-14 15:06:13 +01:00
committed by GitHub
parent e53a221e5c
commit 4b1cadaecb
5 changed files with 212 additions and 53 deletions

View File

@@ -10,6 +10,8 @@ export type FinalizeInboundContextOptions = {
forceConversationLabel?: boolean;
};
const DEFAULT_MEDIA_TYPE = "application/octet-stream";
function normalizeTextField(value: unknown): string | undefined {
if (typeof value !== "string") {
return undefined;
@@ -17,6 +19,21 @@ function normalizeTextField(value: unknown): string | undefined {
return normalizeInboundTextNewlines(value);
}
function normalizeMediaType(value: unknown): string | undefined {
if (typeof value !== "string") {
return undefined;
}
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : undefined;
}
function countMediaEntries(ctx: MsgContext): number {
const pathCount = Array.isArray(ctx.MediaPaths) ? ctx.MediaPaths.length : 0;
const urlCount = Array.isArray(ctx.MediaUrls) ? ctx.MediaUrls.length : 0;
const single = ctx.MediaPath || ctx.MediaUrl ? 1 : 0;
return Math.max(pathCount, urlCount, single);
}
export function finalizeInboundContext<T extends Record<string, unknown>>(
ctx: T,
opts: FinalizeInboundContextOptions = {},
@@ -73,5 +90,35 @@ export function finalizeInboundContext<T extends Record<string, unknown>>(
// Always set. Default-deny when upstream forgets to populate it.
normalized.CommandAuthorized = normalized.CommandAuthorized === true;
// MediaType/MediaTypes alignment:
// - No media: do not inject defaults.
// - Media present: ensure MediaType is always set, and MediaTypes is padded to match
// MediaPaths/MediaUrls length when possible.
const mediaCount = countMediaEntries(normalized);
if (mediaCount > 0) {
const mediaType = normalizeMediaType(normalized.MediaType);
const rawMediaTypes = Array.isArray(normalized.MediaTypes) ? normalized.MediaTypes : undefined;
const normalizedMediaTypes = rawMediaTypes?.map((entry) => normalizeMediaType(entry));
let mediaTypesFinal: string[] | undefined;
if (normalizedMediaTypes && normalizedMediaTypes.length > 0) {
const filled = normalizedMediaTypes.slice();
while (filled.length < mediaCount) {
filled.push(undefined);
}
mediaTypesFinal = filled.map((entry) => entry ?? DEFAULT_MEDIA_TYPE);
} else if (mediaType) {
mediaTypesFinal = [mediaType];
while (mediaTypesFinal.length < mediaCount) {
mediaTypesFinal.push(DEFAULT_MEDIA_TYPE);
}
} else {
mediaTypesFinal = Array.from({ length: mediaCount }, () => DEFAULT_MEDIA_TYPE);
}
normalized.MediaTypes = mediaTypesFinal;
normalized.MediaType = mediaType ?? mediaTypesFinal[0] ?? DEFAULT_MEDIA_TYPE;
}
return normalized as T & FinalizedMsgContext;
}