@mobius-os/mobius 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mobius-os/mobius",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "type": "module",
5
5
  "description": "Mobius terminal client. Reuses Mobius frontend TypeScript types and jsonl entry shapes.",
6
6
  "bin": {
@@ -35,8 +35,7 @@ interface TerminalSize {
35
35
  isTty: boolean
36
36
  }
37
37
 
38
- const VERSION = '0.2.7'
39
- const WELCOME_ROWS = 12
38
+ const VERSION = '0.2.8'
40
39
  const CHROME_ROWS = 11
41
40
 
42
41
  const SLASH_COMMANDS = [
@@ -50,6 +49,7 @@ export function ChatScreen({ client, ready, webUserId, resumeSessionId, onClear,
50
49
  const chat = useChat({ client, ready, resumeSessionId })
51
50
  const [showHelp, setShowHelp] = useState(false)
52
51
  const [scrollBack, setScrollBack] = useState(0)
52
+ const [modelLabel, setModelLabel] = useState<string | null>(null)
53
53
  const terminal = useTerminalSize()
54
54
 
55
55
  const runSlash = useCallback((raw: string) => {
@@ -80,11 +80,12 @@ export function ChatScreen({ client, ready, webUserId, resumeSessionId, onClear,
80
80
  () => fitTranscript(chat.entries, transcriptRows, terminal.columns, scrollBack),
81
81
  [chat.entries, transcriptRows, terminal.columns, scrollBack],
82
82
  )
83
- // Welcome card is for fresh / short sessions only. Once the conversation is
84
- // long enough that fitTranscript hides older entries, switch to the compact
85
- // header + full transcript — otherwise the 12-row welcome card crowds out the
86
- // recent messages and the chat area reads as blank after "已隐藏较早的…".
87
- const showWelcome = fitted.hiddenOlder === 0 && scrollBack === 0 && fitted.estimatedRows + WELCOME_ROWS <= transcriptRows
83
+ // Welcome card is for a truly fresh session only. Once there's any
84
+ // conversation (or an in-flight user message) it disappears, handing the
85
+ // compact header + bottom-anchored transcript the full height. Keeping it
86
+ // while chatting left recent messages stranded mid-screen with a blank gap
87
+ // above the composer.
88
+ const showWelcome = chat.entries.length === 0 && chat.pendingUser === null && scrollBack === 0
88
89
 
89
90
  // In-app history pager. Ink redraws only the live frame, so the terminal's
90
91
  // own scrollback holds no past turns — older entries are unreachable unless we
@@ -100,6 +101,19 @@ export function ChatScreen({ client, ready, webUserId, resumeSessionId, onClear,
100
101
  if (cur > prev && scrollBack > 0) setScrollBack(s => s + (cur - prev))
101
102
  }, [chat.entries.length, scrollBack])
102
103
 
104
+ // Show the model's friendly label (e.g. "GPT-5.6-Sol") in the header/status
105
+ // instead of its opaque key (e.g. "codex:mobiusdefaultaabb").
106
+ useEffect(() => {
107
+ const key = ready.prefs.model
108
+ if (!key) { setModelLabel(null); return }
109
+ let cancelled = false
110
+ client.modelOptions()
111
+ .then(opts => { if (!cancelled) setModelLabel(opts.find(o => o.key === key)?.label ?? null) })
112
+ .catch(() => { if (!cancelled) setModelLabel(null) })
113
+ return () => { cancelled = true }
114
+ }, [client, ready.prefs.model])
115
+ const modelDisplay = modelLabel ?? ready.prefs.model ?? 'default'
116
+
103
117
  useInput((_input, key) => {
104
118
  // The composer ignores pageUp/pageDown, so binding them here can't clash
105
119
  // with text entry, history navigation, or the slash-command popup.
@@ -118,7 +132,7 @@ export function ChatScreen({ client, ready, webUserId, resumeSessionId, onClear,
118
132
  >
119
133
  <Box flexDirection="column" flexGrow={1} overflowY="hidden">
120
134
  {showWelcome
121
- ? <WelcomeCard ready={ready} columns={terminal.columns} resumed={Boolean(resumeSessionId)} />
135
+ ? <WelcomeCard ready={ready} columns={terminal.columns} resumed={Boolean(resumeSessionId)} modelDisplay={modelDisplay} />
122
136
  : <CompactHeader ready={ready} sessionId={chat.sessionId} />}
123
137
 
124
138
  <Box flexGrow={1} flexDirection="column" justifyContent={showWelcome ? 'flex-start' : 'flex-end'} overflowY="hidden">
@@ -157,6 +171,7 @@ export function ChatScreen({ client, ready, webUserId, resumeSessionId, onClear,
157
171
  columns={terminal.columns}
158
172
  webUrl={buildWebUrl(client.server, webUserId, ready, chat.sessionId)}
159
173
  aimuxStatus={aimuxStatus}
174
+ modelDisplay={modelDisplay}
160
175
  />
161
176
  </Box>
162
177
  )
@@ -180,7 +195,7 @@ function useTerminalSize(): TerminalSize {
180
195
  return size
181
196
  }
182
197
 
183
- function WelcomeCard({ ready, columns, resumed }: { ready: ReadyState; columns: number; resumed: boolean }) {
198
+ function WelcomeCard({ ready, columns, resumed, modelDisplay }: { ready: ReadyState; columns: number; resumed: boolean; modelDisplay: string }) {
184
199
  const cwd = compactPath(process.cwd())
185
200
  const width = Math.max(38, Math.min(68, columns - 4))
186
201
  const labelWidth = 11
@@ -193,7 +208,7 @@ function WelcomeCard({ ready, columns, resumed }: { ready: ReadyState; columns:
193
208
  <Text dimColor> (v{VERSION})</Text>
194
209
  </Text>
195
210
  <Text> </Text>
196
- <MetaRow label="model:" value={ready.prefs.model ?? 'default'} hint="/help 查看命令" labelWidth={labelWidth} />
211
+ <MetaRow label="model:" value={modelDisplay} hint="/help 查看命令" labelWidth={labelWidth} />
197
212
  <MetaRow label="project:" value={ready.project.name} labelWidth={labelWidth} />
198
213
  <MetaRow label="task:" value={ready.issue.title} labelWidth={labelWidth} />
199
214
  <MetaRow label="directory:" value={cwd} labelWidth={labelWidth} />
@@ -461,14 +476,15 @@ function Composer({ onSubmit, onStop, onQuit, typing, commands }: ComposerProps)
461
476
  )
462
477
  }
463
478
 
464
- function StatusArea({ ready, sessionId, columns, webUrl, aimuxStatus }: {
479
+ function StatusArea({ ready, sessionId, columns, webUrl, aimuxStatus, modelDisplay }: {
465
480
  ready: ReadyState
466
481
  sessionId: string | null
467
482
  columns: number
468
483
  webUrl: string
469
484
  aimuxStatus?: AimuxStatus
485
+ modelDisplay: string
470
486
  }) {
471
- const model = ready.prefs.model ?? 'default'
487
+ const model = modelDisplay
472
488
  const language = ready.prefs.language === 'en' ? 'English' : '中文'
473
489
  const cwd = compactPath(process.cwd())
474
490
  const leftRaw = columns >= 100