Skip to content

[1130] fix: mimo-parallel-tool-call-policy (2/2) - #49

Closed
myk1yt wants to merge 33 commits into
mainfrom
pr/b12-mimo-enforcement-v2
Closed

[1130] fix: mimo-parallel-tool-call-policy (2/2)#49
myk1yt wants to merge 33 commits into
mainfrom
pr/b12-mimo-enforcement-v2

Conversation

@myk1yt

@myk1yt myk1yt commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Stack Position

Description

스크린샷 2026-07-27 175105 스크린샷 2026-07-27 174745

Full Feature Description

  • Feature Branch: fix/mimo-parallel-tool-call-policy
  • Feature Name: MiMo Parallel Tool Call Policy
  • Purpose: Resolves the problem where MiMo's OpenAI-compatible stream can send two or more tool calls, ghost calls with no name or arguments, and incomplete JSON arguments even in situations where only a single call should be safely processed. Prevents ambiguous side-effect ordering, executes only structurally valid calls, and preserves the existing parallel behavior of other providers.
  • Full Change Description: The shared root B05a provides OpenAI-compatible schema conversion and provider-neutral reasoning/strict controls. B12 connects MiMo model capability, request-level parallel control, streamed native call parsing, ghost quarantine, max-one retention policy, task execution guard, and privacy-safe telemetry. Under the single-call policy, if there is exactly one valid call, only that call is executed; if there are two or more, none are auto-selected and all are returned as typed error results so the model resubmits only one.
  • Impact Scope: Affects mimo.ts, mimo.ts, NativeToolCallParser.ts, ToolCallRetentionPolicy.ts, task policy wiring, and TelemetryService.ts. B05a is shared between this chain and the openai-compatible-strict-reasoning chain.
  • Errors and Edge Cases: Only terminated ghosts with neither name nor arguments are silently removed. If name or argument bytes are present, malformed calls are not erased from history and produce exactly one error result. When two or more valid side-effect calls arrive, none are auto-executed. Telemetry records only counts and policy metadata, not tool names, call IDs, arguments, commands, paths, or prompts. Known parallel provider behavior for OpenAI/Anthropic families is not regressed.
  • Testing Method: Run B05a's schema conversion tests and B12's MiMo single/parallel/malformed/ghost stream fixture, native parser, retention policy, telemetry, and task policy tests. Manually replay a MiMo response with two tool calls, verifying that zero executions and two error results are produced, that a single call is executed exactly once, and that ghosts are removed before history.

Why Split Into 17 PRs

Instead of submitting this feature as a single unified PR, it was split into individual PRs because as code size grows, safely reviewing a PR becomes very difficult. The feature was broken into mutually exclusive individual PRs so that each can be reviewed independently.

What This PR Specifically Changes

Adds MiMo capability/request conversion, stream parser, ghost quarantine, malformed call retention, max-one execution guard, and payload-free telemetry. Does not change other provider behavior or cost calculation.

Included Files

  • packages/types/src/providers/mimo.ts
  • packages/telemetry/src/TelemetryService.ts
  • src/api/providers/mimo.ts
  • src/core/assistant-message/NativeToolCallParser.ts
  • src/core/assistant-message/ToolCallRetentionPolicy.ts
  • task policy wiring and direct tests

Exclusion Scope

  • Request/cost changes for other providers
  • Duplicate changes to B05a settings/UI/request shaping
  • Session report and repair script
  • Changes that log prompt or tool argument payloads to telemetry
  • All items in the common removal rules

Summary by CodeRabbit

  • New Features

    • Added adaptive tool-call handling based on model and provider capabilities, including parallel or single-call modes.
    • Added optional strict tool-schema validation for OpenAI-compatible providers, with localized settings guidance.
    • Improved support for MiMo tool-call behavior and compatibility fallbacks.
  • Bug Fixes

    • Prevented empty or duplicate streamed tool calls from being executed or saved.
    • Improved handling of malformed tool-call arguments and unsupported provider options.
    • Clarified command timeout and working-directory validation.
  • Privacy

    • Added metadata-only telemetry for tool-call policy decisions and enforcement, excluding sensitive command and credential data.

Upstream PR: Zoo-Code-Org#1130

Zoo (VP) and others added 30 commits August 6, 2026 13:50
# Conflicts:
#	src/core/tools/error-interception/StructuralValidator.ts
# Conflicts:
#	src/core/assistant-message/__tests__/NativeToolCallParser.spec.ts
#	src/core/assistant-message/__tests__/presentAssistantMessage-parser-dedup.integration.spec.ts
#	src/core/assistant-message/presentAssistantMessage.ts
# Conflicts:
#	src/core/assistant-message/__tests__/presentAssistantMessage-parser-dedup.integration.spec.ts
MimoHandler was passing raw tool schemas to the API without the
strict mode conversion that all other OpenAI-compatible providers use.
This caused tool call errors due to missing required/strict fields.

- Call this.convertToolsForOpenAI(tools) instead of raw assignment
- Adds strict: true, required properties, additionalProperties: false
An id-less argument-continuation chunk belongs to the most recent id chunk
seen at its index. When a provider reuses index 0 with a NEW id (a disguised
second parallel call), the new call's id chunk was dropped but its id-less
argument fragments were still kept and concatenated into the FIRST call's
accumulator, corrupting its JSON.

Track dropped indexes in filterToFirstToolCall state and drop subsequent
id-less fragments for those indexes. Also rewrite the function docblock,
which referenced a non-existent error-interception retry loop.
The parseErrors/parseFailures docblocks claimed presentAssistantMessage
routes recorded failures to an INVALID_JSON_ARGUMENTS error-interception
pattern. No such routing exists on this codebase; describe the actual
lifecycle (consumed via the consume* APIs, cleared on new API request).
Comment-only change, no behavior difference.
parseErrors/parseFailures static maps accumulated an entry per malformed
tool call and were never cleared in production (the consume* APIs have no
production callers), slowly leaking for the extension-host lifetime.

Add NativeToolCallParser.clearParseFailures() and call it in
Task.recursivelyMakeClineRequests alongside clearAllStreamingToolCalls()/
clearRawChunkState(), where other per-stream state is reset. The consume*
APIs keep working for tests.
MiMo sends tools through convertToolsForOpenAI(), which attaches a strict
flag to every function tool. An OpenAI-compatible endpoint that doesn't
support structured outputs rejects the request with a 400 and the turn
fails outright.

Mirror the existing parallel_tool_calls fallback: detect schema-rejection
errors narrowly (400 status plus a mention of strict/additionalProperties
in a tools context, so unrelated 400s like MiMo's missing-reasoning_content
rejection are not retried) and retry once with the original schemas and no
strict flag.
…oo-Code-Org#1130)

CI failures:
1. Code QA Roo Code run 31229619240: unused 'taskId' binding (lint).
2. E2E Tests (Mocked) run 31229619233: 4 TS errors in mimo-parallel.test.ts:
   - mimoBaseUrl was a 4-literal union, rejecting the local mock server URL
   - 'enableToolUse' is not a RooCodeSettings key
   - 'api_req_failed' is a ClineAsk, not a ClineSay (x2)

Fix:
- provider-settings.ts: widen mimoBaseUrl to z.string().url() (documented
  with the 4 common endpoints) so tests can point the handler at a local mock.
- mimo-parallel.test.ts: drop unused taskId, remove enableToolUse, compare
  m.ask === 'api_req_failed' instead of m.say.
Runs: https://github.com/Zoo-Code-Org/Zoo-Code/actions/runs/31229619240
      https://github.com/Zoo-Code-Org/Zoo-Code/actions/runs/31229619233
@myk1yt myk1yt closed this Aug 12, 2026
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