diff --git a/docs/fixtures/index.html b/docs/fixtures/index.html index acbfc9e2..51c07e1a 100644 --- a/docs/fixtures/index.html +++ b/docs/fixtures/index.html @@ -166,8 +166,9 @@

Match Fields

hasToolResult boolean - true when at least one role: "tool" message is present; - false when none are. Stateless alternative to ordering fixtures by + true when the current turn (the messages after the last + role: "user" message) contains a role: "tool" result; + false when it does not. Stateless alternative to ordering fixtures by toolCallId. See Multi-Turn Conversations diff --git a/docs/multi-turn/index.html b/docs/multi-turn/index.html index 0d98c741..e5d4c00a 100644 --- a/docs/multi-turn/index.html +++ b/docs/multi-turn/index.html @@ -90,7 +90,8 @@

How matching works across turns

- Two additional fields inspect the full message array rather than just the tail: + Two additional fields derive their value from the request shape rather than from a single + tail message:

@@ -166,9 +174,9 @@

turnIndex — match by conversation depth

hasToolResult — match by tool execution state

- hasToolResult checks whether the request contains any - role: "tool" messages. For a simple two-step tool round, this is often - simpler than turnIndex: + hasToolResult checks whether the current turn (the messages after + the last role: "user" message) contains a role: "tool" result. + For a simple two-step tool round, this is often simpler than turnIndex:

@@ -365,8 +373,8 @@

hasToolResult - Boolean check for role: "tool" presence. Stateless. Does not require - pinning a specific tool_call_id. + Boolean check for role: "tool" presence in the current turn. Stateless. + Does not require pinning a specific tool_call_id. diff --git a/docs/record-replay/index.html b/docs/record-replay/index.html index d5974b30..a3530e19 100644 --- a/docs/record-replay/index.html +++ b/docs/record-replay/index.html @@ -636,9 +636,9 @@

Fixture Auto-Generation

inputText), the normalized model becomes model, and for chat requests the recorder also writes the multi-turn disambiguators turnIndex (the number of assistant messages already in the conversation) and - hasToolResult (whether a tool-result message is present). If no match - criteria can be derived (e.g., empty messages), the fixture is saved to disk with a - warning but not registered in memory. + hasToolResult (whether the current turn — the messages after the last + user message — contains a tool result). If no match criteria can be derived (e.g., + empty messages), the fixture is saved to disk with a warning but not registered in memory.

Model-Aware Recording

@@ -1040,11 +1040,11 @@

Recording Multi-Turn Conversationslast user message (match.userMessage), the normalized model, and two shape disambiguators read off the request itself: turnIndex (how many assistant messages the conversation already contains) and - hasToolResult (whether a tool-result message is present). Embedding requests - key on the input text instead. There is no history-based fingerprinting of the full - request body — but because a growing conversation carries a growing - turnIndex, successive turns that happen to end with the same user message - still record as distinct fixtures. + hasToolResult (whether the current turn — the messages after the last + user message — contains a tool result). Embedding requests key on the input text + instead. There is no history-based fingerprinting of the full request body — but + because a growing conversation carries a growing turnIndex, successive turns + that happen to end with the same user message still record as distinct fixtures.

@@ -1063,7 +1063,9 @@

Recording Multi-Turn ConversationsuserMessage: getTextContent(lastUser.content), model: normalizeModelName(request.model), turnIndex: request.messages.filter((m) => m.role === "assistant").length, - hasToolResult: request.messages.some((m) => m.role === "tool"), + // Scoped to the current turn (messages after the last user message), so it + // shares the exact predicate the matcher uses — see router.ts. + hasToolResult: currentTurnHasToolResult(request.messages), }; // Capture context from X-AIMock-Context header if present if (request._context) match.context = request._context;