Problem/Motivation
TokenEstimator::selectModel() (src/Service/TokenEstimator.php:52-67) has no caller. A module-wide search for selectModel — including .module, .install, .inc, Drush commands, Twig, JS, YAML and the test suite — returns exactly one line: its own definition. There is no production caller and no unit test.
No dynamic dispatch can reach it either. The module's only dynamic call sites are method_exists() probes on AI response objects (AiPostGenerateSubscriber.php:243-333) and $provider->{$camelMethod}() on a ProviderProxy (AiPreGenerateSubscriber.php:276); neither can dispatch to this method.
Four of the five model_routing config keys — small_threshold, large_model, small_label, large_label — are read only by selectModel(), so they drive nothing. The fifth, small_model, has one other reader elsewhere in TokenEstimator.
Why this matters beyond dead code: README.md:16 advertises "Two-tier model routing" as a feature. The settings form at /admin/config/ai/ai-metering/settings exposes no fields for it, so an operator who wants it must set the config via drush config:set or a config import. Having done so, nothing happens — every AI call still uses whatever model the ai module's provider default or the calling feature selects. The module documents a cost-control capability it does not perform, and the operator has no feedback indicating that.
Note this is distinct from the pre-generate reroute to a local fallback provider in AiPreGenerateSubscriber, which is a separate mechanism and is wired up. Only the selectModel() two-tier routing path is dead.
Steps to reproduce
- Set the
model_routingkeys inai_metering.settingsviadrush config:set(they cannot be set through the UI), givingsmall_modelandlarge_modeltwo distinct, clearly identifiable models and asmall_thresholdthat the next prompt will fall below. - Issue an AI call whose prompt is below the threshold, then inspect which model was actually used — via the usage log at
/admin/reports/ai-meteringor the provider's own logs. The configured small model is not selected; routing never occurs.
Environment
- Drupal version: n/a — not reproduced on a running site, see AI assistance note
- ai_metering version: 1.0.x at commit a39fea9
- AI provider module + version: provider-independent
- AI feature module tested: none — found by code inspection
Proposed resolution
Decide whether two-tier routing is a feature this module should own, then make code and documentation agree. Either:
- Implement it — call
selectModel()from the pre-generate path, expose themodel_routingkeys in the settings form, and cover it with tests; or - Remove it — delete
selectModel(), the four unused config keys and their config schema, and the README claim, with an update hook to clean stale config from existing sites.
Removal is the smaller change and fits a metering module's scope; implementing it means owning model-selection policy, which arguably belongs to the ai module or the calling feature. Worth a maintainer decision rather than a default.
Remaining tasks
- Maintainer decision: implement or remove.
- If removing, add an update hook to delete the orphaned config keys and update
README.md:16and any docs that mention routing. - If implementing, expose the keys in
MeteringSettingsForm— config-only features with no UI are effectively undiscoverable. - Either way, add a test so the dead-code state cannot recur silently.
User interface changes
If implemented, new fields in the settings form. If removed, the README feature claim goes away. No change to existing screens either way.
API changes
TokenEstimator::selectModel() is a public method on a public service. It has no in-module callers, but removing it is still an API change for any site or contrib module calling it directly — worth a deprecation cycle rather than an outright delete.
Data model changes
None. Config-only: the model_routing keys and their schema entries.
AI assistance
AI-Generated: Yes (Claude Code — multi-agent code analysis found the unreferenced method, and a follow-up pass verified the absence of any caller including dynamic dispatch; this issue text was drafted with AI assistance). No module code was generated. Every claim is code-cited and was reviewed before filing; the searches behind the absence claim can be re-run against the referenced paths.
Issue fork ai_metering-3615561
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
codeitwisely commentedComment #5
codeitwisely commentedComment #7
codeitwisely commented