Functions

messageDigestInput

Function: messageDigestInput()

messageDigestInput(message): string

Defined in: src/lib/time-travel/receipt.ts:450

The bytes a message's hash covers, each field behind a separator: its role, its text, its toolCallId, its toolName, the calls it asked for (id, name, arguments and providerMeta) and its thinkingBlocks.

WHY toolCallId (9.88.0). It is the JOIN KEY — tool_use_id on Anthropic's wire, tool_call_id on OpenAI's — that pairs a tool result to the call that asked for it. Two parallel calls whose results happen to have identical text hashed the SAME without it, so a mis-pairing (the answer to c1 filed under c2) was invisible to the law: exactly the defect a receipt exists to catch.

WHY toolName TOO (9.88.0). On two shipped providers the id is not the join key at all. adapters/llm/GeminiProvider.ts · toGeminiContents pairs a functionResponse to its call BY NAME and says so in its own comment; the id is optional there and dropped when it is not a real one. adapters/llm/OllamaProvider.ts · toOllamaMessages puts tool_name on the wire and only falls back to the id. So on those providers a receipt that covered toolCallId alone still could not see the very mis-pairing the field was added for: two role:'tool' messages with identical text and SWAPPED names fingerprinted identically. It rides as its own field behind the separator, beside the id, so a name moving between two results changes both hashes and neither can absorb the other's bytes.

WHY thinkingBlocks and providerMeta (9.88.0). adapters/types.ts is explicit that a signed thinking block MUST be echoed byte-exact or the API rejects the turn, and providerMeta round-trips vendor state (Gemini's thoughtSignature, without which the turn after a tool call is refused). Both are things the model receives; a fingerprint that omitted them said two requests were the same when one of them would be rejected. They enter as a stableJson FINGERPRINT, so nothing quotable is added — a signature is an opaque token, not content.

Still deliberately NOT covered: injectedBy (stripped before the request exists) and ephemeral (a persistence flag, invisible to the model). Two messages that hash the same are the same thing said to the model.

Parameters

message

LLMMessage

Returns

string

On this page