mirror of
https://github.com/qingchencloud/clawpanel.git
synced 2026-05-30 04:40:18 +08:00
feat(hermes): add auxiliary model config
This commit is contained in:
133
tests/hermes-auxiliary-config.test.js
Normal file
133
tests/hermes-auxiliary-config.test.js
Normal file
@@ -0,0 +1,133 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
|
||||
import {
|
||||
buildHermesAuxiliaryConfigValues,
|
||||
mergeHermesAuxiliaryConfig,
|
||||
} from '../scripts/dev-api.js'
|
||||
|
||||
test('Hermes 辅助模型配置读取会提供上游默认值', () => {
|
||||
const values = buildHermesAuxiliaryConfigValues({})
|
||||
|
||||
assert.deepEqual(values, {
|
||||
auxiliaryVisionProvider: 'auto',
|
||||
auxiliaryVisionModel: '',
|
||||
auxiliaryVisionTimeout: 30,
|
||||
auxiliaryVisionDownloadTimeout: 30,
|
||||
auxiliaryWebExtractProvider: 'auto',
|
||||
auxiliaryWebExtractModel: '',
|
||||
auxiliarySessionSearchProvider: 'auto',
|
||||
auxiliarySessionSearchModel: '',
|
||||
auxiliarySessionSearchTimeout: 30,
|
||||
auxiliarySessionSearchMaxConcurrency: 3,
|
||||
})
|
||||
})
|
||||
|
||||
test('Hermes 辅助模型配置读取会回显 YAML 字段', () => {
|
||||
const values = buildHermesAuxiliaryConfigValues({
|
||||
auxiliary: {
|
||||
vision: {
|
||||
provider: 'openrouter',
|
||||
model: 'google/gemini-2.5-flash',
|
||||
timeout: 45,
|
||||
download_timeout: 60,
|
||||
},
|
||||
web_extract: {
|
||||
provider: 'main',
|
||||
model: 'local-summary',
|
||||
},
|
||||
session_search: {
|
||||
provider: 'nous',
|
||||
model: 'gemini-3-flash',
|
||||
timeout: 50,
|
||||
max_concurrency: 5,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(values.auxiliaryVisionProvider, 'openrouter')
|
||||
assert.equal(values.auxiliaryVisionModel, 'google/gemini-2.5-flash')
|
||||
assert.equal(values.auxiliaryVisionTimeout, 45)
|
||||
assert.equal(values.auxiliaryVisionDownloadTimeout, 60)
|
||||
assert.equal(values.auxiliaryWebExtractProvider, 'main')
|
||||
assert.equal(values.auxiliaryWebExtractModel, 'local-summary')
|
||||
assert.equal(values.auxiliarySessionSearchProvider, 'nous')
|
||||
assert.equal(values.auxiliarySessionSearchModel, 'gemini-3-flash')
|
||||
assert.equal(values.auxiliarySessionSearchTimeout, 50)
|
||||
assert.equal(values.auxiliarySessionSearchMaxConcurrency, 5)
|
||||
})
|
||||
|
||||
test('Hermes 辅助模型配置保存会保留未知字段并写入上游结构', () => {
|
||||
const next = mergeHermesAuxiliaryConfig({
|
||||
model: { provider: 'anthropic' },
|
||||
auxiliary: {
|
||||
vision: {
|
||||
provider: 'auto',
|
||||
custom_flag: 'keep-vision',
|
||||
},
|
||||
web_extract: {
|
||||
custom_flag: 'keep-web',
|
||||
},
|
||||
session_search: {
|
||||
extra_body: { enable_thinking: false },
|
||||
custom_flag: 'keep-search',
|
||||
},
|
||||
custom_task: {
|
||||
provider: 'main',
|
||||
},
|
||||
},
|
||||
streaming: { enabled: true },
|
||||
}, {
|
||||
auxiliaryVisionProvider: 'codex',
|
||||
auxiliaryVisionModel: 'gpt-5.3-codex',
|
||||
auxiliaryVisionTimeout: '40',
|
||||
auxiliaryVisionDownloadTimeout: '55',
|
||||
auxiliaryWebExtractProvider: 'gemini',
|
||||
auxiliaryWebExtractModel: 'gemini-3-flash',
|
||||
auxiliarySessionSearchProvider: 'ollama-cloud',
|
||||
auxiliarySessionSearchModel: 'gpt-oss:20b',
|
||||
auxiliarySessionSearchTimeout: '70',
|
||||
auxiliarySessionSearchMaxConcurrency: '6',
|
||||
})
|
||||
|
||||
assert.deepEqual(next.model, { provider: 'anthropic' })
|
||||
assert.deepEqual(next.streaming, { enabled: true })
|
||||
assert.equal(next.auxiliary.vision.provider, 'codex')
|
||||
assert.equal(next.auxiliary.vision.model, 'gpt-5.3-codex')
|
||||
assert.equal(next.auxiliary.vision.timeout, 40)
|
||||
assert.equal(next.auxiliary.vision.download_timeout, 55)
|
||||
assert.equal(next.auxiliary.vision.custom_flag, 'keep-vision')
|
||||
assert.equal(next.auxiliary.web_extract.provider, 'gemini')
|
||||
assert.equal(next.auxiliary.web_extract.model, 'gemini-3-flash')
|
||||
assert.equal(next.auxiliary.web_extract.custom_flag, 'keep-web')
|
||||
assert.equal(next.auxiliary.session_search.provider, 'ollama-cloud')
|
||||
assert.equal(next.auxiliary.session_search.model, 'gpt-oss:20b')
|
||||
assert.equal(next.auxiliary.session_search.timeout, 70)
|
||||
assert.equal(next.auxiliary.session_search.max_concurrency, 6)
|
||||
assert.deepEqual(next.auxiliary.session_search.extra_body, { enable_thinking: false })
|
||||
assert.equal(next.auxiliary.session_search.custom_flag, 'keep-search')
|
||||
assert.deepEqual(next.auxiliary.custom_task, { provider: 'main' })
|
||||
})
|
||||
|
||||
test('Hermes 辅助模型配置保存会拒绝非法 provider、模型名和越界值', () => {
|
||||
assert.throws(
|
||||
() => mergeHermesAuxiliaryConfig({}, { auxiliaryVisionProvider: 'bad-provider' }),
|
||||
/auxiliary\.vision\.provider/,
|
||||
)
|
||||
assert.throws(
|
||||
() => mergeHermesAuxiliaryConfig({}, { auxiliaryVisionModel: '../secret' }),
|
||||
/auxiliary\.vision\.model/,
|
||||
)
|
||||
assert.throws(
|
||||
() => mergeHermesAuxiliaryConfig({}, { auxiliaryVisionTimeout: '0' }),
|
||||
/auxiliary\.vision\.timeout/,
|
||||
)
|
||||
assert.throws(
|
||||
() => mergeHermesAuxiliaryConfig({}, { auxiliaryVisionDownloadTimeout: '0' }),
|
||||
/auxiliary\.vision\.download_timeout/,
|
||||
)
|
||||
assert.throws(
|
||||
() => mergeHermesAuxiliaryConfig({}, { auxiliarySessionSearchMaxConcurrency: '0' }),
|
||||
/auxiliary\.session_search\.max_concurrency/,
|
||||
)
|
||||
})
|
||||
@@ -150,6 +150,24 @@ test('Hermes 配置页会暴露提示缓存结构化配置字段', () => {
|
||||
}
|
||||
})
|
||||
|
||||
test('Hermes 配置页会暴露辅助模型结构化配置字段', () => {
|
||||
for (const id of [
|
||||
'hm-auxiliary-save',
|
||||
'hm-auxiliary-vision-provider',
|
||||
'hm-auxiliary-vision-model',
|
||||
'hm-auxiliary-vision-timeout',
|
||||
'hm-auxiliary-vision-download-timeout',
|
||||
'hm-auxiliary-web-extract-provider',
|
||||
'hm-auxiliary-web-extract-model',
|
||||
'hm-auxiliary-session-search-provider',
|
||||
'hm-auxiliary-session-search-model',
|
||||
'hm-auxiliary-session-search-timeout',
|
||||
'hm-auxiliary-session-search-max-concurrency',
|
||||
]) {
|
||||
assert.match(source, new RegExp(`id="${id}"`), `缺少 ${id}`)
|
||||
}
|
||||
})
|
||||
|
||||
test('Hermes 配置页会暴露网关流式结构化配置字段', () => {
|
||||
for (const id of [
|
||||
'hm-streaming-save',
|
||||
@@ -316,6 +334,7 @@ test('Hermes 配置页新增结构化配置不会暴露翻译 key', () => {
|
||||
key.includes('HumanDelayConfig') ||
|
||||
key.includes('DisplayConfig') ||
|
||||
key.includes('PromptCachingConfig') ||
|
||||
key.includes('AuxiliaryConfig') ||
|
||||
key.includes('StreamingConfig') ||
|
||||
key.includes('ExecutionLimits') ||
|
||||
key.includes('PrivacyConfig') ||
|
||||
|
||||
Reference in New Issue
Block a user