feat: simplify DeepSeek Harness model selection

- replace competing model-source choices with one DeepSeek connection picker
- keep administrator-provided environment settings compatible without exposing them as a selectable UI source
- update bilingual guidance, tests, and runtime design documentation
This commit is contained in:
lofyer
2026-08-14 10:30:53 +08:00
parent 8286e120a1
commit 36e05d45fa
5 changed files with 71 additions and 120 deletions
+1
View File
@@ -403,6 +403,7 @@ DeepSeek Harness 首版只使用 GoodBuddy 模型连接:
- 服务地址必须是 `https://api.deepseek.com`,且不得包含用户信息。
- 模型名称和服务地址由 Main 传入受控 Host。
- API Key 继续保存在 GoodBuddy 加密设置中。
- 启动环境提供的部署连接只由 Main 自动解析,不在 Renderer 中显示为可选来源。
不允许选择 Harness 自有的用户配置文件或自定义 Host。Runtime 始终使用随当前 GoodBuddy 版本发布的内置 Host,并通过完整内部能力握手。
+21 -13
View File
@@ -1372,7 +1372,7 @@ describe('SettingsPanel runtime files', () => {
)
})
it('configures DeepSeek Harness only with Chat Completions or platform settings', async () => {
it('configures DeepSeek Harness with a compatible GoodBuddy connection', async () => {
const harnessProfileId =
'00000000-0000-4000-8000-000000000051'
getRuntime.mockResolvedValueOnce({
@@ -1451,8 +1451,12 @@ describe('SettingsPanel runtime files', () => {
})
).not.toBeInTheDocument()
const source = screen.getByLabelText(
'DeepSeek Harness GoodBuddy 模型连接'
'DeepSeek Harness DeepSeek 模型连接'
)
expect(screen.queryByRole('radio')).not.toBeInTheDocument()
expect(
screen.queryByText('使用平台 DeepSeek 环境配置')
).not.toBeInTheDocument()
expect(
within(source).getByRole('option', { name: '默认模型(不兼容)' })
).toBeDisabled()
@@ -1460,22 +1464,20 @@ describe('SettingsPanel runtime files', () => {
within(source).getByRole('option', { name: 'DeepSeek Chat' })
).not.toBeDisabled()
fireEvent.click(
screen.getByRole('radio', {
name: /使用平台 DeepSeek 环境配置/
})
)
fireEvent.click(screen.getByRole('button', { name: '保存设置' }))
await waitFor(() =>
expect(updateRuntime).toHaveBeenCalledWith(
expect.objectContaining({
deepseekHarnessModelSource: { kind: 'platform' }
deepseekHarnessModelSource: {
kind: 'profile',
profileId: harnessProfileId
}
})
)
)
})
it('normalizes an environment-managed DeepSeek profile to the platform source when saving', async () => {
it('keeps an environment-managed source compatible without exposing it as an option', async () => {
getRuntime.mockResolvedValueOnce({
...runtimeSettings,
modelBaseUrl: 'https://api.deepseek.com',
@@ -1527,11 +1529,17 @@ describe('SettingsPanel runtime files', () => {
name: 'DeepSeek Harness(预览)'
})
)
fireEvent.click(
screen.getByRole('radio', {
name: /使用 GoodBuddy 模型连接/
})
expect(screen.queryByRole('radio')).not.toBeInTheDocument()
expect(
screen.getByText('管理员预置的 DeepSeek 连接')
).toBeInTheDocument()
const source = screen.getByLabelText(
'DeepSeek Harness DeepSeek 模型连接'
)
expect(source).toHaveValue('')
fireEvent.change(source, {
target: { value: runtimeSettings.modelProfiles[0]!.id }
})
fireEvent.click(screen.getByRole('button', { name: '保存设置' }))
await waitFor(() =>
+41 -93
View File
@@ -1981,7 +1981,7 @@ export function SettingsPanel({
detecting={detecting}
modelConfiguration={
activeRuntimeModelSource.kind === 'platform'
? t('runtime.deepseekHarness.platformSource')
? t('runtime.deepseekHarness.managedSource')
: activeRuntimeModelProfile
? t('runtime.followGoodBuddy', {
name: modelProfileDisplayName(
@@ -1998,100 +1998,48 @@ export function SettingsPanel({
runtime: 'DeepSeek Harness'
})}
/>
<fieldset className="runtime-source-options">
<legend>{t('runtime.sourceLegend')}</legend>
<label>
<input
checked={
deepseekHarnessModelSource.kind === 'profile'
}
disabled={!defaultDeepseekHarnessModelProfile}
name="deepseek-harness-model-source"
onChange={() => {
if (defaultDeepseekHarnessModelProfile) {
setDeepseekHarnessModelSource({
kind: 'profile',
profileId:
defaultDeepseekHarnessModelProfile.id
})
}
}}
type="radio"
/>
<span>
<strong>
{t(
'runtime.deepseekHarness.goodBuddySource'
)}
</strong>
<small>
{t(
'runtime.deepseekHarness.goodBuddySourceDescription'
)}
</small>
</span>
</label>
<label>
<input
checked={
deepseekHarnessModelSource.kind === 'platform'
}
name="deepseek-harness-model-source"
onChange={() =>
setDeepseekHarnessModelSource({
kind: 'platform'
})
}
type="radio"
/>
<span>
<strong>
{t('runtime.deepseekHarness.platformSource')}
</strong>
<small>
{t(
'runtime.deepseekHarness.platformSourceDescription'
)}
</small>
</span>
</label>
</fieldset>
{deepseekHarnessModelSource.kind === 'profile' && (
<label className="field">
<span>{t('runtime.goodBuddyConnection')}</span>
<select
aria-label={`DeepSeek Harness ${t(
'runtime.goodBuddyConnection'
)}`}
onChange={(event) =>
setDeepseekHarnessModelSource(
parseModelSource(event.target.value)
)
}
value={deepseekHarnessModelSource.profileId}
>
{modelProfiles.map((profile) => (
<option
disabled={
!isDeepseekHarnessCompatible(profile)
}
key={profile.id}
value={profile.id}
>
{modelProfileDisplayName(profile)}
{isDeepseekHarnessCompatible(profile)
? ''
: t('runtime.incompatibleSuffix')}
</option>
))}
</select>
<small>
<label className="field">
<span>{t('runtime.deepseekHarness.connection')}</span>
<select
aria-label={`DeepSeek Harness ${t(
'runtime.deepseekHarness.connection'
)}`}
disabled={!defaultDeepseekHarnessModelProfile}
onChange={(event) =>
setDeepseekHarnessModelSource(
parseModelSource(event.target.value)
)
}
value={
deepseekHarnessModelSource.kind === 'profile'
? deepseekHarnessModelSource.profileId
: ''
}
>
<option disabled value="">
{t(
'runtime.deepseekHarness.connectionDescription'
'runtime.deepseekHarness.connectionPlaceholder'
)}
</small>
</label>
)}
</option>
{modelProfiles.map((profile) => (
<option
disabled={!isDeepseekHarnessCompatible(profile)}
key={profile.id}
value={profile.id}
>
{modelProfileDisplayName(profile)}
{isDeepseekHarnessCompatible(profile)
? ''
: t('runtime.incompatibleSuffix')}
</option>
))}
</select>
<small>
{t(
'runtime.deepseekHarness.connectionDescription'
)}
</small>
</label>
<details className="settings-section">
<summary>{t('runtime.advanced')}</summary>
<p className="settings-panel__description">
@@ -242,14 +242,11 @@ export const settings = {
'DeepSeek Harness currently supports DeepSeek models only and is not intended for other model providers.',
description:
'GoodBuddy maintains the fixed Host and control protocol internally and uses pinned Harness libraries underneath. Execute tool calls receive automatic one-time authorization, Ask remains read-only, and cancellation and workspace safety boundaries remain in place. It does not integrate with the DSH plugin or marketplace mechanisms.',
goodBuddySource: 'Use a GoodBuddy model connection',
goodBuddySourceDescription:
'Only OpenAI-compatible Chat Completions connections are available. The connection must point to a DeepSeek model.',
platformSource: 'Use platform DeepSeek environment settings',
platformSourceDescription:
'Reads platform-managed DeepSeek settings from the launch environment without exposing credentials to the renderer.',
managedSource: 'Administrator-provided DeepSeek connection',
connection: 'DeepSeek model connection',
connectionPlaceholder: 'Select a DeepSeek model connection',
connectionDescription:
'The internal GoodBuddy Harness Runtime currently accepts only the OpenAI-compatible Chat Completions protocol.',
'Choose a GoodBuddy model connection. Only OpenAI-compatible Chat Completions connections that point to DeepSeek are supported.',
advancedDescription:
'This Runtime always uses GoodBuddys bundled, version-pinned Host. It does not load external DSH plugins, marketplace packages, user profiles, or custom Hosts.'
}
@@ -220,14 +220,11 @@ export const settings = {
'DeepSeek Harness 当前仅支持 DeepSeek 模型,不适用于其他模型提供商。',
description:
'由 GoodBuddy 内部维护固定 Host 与控制协议,复用锁定的 Harness 底层库;Execute 工具调用自动单次授权,Ask 保持只读,并保留取消和工作区安全边界;不接入 DSH 插件或市场机制。',
goodBuddySource: '使用 GoodBuddy 模型连接',
goodBuddySourceDescription:
'只能选择 OpenAI 兼容 Chat Completions 连接;该连接必须指向 DeepSeek 模型',
platformSource: '使用平台 DeepSeek 环境配置',
platformSourceDescription:
'从启动环境读取平台管理的 DeepSeek 配置,不会在渲染进程中显示凭据。',
managedSource: '管理员预置的 DeepSeek 连接',
connection: 'DeepSeek 模型连接',
connectionPlaceholder: '选择 DeepSeek 模型连接',
connectionDescription:
'GoodBuddy 内部 Harness Runtime 目前仅接受 OpenAI 兼容 Chat Completions 协议。',
'GoodBuddy 模型连接中选择;仅支持指向 DeepSeek 的 OpenAI 兼容 Chat Completions 连接。',
advancedDescription:
'该 Runtime 始终使用 GoodBuddy 内置并固定版本的 Host,不加载外部 DSH 插件、市场包、用户 profile 或自定义 Host。'
}