feat(adapters): add Mistral Vibe profile + vibe-hooks-toml dialect - #413
Draft
ayhid wants to merge 1 commit into
Draft
feat(adapters): add Mistral Vibe profile + vibe-hooks-toml dialect#413ayhid wants to merge 1 commit into
ayhid wants to merge 1 commit into
Conversation
Drives Mistral's `vibe` CLI (>= 2.23) through the generic tmux + hook-signal transport, as `mistral-vibe` (alias `vibe`). Vibe is the first CLI whose hook config is not JSON: `.vibe/hooks.toml` is a flat `hooks = [...]` array of tables whose entries name their own event in a `type` field rather than being keyed by it. Hook-config I/O therefore moves behind a dialect-aware `load_hook_config` / `dump_hook_config` seam; every JSON dialect emits byte-identical output as before. The TOML writer is hand-rolled — tomlkit ships only with the [tui] extra — and refuses a non-scalar rather than emitting something vibe would misparse. Profile facts pinned against 2.23.2: - `post_agent` is the only turn-end event (no SessionStart / SessionEnd / PreCompact analogue) and fires per response turn, so the profile ships stop_without_result_nudges = 5, as copilot's agentStop needed. - `--trust` is mandatory: vibe reads project hooks only in a trusted directory, and without it no Stop ever arrives and every session reads as a timeout. Trust is per-invocation rather than an exact-path store, so isolation = "worktree" keeps working (unlike antigravity). - Vibe exposes no --model flag; the model comes from VIBE_ACTIVE_MODEL or vibe's own config, so `[adapter] model` must stay empty. - usage_parser = "none" pending a probe of ~/.vibe/logs/session/*/messages.jsonl.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization 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:
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Drafted per the Discord thread with @jeremy — flagging early rather than dropping it unannounced, and happy to close it if the pre-1.0 stance on new CLIs means "not yet".
What
Adds
mistral-vibe(aliasvibe), driving Mistral'svibeCLI through the existing generic tmux + hook-signal transport.It is not the usual zero-Python profile add. Vibe is the first CLI whose hook config is not JSON:
.vibe/hooks.tomlis a flathooks = [...]array of tables whose entries name their own event in atypefield rather than being keyed by it. So this also adds a sixth dialect,vibe-hooks-toml.Why it touches install.py
Hook-config I/O was JSON-shaped at four read sites and three write sites. Those now go through a dialect-aware
load_hook_config/dump_hook_configseam; every JSON dialect emits byte-identical output, so the existing merge tests characterize the refactor.The TOML writer is hand-rolled (~25 lines) rather than a new dependency — tomlkit ships only with the
[tui]extra, and vibe'sHookConfigschema is closed and entirely scalar. It raisesProfileErroron a non-scalar rather than emitting something vibe would misparse. Known trade-off, documented in the docstring: re-emitting drops comments in the user'shooks.toml, which only happens whenmerge_hooksreportschanged.Profile facts, pinned against vibe 2.23.2
post_agentis the only turn-end event — no SessionStart / SessionEnd / PreCompact analogue — and it fires per response turn, so the profile shipsstop_without_result_nudges = 5, the same reason copilot'sagentStopneeded it.--trustis load-bearing. Vibe reads project hooks only in a trusted directory; without it noStopever arrives and every session reads as a timeout. Trust is per-invocation rather than an exact-path store, soisolation = "worktree"keeps working — vibe does not inherit antigravity'sisolation = "none"restriction.--modelflag; the model comes fromVIBE_ACTIVE_MODELor vibe's own config, so[adapter] modelmust stay empty.generic.pyonly appendsmodel_flagwhen a model is set, so this is a documented limitation, not a crash.session_id,transcript_path,cwd), sobmad_loop_hook.pyis unchanged.Testing
init→validate→ re-initon a scratch project: registers, detects, idempotent, and a hand-added decoy user hook survives untouched.merge_hooksvibe cases (shape, idempotency, user-hook preservation, the [BUG] bmad-loop validate and probe fail to recognize registered hooks for antigravity adapter #159 marker guarantee, malformed-shape refusal), atomllibround-trip over the emitter,install_intoend-to-end. Addedmistral-vibeto the existing dialect parametrizations intest_probe.pyand the profile assertions intest_profile.py.Known gaps
usage_parser = "none"is pending, not final. The live--probeis blocked on vibe's one-time interactive onboarding wizard, so the hook payload and the token schema in~/.vibe/logs/session/*/messages.jsonlare inferred from reading vibe's source rather than observed. I'll re-probe aftervibe --setupand follow up; ifmessages.jsonlcarries usage, the parser is a separate small PR.post_agentwith a non-emptytranscript_path, so copilot'ssubagent_stop_without_transcriptmechanism won't filter them (they carry a non-nullparent_session_idinstead). I've left this to artifact-gating plus the raised nudge floor rather than adding a profile knob unilaterally — happy to add one if you'd rather, but it seemed like your call.Marked draft since the two above are open and the pre-1.0 stance on new CLIs is yours to set.