Chat: per-conversation model binding for multi-model Multi-Chat - #1174
Draft
worsnoptr wants to merge 2 commits into
Draft
Chat: per-conversation model binding for multi-model Multi-Chat#1174worsnoptr wants to merge 2 commits into
worsnoptr wants to merge 2 commits into
Conversation
Multi-Chat split view + multicast can send one message to several
conversations, but all panes run on the single app-level 'primaryChat'
model assignment - side-by-side multi-turn comparison of DIFFERENT
models isn't possible. Beam covers single-turn scatter/gather; this
enables persistent multi-turn conversations each bound to its own
model. The two compose rather than compete.
Design: optional conversation.userLlmId ("pinned" model), resolved at
execution time as pin ?? 'primaryChat' domain default:
- getConversationChatLLMId(conversationId): validated pin or default;
broken pins (model removed, or chat imported from an install with
different services) silently degrade to the default, mirroring the
broken-domain-assignment semantics of llmsResolveDomainModel.
- _handleExecute reads it instead of getChatLLMId() - one swap covers
send, regenerate, retry, ReAct, and multicast (which already fans
out per conversation, so per-pane models fall out for free).
- Beam seeds (beamOpen/beamImportRays) resolve per-conversation too.
- Utility flows (autotitle, fastUtil, codeApply, imageCaption) are
untouched: they use the separate domain accessors.
UX (conservative: zero behavior change until a chat is pinned):
- Model selector: 'Pin model to this chat' / 'Unpin - follow app
default' menu entry; when pinned, the selector shows the pin and
edits the pin instead of the global default.
- Split view: each pane's title overlay shows the conversation's
bound model - outlined chip + pin for pinned, dimmed italic for
following-default - so non-focused panes' models stay visible.
Persistence: optional field, no store version bump (absent = follow
default, all existing chats unaffected); branching copies the pin;
export carries it and import round-trips it (chats.converters).
|
@worsnoptr is attempting to deploy a commit to the Token Fabrics Pro Team on Vercel. A member of the Team first needs to authorize it. |
Owner
|
Thanks for opening this as a draft - DConversation.userLlmId is the right first move. To make it land cleanly: (1) keep the field; (2) route all chat model resolution through one function (chat pin > persona default > global fallback) instead of reading the pin at call sites - that mirrors how our hosted branch already works, and it is the difference between merging cleanly and fighting every rebase; (3) degrade silently when a pinned model disappears (fall back, never error); (4) leave the utility model domains (title/fast) alone. Reshape to that and review follows quickly. |
… directly Three sites still read the plain 'primaryChat' global instead of the conversation-aware resolver, contradicting the single-seam requirement: - AppChat: Ctrl+Shift+O (Model Options) opened the global default's options instead of the focused pane's bound model. - store-chats: editMessage's and updateMessagesTokenCounts' token counting (import/historyReplace/historyTruncateToIncluded/append) used the global default instead of the owning conversation's model. All now resolve through getConversationChatLLMId(conversationId), the single function per the reviewed seam (chat pin > primaryChat domain default). Adds store-chats.test.ts covering the resolution order and silent broken-pin degradation against the real stores.
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.
Implements the design proposed in #1173 — see that issue for the full rationale, UX mock, and discussion of the pane-binding alternative. Opening as a draft so the design conversation in the issue can proceed independently of code review; happy to adjust (field name, UX details, or switch to pane-binding) based on how that discussion goes.
Summary
DConversation.userLlmId?: DLLMId— optional pinned model, resolved at execution time aspin ?? primaryChat domain default.getConversationChatLLMId(conversationId): validated pin or default; broken pins (model removed, or chat imported from an install with different services) silently degrade to the default, mirroringllmsResolveDomainModel's broken-assignment semantics._handleExecutereads it instead ofgetChatLLMId()— one swap covers send, regenerate, retry, ReAct, and Multi-Chat broadcast (which already dispatches per conversation, so per-pane models fall out with no changes to the broadcast code itself). Beam's seed (beamOpen/beamImportRays) resolves per-conversation too.duplicateDConversationcopies the pin so branches keep their model; export carries it and import round-trips it (chats.converters).Tested
getChatLLMId()would return).tsc --noEmit,eslint, andnext buildall clean.