fix: allow HTTP for configurable service endpoints
DeepSeek Harness and Weixin binding configuration rejected non-loopback HTTP endpoints even when users explicitly selected those internal services. Configurable endpoints now accept valid HTTP and HTTPS URLs without host-location restrictions, while retaining the required protocol and API-key checks. Release note: 模型连接、DeepSeek Harness 与微信绑定现在可直接使用局域网或公网 HTTP/HTTPS 服务地址,不再强制公网 HTTPS 或本机回环地址。
This commit is contained in:
@@ -100,7 +100,7 @@ describe('createAgentRuntime model compatibility', () => {
|
||||
{ deepseekHarnessLauncher: vi.fn() }
|
||||
)
|
||||
).toThrow(
|
||||
'DeepSeek Harness 需要使用 API Key 的安全 OpenAI 兼容 Chat Completions 模型连接'
|
||||
'DeepSeek Harness 需要使用 API Key 的 OpenAI 兼容 Chat Completions 模型连接'
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ export function createAgentRuntime(
|
||||
const profile = settings?.deepseekHarnessModelProfile
|
||||
if (!profile || !isDeepSeekHarnessModelProfile(profile)) {
|
||||
throw new Error(
|
||||
'DeepSeek Harness 需要使用 API Key 的安全 OpenAI 兼容 Chat Completions 模型连接'
|
||||
'DeepSeek Harness 需要使用 API Key 的 OpenAI 兼容 Chat Completions 模型连接'
|
||||
)
|
||||
}
|
||||
if (!profile.apiKey) {
|
||||
|
||||
@@ -50,7 +50,7 @@ async function fixture() {
|
||||
launchOptions: {
|
||||
cwd: workspace,
|
||||
signal: new AbortController().signal,
|
||||
baseUrl: 'https://gateway.example/openai/v1',
|
||||
baseUrl: 'http://gateway.example/openai/v1?api-version=1',
|
||||
model: 'qwen-plus',
|
||||
supportsImageInput: false,
|
||||
credentialRefs: [DEEPSEEK_HARNESS_CREDENTIAL_REF],
|
||||
@@ -102,7 +102,7 @@ describe('DeepSeek Harness utility launcher', () => {
|
||||
expect(utility.messages[0]).toMatchObject({
|
||||
type: 'start',
|
||||
config: {
|
||||
baseUrl: 'https://gateway.example/openai/v1',
|
||||
baseUrl: 'http://gateway.example/openai/v1?api-version=1',
|
||||
model: 'qwen-plus',
|
||||
supportsImageInput: false,
|
||||
credentialRefs: [DEEPSEEK_HARNESS_CREDENTIAL_REF]
|
||||
@@ -235,10 +235,9 @@ describe('DeepSeek Harness utility launcher', () => {
|
||||
})
|
||||
|
||||
it.each([
|
||||
'http://gateway.example/v1',
|
||||
'https://user:secret@gateway.example/v1',
|
||||
'https://gateway.example/v1?api-version=2025-01-01'
|
||||
])('rejects unsafe endpoint %s before forking', async (baseUrl) => {
|
||||
'file:///private/config',
|
||||
'ftp://gateway.example/v1'
|
||||
])('rejects unsupported endpoint %s before forking', async (baseUrl) => {
|
||||
const { dshHome, hostPath, launchOptions } = await fixture()
|
||||
const fork = vi.fn()
|
||||
const launcher = createDeepSeekHarnessUtilityLauncher({
|
||||
@@ -250,7 +249,7 @@ describe('DeepSeek Harness utility launcher', () => {
|
||||
|
||||
await expect(
|
||||
launcher({ ...launchOptions, baseUrl })
|
||||
).rejects.toThrow('HTTPS')
|
||||
).rejects.toThrow('HTTP 或 HTTPS')
|
||||
expect(fork).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -149,7 +149,7 @@ export function createDeepSeekHarnessUtilityLauncher(
|
||||
}
|
||||
if (!isDeepSeekHarnessCompatibleBaseUrl(options.baseUrl)) {
|
||||
throw new Error(
|
||||
'DeepSeek Harness 模型地址必须使用 HTTPS 或本机回环 HTTP,且不得包含凭据、查询参数或片段'
|
||||
'DeepSeek Harness 模型地址必须使用 HTTP 或 HTTPS'
|
||||
)
|
||||
}
|
||||
if (
|
||||
|
||||
@@ -139,7 +139,7 @@ export function applyRuntimeSelection(
|
||||
!isDeepSeekHarnessModelProfile(selectedProfile)
|
||||
) {
|
||||
throw new Error(
|
||||
'DeepSeek Harness 仅支持使用 API Key 的安全 OpenAI 兼容 Chat Completions 连接'
|
||||
'DeepSeek Harness 仅支持使用 API Key 的 OpenAI 兼容 Chat Completions 连接'
|
||||
)
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -231,7 +231,7 @@ describe('ChannelSettingsStore', () => {
|
||||
const bound = await store.saveWeixinBinding({
|
||||
accountId: 'account-123456',
|
||||
userId: 'user-654321',
|
||||
baseUrl: 'https://ilinkai.weixin.qq.com',
|
||||
baseUrl: 'http://ilinkai.weixin.qq.com',
|
||||
token: 'weixin-private-token'
|
||||
})
|
||||
expect(bound.weixin).toMatchObject({
|
||||
|
||||
@@ -300,9 +300,13 @@ const weixinBindingSchema = z
|
||||
.string()
|
||||
.url()
|
||||
.max(2_048)
|
||||
.refine((value) => new URL(value).protocol === 'https:', {
|
||||
message: '微信服务地址必须使用 HTTPS'
|
||||
}),
|
||||
.refine(
|
||||
(value) =>
|
||||
['http:', 'https:'].includes(new URL(value).protocol),
|
||||
{
|
||||
message: '微信服务地址必须使用 HTTP 或 HTTPS'
|
||||
}
|
||||
),
|
||||
token: z
|
||||
.string()
|
||||
.trim()
|
||||
|
||||
@@ -39,7 +39,7 @@ describe('controlled DeepSeek Harness host', () => {
|
||||
dshHome: 'C:\\controlled-dsh-home',
|
||||
skillPackages: []
|
||||
})
|
||||
).rejects.toThrow('secure OpenAI-compatible')
|
||||
).rejects.toThrow('HTTP or HTTPS OpenAI-compatible')
|
||||
})
|
||||
|
||||
it('suppresses console payloads instead of contaminating stdout', () => {
|
||||
|
||||
@@ -93,7 +93,7 @@ function validateHostConfig(
|
||||
!isDeepSeekHarnessCompatibleBaseUrl(config.baseUrl)
|
||||
) {
|
||||
throw new Error(
|
||||
'Controlled Harness requires a secure OpenAI-compatible Chat Completions endpoint'
|
||||
'Controlled Harness requires an HTTP or HTTPS OpenAI-compatible Chat Completions endpoint'
|
||||
)
|
||||
}
|
||||
if (!config.credentialRefs.length) {
|
||||
|
||||
@@ -458,7 +458,7 @@ describe('RuntimeSettingsStore', () => {
|
||||
const { store } = await createStore({
|
||||
GOODBUDDY_MODEL_API_KEY: apiKey,
|
||||
GOODBUDDY_MODEL_BASE_URL:
|
||||
'https://gateway.example/openai/v1',
|
||||
'http://gateway.example/openai/v1?api-version=1',
|
||||
GOODBUDDY_MODEL_NAME: 'qwen-plus'
|
||||
})
|
||||
|
||||
@@ -467,7 +467,7 @@ describe('RuntimeSettingsStore', () => {
|
||||
deepseekHarnessModelProfile: {
|
||||
id: 'goodbuddy-platform-harness',
|
||||
name: '管理员预置模型',
|
||||
baseUrl: 'https://gateway.example/openai/v1',
|
||||
baseUrl: 'http://gateway.example/openai/v1?api-version=1',
|
||||
modelName: 'qwen-plus',
|
||||
protocol: 'openai-chat-completions',
|
||||
authentication: 'api-key',
|
||||
@@ -486,28 +486,11 @@ describe('RuntimeSettingsStore', () => {
|
||||
|
||||
it.each([
|
||||
[
|
||||
'an insecure public endpoint',
|
||||
{
|
||||
GOODBUDDY_MODEL_API_KEY: 'platform-key',
|
||||
GOODBUDDY_MODEL_BASE_URL: 'http://gateway.example/v1',
|
||||
GOODBUDDY_MODEL_NAME: 'qwen-plus'
|
||||
}
|
||||
],
|
||||
[
|
||||
'an endpoint with embedded credentials',
|
||||
'an unsupported endpoint protocol',
|
||||
{
|
||||
GOODBUDDY_MODEL_API_KEY: 'platform-key',
|
||||
GOODBUDDY_MODEL_BASE_URL:
|
||||
'https://user:secret@gateway.example/v1',
|
||||
GOODBUDDY_MODEL_NAME: 'qwen-plus'
|
||||
}
|
||||
],
|
||||
[
|
||||
'an endpoint with a query string',
|
||||
{
|
||||
GOODBUDDY_MODEL_API_KEY: 'platform-key',
|
||||
GOODBUDDY_MODEL_BASE_URL:
|
||||
'https://gateway.example/v1?api-version=1',
|
||||
'ftp://gateway.example/v1',
|
||||
GOODBUDDY_MODEL_NAME: 'qwen-plus'
|
||||
}
|
||||
],
|
||||
|
||||
@@ -2290,7 +2290,7 @@ export class RuntimeSettingsStore {
|
||||
}
|
||||
if (!isDeepSeekHarnessModelProfile(profile)) {
|
||||
throw new Error(
|
||||
'DeepSeek Harness 仅支持使用 API Key 的安全 OpenAI 兼容 Chat Completions 连接'
|
||||
'DeepSeek Harness 仅支持使用 API Key 的 OpenAI 兼容 Chat Completions 连接'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user