Skip to content

fix(actionagent): resolve every engine constant under a host's inflections - #361

Merged
TonsOfFun merged 2 commits into
mainfrom
fix/engine-inflections-whole-tree
Aug 14, 2026
Merged

fix(actionagent): resolve every engine constant under a host's inflections#361
TonsOfFun merged 2 commits into
mainfrom
fix/engine-inflections-whole-tree

Conversation

@TonsOfFun

@TonsOfFunTonsOfFun commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

1.2.1 fixed the api directory and nothing else. Seven files in this engine camelize differently once the host registers an acronym, and each raises Zeitwerk::NameError on first reference:

filehost with acronym expectsfile defines
mcp_catalog.rbMCPCatalogMcpCatalog
mcp_recording_middleware.rbMCPRecordingMiddlewareMcpRecordingMiddleware
playwright_mcp_client.rbPlaywrightMCPClientPlaywrightMcpClient
api_key.rbAPIKeyApiKey
api_keys_controller.rbAPIKeysControllerApiKeysController
mcp_controller.rbMCPControllerMcpController
mcp_servers_controller.rbMCPServersControllerMcpServersController

Found by clicking through the mounted dashboard in a Rails 8.1 app that declares both inflect.acronym "API" and inflect.acronym "MCP". The Tools view is completely unreachable there — it 500s with uninitialized constant ActionAgent::ToolDiscovery::McpCatalog — as are the MCP endpoints and anything touching an API key. Those are not exotic acronyms to register; Rails documents the pattern, and any host with its own MCP integration will have hit this.

The fix

Rather than enumerate names, every path under this engine now camelizes with Zeitwerk's default inflector, ignoring whatever acronyms the host registered. It stays scoped by path, because the loader is shared with the host, whose own constants must keep their spelling.

INFLECTION_OVERRIDES carries any basename this engine wants spelled differently. It is empty today, which is the point: the engine names its files for the constants default camelization produces, and a file that wants a genuine acronym adds itself there rather than depending on the host.

The router half generalizes the same way. Routing does not consult the autoloader's inflector, so an acronym host asks for ActionAgent::API::MCPServersController. An all-caps run in a missing constant is now retried in the relaxed spelling (APIApi, MCPServersControllerMcpServersController) instead of aliasing each pair by hand.

Verification

Installed into that host and clicked every dashboard view. Before: Tools 500s. After: Tools renders (2 tools detected, 6 calls, 0 errors, attributed to the right telemetry spans), and MCP Services lists all 10 catalog entries — the view that reads McpCatalog directly. Traces, Interactions and Metrics render throughout.

Screenshots of the before/after are in the linked Sparkle PR.

Releases as 1.2.2

1.2.1 is already on RubyGems, so this ships as 1.2.2 — a host pinning >= 1.2.1 picks the fix up on its next bundle update. Until it is released, the Tools and MCP Services views 500 on any host that registers these acronyms; Traces, Interactions and Metrics are unaffected.

Note for whoever cuts the release: activeagent stays at 1.2.0 here, and the publish step added in 1.2.1 skips a version already on RubyGems, so a v1.2.2 tag publishes actionagent alone rather than failing on the duplicate.

…tions
1.2.1 scoped the autoloader override to the basename "api", which fixed the
controllers under app/controllers/action_agent/api and nothing else. Seven
files in this engine camelize differently once a host registers an acronym,
and each raises Zeitwerk::NameError on first reference:
mcp_catalog.rb MCPCatalog vs McpCatalog
mcp_recording_middleware.rb MCPRecording… vs McpRecording…
playwright_mcp_client.rb PlaywrightMCP… vs PlaywrightMcp…
api_key.rb APIKey vs ApiKey
api_keys_controller.rb APIKeysController vs ApiKeysController
mcp_controller.rb MCPController vs McpController
mcp_servers_controller.rb MCPServersCont… vs McpServersCont…
The dashboard's Tools view was unreachable in such a host — the request 500s
with "uninitialized constant ActionAgent::ToolDiscovery::McpCatalog" —
as were the MCP endpoints and anything touching an API key.
Rather than enumerate names, every path under this engine now camelizes with
Zeitwerk's default inflector, ignoring whatever acronyms the host registered.
It stays scoped by path because the loader is shared with the host, whose own
constants must keep their spelling. INFLECTION_OVERRIDES carries any basename
this engine wants spelled differently; it is empty today, which is the point:
the engine names its files for the constants default camelization produces.
The router half generalizes too. It does not consult the autoloader's
inflector, so an acronym host asks for ActionAgent::API::MCPServersController.
An all-caps run in a missing constant is now retried in the relaxed spelling
(API -> Api, MCPServersController -> McpServersController) rather than each
pair being aliased by hand.
@TonsOfFun
TonsOfFun marked this pull request as ready for review August 14, 2026 23:47
@TonsOfFun
TonsOfFun merged commit 367136f into mainAug 14, 2026
6 checks passed
@TonsOfFun
TonsOfFun deleted the fix/engine-inflections-whole-tree branch August 14, 2026 23:48
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@TonsOfFun