Skip to content

fix: mimo-parallel-tool-call-policy (2/2) - #32

Closed
myk1yt wants to merge 46 commits into
pr/b05a-strict-reasoning-v2from
pr/b12-mimo-enforcement-v2
Closed

fix: mimo-parallel-tool-call-policy (2/2)#32
myk1yt wants to merge 46 commits into
pr/b05a-strict-reasoning-v2from
pr/b12-mimo-enforcement-v2

Conversation

@myk1yt

@myk1yt myk1yt commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Stack Position

Description

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

@myk1yt myk1yt changed the title B12: MiMo Enforcement v2 fix: mimo-parallel-tool-call-policy (2/2) Aug 3, 2026
@myk1yt
myk1yt force-pushed the pr/b05a-strict-reasoning-v2 branch from 658c4f2 to 4692197 Compare August 4, 2026 11:34
@myk1yt
myk1yt force-pushed the pr/b12-mimo-enforcement-v2 branch from 1cf9a96 to 0532102 Compare August 4, 2026 11:40
@myk1yt
myk1yt force-pushed the pr/b05a-strict-reasoning-v2 branch from 4692197 to 2adc65a Compare August 4, 2026 20:28
@myk1yt
myk1yt force-pushed the pr/b12-mimo-enforcement-v2 branch from b526a57 to 132fb08 Compare August 4, 2026 20:28
@myk1yt
myk1yt force-pushed the pr/b05a-strict-reasoning-v2 branch 2 times, most recently from 77e7207 to a3b22a7 Compare August 4, 2026 20:40
@myk1yt
myk1yt force-pushed the pr/b12-mimo-enforcement-v2 branch 4 times, most recently from 67850e5 to c0e5951 Compare August 6, 2026 04:38
Zoo (VP) and others added 16 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.
@myk1yt
myk1yt force-pushed the pr/b12-mimo-enforcement-v2 branch from c0e5951 to 86477b0 Compare August 6, 2026 05:10
@myk1yt
myk1yt deleted the branch pr/b05a-strict-reasoning-v2 August 7, 2026 13:05
@myk1yt myk1yt closed this Aug 7, 2026
@myk1yt
myk1yt deleted the pr/b12-mimo-enforcement-v2 branch August 7, 2026 13:06
@myk1yt
myk1yt restored the pr/b12-mimo-enforcement-v2 branch August 7, 2026 13:32
@myk1yt myk1yt reopened this Aug 8, 2026
Zoo (VP) and others added 17 commits August 8, 2026 15:13
…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
Co-authored-by: Roomote <roomote@roomote.dev>
…sages load (Zoo-Code-Org#1181)

* fix(task): skip saveClineMessages when history task aborts before messages load

* test: strengthen resume-eviction-race assertions and type mock provider

* test: add fallback mock for second getSavedClineMessages read in resume-eviction spec

* fix(task): prevent saving unhydrated history messages during abort

---------

Co-authored-by: Naved  Merchant <naved.merchant@gmail.com>
…rg#1141)

* refactor(webview): complete provider identifier migration

* test(webview): type selected model hook mocks

* test(webview): keep selected model spec out of provider migration

* test(webview): harden provider identifier migration tests

---------

Co-authored-by: Elliott de Launay <edelauna@gmail.com>
…de-Org#1193)

* chore(deps): update dependency mermaid to v11.16.1 [security]

* fix(webview): harden mermaid securityLevel and tighten dev-mode CSP

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Elliott de Launay <edelauna@gmail.com>
…-Org#1161)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…rg#1146)

* refactor(webview): canonicalize ApiOptions provider identifiers

* test(webview): strengthen ApiOptions interaction coverage

* fix(webview): use providerIdentifiers.openrouter in ApiOptions option sort

---------

Co-authored-by: Elliott de Launay <edelauna@gmail.com>
@myk1yt
myk1yt force-pushed the pr/b12-mimo-enforcement-v2 branch from 4ca9b06 to b745aef Compare August 9, 2026 06:30
@myk1yt

myk1yt commented Aug 10, 2026

Copy link
Copy Markdown
Owner Author

Closing to recreate with main as target base branch. This PR had stale base branch references after fork sync.

@myk1yt myk1yt closed this Aug 10, 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.

3 participants