Skip to content

[FEATURE] Add Mistral Vibe support - #4720

Closed
GijsRommers wants to merge 27 commits into
pingdotgg:mainfrom
GijsRommers:main
Closed

GijsRommers wants to merge 27 commits into
pingdotgg:mainfrom
GijsRommers:main

Conversation

@GijsRommers

@GijsRommers GijsRommers commented Jul 28, 2026 •

Copy link
Copy Markdown

What Changed

Adds Mistral Vibe as a provider in T3 Code, addressing #1356.

The integration includes:

  • Mistral Vibe provider detection and authentication status
  • Provider configuration in Settings
  • Mistral Vibe models in the model picker
  • Configurable ACP binary path and environment variables
  • Optional local-model support through an OpenAI-compatible endpoint
  • Configurable local endpoint and model ID
  • Workspace trust configuration

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

Provider list before adding Mistral Vibe

After

Provider list after adding Mistral Vibe

Model picker

Before

Model picker before adding Mistral Vibe

After

Model picker showing Mistral Vibe models

Provider configuration

Mistral Vibe provider and local-model settings

Testing

Tested the following:

  • Mistral Vibe is detected when the vibe-acp binary is available
  • Authentication status appears in the provider list
  • Mistral Vibe models appear in the model picker
  • Hosted models can be selected and used
  • The binary path and environment variables can be configured
  • Local mode connects to a configured OpenAI-compatible endpoint
  • The configured local model appears in the model picker
  • Provider enable and disable controls work correctly

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for UI changes
  • No animation or interaction changes require a video

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: VibeDriver builds adapter, snapshot, and text-generation services; VibeAdapter runs 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: VibeProvider probes vibe-acp --version and ACP config options for models/thinking; auth stays unknown (no interactive authenticate on probes). VibeTextGeneration reuses the ACP runtime for commit/PR/branch/title helpers. VibeAcpSupport maps runtime modes to Vibe modes, optional Ollama/OpenAI-compatible local overrides via env, and sets interruptPromptOnCancel: false so 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: authMethodId is optional (skip authenticate when unset); cancel can avoid locally interrupting the prompt RPC when interruptPromptOnCancel is 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

  • Introduces a new vibe provider driver that communicates with the vibe-acp binary over ACP, performing installation probing, model discovery, and status reporting with a 5-minute refresh cycle.
  • Adds VibeTextGeneration to generate commit messages, PR content, branch names, and thread titles via the Vibe ACP runtime with a 180s timeout.
  • Adds VibeSettings to 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.
  • The provider appears in the model picker with a 'new' badge, positioned immediately after OpenCode in provider instance lists.
  • Extends the ACP mock agent to support Vibe-flavored config options, trust endpoints, and cancellation-aware prompt handling when T3_ACP_VIBE_CONFIG=1.
  • Risk: ACP discovery runs as a subprocess and can time out; on failure the provider degrades to a warning status rather than erroring hard, and auth status is always reported as 'unknown'.

Macroscope summarized 5179dce.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ae19453a-8bac-4e7a-b133-b3d10f542a01

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Jul 28, 2026
@macroscopeapp

macroscopeapp Bot commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: 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.

@GijsRommers GijsRommers mentioned this pull request Jul 28, 2026
3 tasks done
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>
Gijs Rommers and others added 2 commits July 28, 2026 16:11
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
Gijs Rommers added 3 commits July 28, 2026 18:03
- 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
Gijs Rommers and others added 3 commits July 28, 2026 21:15

@macroscopeapp macroscopeapp 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.

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

Comment on lines +217 to +224
Effect.mapError(
(cause) =>
new EffectAcpErrors.AcpRequestError({
code: -32603,
errorMessage: `Vibe returned an invalid workspace trust response: ${cause.message}`,
data: cause,
}),
),

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.

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:

Suggested change
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

Comment on lines +246 to +253
Effect.mapError(
(cause) =>
new EffectAcpErrors.AcpRequestError({
code: -32603,
errorMessage: `Vibe returned an invalid workspace trust response: ${cause.message}`,
data: cause,
}),
),

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.

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:

Suggested change
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

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ 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,

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.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5179dce. Configure here.

@juliusmarminge

Copy link
Copy Markdown
Member

Closing in favor of #2829 (orchestration V2).

Two things changed under this PR:

  1. It implements a provider against the V1 adapter contract (provider/Layers/*Adapter.ts, provider/Services/ProviderAdapter.ts, ProviderAdapterRegistry), all of which feat(orchestrator): introduce new orchestrator #2829 deletes. Providers are now orchestration-v2/Adapters/*AdapterV2.ts entries in ProviderAdapterRegistry.ts.
  2. feat(orchestrator): introduce new orchestrator #2829 adds a generic ACP Registry driver (provider/Drivers/AcpRegistryDriver.ts, Adapters/AcpRegistryAdapterV2.ts) that resolves and runs any agent published to the official ACP registry — so a bespoke adapter may no longer be needed at all for this agent.

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 main and reopen against the V2 adapter shape and we'll take a look.

@GijsRommers

Copy link
Copy Markdown
Author

Thanks for the update, will do!
Would also like to thank you (and the others working on t3) for the work, made my life significantly easier!

@GijsRommers

Copy link
Copy Markdown
Author

Updated in #31881 — rebased onto current main against the orchestration-v2 adapter shape and reimplemented on Mistral's native vibe-app-server JSON-RPC protocol (the runtime behind vibe-acp), with thread checkouts (worktree: existing + workspace/git/checkouts) and native usage limits from account/read billing wired into the provider snapshot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants