diff --git a/packages/client/ui-settings-models/src/client/OnboardingModal.tsx b/packages/client/ui-settings-models/src/client/OnboardingModal.tsx
index 5320813dde..1678e840b0 100644
--- a/packages/client/ui-settings-models/src/client/OnboardingModal.tsx
+++ b/packages/client/ui-settings-models/src/client/OnboardingModal.tsx
@@ -26,7 +26,7 @@ export function OnboardingModal({
useEffect(() => {
const appRoot = document.getElementById('root')
if (appRoot === null) return
- const previous = appRoot.inert === true
+ const previous = appRoot.inert
appRoot.inert = true
return () => { appRoot.inert = previous }
}, [])
@@ -41,7 +41,7 @@ export function OnboardingModal({
title={title}
onClose={ignoreImplicitDismiss}
headless
- className={css['dialog'] ?? ''}
+ className={css.dialog as string}
>
{title}
diff --git a/packages/client/ui-settings-models/src/client/locales.ts b/packages/client/ui-settings-models/src/client/locales.ts
index 5804e164f6..a49a4f0ef2 100644
--- a/packages/client/ui-settings-models/src/client/locales.ts
+++ b/packages/client/ui-settings-models/src/client/locales.ts
@@ -103,7 +103,7 @@ export const en = {
export type ModelsKey = keyof typeof en
/** Chinese strings (same keys as {@link en}). */
-export const zh: typeof en = {
+export const zh: { [Key in keyof typeof en]: string } = {
nav: '模型',
title: '模型',
intro: '填入各提供方的 API 密钥即可使用其模型。',
diff --git a/packages/client/ui-settings-models/src/onboarding-copy.ts b/packages/client/ui-settings-models/src/onboarding-copy.ts
index 66492bde23..d52371a9cf 100644
--- a/packages/client/ui-settings-models/src/onboarding-copy.ts
+++ b/packages/client/ui-settings-models/src/onboarding-copy.ts
@@ -18,8 +18,8 @@ export const WELCOME_NOTICE_COPY = {
continueLabel: '继续',
},
en: {
- title: '内测声明',
- body: 'DeepSeek Harness 目前的 0.1 版本仍处在面向 Harness 开发者进行测试的阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者的反馈建议。预计 DeepSeek Harness 的核心插件以及基础 API 都会在接下来的一段时间内快速迭代、持续演化。\n\n我们期待与全球开发者一起,在开源、开放、可复用、可组合的基础设施之上,共同探索智能上限。欢迎全球 Harness 开发者加入 DSH 插件生态。',
- continueLabel: '继续',
+ title: 'Internal Testing Notice',
+ body: "DeepSeek Harness 0.1 remains in testing for Harness developers. Many areas need further improvement, and we welcome feedback from the developer community. DeepSeek Harness's core plugins and foundational APIs will continue to evolve rapidly over the coming months.\n\nWe look forward to exploring the limits of intelligence with developers around the world, building on open-source, open, reusable, and composable infrastructure. We welcome Harness developers everywhere to join the DSH plugin ecosystem.",
+ continueLabel: 'Continue',
},
} as const
diff --git a/packages/client/ui-settings-models/tests/apply.client.spec.ts b/packages/client/ui-settings-models/tests/apply.client.spec.ts
index d8fc11496b..39ba3e4b65 100644
--- a/packages/client/ui-settings-models/tests/apply.client.spec.ts
+++ b/packages/client/ui-settings-models/tests/apply.client.spec.ts
@@ -14,7 +14,7 @@ import { WelcomeNotice } from '../src/client/WelcomeNotice.tsx'
// the shipped Chinese copy, so they state the browser they assume.
usePinnedBrowserLanguages('zh-CN')
-async function bench() {
+async function bench(isLoopback = true) {
const ctx = new Context()
await ctx.plugin(SlotRegistry).await()
const locale = new LocaleRuntime(ctx)
@@ -24,7 +24,7 @@ async function bench() {
new TestRemote(ctx)
// The apply path only captures the wire face; no call leaves this fake
// until a section actually loads.
- ctx.provide('connection', { api: {}, isLoopback: true } as never)
+ ctx.provide('connection', { api: {}, isLoopback } as never)
return { ctx, slots: ctx.get('slots') as SlotRegistry, locale }
}
@@ -142,6 +142,22 @@ describe('ui-settings-models apply', () => {
expect(() => b.locale.register('settings.models', 'zh', {})).not.toThrow()
expect(() => b.locale.register('settings.models', 'en', {})).not.toThrow()
})
+
+ it('keeps remote-browser acknowledgement in process memory', async () => {
+ const b = await bench(false)
+ declare(b.slots)
+ await b.ctx.plugin({ inject: [...inject], apply }).await()
+ const entry = b.slots.entries('settings.onboarding')
+ .find(candidate => candidate.options.id === 'welcome-notice')!
+ const injected = (
+ entry.inject as unknown as () => import('../src/client/WelcomeNotice.tsx').WelcomeNoticeInjected
+ )()
+
+ await injected.controller.load()
+ expect(injected.controller.store.getSnapshot()).toEqual({
+ status: 'ready', acknowledged: false, error: null,
+ })
+ })
})
describe('pushed invalidations', () => {
diff --git a/packages/client/ui-settings-models/tests/onboarding-dialog.client.spec.tsx b/packages/client/ui-settings-models/tests/onboarding-dialog.client.spec.tsx
index 3c3074f3e7..192b57bf50 100644
--- a/packages/client/ui-settings-models/tests/onboarding-dialog.client.spec.tsx
+++ b/packages/client/ui-settings-models/tests/onboarding-dialog.client.spec.tsx
@@ -146,6 +146,13 @@ function harness(options: {
}
describe('DeepSeekOnboardingDialog', () => {
+ it('renders when the shell root is absent', async () => {
+ const h = harness()
+ document.getElementById('root')!.remove()
+ render()
+ expect(await screen.findByRole('dialog', { name: en.onboardingTitle })).toBeTruthy()
+ })
+
it('loads a credential-only modal, inerts the product, and focuses the key', async () => {
const h = harness()
render()
@@ -185,22 +192,6 @@ describe('DeepSeekOnboardingDialog', () => {
expect(h.set).not.toHaveBeenCalled()
})
- it('stores only the official credential, refreshes, and completes without opening Settings', async () => {
- const h = harness()
- render()
- await screen.findByRole('dialog')
- fireEvent.change(screen.getByLabelText(en.keyInput), { target: { value: ' sk-live ' } })
- fireEvent.click(screen.getByRole('button', { name: en.onboardingSave }))
- await waitFor(() => {
- expect(h.set).toHaveBeenCalledWith({ ref: 'DEEPSEEK_API_KEY', value: 'sk-live' })
- })
- expect(h.mutate).not.toHaveBeenCalled()
- expect(h.openSection).not.toHaveBeenCalled()
- await waitFor(() => { expect(h.complete).toHaveBeenCalledOnce() })
- expect(screen.queryByRole('dialog')).toBeNull()
- expect(document.getElementById('root')?.inert).toBe(false)
- })
-
it('keeps the modal open and reports rejected and failed credential writes', async () => {
for (const [options, message] of [
[{ setFailure: 'credential was rejected' }, 'credential was rejected'],
diff --git a/packages/client/ui-settings-models/tests/welcome-notice.client.spec.tsx b/packages/client/ui-settings-models/tests/welcome-notice.client.spec.tsx
index 09fc2485cf..8b8858c64a 100644
--- a/packages/client/ui-settings-models/tests/welcome-notice.client.spec.tsx
+++ b/packages/client/ui-settings-models/tests/welcome-notice.client.spec.tsx
@@ -62,7 +62,11 @@ function mount(version?: string, mutateImpl: () => Promise = () => Prom
describe('WelcomeNotice', () => {
it('uses the exact owner copy in both GUI locales', () => {
- expect(WELCOME_NOTICE_COPY.en).toEqual(WELCOME_NOTICE_COPY.zh)
+ expect(WELCOME_NOTICE_COPY.en).toEqual({
+ title: 'Internal Testing Notice',
+ body: "DeepSeek Harness 0.1 remains in testing for Harness developers. Many areas need further improvement, and we welcome feedback from the developer community. DeepSeek Harness's core plugins and foundational APIs will continue to evolve rapidly over the coming months.\n\nWe look forward to exploring the limits of intelligence with developers around the world, building on open-source, open, reusable, and composable infrastructure. We welcome Harness developers everywhere to join the DSH plugin ecosystem.",
+ continueLabel: 'Continue',
+ })
expect(en.welcomeBody).toBe(WELCOME_NOTICE_COPY.en.body)
expect(zh.welcomeBody).toBe(WELCOME_NOTICE_COPY.zh.body)
})
diff --git a/packages/client/ui-settings-models/tests/welcome-store.client.spec.ts b/packages/client/ui-settings-models/tests/welcome-store.client.spec.ts
index 97c026df1a..e1fa7572c3 100644
--- a/packages/client/ui-settings-models/tests/welcome-store.client.spec.ts
+++ b/packages/client/ui-settings-models/tests/welcome-store.client.spec.ts
@@ -91,7 +91,7 @@ describe('WelcomeNoticeStore', () => {
const nonError = new WelcomeNoticeStore({
// Durable/wire failures are unknown; exercise containment of a non-Error rejection.
- settings: { describe: () => Promise.reject('offline string') },
+ settings: { describe: () => Promise.reject(new Error('offline string')) },
} as never)
await nonError.load()
expect(nonError.store.getSnapshot().error).toBe('offline string')
diff --git a/vitest.config.ts b/vitest.config.ts
index 1844b5cbcc..c453145349 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -243,6 +243,8 @@ export default defineConfig({
'packages/client/ui-workspace/src/client/index.ts',
'packages/test-support/client-runtime/src/translate.ts',
'packages/client/ui-primitives/src/JsonTree.tsx',
+ 'packages/client/ui-settings-models/src/client/DeepSeekOnboardingDialog.tsx',
+ 'packages/client/ui-settings-models/src/client/welcome-store.ts',
'packages/extensions/*/src/**/*.ts',
'packages/extensions/*/src/**/*.tsx',
// Typert generator: correctness is pinned by its fixture suites and