Merge nucleic/warm-coral-viper-sn0m into dev
This commit is contained in:
@@ -352,10 +352,13 @@ struct SessionDetailView: View {
|
||||
@ViewBuilder
|
||||
private func modelEffortMenu(_ summary: WireSessionSummary) -> some View {
|
||||
if !store.routesIntelligence {
|
||||
// A session's backend is fixed at creation, so only same-backend models are offered.
|
||||
// Context Switch can replace the backend between turns. The summary is the live source
|
||||
// of truth, and the explicit identity rebuilds a native Menu that happened to be open
|
||||
// across the update instead of retaining its old provider's snapshot.
|
||||
ModelMenu(model: modelBinding, catalog: store.modelCatalog, backend: summary.backend)
|
||||
.id(summary.backend)
|
||||
EffortMenu(effort: effortBinding, catalog: store.modelCatalog,
|
||||
// No explicit model yet → use the session backend's default, so the menu
|
||||
// No explicit model yet → use the current backend's default, so the menu
|
||||
// shows that backend's effort range rather than collapsing to one level.
|
||||
modelSKU: summary.model ?? store.modelCatalog.models(for: summary.backend).first?.sku,
|
||||
controlled: controlled,
|
||||
@@ -368,7 +371,7 @@ struct SessionDetailView: View {
|
||||
// MARK: - The in-session Intelligence rail
|
||||
|
||||
/// The stop this chat's rail sits at. The host owns it — moving the rail sends the stop and
|
||||
/// the host re-routes within the chat's fixed backend lane, then broadcasts the resulting
|
||||
/// the host re-routes within the chat's current backend lane, then broadcasts the resulting
|
||||
/// model/effort — so the committed value is *derived* from the summary rather than held here.
|
||||
/// `pendingIntelligence` covers only the round trip, and `intelligencePreview` the drag.
|
||||
private var sessionIntelligence: Int {
|
||||
@@ -433,6 +436,7 @@ struct SessionDetailView: View {
|
||||
.onChange(of: summary.routedLevel) { _, _ in pendingIntelligence = nil }
|
||||
.onChange(of: summary.model) { _, _ in pendingIntelligence = nil }
|
||||
.onChange(of: summary.effort) { _, _ in pendingIntelligence = nil }
|
||||
.onChange(of: summary.backend) { _, _ in pendingIntelligence = nil }
|
||||
// A refused move — every candidate for that stop is inside a reached quota window —
|
||||
// changes nothing at all; the host answers with an error instead. Without this the
|
||||
// rail would stay parked on a stop the chat never reached, so it springs back here
|
||||
|
||||
@@ -477,8 +477,10 @@ extension WireModelCatalog {
|
||||
|
||||
/// A compact model selector driven by the wire catalog (SYNC §5.2). `backend == nil` — the
|
||||
/// home composer, where the model also selects the backend — shows every provider group with
|
||||
/// dividers; a fixed `backend` (in-session, where the backend is immutable) shows only that
|
||||
/// provider's models. Selecting sets the SKU; the binding's `nil` means "host default".
|
||||
/// dividers; an in-session `backend` shows only the models for the session summary's *current*
|
||||
/// provider. Context Switch may change that field between turns, so callers pass the live summary
|
||||
/// rather than retaining the creation-time lane. Selecting sets the SKU; the binding's `nil` means
|
||||
/// "host default".
|
||||
struct ModelMenu: View {
|
||||
@Binding var model: String?
|
||||
let catalog: WireModelCatalog
|
||||
|
||||
Reference in New Issue
Block a user