Repository navigation
[FEATURE] Add Mistral Vibe support - #4720
GijsRommers wants to merge 27 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review This PR introduces a complete new AI provider integration (Mistral Vibe) with ~3500 lines of new code spanning session management, ACP protocol handling, text generation, and UI components. New features of this scope require human review. An unresolved comment about trust preference logic also warrants verification. You can customize Macroscope's approvability policy. Learn more. |
Fixes cursor bot issue: interruptTurn was holding the per-thread lock while awaiting the ACP cancel operation. If the agent's cancel response is slow or never arrives, this lock remains held indefinitely, blocking all subsequent operations like sendTurn or stopSession for that thread. The fix moves the ACP cancel call outside the thread lock: - The lock protects session validation, pending approval cancellation, and local turn settlement - The actual ACP cancel effect executes after the lock is released Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Fixes cursor bot issue: Moving acp.cancel outside the thread lock created a race condition where a concurrent startSession or new turn could replace the session context for the threadId, causing acp.cancel to target the wrong session/turn. The fix captures the acp.cancel effect reference while still holding the lock, then executes it after the lock is released: - Inside lock: validate session, capture ctx.acp.cancel as Effect - Outside lock: execute the captured cancel effect This ensures: - No indefinite lock holding (cancel executes outside lock) - No wrong-session race (acp reference captured under lock) Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Problem: When messages are sent rapidly, the second sendTurn would fail with 'Mistral Vibe already has an active turn' error. This was caused by prepareTurn and sendTurn each acquiring the thread lock separately, creating a window where the second prepareTurn could see activeTurnId set from the first turn. Solution: Merged prepareTurn and prompt start into a single function (prepareAndStartTurn) that holds the lock continuously. The prompt is still forked so it doesn't block the lock, but activeTurnId is set before the prompt starts, ensuring proper serialization of turns. This allows rapid follow-up messages to queue properly instead of erroring. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Align Vibe’s provider adapter behavior with Cursor/Grok by reusing the active turn id when multiple prompts overlap, and only settling the merged turn when the last prompt finishes.
- Settle interrupted prompts and prevent stale active turns - Forward native ACP events and deduplicate plan updates - Expand cancellation and provider registry coverage
- Reset cancelled sessions silently when a turn never started - Update coverage for ready session state and absent completion events
- Settle only the interrupted prompt reservation - Ignore targeted cancels for missing or stale turns
- Avoid failing session startup when Vibe has no pending trust prompt - Select an available trust decision and cover both cases in tests
- Avoid automatically trusting sibling directories in the repository
There was a problem hiding this comment.
Effect service conventions review of the new Mistral Vibe provider code.
One convention violation found, in two places: the workspace-trust decode boundary in apps/server/src/provider/acp/VibeAcpSupport.ts builds its wrapper message from cause.message and stores the underlying SchemaError in data instead of cause. Everything else (dependency acquisition via yield*, Effect.catchTags usage, error pass-through in VibeTextGeneration, snapshot/driver wiring) matches the existing Grok/Cursor ACP patterns.
Posted via Macroscope — Effect Service Conventions
| Effect.mapError( | ||
| (cause) => | ||
| new EffectAcpErrors.AcpRequestError({ | ||
| code: -32603, | ||
| errorMessage: `Vibe returned an invalid workspace trust response: ${cause.message}`, | ||
| data: cause, | ||
| }), | ||
| ), |
There was a problem hiding this comment.
The wrapper message is derived from cause.message (a schema error whose text can embed the raw agent response) and the underlying failure is stored in data rather than cause, so the error chain is lost and unbounded wire text reaches error.message. Consider using the existing static factory, which keeps a stable message and preserves the real cause:
| Effect.mapError( | |
| (cause) => | |
| new EffectAcpErrors.AcpRequestError({ | |
| code: -32603, | |
| errorMessage: `Vibe returned an invalid workspace trust response: ${cause.message}`, | |
| data: cause, | |
| }), | |
| ), | |
| Effect.mapError((cause) => | |
| EffectAcpErrors.AcpRequestError.internalError( | |
| "Vibe returned an invalid workspace trust response.", | |
| undefined, | |
| { method: "_trust/status", cause }, | |
| ), | |
| ), |
Posted via Macroscope — Effect Service Conventions
| Effect.mapError( | ||
| (cause) => | ||
| new EffectAcpErrors.AcpRequestError({ | ||
| code: -32603, | ||
| errorMessage: `Vibe returned an invalid workspace trust response: ${cause.message}`, | ||
| data: cause, | ||
| }), | ||
| ), |
There was a problem hiding this comment.
Same issue as the _trust/status mapping above: message built from cause.message, cause placed in data. Since both sites decode the same response, a shared helper (or the static factory) keeps the policy in one place:
| Effect.mapError( | |
| (cause) => | |
| new EffectAcpErrors.AcpRequestError({ | |
| code: -32603, | |
| errorMessage: `Vibe returned an invalid workspace trust response: ${cause.message}`, | |
| data: cause, | |
| }), | |
| ), | |
| Effect.mapError((cause) => | |
| EffectAcpErrors.AcpRequestError.internalError( | |
| "Vibe returned an invalid workspace trust response.", | |
| undefined, | |
| { method: "_trust/decision", cause }, | |
| ), | |
| ), |
Posted via Macroscope — Effect Service Conventions
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 5179dce. Configure here.
| ); | ||
| yield* Option.match(acpCancel, { | ||
| onNone: () => Effect.void, | ||
| onSome: (cancelEffect) => cancelEffect, |
There was a problem hiding this comment.
Failed cancel can wedge Vibe sessions
Medium Severity
With interruptPromptOnCancel: false, cancel does not interrupt the local prompt fiber; recovery depends on the agent completing the prompt after session/cancel. interruptTurn still Effect.ignores cancel failures after already settling the turn, so a failed or non-unblocking cancel leaves the ACP prompt semaphore held. Later sendTurn calls on that session can prepare and emit turn.started but then hang indefinitely on prompt.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 5179dce. Configure here.
|
Closing in favor of #2829 (orchestration V2). Two things changed under this PR:
Once #2829 merges, please check whether the ACP Registry driver already covers this agent. If it does, great — no code needed. If it doesn't, rebase onto |
|
Thanks for the update, will do! |
|
Updated in #31881 — rebased onto current main against the orchestration-v2 adapter shape and reimplemented on Mistral's native |


What Changed
Adds Mistral Vibe as a provider in T3 Code, addressing #1356.
The integration includes:
Why
This enables users with an existing Mistral Vibe installation or account to use its models directly from T3 Code instead of running Vibe separately.
UI Changes
Provider list
Before
After
Model picker
Before
After
Provider configuration
Testing
Tested the following:
vibe-acpbinary is availableChecklist
Note
Medium Risk
Large new adapter with subprocess ACP, trust, and concurrent turn/cancel semantics; mitigated by extensive tests and graceful discovery degradation, but regressions could affect session stability for Vibe threads.
Overview
Adds Mistral Vibe as a first-class provider (
vibe) wired through the same driver/registry pattern as Codex, Grok, and OpenCode:VibeDriverbuilds adapter, snapshot, and text-generation services;VibeAdapterruns chat over ACP with workspace trust (_trust/status/_trust/decision), mode/model/thinking config, permission handling, and turn lifecycle rules aligned with Cursor/Grok (steering into one turn, cancel during prep, no terminal events for turns that never started).Server-side discovery and headless use:
VibeProviderprobesvibe-acp --versionand ACP config options for models/thinking; auth staysunknown(no interactiveauthenticateon probes).VibeTextGenerationreuses the ACP runtime for commit/PR/branch/title helpers.VibeAcpSupportmaps runtime modes to Vibe modes, optional Ollama/OpenAI-compatible local overrides via env, and setsinterruptPromptOnCancel: falseso cancel waits on the agent.Contracts & web: New
VibeSettings(binary path, trust workspaces, local endpoint/model) and default model slugs; provider appears in settings (Early Access), model picker, and instance sorting immediately after OpenCode.Shared ACP layer:
authMethodIdis optional (skipauthenticatewhen unset); cancel can avoid locally interrupting the prompt RPC wheninterruptPromptOnCancelis false. The ACP mock agent gains Vibe-shaped config, trust env knobs, and cancellation-aware hung prompts for integration tests.Reviewed by Cursor Bugbot for commit 5179dce. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add Mistral Vibe as a built-in provider with ACP-based model discovery and text generation
vibeprovider driver that communicates with thevibe-acpbinary over ACP, performing installation probing, model discovery, and status reporting with a 5-minute refresh cycle.VibeTextGenerationto generate commit messages, PR content, branch names, and thread titles via the Vibe ACP runtime with a 180s timeout.VibeSettingsto server settings (binary path, Ollama override, workspace trust, custom models) and surfaces the provider in the settings UI with an 'Early Access' badge and Mistral icon.T3_ACP_VIBE_CONFIG=1.Macroscope summarized 5179dce.