Repository navigation
feat: Feishu model-picker card, multi-key provider groups, i18n card copy - #129974
Open
daydayup123v wants to merge 1 commit into
Open
daydayup123v wants to merge 1 commit into
daydayup123v wants to merge 1 commit into
Conversation
…copy /model on Feishu becomes a native interactive card: provider, model, and the full reasoning-effort set (minimal/low/medium/high/xhigh/max/ultra, plus none/keep) are picked in one card and committed once by the gateway in a single atomic config write. Every card action re-validates the operator, chat, message, bound session, and profile; stale card revisions are fenced so a delayed click cannot land on a replaced session. Custom providers sharing one base URL but using different API keys are kept as separate groups through config entries, the provider catalog, slug resolution, picker listing, session and global restore, model discovery, and the runtime credential pool. Groups display under the name the user gave each one when adding it. The card copy is served from agent/i18n (gateway.model.picker.*), translated in all 17 locales, with the language captured when the card is sent. This also fixes doubled newline escapes in the existing /fast and /reasoning picker strings (15 locales) that rendered a literal backslash-n. Tests: scripts/run_tests.sh - 48 related files, 576 tests, 0 failures.
Open
14 tasks done
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Two related improvements to model switching, developed together.
1. Feishu: native interactive
/modelcard. Picking a provider, model, and reasoning effort (minimal/low/medium/high/xhigh/max/ultra, plus none and keep) now happens in one native card, and the gateway commits model + effort in a single atomic config write. Every card action re-validates the requesting operator, chat, message, bound session, and profile; stale card revisions are fenced, so a delayed click can never apply to a session that has been replaced by/newor to a chat the card does not belong to. While an agent is running, the switch is refused with the existing busy message unless the user confirms "continue" in the card.Previously, Feishu users switched models through text commands, and there was no way to pick reasoning effort from the chat.
2. Same-URL, different-key custom providers stay separate. Two custom providers that share one base URL but authenticate with different API keys are now tracked as distinct groups through config entries, the provider catalog, slug resolution, the
/modellisting, session and global restore, model-discovery write-back, and the runtime credential pool — so the second key group is never hidden by, overwritten by, or restored as the first. Each group is listed under the name the user gave it when adding it; only exactly identical names fall back to a suffix.The card copy is served from
agent/i18n(gateway.model.picker.*, added to all 17 locales); the language is captured when the card is sent so an open card never repaints mid-flow. The same change fixes doubled\nescapes in the previously shipped/fastand/reasoningpicker strings (15 locales), which rendered a literal backslash-n; a regression test now renders every locale's picker strings and asserts real line breaks.Type of Change
Changes Made
plugins/platforms/feishu/model_picker.py(new): card state machine (provider → model → effort → apply/confirm), per-card update lock, revision fencing, TTL.gateway/slash_commands_model.py: picker plumbing; authorization/session re-checks on every action; one atomic commit per apply.hermes_cli/model_switch.py,utils.py: model+effort persistence goes through one targeted read-modify-write (_CONFIG_RW_LOCK+ dotted-key update) so concurrent writers are not clobbered.hermes_cli/custom_provider_identity.py(new) +providers.py,config_providers.py,model_switch_providers.py,main_provider_setup.py,model_setup_flows_custom.py,runtime_provider_custom.py,cli_model_switch_mixin.py,agent/credential_pool.py: one shared identity for same-URL key groups across listing, selection, persistence, restore, and the runtime pool.locales/*.yaml(17 files):gateway.model.picker.*keys; newline-escape fix.tests/gateway/test_feishu_model_picker.py(new),tests/hermes_cli/test_same_relay_key_routing.py(new), plus aligned suites;tests/agent/test_i18n.pyregression for real newlines.How to Test
/modelin a Feishu chat — both groups appear separately, named as you added them.ultra) → Apply. The config updates model + reasoning_effort in one atomic write./new: the delayed click is refused with "this card's session or authorization changed"; nothing lands on the new session.Local test evidence
scripts/run_tests.sh) across all affected areas —300 files: 2,367 tests passed, 13 skipped, 0 failing tests. (The only red rows
in the sweep were two PM-toolchain suites that require the
uvbinary, whichwas absent from the test box; with
uvon PATH they pass 11/11.)Checklist
pytest tests/sweep — CI will run the full matrix; local run covered the affected areas above