fix select boxes of models #105

Closed
opened 2026-06-10 11:51:51 +00:00 by salmaelsoly · 3 comments
Member
No description provided.
Author
Member

Implementation Spec for Issue #105

Objective

Make the model select boxes in the Hero Shrimp web UI show the models actually configured in the daemon's model catalog (the models: section of shrimp.yml, plus bundled defaults), instead of a hardcoded six-entry list, so operators can correctly choose a model that the router can actually resolve.

Current Behavior

  1. crates/hero_shrimp_web/ui/src/components/SettingsModal.tsx:27-30 — the per-phase model inputs get their suggestions from a hardcoded KNOWN_MODELS array (deepseek-v4-flash, deepseek-v4-pro, kimi-2.6, qwen-3.6-plus, mercury-2, minimax-m2.7). When the operator changes the models: catalog in shrimp.yml, the suggestions no longer match anything configured, and picking one writes an unresolvable alias into llm.routing.<phase>.
  2. crates/hero_shrimp_web/ui/src/components/CrewPage.tsx:470-478 — the hire-agent "Model" field is a plain text input with no suggestions at all.
  3. Backend gap: method_config_get in crates/hero_shrimp_server/src/rpc/methods/admin.rs never exposes the configured catalog, so the UI has nothing real to populate from. The authoritative source is hero_shrimp_runtime::global_catalog() (a ModelCatalog set at daemon boot and on live reloads).

Requirements

  • The config.get RPC response gains a models array listing every configured catalog entry (alias plus light metadata: tier, ctx, caps), in alphabetical order.
  • The Settings modal per-phase model datalist is populated from that array; the hardcoded list remains only as a fallback when the daemon reports no catalog.
  • The Crew hire modal "Model" field gets the same configured-model suggestions via a datalist.
  • Free-text entry remains allowed everywhere (ModelCatalog::resolve accepts provider/model[@backend] strings), so the inputs stay datalist-backed combo boxes rather than strict selects.
  • No restart needed: the list reflects the running daemon's catalog at modal-open time (SettingsModal already refetches config.get).
  • A backend unit test asserts the models field is present and well-formed.
  • The committed UI bundle under crates/hero_shrimp_web/static/assets/ is rebuilt.

Files to Modify

  • crates/hero_shrimp_server/src/rpc/methods/admin.rs - extend method_config_get to emit a models array from global_catalog()
  • crates/hero_shrimp_server/src/rpc/jsonrpc/tests/chunk_2.rs - test for the new models field
  • crates/hero_shrimp_web/ui/src/store.ts - add a configuredModels signal populated in loadConfig()
  • crates/hero_shrimp_web/ui/src/components/SettingsModal.tsx - populate the known-models datalist from configured models
  • crates/hero_shrimp_web/ui/src/components/CrewPage.tsx - attach a configured-models datalist to the hire-modal Model input
  • crates/hero_shrimp_web/static/assets/* - regenerated build artifacts (npm run build)

Implementation Plan

Step 1: Expose configured models through config.get

Files: crates/hero_shrimp_server/src/rpc/methods/admin.rs

  • In method_config_get, read hero_shrimp_runtime::global_catalog() and map each entry to { alias, tier, ctx, caps }.
  • Add "models": models to the JSON response. Keep the payload small (no serve or pricing metadata). No secrets involved.
    Dependencies: none

Step 2: Backend test

Files: crates/hero_shrimp_server/src/rpc/jsonrpc/tests/chunk_2.rs

  • Add a test that sets the global catalog to the default catalog, invokes method_config_get, and asserts config["models"] is a non-empty array whose elements each have a non-empty string alias. Assert shape only (globals are process-wide and tests run in parallel).
    Dependencies: Step 1

Step 3: Share configured models in the web store

Files: crates/hero_shrimp_web/ui/src/store.ts

  • Add export const [configuredModels, setConfiguredModels] = createSignal<string[]>([]).
  • In loadConfig(), populate it from the models array of the config.get response. loadConfig() already runs at boot and after every settings save, so the list stays fresh.
    Dependencies: Step 1

Step 4: Populate the Settings modal datalist from configuration

Files: crates/hero_shrimp_web/ui/src/components/SettingsModal.tsx

  • Rename KNOWN_MODELS to FALLBACK_MODELS and use it only when the config resource reports no catalog.
  • Derive the datalist options from the modal's own config.get resource (it refetches on save), falling back to FALLBACK_MODELS when empty.
  • Keep the inputs as datalist combo boxes so free text stays legal.
    Dependencies: Step 1

Step 5: Add the configured-models datalist to the Crew hire modal

Files: crates/hero_shrimp_web/ui/src/components/CrewPage.tsx

  • Import configuredModels from the store, render a <datalist id="crew-known-models"> next to the hire-modal Model input, and set list="crew-known-models" on it. Keep placeholder and free-text behavior (empty = inherit from cascade).
    Dependencies: Step 3

Step 6: Rebuild the committed UI bundle and verify

Files: crates/hero_shrimp_web/static/assets/*

  • Run npm run build in crates/hero_shrimp_web/ui/ and commit the regenerated assets.
  • Run cargo check and cargo test -p hero_shrimp_server.
  • Manual check: with a shrimp.yml whose models: list differs from the defaults, the Settings and Crew hire model inputs must suggest exactly the configured aliases.
    Dependencies: Steps 1-5

Acceptance Criteria

  • config.get response contains a models array with one object per configured catalog entry (alias, tier, ctx, caps), reflecting shrimp.yml overrides.
  • Settings modal model suggestions exactly match the configured catalog aliases; the hardcoded list appears only when the daemon reports no catalog.
  • Crew hire modal Model field offers the same configured-model suggestions.
  • Free-text model entry (e.g. anthropic/claude-opus-4@openrouter) still works in both places.
  • Selecting a suggested model and saving persists after modal refetch.
  • cargo test -p hero_shrimp_server passes, including the new models field test.
  • Regenerated UI bundle is committed and served.

Notes

  • The model inputs deliberately stay datalist-backed combo inputs instead of strict <select> elements, because ModelCatalog::resolve accepts non-catalog provider/model[@backend] strings and the existing UI promises free text.
  • Extending config.get is preferred over a new models.list RPC because SettingsModal already consumes config.get with refetch-on-save, and it avoids new method and auth wiring.
  • global_catalog() is updated on live reload paths, so the list stays consistent with active routing without plumbing a catalog parameter through.
## Implementation Spec for Issue #105 ### Objective Make the model select boxes in the Hero Shrimp web UI show the models actually configured in the daemon's model catalog (the `models:` section of `shrimp.yml`, plus bundled defaults), instead of a hardcoded six-entry list, so operators can correctly choose a model that the router can actually resolve. ### Current Behavior 1. `crates/hero_shrimp_web/ui/src/components/SettingsModal.tsx:27-30` — the per-phase model inputs get their suggestions from a hardcoded `KNOWN_MODELS` array (`deepseek-v4-flash`, `deepseek-v4-pro`, `kimi-2.6`, `qwen-3.6-plus`, `mercury-2`, `minimax-m2.7`). When the operator changes the `models:` catalog in `shrimp.yml`, the suggestions no longer match anything configured, and picking one writes an unresolvable alias into `llm.routing.<phase>`. 2. `crates/hero_shrimp_web/ui/src/components/CrewPage.tsx:470-478` — the hire-agent "Model" field is a plain text input with no suggestions at all. 3. Backend gap: `method_config_get` in `crates/hero_shrimp_server/src/rpc/methods/admin.rs` never exposes the configured catalog, so the UI has nothing real to populate from. The authoritative source is `hero_shrimp_runtime::global_catalog()` (a `ModelCatalog` set at daemon boot and on live reloads). ### Requirements - The `config.get` RPC response gains a `models` array listing every configured catalog entry (alias plus light metadata: tier, ctx, caps), in alphabetical order. - The Settings modal per-phase model datalist is populated from that array; the hardcoded list remains only as a fallback when the daemon reports no catalog. - The Crew hire modal "Model" field gets the same configured-model suggestions via a datalist. - Free-text entry remains allowed everywhere (`ModelCatalog::resolve` accepts `provider/model[@backend]` strings), so the inputs stay datalist-backed combo boxes rather than strict selects. - No restart needed: the list reflects the running daemon's catalog at modal-open time (SettingsModal already refetches `config.get`). - A backend unit test asserts the `models` field is present and well-formed. - The committed UI bundle under `crates/hero_shrimp_web/static/assets/` is rebuilt. ### Files to Modify - `crates/hero_shrimp_server/src/rpc/methods/admin.rs` - extend `method_config_get` to emit a `models` array from `global_catalog()` - `crates/hero_shrimp_server/src/rpc/jsonrpc/tests/chunk_2.rs` - test for the new `models` field - `crates/hero_shrimp_web/ui/src/store.ts` - add a `configuredModels` signal populated in `loadConfig()` - `crates/hero_shrimp_web/ui/src/components/SettingsModal.tsx` - populate the `known-models` datalist from configured models - `crates/hero_shrimp_web/ui/src/components/CrewPage.tsx` - attach a configured-models datalist to the hire-modal Model input - `crates/hero_shrimp_web/static/assets/*` - regenerated build artifacts (`npm run build`) ### Implementation Plan #### Step 1: Expose configured models through `config.get` Files: `crates/hero_shrimp_server/src/rpc/methods/admin.rs` - In `method_config_get`, read `hero_shrimp_runtime::global_catalog()` and map each entry to `{ alias, tier, ctx, caps }`. - Add `"models": models` to the JSON response. Keep the payload small (no `serve` or pricing metadata). No secrets involved. Dependencies: none #### Step 2: Backend test Files: `crates/hero_shrimp_server/src/rpc/jsonrpc/tests/chunk_2.rs` - Add a test that sets the global catalog to the default catalog, invokes `method_config_get`, and asserts `config["models"]` is a non-empty array whose elements each have a non-empty string `alias`. Assert shape only (globals are process-wide and tests run in parallel). Dependencies: Step 1 #### Step 3: Share configured models in the web store Files: `crates/hero_shrimp_web/ui/src/store.ts` - Add `export const [configuredModels, setConfiguredModels] = createSignal<string[]>([])`. - In `loadConfig()`, populate it from the `models` array of the `config.get` response. `loadConfig()` already runs at boot and after every settings save, so the list stays fresh. Dependencies: Step 1 #### Step 4: Populate the Settings modal datalist from configuration Files: `crates/hero_shrimp_web/ui/src/components/SettingsModal.tsx` - Rename `KNOWN_MODELS` to `FALLBACK_MODELS` and use it only when the config resource reports no catalog. - Derive the datalist options from the modal's own `config.get` resource (it refetches on save), falling back to `FALLBACK_MODELS` when empty. - Keep the inputs as datalist combo boxes so free text stays legal. Dependencies: Step 1 #### Step 5: Add the configured-models datalist to the Crew hire modal Files: `crates/hero_shrimp_web/ui/src/components/CrewPage.tsx` - Import `configuredModels` from the store, render a `<datalist id="crew-known-models">` next to the hire-modal Model input, and set `list="crew-known-models"` on it. Keep placeholder and free-text behavior (empty = inherit from cascade). Dependencies: Step 3 #### Step 6: Rebuild the committed UI bundle and verify Files: `crates/hero_shrimp_web/static/assets/*` - Run `npm run build` in `crates/hero_shrimp_web/ui/` and commit the regenerated assets. - Run `cargo check` and `cargo test -p hero_shrimp_server`. - Manual check: with a `shrimp.yml` whose `models:` list differs from the defaults, the Settings and Crew hire model inputs must suggest exactly the configured aliases. Dependencies: Steps 1-5 ### Acceptance Criteria - [ ] `config.get` response contains a `models` array with one object per configured catalog entry (`alias`, `tier`, `ctx`, `caps`), reflecting `shrimp.yml` overrides. - [ ] Settings modal model suggestions exactly match the configured catalog aliases; the hardcoded list appears only when the daemon reports no catalog. - [ ] Crew hire modal Model field offers the same configured-model suggestions. - [ ] Free-text model entry (e.g. `anthropic/claude-opus-4@openrouter`) still works in both places. - [ ] Selecting a suggested model and saving persists after modal refetch. - [ ] `cargo test -p hero_shrimp_server` passes, including the new `models` field test. - [ ] Regenerated UI bundle is committed and served. ### Notes - The model inputs deliberately stay datalist-backed combo inputs instead of strict `<select>` elements, because `ModelCatalog::resolve` accepts non-catalog `provider/model[@backend]` strings and the existing UI promises free text. - Extending `config.get` is preferred over a new `models.list` RPC because SettingsModal already consumes `config.get` with refetch-on-save, and it avoids new method and auth wiring. - `global_catalog()` is updated on live reload paths, so the list stays consistent with active routing without plumbing a catalog parameter through.
Author
Member

Test Results

cargo test -p hero_shrimp_server on branch integration_fix_model_select_boxes

  • Total: 308
  • Passed: 305
  • Failed: 0
  • Ignored: 3

The new test config_get_includes_model_catalog verifies the models array in the config.get response.

## Test Results `cargo test -p hero_shrimp_server` on branch `integration_fix_model_select_boxes` - Total: 308 - Passed: 305 - Failed: 0 - Ignored: 3 The new test `config_get_includes_model_catalog` verifies the `models` array in the `config.get` response.
Author
Member

Implementation Summary

All changes are on branch integration_fix_model_select_boxes (based on integration).

Changes

  • crates/hero_shrimp_server/src/rpc/methods/admin.rsmethod_config_get now emits a models array sourced from the global model catalog (hero_shrimp_runtime::global_catalog()). Each entry carries alias, tier, ctx, and caps, sorted alphabetically by alias. Empty array when no catalog is loaded.
  • crates/hero_shrimp_server/src/rpc/jsonrpc/tests/chunk_2.rs — new test config_get_includes_model_catalog asserting the models field is a non-empty array whose entries each have a non-empty alias.
  • crates/hero_shrimp_web/ui/src/store.ts — new shared configuredModels signal, populated in loadConfig() from the models field; refreshed at boot and after every settings save.
  • crates/hero_shrimp_web/ui/src/components/SettingsModal.tsx — the per-phase model inputs' datalist is now populated from the configured catalog reported by config.get; the old hardcoded list remains only as FALLBACK_MODELS for daemons that report no catalog. Inputs stay datalist-backed combo boxes, so free-text provider/model[@backend] entries remain valid.
  • crates/hero_shrimp_web/ui/src/components/CrewPage.tsx — the hire-agent Model field now offers the same configured-model suggestions via a crew-known-models datalist; free text and empty-means-inherit behavior unchanged.
  • crates/hero_shrimp_web/static/ — UI bundle rebuilt (app.D5h1qBfB.js); regenerated artifacts committed.

Test Results

cargo test -p hero_shrimp_server: 308 total — 305 passed, 0 failed, 3 ignored (pre-existing ignored doc-tests).

Notes

  • The select boxes now always reflect the running daemon's active catalog (shrimp.yml models: section plus bundled defaults), including after live config reloads, with no restart needed.
  • A strict select element was deliberately avoided because the router accepts non-catalog provider/model[@backend] strings.
## Implementation Summary All changes are on branch `integration_fix_model_select_boxes` (based on `integration`). ### Changes - `crates/hero_shrimp_server/src/rpc/methods/admin.rs` — `method_config_get` now emits a `models` array sourced from the global model catalog (`hero_shrimp_runtime::global_catalog()`). Each entry carries `alias`, `tier`, `ctx`, and `caps`, sorted alphabetically by alias. Empty array when no catalog is loaded. - `crates/hero_shrimp_server/src/rpc/jsonrpc/tests/chunk_2.rs` — new test `config_get_includes_model_catalog` asserting the `models` field is a non-empty array whose entries each have a non-empty `alias`. - `crates/hero_shrimp_web/ui/src/store.ts` — new shared `configuredModels` signal, populated in `loadConfig()` from the `models` field; refreshed at boot and after every settings save. - `crates/hero_shrimp_web/ui/src/components/SettingsModal.tsx` — the per-phase model inputs' datalist is now populated from the configured catalog reported by `config.get`; the old hardcoded list remains only as `FALLBACK_MODELS` for daemons that report no catalog. Inputs stay datalist-backed combo boxes, so free-text `provider/model[@backend]` entries remain valid. - `crates/hero_shrimp_web/ui/src/components/CrewPage.tsx` — the hire-agent Model field now offers the same configured-model suggestions via a `crew-known-models` datalist; free text and empty-means-inherit behavior unchanged. - `crates/hero_shrimp_web/static/` — UI bundle rebuilt (`app.D5h1qBfB.js`); regenerated artifacts committed. ### Test Results `cargo test -p hero_shrimp_server`: 308 total — 305 passed, 0 failed, 3 ignored (pre-existing ignored doc-tests). ### Notes - The select boxes now always reflect the running daemon's active catalog (`shrimp.yml` `models:` section plus bundled defaults), including after live config reloads, with no restart needed. - A strict select element was deliberately avoided because the router accepts non-catalog `provider/model[@backend]` strings.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_shrimp#105
No description provided.