Skip to content

fix(models): name provider + endpoint in anthropic_messages fallback warning#1

Merged
Kyzcreig merged 1 commit into
mainfrom
improve-anthropic-messages-warning-clarity
May 14, 2026
Merged

fix(models): name provider + endpoint in anthropic_messages fallback warning#1
Kyzcreig merged 1 commit into
mainfrom
improve-anthropic-messages-warning-clarity

Conversation

@Kyzcreig

Copy link
Copy Markdown
Owner

When /model <name> runs against an endpoint whose api_mode is anthropic_messages and that endpoint does not implement GET /v1/models, Hermes used to print a generic warning that started with "Many Anthropic-compatible proxies do not implement GET /v1/models".

That wording confused users who had just typed a non-Anthropic-looking model string (e.g. openai-codex/gpt-5.5 while still on a Claude-flavored proxy): the message implied the model was Anthropic-related when only the currently selected provider was Anthropic-shaped.

The warning now names the active provider label and the resolved endpoint explicitly:

Note: could not verify <model> against Claude API Proxy at http://127.0.0.1:18801/v1. That endpoint speaks the Anthropic Messages API, which often does not expose GET /v1/models. The model name has been accepted without verification.

Also fixes a latent shadowing bug in validate_requested_model: a later branch rebound provider_label (the module-level function) to a local string, which made the function-level name local everywhere in the function and would have raised UnboundLocalError on any earlier reference. The local var is renamed to provider_label_for_catalog.

Regression tests in tests/hermes_cli/test_anthropic_messages_warning_clarity.py pin both the new wording and the missing-base_url fallback.

…warning

The Anthropic Messages API GET /v1/models fallback warning used to read:

  Note: could not verify `<model>` against this endpoint's model listing.
  Many Anthropic-compatible proxies do not implement GET /v1/models.  The
  model name has been accepted without verification.

That wording implied the *model* was Anthropic-related, when actually the
message only describes the currently selected *provider*.  Users who typed
openai-codex/gpt-5.5 against a claude-shaped proxy got confused because the
warning sounded Anthropic-flavored even though they had just asked for an
OpenAI model.

The warning now names the active provider label and the resolved endpoint
explicitly so it is clear which side is Anthropic-shaped:

  Note: could not verify `<model>` against `Claude API Proxy` at
  http://127.0.0.1:18801/v1.  That endpoint speaks the Anthropic Messages
  API, which often does not expose GET /v1/models.  The model name has
  been accepted without verification.

Also fix a latent shadowing bug in validate_requested_model: a later branch
rebound provider_label (the module-level function) to a string, which made
the function-level name local and unreachable everywhere in the function.
The local var is renamed to provider_label_for_catalog so the function name
stays accessible.

Regression tests in tests/hermes_cli/test_anthropic_messages_warning_clarity.py
pin both the new wording and the missing-base_url fallback.
@Kyzcreig Kyzcreig merged commit a02a289 into main May 14, 2026
11 of 13 checks passed
@Kyzcreig Kyzcreig deleted the improve-anthropic-messages-warning-clarity branch May 14, 2026 03:16
@github-actions

Copy link
Copy Markdown

🔎 Lint report: improve-anthropic-messages-warning-clarity vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 8221 on HEAD, 8221 on base (➖ 0)

🆕 New issues (41):

Rule Count
invalid-argument-type 35
unresolved-attribute 5
unsupported-operator 1
First entries
run_agent.py:3450: [invalid-argument-type] invalid-argument-type: Argument to function `get_provider_stale_timeout` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown, Unknown] | int | dict[Unknown | str, Unknown | str | dict[str, str]]`
cli.py:8711: [invalid-argument-type] invalid-argument-type: Argument to function `estimate_usage_cost` is incorrect: Expected `str`, found `str | Unknown | Divergent | ... omitted 3 union elements`
run_agent.py:3450: [invalid-argument-type] invalid-argument-type: Argument to function `get_provider_stale_timeout` is incorrect: Expected `str | None`, found `str | Unknown | Divergent | ... omitted 3 union elements`
run_agent.py:6021: [unresolved-attribute] unresolved-attribute: Attribute `split` is not defined on `dict[Unknown, Unknown]`, `int`, `dict[Unknown | str, Unknown | str | dict[str, str]]` in union `str | Unknown | Divergent | ... omitted 3 union elements`
run_agent.py:7480: [invalid-argument-type] invalid-argument-type: Argument to function `build_anthropic_client` is incorrect: Expected `str`, found `str | dict[Unknown | str, Unknown | str | dict[str, str]] | Any | ... omitted 4 union elements`
run_agent.py:7926: [invalid-argument-type] invalid-argument-type: Argument to function `get_provider_request_timeout` is incorrect: Expected `str | None`, found `str | Unknown | Divergent | ... omitted 3 union elements`
run_agent.py:8715: [unresolved-attribute] unresolved-attribute: Attribute `strip` is not defined on `dict[Unknown, Unknown] & ~AlwaysFalsy`, `int & ~AlwaysFalsy`, `dict[Unknown | str, Unknown | str | dict[str, str]] & ~AlwaysFalsy` in union `Divergent | (Unknown & ~AlwaysFalsy) | (str & ~AlwaysFalsy) | ... omitted 4 union elements`
run_agent.py:13233: [invalid-argument-type] invalid-argument-type: Argument to function `estimate_usage_cost` is incorrect: Expected `str | None`, found `str | Unknown | dict[Unknown, Unknown] | int | dict[Unknown | str, Unknown | str | dict[str, str]]`
run_agent.py:10128: [unresolved-attribute] unresolved-attribute: Attribute `lower` is not defined on `dict[Unknown, Unknown] & ~AlwaysFalsy`, `int & ~AlwaysFalsy`, `dict[Unknown | str, Unknown | str | dict[str, str]] & ~AlwaysFalsy` in union `(str & ~AlwaysFalsy) | (Unknown & ~AlwaysFalsy) | (dict[Unknown, Unknown] & ~AlwaysFalsy) | ... omitted 3 union elements`
run_agent.py:4359: [invalid-argument-type] invalid-argument-type: Argument to `AIAgent.__init__` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown, Unknown] | int | dict[Unknown | str, Unknown | str | dict[str, str]]`
run_agent.py:2594: [invalid-argument-type] invalid-argument-type: Argument to function `ensure_lmstudio_model_loaded` is incorrect: Expected `str`, found `str | Unknown | Divergent | ... omitted 3 union elements`
run_agent.py:9685: [invalid-argument-type] invalid-argument-type: Argument to function `_get_anthropic_max_output` is incorrect: Expected `str`, found `str | Unknown | Divergent | ... omitted 3 union elements`
run_agent.py:13270: [invalid-argument-type] invalid-argument-type: Argument to bound method `SessionDB.update_token_counts` is incorrect: Expected `str | None`, found `str | Unknown | dict[Unknown, Unknown] | int | dict[Unknown | str, Unknown | str | dict[str, str]]`
run_agent.py:9084: [invalid-argument-type] invalid-argument-type: Argument to function `get_provider_request_timeout` is incorrect: Expected `str`, found `Divergent | Unknown | str | ... omitted 3 union elements`
run_agent.py:9877: [invalid-argument-type] invalid-argument-type: Argument to function `github_model_reasoning_efforts` is incorrect: Expected `str | None`, found `str | Unknown | Divergent | ... omitted 3 union elements`
run_agent.py:9850: [invalid-argument-type] invalid-argument-type: Argument to function `lmstudio_model_reasoning_options` is incorrect: Expected `str`, found `str | Unknown | Divergent | ... omitted 3 union elements`
run_agent.py:11708: [unresolved-attribute] unresolved-attribute: Attribute `strip` is not defined on `dict[Unknown, Unknown] & ~AlwaysFalsy`, `int & ~AlwaysFalsy`, `dict[Unknown | str, Unknown | str | dict[str, str]] & ~AlwaysFalsy` in union `(str & ~AlwaysFalsy) | (Unknown & ~AlwaysFalsy) | (dict[Unknown, Unknown] & ~AlwaysFalsy) | ... omitted 3 union elements`
run_agent.py:9277: [invalid-argument-type] invalid-argument-type: Argument to function `get_transport` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown, Unknown] | int | dict[Unknown | str, Unknown | str | dict[str, str]]`
run_agent.py:9084: [invalid-argument-type] invalid-argument-type: Argument to function `get_provider_request_timeout` is incorrect: Expected `str | None`, found `Divergent | Unknown | str | ... omitted 3 union elements`
run_agent.py:11637: [invalid-argument-type] invalid-argument-type: Argument to function `_fixed_temperature_for_model` is incorrect: Expected `str | None`, found `str | Unknown | Divergent | ... omitted 3 union elements`
run_agent.py:4948: [invalid-argument-type] invalid-argument-type: Argument to function `save_trajectory` is incorrect: Expected `str`, found `str | Unknown | Divergent | ... omitted 3 union elements`
run_agent.py:9003: [invalid-argument-type] invalid-argument-type: Argument to bound method `ContextCompressor.update_model` is incorrect: Expected `str`, found `Divergent | Unknown | str | ... omitted 3 union elements`
run_agent.py:10129: [unresolved-attribute] unresolved-attribute: Attribute `lower` is not defined on `dict[Unknown, Unknown] & ~AlwaysFalsy`, `int & ~AlwaysFalsy`, `dict[Unknown | str, Unknown | str | dict[str, str]] & ~AlwaysFalsy` in union `(str & ~AlwaysFalsy) | (Unknown & ~AlwaysFalsy) | Divergent | ... omitted 4 union elements`
run_agent.py:6021: [unsupported-operator] unsupported-operator: Operator `in` is not supported between objects of type `Literal["/"]` and `str | Unknown | Divergent | ... omitted 3 union elements`
run_agent.py:4355: [invalid-argument-type] invalid-argument-type: Argument to `AIAgent.__init__` is incorrect: Expected `str`, found `str | Unknown | Divergent | ... omitted 3 union elements`
... and 16 more

✅ Fixed issues (34):

Rule Count
invalid-argument-type 30
unresolved-attribute 3
unsupported-operator 1
First entries
run_agent.py:13270: [invalid-argument-type] invalid-argument-type: Argument to bound method `SessionDB.update_token_counts` is incorrect: Expected `str | None`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:9084: [invalid-argument-type] invalid-argument-type: Argument to function `get_provider_request_timeout` is incorrect: Expected `str | None`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:4948: [invalid-argument-type] invalid-argument-type: Argument to function `save_trajectory` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:9702: [invalid-argument-type] invalid-argument-type: Argument to function `get_provider_profile` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
cli.py:8711: [invalid-argument-type] invalid-argument-type: Argument to function `estimate_usage_cost` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:6021: [unresolved-attribute] unresolved-attribute: Attribute `split` is not defined on `dict[Unknown | str, Unknown | str | dict[str, str]]`, `int`, `dict[Unknown, Unknown]` in union `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:13736: [invalid-argument-type] invalid-argument-type: Argument to function `len` is incorrect: Expected `Sized`, found `(str & ~AlwaysFalsy) | (dict[Unknown, Unknown] & ~AlwaysFalsy) | (Any & ~AlwaysFalsy) | ... omitted 3 union elements`
run_agent.py:13967: [invalid-argument-type] invalid-argument-type: Argument to function `_pool_may_recover_from_rate_limit` is incorrect: Expected `str | None`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:13204: [invalid-argument-type] invalid-argument-type: Argument to function `save_context_length` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:12490: [invalid-argument-type] invalid-argument-type: Argument to function `apply_anthropic_cache_control` is incorrect: Expected `bool`, found `int | str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | dict[Unknown, Unknown]`
run_agent.py:9083: [invalid-argument-type] invalid-argument-type: Argument to function `build_anthropic_client` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:10129: [unresolved-attribute] unresolved-attribute: Attribute `lower` is not defined on `dict[Unknown | str, Unknown | str | dict[str, str]] & ~AlwaysFalsy`, `int & ~AlwaysFalsy`, `dict[Unknown, Unknown] & ~AlwaysFalsy` in union `(str & ~AlwaysFalsy) | (Unknown & ~AlwaysFalsy) | (dict[Unknown | str, Unknown | str | dict[str, str]] & ~AlwaysFalsy) | ... omitted 3 union elements`
run_agent.py:9877: [invalid-argument-type] invalid-argument-type: Argument to function `github_model_reasoning_efforts` is incorrect: Expected `str | None`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:6021: [unsupported-operator] unsupported-operator: Operator `in` is not supported between objects of type `Literal["/"]` and `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:11637: [invalid-argument-type] invalid-argument-type: Argument to function `_fixed_temperature_for_model` is incorrect: Expected `str | None`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:9000: [invalid-argument-type] invalid-argument-type: Argument to bound method `ContextCompressor.update_model` is incorrect: Expected `int`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:5593: [invalid-argument-type] invalid-argument-type: Argument to function `parse_rate_limit_headers` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:13233: [invalid-argument-type] invalid-argument-type: Argument to function `estimate_usage_cost` is incorrect: Expected `str | None`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:11708: [unresolved-attribute] unresolved-attribute: Attribute `strip` is not defined on `dict[Unknown | str, Unknown | str | dict[str, str]] & ~AlwaysFalsy`, `int & ~AlwaysFalsy`, `dict[Unknown, Unknown] & ~AlwaysFalsy` in union `(str & ~AlwaysFalsy) | (Unknown & ~AlwaysFalsy) | (dict[Unknown | str, Unknown | str | dict[str, str]] & ~AlwaysFalsy) | ... omitted 3 union elements`
run_agent.py:9685: [invalid-argument-type] invalid-argument-type: Argument to function `_get_anthropic_max_output` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:2594: [invalid-argument-type] invalid-argument-type: Argument to function `ensure_lmstudio_model_loaded` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:9850: [invalid-argument-type] invalid-argument-type: Argument to function `lmstudio_model_reasoning_options` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:14187: [invalid-argument-type] invalid-argument-type: Argument to bound method `ContextCompressor.update_model` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
run_agent.py:12484: [invalid-argument-type] invalid-argument-type: Argument to function `apply_anthropic_cache_control_long_lived` is incorrect: Expected `bool`, found `int | str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | dict[Unknown, Unknown]`
run_agent.py:9084: [invalid-argument-type] invalid-argument-type: Argument to function `get_provider_request_timeout` is incorrect: Expected `str`, found `str | Unknown | dict[Unknown | str, Unknown | str | dict[str, str]] | int | dict[Unknown, Unknown]`
... and 9 more

Unchanged: 4284 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

Kyzcreig added a commit that referenced this pull request Jun 4, 2026
)

* blackbox T1: per-turn usage accumulator + on_session_end turn_usage enrichment + subagent attribution + shared TurnRecord contract

* blackbox: plugin (store/cost/card/routing/commands/__init__) + diff-review fixes

Senior Opus diff-review BLOCK resolved:
- B1: /cost crashed — card.render(dict) didn't exist (only render_card(TurnRecord)).
  Added card.render() dict-or-TurnRecord facade; added real-card integration tests
  (test_commands_real_card.py) that exercise the path with NO card mock.
- B3: log inside on_session_end outer except (silent telemetry failures).
- B5: pop _sessions entry on disabled/early-return path (leak guard).
- RC6: Decimal(str(amount)) to avoid float fp drift in cost sum.
- RC9: atomic sweep — deletes + sentinel in one commit.
- RC11: routing prefers run_coroutine_threadsafe onto gateway loop (on_session_end
  runs in a worker thread); retain task refs to avoid GC.
- RC16: seam test pins real post_tool_call kwarg (tool_name), drops masking fallback.

35 blackbox+core tests green; 19 adjacent usage tests green (no regression).

* blackbox: re-review refinements (RC2/RC7) — config-aware /cost threshold, status-vocab pin tests

Focused re-review (APPROVE WITH CHANGES) follow-ups:
- card.render() threshold now reads blackbox.cost_alert_threshold_usd from config
  (falls back to turn cost) so /cost dig-in Threshold line is meaningful.
- RC7: test_cost_status_vocabulary_pinned asserts every status agent.usage_pricing
  can emit (actual/estimated/included/unknown) is handled by cost._STATUS_RANK;
  test_cost_actual_maps_to_estimated pins the actual->estimated remap.
- Verified reviewer false-positive #1 (latency_s 'missing'): it's a @Property on
  TurnRecord deriving ts_end-ts_start; real-card test renders it and passes.
37 blackbox+core tests green.

* blackbox: capture tool args/result previews into side table

The post_tool_call hook now records args/result previews (gated by
store_text) alongside tool names, populating the turn_tool_calls side
table that /cost <id> dig-in already reads. Closes the last spec gap:
the dig-in now shows per-tool args/results, not just names.

- _on_post_tool_call captures args/result via _preview (bounded, JSON-coerced)
- _build_record threads state['tool_calls'] into TurnRecord.tool_calls
- store scrubs+truncates previews before persist (already wired)
- 2 real-store seam tests: dig-in round-trip + store_text:false privacy gate

* blackbox: fix /cost registration + real-loader E2E + /cost debug

CRITICAL FIX: register() only registered hooks, never delegated to
commands.register() — so /cost would NOT exist in a live gateway despite
every unit test passing (they called handle_cost directly). The new
real-loader E2E test (test_loader_e2e.py) drives PluginManager.discover_and_load
→ invoke_hook → registered command handler and would have caught this.

E2E coverage (no mocks):
- registration: hooks + /cost wired through the real loader
- opt-in gating: not loaded without plugins.enabled
- full turn lifecycle: hooks fire → real SQLite persist → /cost renders card+dig-in
- disabled gate: hooks are no-ops

Debugging capability — /cost debug:
- store.debug_stats(): DB path/size, turn/tool/alerted/subagent counts,
  ts range, last sweep date (read-only, never raises)
- _handle_debug: config gate state + resolved channel + store health, so
  'why no cards?' is self-diagnosable in-session
- plugin.yaml: declare provides_commands: [cost]

48 blackbox+core green; 110 adjacent plugin-loader tests green (no regression).

---------

Co-authored-by: Kyzcreig <9063726+Kyzcreig@users.noreply.github.com>
Kyzcreig added a commit that referenced this pull request Jun 5, 2026
)

* blackbox T1: per-turn usage accumulator + on_session_end turn_usage enrichment + subagent attribution + shared TurnRecord contract

* blackbox: plugin (store/cost/card/routing/commands/__init__) + diff-review fixes

Senior Opus diff-review BLOCK resolved:
- B1: /cost crashed — card.render(dict) didn't exist (only render_card(TurnRecord)).
  Added card.render() dict-or-TurnRecord facade; added real-card integration tests
  (test_commands_real_card.py) that exercise the path with NO card mock.
- B3: log inside on_session_end outer except (silent telemetry failures).
- B5: pop _sessions entry on disabled/early-return path (leak guard).
- RC6: Decimal(str(amount)) to avoid float fp drift in cost sum.
- RC9: atomic sweep — deletes + sentinel in one commit.
- RC11: routing prefers run_coroutine_threadsafe onto gateway loop (on_session_end
  runs in a worker thread); retain task refs to avoid GC.
- RC16: seam test pins real post_tool_call kwarg (tool_name), drops masking fallback.

35 blackbox+core tests green; 19 adjacent usage tests green (no regression).

* blackbox: re-review refinements (RC2/RC7) — config-aware /cost threshold, status-vocab pin tests

Focused re-review (APPROVE WITH CHANGES) follow-ups:
- card.render() threshold now reads blackbox.cost_alert_threshold_usd from config
  (falls back to turn cost) so /cost dig-in Threshold line is meaningful.
- RC7: test_cost_status_vocabulary_pinned asserts every status agent.usage_pricing
  can emit (actual/estimated/included/unknown) is handled by cost._STATUS_RANK;
  test_cost_actual_maps_to_estimated pins the actual->estimated remap.
- Verified reviewer false-positive #1 (latency_s 'missing'): it's a @Property on
  TurnRecord deriving ts_end-ts_start; real-card test renders it and passes.
37 blackbox+core tests green.

* blackbox: capture tool args/result previews into side table

The post_tool_call hook now records args/result previews (gated by
store_text) alongside tool names, populating the turn_tool_calls side
table that /cost <id> dig-in already reads. Closes the last spec gap:
the dig-in now shows per-tool args/results, not just names.

- _on_post_tool_call captures args/result via _preview (bounded, JSON-coerced)
- _build_record threads state['tool_calls'] into TurnRecord.tool_calls
- store scrubs+truncates previews before persist (already wired)
- 2 real-store seam tests: dig-in round-trip + store_text:false privacy gate

* blackbox: fix /cost registration + real-loader E2E + /cost debug

CRITICAL FIX: register() only registered hooks, never delegated to
commands.register() — so /cost would NOT exist in a live gateway despite
every unit test passing (they called handle_cost directly). The new
real-loader E2E test (test_loader_e2e.py) drives PluginManager.discover_and_load
→ invoke_hook → registered command handler and would have caught this.

E2E coverage (no mocks):
- registration: hooks + /cost wired through the real loader
- opt-in gating: not loaded without plugins.enabled
- full turn lifecycle: hooks fire → real SQLite persist → /cost renders card+dig-in
- disabled gate: hooks are no-ops

Debugging capability — /cost debug:
- store.debug_stats(): DB path/size, turn/tool/alerted/subagent counts,
  ts range, last sweep date (read-only, never raises)
- _handle_debug: config gate state + resolved channel + store health, so
  'why no cards?' is self-diagnosable in-session
- plugin.yaml: declare provides_commands: [cost]

48 blackbox+core green; 110 adjacent plugin-loader tests green (no regression).

---------

Co-authored-by: Kyzcreig <9063726+Kyzcreig@users.noreply.github.com>
Sign up for free to 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