Commit e039893
authored
feat(agent): Discover Claude Code models dynamically from the CLI (#244)
## Motivation
Previously, LeapMux used a static catalog to determine which Claude Code
models and effort levels were available. This meant the catalog could
fall
out of sync with what the user's installed CLI actually supports -- new
models would be missing, removed models would appear, and plan-tier
differences were invisible to the system.
The Claude Code CLI already reports its full model list (including
unavailable ones) in the `initialize` response. This change harvests
that
data to build a per-agent dynamic catalog at runtime, with the static
catalog retained as a fallback for CLIs that predate the feature.
## Modifications
- Added `claudeCodeModelInfo` struct and `convertClaudeModels()` to
parse
the `models`/`unavailable_models` arrays from the CLI initialize
response into LeapMux `AvailableModels`, including effort ordering,
context-window inference from the `[1m]` marker, and deduplication.
- Introduced `effortResolver`, which wraps a dynamic catalog plus a
static fallback for all capability queries (`supports`,
`supportsUltracode`, `resolveEffort`, `contextWindow`). Constructed
static-only at launch and promoted to dynamic+fallback post-init, so a
model the live CLI dropped still resolves real capabilities from the
fallback.
- Extracted `runStartupHandshake()` from `StartClaudeCode` and moved
startup effort reconciliation onto `effortResolver`
(`reconcileStartupFlags`, `reconciledEffortFlags`,
`reconcileOmittedLaunch`).
- Added the "default" model sentinel (`DefaultModelSentinel`) -- a
selectable entry that tracks the account's own default. Launch omits
`--model`/`--effort` when it is selected so the CLI resolves the
concrete model; the resolved identity is reported back via
`get_settings`.
- Extended Ultracode (xhigh+workflow tier) to any model whose CLI effort
levels include `xhigh`, removing the previous Opus-only restriction.
The decode and live-update paths gate the ultracode strip on the model
being *known*, so a model in neither catalog running ultracode is left
as the CLI applied it rather than silently downgraded.
- Added `windowModel` to `contextUsageSnapshot` and three focused
methods
(`reseedWindow`, `adoptResultWindow`, `buildBroadcast`) to re-seed the
context window on model change, omit it when unknown, and debounce the
usage broadcast.
- Fixed `findPrimaryContextWindow` to use `normalizeClaudeCodeModel`
equality instead of substring matching, eliminating false positives
such as "opus" matching "opusplus".
- Replaced `buildShellWrappedCommand`'s positional parameter tail with a
`shellWrapSpec` struct (all 9 provider `Start` functions migrated to
named-field literals), and added a `ProbeThirdParty` field so Claude's
default-model launch still detects a provider configured only in the
user's shell profile.
- Added `defaultModelForList()` with 3-tier badge priority (operator env
override -> provider-reported sentinel -> configured default);
`reportModelChange()`/`buildSettingsChanges()` suppress spurious
model-change events on re-spelling but report the sentinel resolving to
a concrete model as a real transition; the live-update path persists
the settled model/effort to prevent DB drift.
- `stripDefaultModelBadge()` strips the transient `IsDefault` badge and
drops nil catalog entries before persistence, so the DB never stores a
derived badge or a hollow `{}`.
- Frontend: `DEFAULT_CLAUDE_MODEL` changed from `'opus[1m]'` to
`'default'`; the sentinel renders as "Default (recommended)". Fable
added to the static fallback catalog.
## Result
The model picker in the Claude agent settings panel is now populated
from the live CLI response rather than a hard-coded list. Models
unavailable on the current plan are hidden automatically, and new
models appear as soon as the CLI reports them -- no LeapMux update
required.
Selecting "Default (recommended)" lets the CLI pick the concrete model
based on the user's account and plan tier. The resolved model is
reflected back to the UI via `get_settings` so the chat header and
settings panel stay in sync.
Old CLI versions that do not include a `models` array in their
initialize response fall back to the static catalog transparently, with
no change in behavior.1 parent 86e90ac commit e039893
24 files changed
Lines changed: 3149 additions & 439 deletions
File tree
- backend/internal/worker
- agent
- service
- frontend/src/components/chat/providers/claude
Large diffs are not rendered by default.
Lines changed: 60 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
210 | 210 | | |
211 | 211 | | |
212 | 212 | | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
213 | 224 | | |
214 | 225 | | |
215 | 226 | | |
| |||
531 | 542 | | |
532 | 543 | | |
533 | 544 | | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
534 | 594 | | |
535 | 595 | | |
536 | 596 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
60 | | - | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
61 | 135 | | |
62 | 136 | | |
63 | 137 | | |
| |||
627 | 701 | | |
628 | 702 | | |
629 | 703 | | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
630 | 735 | | |
| 736 | + | |
631 | 737 | | |
632 | 738 | | |
633 | 739 | | |
| |||
640 | 746 | | |
641 | 747 | | |
642 | 748 | | |
643 | | - | |
644 | | - | |
645 | | - | |
646 | | - | |
647 | | - | |
648 | | - | |
649 | | - | |
650 | | - | |
651 | | - | |
652 | | - | |
653 | | - | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
654 | 756 | | |
655 | 757 | | |
656 | | - | |
657 | | - | |
658 | | - | |
659 | | - | |
660 | | - | |
661 | | - | |
662 | | - | |
663 | | - | |
664 | | - | |
665 | | - | |
666 | | - | |
667 | | - | |
668 | | - | |
669 | | - | |
670 | | - | |
671 | | - | |
672 | | - | |
673 | | - | |
674 | | - | |
675 | | - | |
| 758 | + | |
| 759 | + | |
676 | 760 | | |
677 | | - | |
678 | 761 | | |
679 | 762 | | |
680 | 763 | | |
681 | 764 | | |
682 | 765 | | |
683 | 766 | | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
684 | 773 | | |
685 | 774 | | |
686 | | - | |
687 | | - | |
688 | | - | |
| 775 | + | |
689 | 776 | | |
690 | 777 | | |
691 | 778 | | |
692 | 779 | | |
693 | 780 | | |
694 | | - | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
695 | 784 | | |
696 | | - | |
697 | | - | |
698 | | - | |
699 | | - | |
| 785 | + | |
| 786 | + | |
700 | 787 | | |
701 | 788 | | |
702 | 789 | | |
703 | 790 | | |
704 | | - | |
705 | | - | |
706 | | - | |
707 | | - | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
708 | 800 | | |
709 | 801 | | |
710 | | - | |
| 802 | + | |
711 | 803 | | |
712 | 804 | | |
713 | | - | |
714 | | - | |
715 | | - | |
716 | | - | |
717 | | - | |
718 | | - | |
719 | | - | |
720 | | - | |
721 | | - | |
722 | | - | |
| 805 | + | |
723 | 806 | | |
724 | | - | |
| 807 | + | |
725 | 808 | | |
726 | 809 | | |
727 | | - | |
728 | | - | |
729 | | - | |
730 | | - | |
731 | | - | |
732 | | - | |
733 | | - | |
734 | | - | |
735 | | - | |
736 | | - | |
737 | | - | |
738 | | - | |
739 | | - | |
740 | | - | |
741 | 810 | | |
742 | 811 | | |
743 | 812 | | |
| |||
0 commit comments