feat(web): configure DeepSeek during onboarding

This commit is contained in:
Yichen Jiang
2026-07-30 12:41:09 +08:00
parent 65bd54f8b4
commit 9182db00ef
24 changed files with 1051 additions and 53 deletions

View File

@@ -24,12 +24,13 @@ function injectedOf(slots: SlotsService): SettingsRootInjected {
return (entry.inject as () => SettingsRootInjected)()
}
/** The shell's four child declarations (chrome seats + the section list). */
/** The shell's five child declarations (chrome, sections, and onboarding overlays). */
const CHILD_SPECS = {
'settings.trigger': { kind: 'single', scope: 'root' },
'settings.header': { kind: 'single', scope: 'root' },
'settings.close': { kind: 'single', scope: 'root' },
'settings.section': { kind: 'list', scope: 'root' },
'settings.onboarding': { kind: 'list', scope: 'root' },
} as const
describe('ui-settings apply', () => {
@@ -37,7 +38,7 @@ describe('ui-settings apply', () => {
expect(inject).toEqual(['slots'])
})
it('registers the shell and declares the four child slots, before or after the declaration', async () => {
it('registers the shell and declares the five child slots, before or after the declaration', async () => {
const before = await bench()
declare(before.slots)
await before.ctx.plugin({ inject: [...inject], apply }).await()
@@ -100,7 +101,7 @@ describe('ui-settings apply', () => {
}
})
it('unregisters the shell and collapses all four child slots on teardown', async () => {
it('unregisters the shell and collapses all five child slots on teardown', async () => {
const b = await bench()
declare(b.slots)
const fiber = b.ctx.plugin({ inject: [...inject], apply })

View File

@@ -18,11 +18,12 @@ const SEAT_CONTENT: Record<string, string> = {
function mount({
wide = true,
onboardingActive = true,
rows = [
{ id: 'general', order: 0, label: 'General' },
{ id: 'models', order: 10, label: 'Models' },
],
}: { wide?: boolean; rows?: Row[] } = {}) {
}: { wide?: boolean; onboardingActive?: boolean; rows?: Row[] } = {}) {
// Mutable row source standing in for the bound useSections hook; bump()
// plays a ledger change through the same observable contract.
let current = rows
@@ -33,10 +34,16 @@ function mount({
return SEAT_CONTENT[key]
}) as SettingsRootComponentProps['renderSlot'],
)
// Global standard kit stubs: the shell consumes neither hook.
const useSessions = ((select: (state: unknown) => unknown) => select(onboardingActive
? { phase: 'ready', current: undefined, byId: {} }
: {
phase: 'ready',
current: 'active-session',
byId: { 'active-session': { blank: false } },
})) as never
const unusedHook = (() => { throw new Error('unused by SettingsRoot') }) as never
const props: SettingsRootComponentProps = {
useSessions: unusedHook,
useSessions,
useWorkspaces: unusedHook,
wide,
useSections: (select) => {
@@ -157,6 +164,22 @@ describe('SettingsPanel navigation', () => {
expect(screen.queryByTestId('section-general')).toBeNull()
})
it('hands Hero readiness and a direct section opener to onboarding registrants', () => {
const { renderSlot } = mount()
const onboardingCall = renderSlot.mock.calls.find(call => call[0] === 'settings.onboarding')
expect(onboardingCall?.[1]).toMatchObject({ active: true })
act(() => {
(onboardingCall?.[1] as { openSection: (id: string) => void }).openSection('models')
})
expect(screen.getByRole('dialog')).toBeTruthy()
expect(screen.getByTestId('section-models')).toBeTruthy()
cleanup()
const active = mount({ onboardingActive: false }).renderSlot.mock.calls
.find(call => call[0] === 'settings.onboarding')
expect(active?.[1]).toMatchObject({ active: false })
})
it('falls back to the first row when the active entry unregisters', () => {
const { bump } = mount()
openPanel()