Skip to content

fix(agent): classify model status from the live catalog - #7123

Open
Drchennnn wants to merge 1 commit into
amd:mainfrom
Drchennnn:fix/7105-model-status-catalog-20261110
Open

Drchennnn wants to merge 1 commit into
amd:mainfrom
Drchennnn:fix/7105-model-status-catalog-20261110

Conversation

@Drchennnn

Copy link
Copy Markdown
Contributor

Summary

Custom-ID cloud models now report remote inference after a /model switch, so the terminal header can agree with the provider notice. Live TUI verification remains outstanding.

Why

A catalog-defined Fireworks or AMD model can have a custom.* ID. Classifying that ID by its prefix incorrectly tells the terminal that the conversation is local.

Linked issue

Closes #7105

Changes

  • Reuse the inference-location resolver with the live client's cached catalog classifier, without adding catalog requests.
  • Cover custom Fireworks/AMD IDs, cloud→local→cloud switching, dotted local IDs and known provider prefixes, and update the flagship changelog.
  • The same status also controls warm-up, so catalog-defined cloud models now skip remote priming. Normal chat inference and model selection are unchanged.

AI assistance was used. Codex applied the supplied patch, inspected the implementation, ran the Mac checks, and obtained a separate read-only code review. The account owner authorized submission after the missing live-TUI evidence and incomplete full-unit run were reported.

Test plan

  • On current main with only the regression tests added, python -m pytest hub/agents/gaia/python/tests/test_stdio.py -k model_status_ -q produced 3 failed and 4 passed. With the fix, all 7 passed.
  • Mac arm64, Python 3.12.14, the following suite passed all 339 tests.
python -m pytest \
  hub/agents/gaia/python/tests/test_stdio.py \
  hub/agents/gaia/python/tests/test_stdio_lemonade_reconnect.py \
  hub/agents/gaia/python/tests/test_compact_tier.py \
  hub/agents/gaia/python/tests/test_lemonade_start_hint.py \
  hub/agents/gaia/python/tests/test_stdio_wire_contract.py \
  tests/unit/test_inference_location.py \
  tests/unit/test_lemonade_cloud_classification.py \
  tests/unit/test_lemonade_cloud_models.py -q
  • Mac python util/lint.py --all exited 0 with 17 checks passed, zero failed and one non-blocking MyPy warning category. Black, pinned isort 8.0.1, Flake8, changed-production Pylint errors-only, compileall, the actual added-lines guard and git diff --check passed.
  • The full python -m pytest tests/unit/ -q -x run was deliberately interrupted when the live-E2E submission gap was identified. It had 3827 passed and 70 skipped, exited 2, and provides no full-suite pass.
  • Exercise /model custom… in a real TUI with a catalog-defined cloud model and confirm its header reports remote and agrees with the provider notice.
Earlier cloud records and environment notes

The supplied archive used base 7e5853ff and recorded 320 related tests passed, full-unit first failure with 1 failed/46 passed/66 skipped, and aggregate lint with 15 passed/2 failed/1 warning. Its first unit failure reproduced on that exact clean base. Those are historical cloud results, separate from this Mac run and future GitHub CI. The cloud-failing test passed individually against current-main production source on this Mac.

Tests used isolated writable homes. An initial Mac resubmission run stopped in collection because editable imports no longer resolved. Re-registering this checkout's two editable packages restored imports, after which the full 339-test command above passed. The source patch was unchanged.

Evidence

  • Agent exposed in the Agent UI — N/A for this change. The changed status payload belongs to the TUI's stdio transport.
  • MCP tools / servers — N/A, no MCP surface changed.
  • CLI / TUI — real terminal evidence remains missing. Current tests use synthetic catalogs and an HTTP-boundary fixture, plus the wire-contract suite. No live Lemonade/cloud inference, rendered TUI, AMD GPU/NPU hardware or packaged application was exercised.
  • HTTP API / REST — N/A, the HTTP contract was unchanged.

Checklist

  • I have linked a GitHub issue above.
  • I have described why this change is being made.
  • I have run linting and tests locally. Lint and focused tests passed, but the full unit suite is incomplete as detailed above.
  • I have attached real-world evidence matched to the surface I changed. The live TUI evidence remains outstanding.
  • I have updated documentation for the user-visible fix in the flagship changelog.

@github-actions

Copy link
Copy Markdown
Contributor

Verdict: Approve with suggestions

After a /model switch, a cloud model whose ID doesn't start with fireworks. or amd. (for example custom.gemma-4-31b-it) showed as local in the terminal header, even though the switch notice called it cloud. The header now looks the model up in the catalog the agent already holds, the same way the notice does, so the two agree. The fix is small, adds no network calls, and the tests cover the cases that matter. Nothing blocks the merge. The one gap is that nobody has yet looked at a real TUI after a switch, as the author notes.

Side effect, which is correct: because warm-up reads the same status, these cloud models now skip local warm-up, as cloud models already did.

Real-world evidence

N/A: no evidence bundle was produced for this run (this is a fork PR). The verdict rests on static review. The author's PR body says the same: no live TUI or cloud model was exercised. The status classifier is a pure catalog lookup with no request, so the risk is low, but a screenshot of the header after /model custom.… against a catalog-defined cloud model would close the open Test plan item.

🔍 Technical details

Issues found

🟢 The switch path classifies the model twice (hub/agents/gaia/python/gaia_agent/stdio.py:1061-1072). _switch_model writes _model_state_event(agent), then repeats the same getattr(... "cloud_model_provider") + resolve_inference_location(...) block for the notice. Pulling it into one helper, such as _inference_location(agent) used by both, would stop the header and the notice drifting apart again, which is the bug this PR fixes. Both copies match today, so this is optional.

Checks run

  • LemonadeClient.cloud_model_provider (src/gaia/llm/lemonade_client.py:7682) reads only _model_metadata and the id prefix and makes no HTTP call. That makes it safe on the startup ping (stdio.py:1930) and in run_warm_up (stdio.py:1689), and assert lemonade_http == [] pins it.
  • _ask in inference_location.py rejects a lookup that returns something other than a string, and a None or non-callable llm_client falls back to the prefix rule. A non-Lemonade client can't crash the status event.
  • The TUI's providerOfBackend already passes through any non-lemonade backend name, so model_backend: "fireworks" for a custom.* ID needs no Go change.
  • user.* and dotted local IDs without cloud catalog metadata still resolve to lemonade, which the parametrized test covers.
  • Docs: no README, SPEC or SKILL text describes the model_backend classification, so the CHANGELOG entry under [Unreleased] is the only doc that needed updating. I couldn't run the tests here because pytest isn't installed on this runner. The author reports 7/7 targeted and 339 related tests passing.

Strengths

  • It reuses the existing resolve_inference_location resolver instead of adding a third classifier.
  • The regression test switches cloud → local → cloud and asserts that the header status and the (cloud) notice agree each time, which is the user-visible contract.

This branch has not been deployed

No deployments
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.

The status sent after /model calls a custom.-prefixed cloud model local

1 participant