返回 DeepSeek-Reasonix
blank_session_model.go
根目录 / desktop / blank_session_model.go
1 package main
2
3 import (
4 "fmt"
5 "strings"
6
7 "reasonix/internal/config"
8 )
9
10 // alignReusableBlankTabModel makes a reused empty session obey the same
11 // provider/model default as a newly-created session. Ready runtimes use the
12 // normal failure-atomic model switch. A tab that is still starting has no
13 // controller to swap, so invalidate its startup generation, update the empty
14 // session's model metadata, and restart the build from the intended provider.
15 func (a *App) alignReusableBlankTabModel(tab *WorkspaceTab, model string) error {
16 model = strings.TrimSpace(model)
17 if tab == nil || model == "" {
18 return nil
19 }
20
21 a.mu.RLock()
22 if tab.removed || a.tabs[tab.ID] != tab {
23 a.mu.RUnlock()
24 return fmt.Errorf("blank session changed while applying the default model; retry")
25 }
26 currentModel := strings.TrimSpace(tab.model)
27 ctrl := tab.Ctrl
28 buildDone := tab.buildDone
29 a.mu.RUnlock()
30
31 if ctrl != nil {
32 if currentModel != model {
33 if err := a.SetModelForTab(tab.ID, model); err != nil {
34 return err
35 }
36 }
37 return nil
38 }
39 if currentModel == model && buildDone != nil {
40 // Reusing an in-flight blank must reuse its pending create, too. Cancelling
41 // an identical build can leave durable content awaiting registry attach;
42 // startup recovery would later publish that as a second blank session.
43 select {
44 case <-buildDone:
45 case <-a.bootContext().Done():
46 return a.bootContext().Err()
47 }
48 a.mu.RLock()
49 ready := !tab.removed && a.tabs[tab.ID] == tab && tab.Ctrl != nil && tab.SessionID != ""
50 startupErr := tab.StartupErr
51 a.mu.RUnlock()
52 if !ready {
53 return fmt.Errorf("create session runtime: %s", startupErr)
54 }
55 return nil
56 }
57
58 // Fence the old build before publishing its replacement model. Legacy
59 // sources stay read-only; the replacement commits the selected model as a
60 // session/config event when it publishes its canonical identity.
61 a.mu.Lock()
62 if tab.removed || a.tabs[tab.ID] != tab {
63 a.mu.Unlock()
64 return fmt.Errorf("blank session changed while applying the default model; retry")
65 }
66 if tab.Ctrl != nil {
67 a.mu.Unlock()
68 return a.alignReusableBlankTabModel(tab, model)
69 }
70 a.supersedeTabBuildLocked(tab)
71 tab.effort = config.RebindSessionEffort(nil, tab.model, model, tab.effort)
72 tab.model = model
73 tab.Label = model
74 tab.Ready = false
75 clearTabStartupError(tab)
76 a.saveTabsLocked()
77 a.mu.Unlock()
78 a.buildTabController(tab)
79 a.mu.RLock()
80 ready := tab.Ctrl != nil && tab.SessionID != ""
81 startupErr := tab.StartupErr
82 a.mu.RUnlock()
83 if !ready {
84 return fmt.Errorf("create session runtime: %s", startupErr)
85 }
86 return nil
87 }
88
88 lines GO