When code must normalize or classify structured data (messages, request bodies, model/provider selection, metrics), implement it as deterministic, idempotent, and non-mutating transformations.
Apply these rules:
includes() where false positives are possible.Example (non-mutating consecutive-role merge + idempotent ops sketch):
type Content = { role: string; parts: Array<{ text: string }> };
function mergeConsecutiveSameRole(contents: Content[]): Content[] {
const merged: Content[] = [];
for (const entry of contents) {
const last = merged[merged.length - 1];
if (last && last.role === entry.role) {
// mutate only the new output copy
last.parts.push(...entry.parts);
} else {
// prevent caller mutation
merged.push({ ...entry, parts: [...entry.parts] });
}
}
return merged;
}
type Op = { kind: 'prepend_system_block'; text: string; idempotencyKey?: string };
function applyOp(blocks: Array<{ type: 'text'; text: string }>, op: Op) {
const alreadyThere = blocks.some((b) => b.text === op.text || b.text.startsWith(op.text));
return alreadyThere ? blocks : [{ type: 'text', text: op.text }, ...blocks];
}
Practical checklist:
sum += value) rather than overwriting. If you follow these, you’ll prevent the common failure modes seen across the discussions: invalid request shapes, duplicated system blocks, false-positive classification, and incorrect aggregation totals.