Skip to content

Release/v6.8.5 - #129

Merged
code-crusher merged 3 commits into
mainfrom
release/v6.8.5
Sep 4, 2026
Merged

code-crusher merged 3 commits into
mainfrom
release/v6.8.5

Conversation

@code-crusher

Copy link
Copy Markdown
Member

Release v6.8.5

Fixed

  • Placeholder-tagged tool arguments are repaired instead of dropped. When a model emits malformed native tool-call JSON with a placeholder tag in value position (e.g. "limit": <longcat_arg_value>180 or "limit": <longcat_arg_value>), AssistantMessageParser now strips the tag and keeps the trailing value, or drops the dangling key entirely when no value follows so the tool's default applies. The repair runs only after strict JSON.parse fails, so valid JSON is never altered. useMcpToolTool applies the same cleanup when validating MCP tool arguments, and streaming partial previews are tag-cleaned as well.

Includes version bump to 6.8.5 and changelog entry.

matterai-app[bot] added 2 commits September 4, 2026 11:44
… dropping them

Some models leak internal argument-templating tags (e.g.
<longcat_arg_value>) into native tool-call JSON arguments, making the
JSON invalid and dropping the call at stream finalization.

- tryParseToolArguments strips value-position placeholder tags after
  the strict parse fails: a tag prefixing a real value keeps the value
  ("limit": <tag>180 parses as 180), while a tag-only value removes
  the key entirely so the tool's own default applies (read_file without
  limit reads the complete file).
- Tags inside legitimate string values are never touched; well-formed
  JSON still parses verbatim; incomplete streaming buffers keep
  accumulating instead of completing early.
- The XML-path use_mcp_tool argument parse applies the same cleanup
  before failing the call.
- Partial-parameter extraction strips tags so the streaming UI shows
  the real value behind the tag.
- 39 regression tests: both tag shapes, nested files arrays, tag-only
  keys followed by other members, composition with the bare-scalar
  repair, tags inside valid strings untouched, incomplete-buffer
  accumulation, and end-to-end processNativeToolCalls runs streamed at
  chunk sizes 1/7/64/full.
@matterai-app

matterai-app Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

✅ Reviewed the changes: Solid, well-tested placeholder-tag repair with good streaming coverage. One logging issue: the repair warning fires on every failed candidate (including every streaming delta) instead of only on successful repair. Reviewed src/core/assistant-message/tests/AssistantMessageParser.spec.ts: no issues found. Reviewed src/core/tools/useMcpToolTool.ts: no issues found. Reviewed src/package.json: version bump only, no issues.

…ools

Replace the narrow placeholder-tag regex cleanup with a best-effort
repair layer (src/utils/jsonRepair.ts) used by every argument
ingestion path: live streaming, stream finalization, and MCP argument
validation.

- strict JSON.parse first; valid arguments are never mutated (the only
  exception: stripping a leaked placeholder tag from a key, since keys
  are structural parameter names; tags inside string values survive)
- repairs placeholder tags in structural positions (tag-prefixed value
  kept, tag-only value nulled so the tool default applies), unquoted
  keys/values, single quotes, Python literals, comments, trailing
  commas, missing commas, and lost key quotes
- at finalization only: closes dangling strings/containers innermost-
  first, nulls a dangling colon value, wraps braceless bodies; during
  streaming incomplete buffers stay unparseable so deltas accumulate
- unwraps a single-object array the model wrapped by mistake
- ToolUse carries a repaired flag; repaired executions append the
  executed arguments to the tool result so the model does not repeat
  the malformed form
- executor hardening: parsePositiveInteger for read_file/kilocode
  offset/limit (floor, clamp min 1, default on non-numeric), floored
  search_files max_results/context_lines

@matterai-app matterai-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧪 PR Review is completed: Well-structured JSON-repair layer with strict-parse-first semantics and strong test coverage; the prior per-delta console.warn spam is fixed. One concern to verify: the new repair-note push in presentAssistantMessage may create a second tool_result block with a duplicate tool_use_id. Reviewed src/core/assistant-message/AssistantMessageParser.ts: no other issues found. Reviewed src/utils/jsonRepair.ts: no issues found. Reviewed src/utils/tests/jsonRepair.spec.ts: no issues found. Reviewed src/core/assistant-message/tests/AssistantMessageParser.spec.ts: no issues found. Reviewed src/core/tools/useMcpToolTool.ts: no issues found. Reviewed src/core/tools/kilocode.ts: no issues found. Reviewed src/core/tools/readFileTool.ts: no issues found. Reviewed src/services/search-files/types.ts: no issues found. Reviewed src/shared/tools.ts: no issues found.

Skipped files
  • CHANGELOG.md: Skipped file pattern
⬇️ Low Priority Suggestions (1)
src/core/assistant-message/presentAssistantMessage.ts (1 suggestion)

Location: src/core/assistant-message/presentAssistantMessage.ts (Lines 962-975)

🟠 API Contract / Tool-Result Pairing

Issue: This block runs only when toolResultPushed is already true — i.e. the tool handler has already pushed a tool_result for block.toolUseId. Unless pushToolResult_withToolUseId_kilocode (defined ~line 320) merges content into the existing tool_result for that id, this pushes a second tool_result block with the same tool_use_id into the conversation history. Anthropic (and most OpenAI-compatible providers) enforce 1:1 tool_use/tool_result pairing — a duplicate tool_use_id in tool_result blocks can cause the next API request to be rejected with a 400, killing the task loop. Since this fires on every repaired tool call (the exact scenario this PR enables), please verify the helper's behavior.

Fix: Append the repair note to the already-pushed tool_result for block.toolUseId instead of pushing a separate tool_result block.

Impact: Guarantees exactly one tool_result per tool_use, keeping the assistant/user message pairing valid across all providers.

-  				if (block.repaired && !block.partial && toolResultPushed && !cline.didRejectTool) {
-  					try {
-  						const executedArguments =
-  							block.name === "use_mcp_tool"
-  								? String(block.params.arguments ?? "{}")
-  								: JSON.stringify(block.params)
-  						pushToolResult_withToolUseId_kilocode({
-  							type: "text",
-  							text: formatArgumentRepairNote(executedArguments),
-  						})
-  					} catch (error) {
-  						console.error("[presentAssistantMessage] Failed to append argument repair note:", error)
-  					}
-  				}
+  				if (block.repaired && !block.partial && toolResultPushed && !cline.didRejectTool) {
+  					try {
+  						const executedArguments =
+  							block.name === "use_mcp_tool"
+  								? String(block.params.arguments ?? "{}")
+  								: JSON.stringify(block.params)
+  						const note = formatArgumentRepairNote(executedArguments)
+  						const buffer = options.resultBuffer ?? cline.userMessageContent
+  						const existing = [...buffer]
+  							.reverse()
+  							.find(
+  								(m) =>
+  									(m as { type?: string }).type === "tool_result" &&
+  									(m as { tool_use_id?: string }).tool_use_id === block.toolUseId,
+  							) as { content: unknown } | undefined
+  						if (existing && Array.isArray(existing.content)) {
+  							;(existing.content as Array<{ type: "text"; text: string }>).push({ type: "text", text: note })
+  						}
+  					} catch (error) {
+  						console.error("[presentAssistantMessage] Failed to append argument repair note:", error)
+  					}
+  				}

@code-crusher
code-crusher merged commit ac82a92 into main Sep 4, 2026
3 of 9 checks passed
@code-crusher
code-crusher deleted the release/v6.8.5 branch September 4, 2026 07:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant