feat(advisor) 1/4: helpers + settings field + orphan tool_use guard - #176
Merged
Conversation
Foundation layer for the /advisor port from typescript/src. Three
independent pieces, all read-only at runtime until the rest of the
stack lands:
- `src/utils/advisor.py` (NEW): constants (ADVISOR_BETA_HEADER,
ADVISOR_TOOL_TYPE, ADVISOR_TOOL_INSTRUCTIONS), provider/env gates,
block predicates, schema builder, strip_advisor_blocks, and
extract_advisor_{result_text,error_code}. ADVISOR_TOOL_INSTRUCTIONS
is a byte-for-byte copy of typescript/src/utils/advisor.ts:130-145;
a SHA pin plus a live cross-check against the TS source catch drift.
- `src/settings/types.py`: adds `advisor_model: str = ""` to
SettingsSchema. Empty string = unset; future layers read it via
`get_settings().advisor_model` at request time.
- `src/types/messages.py`: extends `ensure_tool_result_pairing` to
strip orphan `server_tool_use` and `mcp_tool_use` blocks whose
matching `*_tool_result` never landed in the same assistant message
(interrupted stream). Mirrors TS messages.ts:5217-5255. Prevents
the API from 400-ing the next turn after a mid-advisor ESC.
## Test plan
- [x] `tests/test_advisor_helpers.py` (32 tests): constants, all gates,
block detection (dict + attribute-style), strip pass shapes
including the empty/thinking-only placeholder fallback, schema
shape, SHA + live TS byte-equality.
- [x] `tests/test_advisor_orphan_pairing.py` (6 tests): advisor orphan
stripped; pair retained; mcp orphan stripped; empty-content
placeholder; regular client tool_use unaffected; multi-message
independence.
- [x] No regressions in adjacent suites (settings, messages utility,
command system, tool normalization, transcript, tui).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This was referenced May 18, 2026
7 tasks
singlaamitesh
pushed a commit
to singlaamitesh/clawcodex
that referenced
this pull request
Jul 7, 2026
…undation feat(advisor) 1/4: helpers + settings field + orphan tool_use guard
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.
First in a 4-PR stack porting
/advisorfrom TypeScript at server-side parity. This PR lands the runtime-inert foundation; activation lands in PR 3.Summary
src/utils/advisor.py(NEW) — constants (ADVISOR_BETA_HEADER,ADVISOR_TOOL_TYPE,ADVISOR_TOOL_INSTRUCTIONS), provider/env gates, block predicates, schema builder,strip_advisor_blocks, andextract_advisor_{result_text,error_code}.ADVISOR_TOOL_INSTRUCTIONSis byte-for-byte fromtypescript/src/utils/advisor.ts:130-145; a SHA pin plus live cross-check catch drift.src/settings/types.py— addsadvisor_model: str = ""toSettingsSchema. Empty string = unset; future layers read at request time.src/types/messages.py— extendsensure_tool_result_pairingto strip orphanserver_tool_useandmcp_tool_useblocks whose matching*_tool_resultnever landed in the same assistant message (interrupted stream). Mirrors TSmessages.ts:5217-5255. Prevents the API from 400-ing the next turn after a mid-advisor ESC.Stack
mainTest plan
tests/test_advisor_helpers.py— 32 tests: constants, all gates, block detection (dict + attribute-style), strip pass shapes including the empty/thinking-only placeholder fallback, schema shape, SHA + live TS byte-equality.tests/test_advisor_orphan_pairing.py— 6 tests: advisor orphan stripped; pair retained; mcp orphan stripped; empty-content placeholder; regular client tool_use unaffected; multi-message independence.🤖 Generated with Claude Code