diff --git a/src/app.tsx b/src/app.tsx index db823fc..7fd80f4 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -21,11 +21,13 @@ export type ExternalRunner = (args: { export const App: FC<{ manager: SessionManager; cwd?: string; + model?: string; messages?: Messages; runExternal?: ExternalRunner; }> = ({ manager, cwd, + model, // 既定は ja。index.tsx が解決済みカタログを注入する。 messages = catalogs.ja, runExternal, @@ -83,6 +85,7 @@ export const App: FC<{ onOpenExternal={runExternal ? openExternal : undefined} onQuit={quit} cwd={cwd} + model={model} /> diff --git a/src/core/i18n.ts b/src/core/i18n.ts index 633b303..08d24a1 100644 --- a/src/core/i18n.ts +++ b/src/core/i18n.ts @@ -71,6 +71,10 @@ export interface Messages { /** 起動バナー(banner.tsx) */ banner: { subtitle: string; + /** 使用中モデルの表示(設定 model。未設定は CLI 既定)。 */ + model: (name: string) => string; + /** model 未設定時に表示するプレースホルダ(CLI 既定)。 */ + defaultModel: string; }; /** 下部モード行(status-footer.tsx) */ footer: { @@ -128,6 +132,8 @@ const ja: Messages = { }, banner: { subtitle: '並列 Claude Code セッションを git worktree 上で実行', + model: (name) => `モデル: ${name}`, + defaultModel: 'CLI 既定', }, footer: { autoMode: '自動モード', @@ -184,6 +190,8 @@ const en: Messages = { }, banner: { subtitle: 'Parallel Claude Code sessions in git worktrees', + model: (name) => `model: ${name}`, + defaultModel: 'CLI default', }, footer: { autoMode: 'auto mode on', diff --git a/src/index.tsx b/src/index.tsx index e7f3a3f..fb497ad 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -129,7 +129,13 @@ async function main(): Promise { }; const { waitUntilExit } = render( - , + , { exitOnCtrlC: false }, ); await waitUntilExit(); diff --git a/src/ui/banner.spec.tsx b/src/ui/banner.spec.tsx new file mode 100644 index 0000000..6776a0d --- /dev/null +++ b/src/ui/banner.spec.tsx @@ -0,0 +1,34 @@ +import { render } from 'ink-testing-library'; +import { describe, expect, it } from 'vitest'; +import { messages } from '@/core'; +import { Banner } from './banner'; +import { MessagesProvider } from './i18n-context'; + +function renderBanner(props: Parameters[0], lang: 'ja' | 'en' = 'en') { + return render( + + + , + ); +} + +describe('Banner', () => { + it('設定されたモデル名をヘッダに表示する', () => { + const { lastFrame } = renderBanner({ sessionCount: 0, model: 'claude-opus-4-8' }, 'en'); + expect(lastFrame()).toContain('model: claude-opus-4-8'); + }); + + it('モデル未設定なら CLI 既定を表示する', () => { + const { lastFrame } = renderBanner({ sessionCount: 0 }, 'en'); + expect(lastFrame()).toContain('model: CLI default'); + }); + + it('モデル行は cwd 行の上に描画される', () => { + const { lastFrame } = renderBanner( + { sessionCount: 0, model: 'sonnet', cwd: '/tmp/repo' }, + 'en', + ); + const frame = lastFrame() ?? ''; + expect(frame.indexOf('model: sonnet')).toBeLessThan(frame.indexOf('/tmp/repo')); + }); +}); diff --git a/src/ui/banner.tsx b/src/ui/banner.tsx index 1bc439c..3eac625 100644 --- a/src/ui/banner.tsx +++ b/src/ui/banner.tsx @@ -45,11 +45,12 @@ const LOGO_ROWS = LOGO.map((line, row) => ({ * Borderless startup header echoing Claude Code's banner: the mascot on the left * and identity / subtitle / cwd on the right (vertically centered against it). */ -export const Banner: FC<{ cwd?: string; sessionCount: number; totalCostUsd?: number }> = ({ - cwd, - sessionCount, - totalCostUsd = 0, -}) => { +export const Banner: FC<{ + cwd?: string; + model?: string; + sessionCount: number; + totalCostUsd?: number; +}> = ({ cwd, model, sessionCount, totalCostUsd = 0 }) => { const m = useMessages(); return ( @@ -76,6 +77,7 @@ export const Banner: FC<{ cwd?: string; sessionCount: number; totalCostUsd?: num {m.banner.subtitle} + {m.banner.model(model ?? m.banner.defaultModel)} {cwd ? {cwd} : null} diff --git a/src/ui/session-list.tsx b/src/ui/session-list.tsx index b7917ab..4d02263 100644 --- a/src/ui/session-list.tsx +++ b/src/ui/session-list.tsx @@ -38,7 +38,8 @@ export const SessionList: FC<{ onOpenExternal?: OpenExternal; onQuit: () => void; cwd?: string; -}> = ({ manager, onOpenExternal, onQuit, cwd }) => { + model?: string; +}> = ({ manager, onOpenExternal, onQuit, cwd, model }) => { const m = useMessages(); const sessions = useSessions(manager); const mode = useRunMode(manager); @@ -246,7 +247,12 @@ export const SessionList: FC<{ return ( - + {/* flexGrow で残り高さを占め、入力欄とフッタを画面最下部へ押し下げる */}