feat(dashboard): model switch UI per instance #157

Merged
code-lead merged 1 commit from dev/156 into main 2026-04-20 15:38:33 +00:00
Collaborator

Summary

  • Update the edit-agent modal model dropdown to the canonical list: claude-opus-4-7, claude-opus-4-7[1m], claude-sonnet-4-6, claude-sonnet-4-6[1m], claude-haiku-4-5-20251001, "Use type default"
  • Override badge () already renders in the agents table when model_override is set — verified working
  • PATCH /agents/:name with { model } and reconcileOne call already correct — no container recreation (model is per-dispatch)
  • Add main-agents.test.ts test: PATCH model → GET /agents returns correct resolved model and flags model_override
  • Add dashboard-browser.test.ts tests: dropdown has all canonical options; edit modal PATCH submission sends correct model value

Closes #156

## Summary - Update the edit-agent modal model dropdown to the canonical list: `claude-opus-4-7`, `claude-opus-4-7[1m]`, `claude-sonnet-4-6`, `claude-sonnet-4-6[1m]`, `claude-haiku-4-5-20251001`, "Use type default" - Override badge (`✎`) already renders in the agents table when `model_override` is set — verified working - `PATCH /agents/:name` with `{ model }` and `reconcileOne` call already correct — no container recreation (model is per-dispatch) - Add `main-agents.test.ts` test: PATCH model → GET /agents returns correct resolved model and flags `model_override` - Add `dashboard-browser.test.ts` tests: dropdown has all canonical options; edit modal PATCH submission sends correct model value Closes #156
feat(dashboard): model switch UI per instance (#156)
All checks were successful
qa / qa (pull_request) Successful in 3m4s
qa / dockerfile (pull_request) Successful in 9s
b8fb797da4
Update edit-agent modal model dropdown to the canonical model list
(claude-opus-4-7, claude-opus-4-7[1m], claude-sonnet-4-6,
claude-sonnet-4-6[1m], claude-haiku-4-5-20251001, "Use type default").
Override badge already rendered when model_override is set.

Add tests: PATCH→GET resolved model round-trip (main-agents), and
browser smoke tests for dropdown options and edit-form PATCH submission.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dev requested review from reviewer 2026-04-20 15:30:33 +00:00
reviewer approved these changes 2026-04-20 15:34:44 +00:00
Dismissed
reviewer left a comment

Review: feat(dashboard): model switch UI per instance

CI: Green (run #1745, 3m13s)

Acceptance criteria check

Criterion Status
Model dropdown has all 5 canonical models + "Use type default" dashboard.html lines 1374–1380
Override badge () shows when model_override is set renderAgentsTable line 2542
PATCH /agents/:name accepts `{ model: string null }`
null clears the override back to type default tested in main-agents.test.ts
No container recreation on model PATCH model is per-dispatch, reconcileOne does not recreate
main-agents.test.ts — PATCH model → GET reflects resolved model + override flag "PATCH with model — GET /agents reflects resolved model immediately"
dashboard-browser.test.ts — dropdown has all canonical options "model dropdown contains all canonical options"
dashboard-browser.test.ts — edit form PATCH sends correct model "submitting the edit form with model change triggers PATCH /agents/:name"

Code review

openEditModal correctly pre-selects the override (or \x27\x27 for "Use type default"):

document.getElementById('agentModel').value = agent.model_override || '';

submitAgentModal converts empty string → null before sending:

const model = document.getElementById('agentModel').value || null;

This is the right semantics — null in the PATCH body clears the override server-side.

The agentModelHint showing Type default: claude-sonnet-4-6 is a nice operator UX touch.

Minor nit (non-blocking)

src/dashboard-browser.test.tsSAMPLE_AGENT.model_override is set to false:

const SAMPLE_AGENT = {
  
  model_override: false,   // ← real API returns null
  
};

The real API returns null for no override (verified in main-agents.test.ts: expect(entry.model_override).toBeNull()). Both null and false are falsy so this does not break anything, but the fixture should match the actual API shape to avoid confusion in future tests.

## Review: feat(dashboard): model switch UI per instance **CI:** ✅ Green (run #1745, 3m13s) ### Acceptance criteria check | Criterion | Status | |---|---| | Model dropdown has all 5 canonical models + "Use type default" | ✅ `dashboard.html` lines 1374–1380 | | Override badge (`✎`) shows when `model_override` is set | ✅ `renderAgentsTable` line 2542 | | `PATCH /agents/:name` accepts `{ model: string | null }` | ✅ existing handler, tested | | `null` clears the override back to type default | ✅ tested in `main-agents.test.ts` | | No container recreation on model PATCH | ✅ model is per-dispatch, `reconcileOne` does not recreate | | `main-agents.test.ts` — PATCH model → GET reflects resolved model + override flag | ✅ "PATCH with model — GET /agents reflects resolved model immediately" | | `dashboard-browser.test.ts` — dropdown has all canonical options | ✅ "model dropdown contains all canonical options" | | `dashboard-browser.test.ts` — edit form PATCH sends correct model | ✅ "submitting the edit form with model change triggers PATCH /agents/:name" | ### Code review `openEditModal` correctly pre-selects the override (or `\x27\x27` for "Use type default"): ```js document.getElementById('agentModel').value = agent.model_override || ''; ``` `submitAgentModal` converts empty string → `null` before sending: ```js const model = document.getElementById('agentModel').value || null; ``` This is the right semantics — `null` in the PATCH body clears the override server-side. The `agentModelHint` showing `Type default: claude-sonnet-4-6` is a nice operator UX touch. ### Minor nit (non-blocking) `src/dashboard-browser.test.ts` — `SAMPLE_AGENT.model_override` is set to `false`: ```ts const SAMPLE_AGENT = { … model_override: false, // ← real API returns null … }; ``` The real API returns `null` for no override (verified in `main-agents.test.ts`: `expect(entry.model_override).toBeNull()`). Both `null` and `false` are falsy so this does not break anything, but the fixture should match the actual API shape to avoid confusion in future tests.
reviewer approved these changes 2026-04-20 15:34:53 +00:00
reviewer left a comment

Review: feat(dashboard): model switch UI per instance

CI: Green (run #1745, 3m13s)

Acceptance criteria check

Criterion Status
Model dropdown has all 5 canonical models + "Use type default" dashboard.html lines 1374–1380
Override badge () shows when model_override is set renderAgentsTable line 2542
PATCH /agents/:name accepts `{ model: string null }`
null clears the override back to type default tested in main-agents.test.ts
No container recreation on model PATCH model is per-dispatch, reconcileOne does not recreate
main-agents.test.ts — PATCH model → GET reflects resolved model + override flag "PATCH with model — GET /agents reflects resolved model immediately"
dashboard-browser.test.ts — dropdown has all canonical options "model dropdown contains all canonical options"
dashboard-browser.test.ts — edit form PATCH sends correct model "submitting the edit form with model change triggers PATCH /agents/:name"

Code review

openEditModal correctly pre-selects the override (or '' for "Use type default"):

document.getElementById('agentModel').value = agent.model_override || '';

submitAgentModal converts empty string → null before sending:

const model = document.getElementById('agentModel').value || null;

This is the right semantics — null in the PATCH body clears the override server-side.

The agentModelHint showing Type default: claude-sonnet-4-6 is a nice operator UX touch.

Minor nit (non-blocking)

src/dashboard-browser.test.tsSAMPLE_AGENT.model_override is set to false:

const SAMPLE_AGENT = {
  
  model_override: false,   // ← real API returns null
  
};

The real API returns null for no override (verified in main-agents.test.ts: expect(entry.model_override).toBeNull()). Both null and false are falsy so this does not break anything, but the fixture should match the actual API shape to avoid confusion in future tests.

## Review: feat(dashboard): model switch UI per instance **CI:** ✅ Green (run #1745, 3m13s) ### Acceptance criteria check | Criterion | Status | |---|---| | Model dropdown has all 5 canonical models + "Use type default" | ✅ `dashboard.html` lines 1374–1380 | | Override badge (`✎`) shows when `model_override` is set | ✅ `renderAgentsTable` line 2542 | | `PATCH /agents/:name` accepts `{ model: string | null }` | ✅ existing handler, tested | | `null` clears the override back to type default | ✅ tested in `main-agents.test.ts` | | No container recreation on model PATCH | ✅ model is per-dispatch, `reconcileOne` does not recreate | | `main-agents.test.ts` — PATCH model → GET reflects resolved model + override flag | ✅ "PATCH with model — GET /agents reflects resolved model immediately" | | `dashboard-browser.test.ts` — dropdown has all canonical options | ✅ "model dropdown contains all canonical options" | | `dashboard-browser.test.ts` — edit form PATCH sends correct model | ✅ "submitting the edit form with model change triggers PATCH /agents/:name" | ### Code review `openEditModal` correctly pre-selects the override (or `''` for "Use type default"): ```js document.getElementById('agentModel').value = agent.model_override || ''; ``` `submitAgentModal` converts empty string → `null` before sending: ```js const model = document.getElementById('agentModel').value || null; ``` This is the right semantics — `null` in the PATCH body clears the override server-side. The `agentModelHint` showing `Type default: claude-sonnet-4-6` is a nice operator UX touch. ### Minor nit (non-blocking) `src/dashboard-browser.test.ts` — `SAMPLE_AGENT.model_override` is set to `false`: ```ts const SAMPLE_AGENT = { … model_override: false, // ← real API returns null … }; ``` The real API returns `null` for no override (verified in `main-agents.test.ts`: `expect(entry.model_override).toBeNull()`). Both `null` and `false` are falsy so this does not break anything, but the fixture should match the actual API shape to avoid confusion in future tests.
code-lead deleted branch dev/156 2026-04-20 15:38:34 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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
charles/claude-hooks!157
No description provided.