import type {
CanonicalContentBlock,
CanonicalMessage,
CanonicalToolCallBlock,
CanonicalToolResultBlock,
} from "./canonical.js";
* Deep-clone a single content block. Handles nested structures that a plain
* spread would share by reference:
*
* - `tool_result` → deep-clones the inner `content` array and each element.
* - `tool_call` → `structuredClone`s the opaque `input` payload.
* - All other block types have only primitive-valued properties; a spread
* is sufficient.
*
* The `raw` field is intentionally left as a shared reference — it is a
* read-only provider echo used only for debugging and never mutated.
*/
export function cloneContentBlock(block: CanonicalContentBlock): CanonicalContentBlock {
if (block.type === "tool_result") {
const tr = block as CanonicalToolResultBlock;
return {
...tr,
content: tr.content.map((item) => ({ ...item })),
};
}
if (block.type === "tool_call") {
const tc = block as CanonicalToolCallBlock;
return {
...tc,
input: tc.input !== undefined ? structuredClone(tc.input) : tc.input,
};
}
return { ...block };
}
export function cloneMessage(message: CanonicalMessage): CanonicalMessage {
return {
...message,
content: message.content.map(cloneContentBlock),
};
}
export function cloneMessages(messages: CanonicalMessage[]): CanonicalMessage[] {
return messages.map(cloneMessage);
}