Skip to content

fix(amp): smart-mode tool name fixes + deep-mode response repair - #2896

Merged
luispater merged 7 commits into
router-for-me:devfrom
edlsh:fix/oauth-tool-rename-per-request-map
May 4, 2026
Merged

luispater merged 7 commits into
router-for-me:devfrom
edlsh:fix/oauth-tool-rename-per-request-map

Conversation

@edlsh

@edlsh edlsh commented Apr 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This consolidates the Amp smart-mode and deep-mode tool fixes into one PR.

  • Fixes Claude OAuth tool-name reverse remapping so responses only map tool names back when the request actually forward-renamed that tool for the same request.
  • Keeps the OAuth tool-name transform flow centralized and pre-allocates the reverse map.
  • Preserves Amp's lowercase glob tool casing in proxied responses.
  • Repairs OpenAI Responses streaming when upstream sends response.completed with an empty response.output by reconstructing it from prior response.output_item.done events.

Amp Coverage

Smart mode:

Deep mode:

  • Includes the OpenAI Responses stream repair from fix(amp): preserve tool calls in proxied streams #2766.
  • Validated locally on April 25, 2026 against Amp deep mode / oracle on gpt-5.4 high reasoning: before the fix, reasoning appeared but the final answer was blank; after running the fixed build, the final answer appeared correctly.

Closes #2766.

Testing

  • go build ./internal/api/modules/amp/... ./sdk/api/handlers/openai/... ./internal/runtime/executor/...
  • go test ./internal/api/modules/amp/... ./sdk/api/handlers/openai/... ./internal/runtime/executor/...
  • go test -run "TestForwardResponsesStream|TestNormalizeAmpToolNames|TestRewriteStreamChunk" -v ./internal/api/modules/amp/... ./sdk/api/handlers/openai/...

Note: TestMultiSourceSecret_CacheEmptyResult in internal/api/modules/amp/secret_test.go is a pre-existing failure on the parent commit as well.

@github-actions
github-actions Bot changed the base branch from main to dev April 18, 2026 14:35
@github-actions

Copy link
Copy Markdown

This pull request targeted main.

The base branch has been automatically changed to dev.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request replaces the global oauthToolRenameReverseMap with a per-request reverse map to prevent incorrect tool name restoration in mixed-case scenarios. This ensures that only tool names explicitly renamed during the request are reversed in the response, fixing a bug where original TitleCase names were being corrupted. A suggestion was made to pre-allocate the reverseMap in remapOAuthToolNames to improve efficiency by avoiding reallocations.

Comment thread internal/runtime/executor/claude_executor.go Outdated
@edlsh

edlsh commented Apr 19, 2026

Copy link
Copy Markdown
Contributor Author

⚠️ Severity: Amp CLI is completely broken without this fix

Want to flag the impact clearly for anyone triaging this PR:

This is not a cosmetic or edge-case bug. With any Claude OAuth account in the pool, Amp CLI is 100% unusable end-to-end.

Every single Amp request sends at least one lowercase tool (glob, skill, todo_write, task_list, …) alongside the TitleCase ones (Bash, Read, Grep, Edit, Task, Write, …). That means the renamed=true flag fires on literally every request, which means the global reverse map unconditionally lowercases every Bash/Read/Grep/Edit/Task/Write in the response. Amp's tool registry has these names in TitleCase only, so:

  • Bash → bash → tool "bash" is not allowed for smart mode → no commands run
  • Read → read → rejected → no file reads
  • Edit/Write → edit/write → rejected → no file edits
  • Grep → grep → rejected → no searches
  • Task → task → rejected → no subagents

In practice the agent loop stalls on the very first turn. Users see "Done." with no work performed, or silent tool failures, depending on the request. There's no workaround short of disabling all Claude OAuth accounts in the config, which defeats the whole point of routing Amp through CLIProxyAPI.

This is the root cause of a cluster of "Amp doesn't work" reports that have been attributed to cloaking, cache-control, or model routing — none of which are the issue. The forward rename is correct; only the reverse pass is wrong.

Repro in under a minute on origin/main:

amp -m smart --execute "run: echo hi"
# → hangs or exits with no tool execution

With this patch applied, Amp works on the first try. Regression tests (TestRemapOAuthToolNames_MixedCase_OnlyRenamedToolsReversed, TestReverseRemapOAuthToolNamesFromStreamLine_HonorsPerRequestMap) lock in the mixed-case invariant so this can't regress silently.

Would appreciate a prioritized review — every day this sits unmerged, every Amp user on an OAuth account is dead in the water.

@edlsh edlsh changed the title fix(claude): only reverse-remap OAuth tool names that were forward-renamed fix(claude): only reverse-remap OAuth tool names that were forward-renamed [Amp CLI completely broken without this] Apr 19, 2026
@0xkaisa

0xkaisa commented Apr 22, 2026

Copy link
Copy Markdown

@luispater can you check this PR? Thanks.

@edlsh

edlsh commented Apr 24, 2026

Copy link
Copy Markdown
Contributor Author

Quick verification update: this is still reproducible on current upstream dev (36cc762f). A focused mixed-case repro still turns an original TitleCase Bash response tool into bash when the same request also includes a lowercase-renamed tool like glob.

The PR branch (ed320c83) passes the targeted regression tests:

TestRemapOAuthToolNames_MixedCase_OnlyRenamedToolsReversed
TestReverseRemapOAuthToolNamesFromStreamLine_HonorsPerRequestMap

So the branch is still fixing the current upstream behavior, not a stale issue.

@luispater luispater left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Solid fix for the mixed-case OAuth tool-name anti-fingerprinting remap: reverse mapping is now per-request, so only tools that were actually forward-renamed get restored. This prevents TitleCase tools like Bash from being incorrectly lowercased when a different tool in the same request (e.g. glob) triggers a rename.

Key findings

  • ✅ remapOAuthToolNames now produces a per-request reverse map; reverse functions only touch entries present in that map.
  • ✅ Call sites are updated across non-stream, stream (both passthrough and translated paths), and count_tokens.
  • ✅ Good regression tests for the Amp mixed-case scenario, including the SSE line path.

Test plan

  • Not run locally (review only).
  • PR description reports go test ./internal/runtime/executor/...; CI build is green.

This is an automated Codex review result and still requires manual verification by a human reviewer.

edlsh added 5 commits April 25, 2026 17:45
…named

remapOAuthToolNames renames lowercase client-sent tools (e.g. `glob` →
`Glob`) to Claude Code equivalents on OAuth requests to avoid tool-name
fingerprinting. The reverse pass previously ran against a *global*
reverse map and rewrote every tool_use block whose name matched any
value in oauthToolRenameMap — regardless of what the client actually
sent.

For clients that send mixed casing (notably Amp CLI — `Bash`, `Read`,
`Grep`, `Task` alongside `glob`, `skill`, etc.) this corrupted the
response. Any forward rename in the request set the "renamed" flag,
which then unconditionally lowercased every `Bash` in the response to
`bash`. Amp's tool registry has `Bash`, not `bash`, so it rejected the
tool_use with `tool "bash" is not allowed for smart mode` and tool
execution failed.

Fix: `remapOAuthToolNames` now returns a per-request map keyed on the
upstream (TitleCase) name valued with the original client-sent name.
The reverse functions take this map and only touch entries in it.
Names the client sent in TitleCase pass through untouched in both
directions.

- Change remapOAuthToolNames signature from `([]byte, bool)` to
  `([]byte, map[string]string)`; populate at every rename site
  (tools[], tool_choice.name, message tool_use, tool_reference,
  nested tool_reference inside tool_result).
- Change reverseRemapOAuthToolNames and
  reverseRemapOAuthToolNamesFromStreamLine to accept and consume the
  per-request map; remove the global oauthToolRenameReverseMap.
- Update all three executor call sites (Execute, ExecuteStream direct
  passthrough, ExecuteStream translated) + count_tokens.
- Add regression tests for the mixed-case scenario in both the
  non-streaming and SSE code paths.
Address Gemini code review suggestion: the reverseMap can contain at
most len(oauthToolRenameMap) entries, so pre-allocating avoids
reallocations as entries are added.
@edlsh
edlsh force-pushed the fix/oauth-tool-rename-per-request-map branch from 422bb1c to fd45dec Compare April 25, 2026 21:53
@edlsh edlsh changed the title fix(claude): only reverse-remap OAuth tool names that were forward-renamed [Amp CLI completely broken without this] fix(amp): smart-mode tool name fixes + deep-mode response repair Apr 25, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fd45dece7f

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sdk/api/handlers/openai/openai_responses_handlers.go Outdated

ben-vargas commented Apr 25, 2026 •

Copy link
Copy Markdown
Collaborator

@luispater quick update: I’ve been working with @edlsh over X/Twitter DMs and testing this PR locally against Amp CLI.

I pulled the latest PR branch, rebuilt cli-proxy-api, restarted the proxy, and re-ran Amp tests. The latest version fixes both issues I was seeing:

  • Amp smart-mode tool-call failures caused by case-sensitive tool names like Bash / Read being rewritten incorrectly.
  • Deep-mode / gpt-5.4 Responses failures where streamed tool calls were present, but the final response.completed.response.output could arrive empty.

I also checked the CLIProxyAPI logs directly. With this PR, the repaired completed event includes the expected output items/function calls, and Amp continues the turn correctly.

The latest SSE framing follow-up also looks good to me: repaired multiline payloads are emitted with data: on each line, with regression coverage for multiline completed frames and indexed/unindexed output items.

Focused tests pass locally: go test ./sdk/api/handlers/openai ./internal/runtime/executor ./internal/api/modules/amp

I did see a few normal tool execution errors from the model guessing nonexistent paths, but not proxy formatting errors. The remaining full-suite internal/registry failure around gpt-5.5 free-tier metadata appears unrelated.

From my local testing and log inspection, this PR looks good for the Amp smart-mode and deep-mode failures.

@Amoodaa

Amoodaa commented Apr 29, 2026

Copy link
Copy Markdown

Deep-mode / gpt-5.4 Responses failures where streamed tool calls were present, but the final response.completed.response.output could arrive empty.
this was fixed in latest release and gpt-5.5 is now working if i use it through the amp.internal.model flags

@0xkaisa

0xkaisa commented May 4, 2026

Copy link
Copy Markdown

Still error, how can we fix it @ben-vargas @Amoodaa @edlsh

@ben-vargas

Copy link
Copy Markdown
Collaborator

@0xkaisa - I don't know why this hasn't been merged/fixed, I'm maintaining a fork branch here and keeping it up to date - this is what I'm using: https://github.com/ben-vargas/ai-cli-proxy-api/tree/fix-amp-patch

That branch is on v6.10.5 with Amp fixes in this PR.

@luispater

Copy link
Copy Markdown
Collaborator

@0xkaisa - I don't know why this hasn't been merged/fixed, I'm maintaining a fork branch here and keeping it up to date - this is what I'm using: https://github.com/ben-vargas/ai-cli-proxy-api/tree/fix-amp-patch

That branch is on v6.10.5 with Amp fixes in this PR.

Sorry for the wait, we've been swamped with issues, PRs, and other chores lately.

As a maintainer, if everything looks good to you, I'll merge this right away and release a new version.

@luispater
luispater merged commit bdc4240 into router-for-me:dev May 4, 2026
3 checks passed
@luispater

Copy link
Copy Markdown
Collaborator

@ben-vargas BTW, due to well-known reasons, the core team has lost all Claude subscriptions.

This has significantly impacted the review progress of all Claude related PRs.

We sincerely apologize for the inconvenience.

@ben-vargas

Copy link
Copy Markdown
Collaborator

Thanks @luispater - Wasn't sure if this was being ignored on purpose or just delayed in the workload... obviously the latter, so no worries and thanks for the attention!

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants