Skip to content

Commit 434578a

Browse files
authored
docs: correct hasToolResult turn-scoping on the docs site (#321)
## What The in-repo docs site (deploys to aimock.copilotkit.dev via GitHub Pages from `docs/`) still described `hasToolResult` with its **old whole-conversation semantics** in several places. Those pages are now wrong on the live site. As of **v1.37.3** the matcher made `hasToolResult` **turn-scoped**, and **v1.37.4** made the record side symmetric. It now means: > `hasToolResult` is `true` when the **current turn** — the messages after the last `user` message — contains a tool result; with a no-`user`-message fallback to scanning the whole conversation. This is exactly what `src/router.ts` `currentTurnHasToolResult` does, and what the recorder stamps via the same shared predicate. Turn-scoping is what keeps leg-1 (tool call, `false`) vs leg-2 (post-tool narration, `true`) fixtures working across **multiple** user turns — a whole-conversation check would force `true` forever once any earlier turn carried a tool result. ## Changes (docs only) - **docs/multi-turn/index.html** — field-overview bullet, the "hasToolResult — match by tool execution state" prose, and the comparison-table row now describe current-turn scoping and the leg-1/leg-2 multi-turn discrimination it enables. - **docs/fixtures/index.html** — match-fields table row now states current-turn scoping. - **docs/record-replay/index.html** — both recorder-derivation prose spots corrected, and the `buildFixtureMatch` code snippet now uses the shared `currentTurnHasToolResult(...)` predicate instead of the stale whole-conversation `request.messages.some((m) => m.role === "tool")` scan. Left untouched: pages that only mention `hasToolResult` in passing or in already-correct code examples (examples, sequential-responses, integrate-*, agui-mock, gemini-interactions). Edits are minimal and match each page's existing tone/structure — no restyling. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
2 parents 3e539a6 + 331f668 commit 434578a

3 files changed

Lines changed: 31 additions & 20 deletions

File tree

docs/fixtures/index.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,9 @@ <h2>Match Fields</h2>
166166
<td>hasToolResult</td>
167167
<td>boolean</td>
168168
<td>
169-
<code>true</code> when at least one <code>role: "tool"</code> message is present;
170-
<code>false</code> when none are. Stateless alternative to ordering fixtures by
169+
<code>true</code> when the current turn (the messages after the last
170+
<code>role: "user"</code> message) contains a <code>role: "tool"</code> result;
171+
<code>false</code> when it does not. Stateless alternative to ordering fixtures by
171172
<code>toolCallId</code>. See <a href="/multi-turn">Multi-Turn Conversations</a>
172173
</td>
173174
</tr>

docs/multi-turn/index.html

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ <h2>How matching works across turns</h2>
9090
</p>
9191

9292
<p>
93-
Two additional fields inspect the <em>full</em> message array rather than just the tail:
93+
Two additional fields derive their value from the request shape rather than from a single
94+
tail message:
9495
</p>
9596
<ul>
9697
<li>
@@ -100,9 +101,16 @@ <h2>How matching works across turns</h2>
100101
entirely from the request content, not from a server-side counter.
101102
</li>
102103
<li>
103-
<code>hasToolResult</code> checks whether <em>any</em> <code>role: "tool"</code> message
104-
exists in the request. <code>true</code> means &ldquo;this request carries tool
105-
results&rdquo;; <code>false</code> means &ldquo;no tools have executed yet.&rdquo;
104+
<code>hasToolResult</code> checks whether the <strong>current turn</strong> &mdash; the
105+
messages after the last <code>role: "user"</code> message &mdash; contains a
106+
<code>role: "tool"</code> result. <code>true</code> means &ldquo;a tool has executed in
107+
this turn&rdquo;; <code>false</code> means &ldquo;no tool result yet this turn.&rdquo;
108+
It is scoped to the current turn, not the whole conversation &mdash; that is what keeps
109+
the leg-1 tool-call fixture (<code>false</code>) and the leg-2 narration fixture
110+
(<code>true</code>) working on <em>every</em> turn of a multi-turn session, because
111+
earlier turns&rsquo; tool results no longer force <code>true</code> forever. (If the
112+
request carries no <code>user</code> message at all, it falls back to scanning the whole
113+
conversation.)
106114
</li>
107115
</ul>
108116

@@ -166,9 +174,9 @@ <h3>turnIndex &mdash; match by conversation depth</h3>
166174

167175
<h3>hasToolResult &mdash; match by tool execution state</h3>
168176
<p>
169-
<code>hasToolResult</code> checks whether the request contains any
170-
<code>role: "tool"</code> messages. For a simple two-step tool round, this is often
171-
simpler than <code>turnIndex</code>:
177+
<code>hasToolResult</code> checks whether the <em>current turn</em> (the messages after
178+
the last <code>role: "user"</code> message) contains a <code>role: "tool"</code> result.
179+
For a simple two-step tool round, this is often simpler than <code>turnIndex</code>:
172180
</p>
173181

174182
<div class="code-block">
@@ -365,8 +373,8 @@ <h2>
365373
</td>
366374
<td><code>hasToolResult</code></td>
367375
<td>
368-
Boolean check for <code>role: "tool"</code> presence. Stateless. Does not require
369-
pinning a specific <code>tool_call_id</code>.
376+
Boolean check for <code>role: "tool"</code> presence in the current turn. Stateless.
377+
Does not require pinning a specific <code>tool_call_id</code>.
370378
</td>
371379
</tr>
372380
<tr>

docs/record-replay/index.html

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -636,9 +636,9 @@ <h2>Fixture Auto-Generation</h2>
636636
<code>inputText</code>), the normalized model becomes <code>model</code>, and for chat
637637
requests the recorder also writes the multi-turn disambiguators
638638
<code>turnIndex</code> (the number of assistant messages already in the conversation) and
639-
<code>hasToolResult</code> (whether a tool-result message is present). If no match
640-
criteria can be derived (e.g., empty messages), the fixture is saved to disk with a
641-
warning but not registered in memory.
639+
<code>hasToolResult</code> (whether the current turn &mdash; the messages after the last
640+
user message &mdash; contains a tool result). If no match criteria can be derived (e.g.,
641+
empty messages), the fixture is saved to disk with a warning but not registered in memory.
642642
</p>
643643

644644
<h2 id="model-aware-recording">Model-Aware Recording</h2>
@@ -1040,11 +1040,11 @@ <h2 id="recording-multi-turn-conversations">Recording Multi-Turn Conversations</
10401040
<strong>last user message</strong> (<code>match.userMessage</code>), the normalized
10411041
<code>model</code>, and two shape disambiguators read off the request itself:
10421042
<code>turnIndex</code> (how many assistant messages the conversation already contains) and
1043-
<code>hasToolResult</code> (whether a tool-result message is present). Embedding requests
1044-
key on the input text instead. There is no history-based fingerprinting of the full
1045-
request body &mdash; but because a growing conversation carries a growing
1046-
<code>turnIndex</code>, successive turns that happen to end with the same user message
1047-
still record as <em>distinct</em> fixtures.
1043+
<code>hasToolResult</code> (whether the current turn &mdash; the messages after the last
1044+
user message &mdash; contains a tool result). Embedding requests key on the input text
1045+
instead. There is no history-based fingerprinting of the full request body &mdash; but
1046+
because a growing conversation carries a growing <code>turnIndex</code>, successive turns
1047+
that happen to end with the same user message still record as <em>distinct</em> fixtures.
10481048
</p>
10491049

10501050
<div class="code-block">
@@ -1063,7 +1063,9 @@ <h2 id="recording-multi-turn-conversations">Recording Multi-Turn Conversations</
10631063
<span class="prop">userMessage</span>: <span class="fn">getTextContent</span>(lastUser.content),
10641064
<span class="prop">model</span>: <span class="fn">normalizeModelName</span>(request.model),
10651065
<span class="prop">turnIndex</span>: request.messages.filter((m) => m.role === <span class="str">"assistant"</span>).length,
1066-
<span class="prop">hasToolResult</span>: request.messages.some((m) => m.role === <span class="str">"tool"</span>),
1066+
<span class="cm">// Scoped to the current turn (messages after the last user message), so it</span>
1067+
<span class="cm">// shares the exact predicate the matcher uses &mdash; see router.ts.</span>
1068+
<span class="prop">hasToolResult</span>: <span class="fn">currentTurnHasToolResult</span>(request.messages),
10671069
};
10681070
<span class="cm">// Capture context from X-AIMock-Context header if present</span>
10691071
<span class="kw">if</span> (request._context) match.<span class="prop">context</span> = request._context;

0 commit comments

Comments
 (0)