fix: widen MOIM allowlist to apply fix_conversation repairs for orphaned tool blocks#7684
fix: widen MOIM allowlist to apply fix_conversation repairs for orphaned tool blocks#7684wpfleger96 wants to merge 5 commits intomainfrom
Conversation
d96cdff to
134fe42
Compare
…ned tool blocks Production death loop: after tool-heavy responses, orphaned tool_use/tool_result blocks cause persistent Anthropic API 400 errors. fix_conversation correctly detects and repairs these orphans, but MOIM's allowlist only permitted merge operations. Any other fix — including orphan removal — caused MOIM to discard the repair and return the original broken conversation to the provider. Widens the allowlist to also accept orphan removal, empty message cleanup, leading/trailing assistant removal, and text content merging. These are all legitimate repairs that fix_conversation should be allowed to apply regardless of whether MOIM insertion triggered the detection.
134fe42 to
81bcac5
Compare
…e-issue * origin/main: feat: combine TUI UX from alexhancock/tui-goodness with publishing config from jackamadeo/package-tui (#7683) chore: cleanup old sandbox (#7700) Correct windows artifact (#7699) gh fall back (#7695) fix: restore smart-approve mode (#7690) fix: make TLS configurable in goosed agent via GOOSE_TLS env var (#7686) Update to rmcp 1.1.0 (#7619)
CI fails with E0639 because CallToolRequestParams and CallToolResult are #[non_exhaustive] — struct literals are forbidden from outside the crate. Replace with CallToolRequestParams::new() and CallToolResult::success().
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 698d41757e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…e-issue * origin/main: fix(ui-desktop): unify path resolution around GOOSE_PATH_ROOT (#7335) fix: pass OAuth scopes to DCR and extract granted_scopes from token response (#7571) fix: write to real file if config.yaml is symlink (#7669) fix: preserve pairings when stopping gateway (#7733) fix: reduce server log verbosity — skip session in instrument, defaul… (#7729) fix: provider test infrastructure (#7738) fix: sanitize streamable HTTP extension names derived from URLs (#7740) refactor: derive GooseMode string conversions with strum (#7706) docs: Add Spraay Batch Payments MCP Extension Tutorial (#7525) fix: flake.nix (#7224) delete goose web (#7696) Add @angiejones as CODEOWNER for documentation (#7711) Add MLflow integration guide (#7563) docs: LM Studio availability (#7698) feat: add Avian as an LLM provider (#7561) Adds `linux-mcp-server` to the goose registry (#6979) fix: add #[serde(default)] to description field on 4 ExtensionConfig variants (#7708)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 59d4485d4f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20f55ef908
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| && !issue.contains("Removed leading assistant message") | ||
| && !issue.contains("Removed trailing assistant message") |
There was a problem hiding this comment.
Keep assistant-removal issues out of MOIM allowlist
Allowlisting "Removed leading assistant message" and "Removed trailing assistant message" here makes inject_moim accept fix_conversation outputs that delete assistant turns instead of falling back to the original conversation. In compacted sessions, the compaction summary/continuation is stored in assistant message(s) (compact_messages builds and merges them in context_mgmt/mod.rs), so once MOIM is inserted and fix_conversation trims a leading/trailing assistant, this path now returns a context with that compaction payload removed, which can drop critical summary/tool-loop guidance for the next provider call.
Useful? React with 👍 / 👎.
20f55ef to
b9edd9c
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b9edd9c0b9
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| && !issue.contains("Removed orphaned tool request") | ||
| && !issue.contains("Removed empty message") | ||
| && !issue.contains("Removed leading assistant message") | ||
| && !issue.contains("Removed trailing assistant message") |
There was a problem hiding this comment.
Remove assistant-trim issues from MOIM allowlist
Allowlisting "Removed leading assistant message"/"Removed trailing assistant message" here lets inject_moim accept fix_conversation outputs that delete assistant turns instead of falling back to the original conversation. In recovery compaction when no trailing text-only user message is preserved, compact_messages builds the compacted context as assistant summary + assistant continuation (crates/goose/src/context_mgmt/mod.rs:151-167), so accepting a trailing-assistant removal drops the only compacted payload before the next provider call. Fresh evidence: those two compaction assistant messages are merged into one assistant turn there, so removing that turn deletes both the summary and tool-loop continuation guidance.
Useful? React with 👍 / 👎.
b9edd9c to
ec45e8f
Compare
|
/goose |
PR #7684 Review: fix: widen MOIM allowlist to apply fix_conversation repairsSummary: This PR fixes a real bug where orphaned tool blocks caused a "death loop" of API 400 errors. The core fix (widening the allowlist) is correct, but the PR description claims to include tests that are not present in the diff. 🔴 Blocking Issues
🟡 Warnings
✅ Highlights
Review generated by goose |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ec45e8f0c3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| && !issue.contains("Removed leading assistant message") | ||
| && !issue.contains("Removed trailing assistant message") |
There was a problem hiding this comment.
Remove assistant-trim issues from MOIM allowlist
Allowing "Removed leading assistant message" and "Removed trailing assistant message" here makes inject_moim accept fix_conversation results that delete assistant turns instead of falling back to the original conversation. Fresh evidence: compact_messages constructs the compacted payload as assistant summary + assistant continuation (crates/goose/src/context_mgmt/mod.rs around lines 151-167), and in the no-preserved-user path fix_lead_trail removes both assistant endpoints after MOIM inserts a user message between them, so the next provider call can lose the entire compacted summary/tool-loop guidance.
Useful? React with 👍 / 👎.
Pull request was closed
Widen MOIM allowlist so
fix_conversationrepairs for orphaned tool blocks are applied instead of discarded.When a session contains orphaned
tool_use/tool_resultblocks (e.g., from cancellation during tool collection or interrupted streaming),inject_moimcallsfix_conversationwhich correctly detects and removes the orphans — but then checks the resulting issues against an allowlist before deciding whether to use the fixed conversation."Removed orphaned tool response"and"Removed orphaned tool request"were not in the allowlist, sohas_unexpected_issueswastrueand MOIM discarded the fix, returning the original broken conversation to the provider. This caused persistent Anthropic API 400 errors (tool_use ids were found without tool_result blocks) on every subsequent request in an affected session — a death loop.MOIM operates on a clone of the conversation each iteration, so it effectively becomes a per-turn safety net: even if the underlying
conversationvariable retains the orphan, the fixed copy is what reaches the provider.has_unexpected_issuesallowlist ininject_moimto include allfix_conversationrepair types: orphan removal, empty message cleanup, leading/trailing assistant removal, and text content mergingtracing::info!when MOIM applies conversation fixes (previously, successful fixes were silent — only rejected fixes logged a warning)moim.rs:test_moim_fixes_orphaned_tool_request(core allowlist fix),test_moim_fixes_cancellation_orphan(production scenario with empty pre-allocated user message)context_mgmt/mod.rs:test_compaction_output_with_new_tool_pair_is_valid(regression guard proving compaction output is structurally clean)