feat(hermes): add execution limits config form

This commit is contained in:
晴天
2026-05-24 19:28:30 +08:00
parent c0b40070c0
commit 122d7a63be
10 changed files with 834 additions and 9 deletions

View File

@@ -3322,6 +3322,7 @@ function normalizeHermesPlatform(platform) {
const HERMES_SESSION_RESET_MODES = new Set(['both', 'idle', 'daily', 'none'])
const HERMES_STREAMING_TRANSPORTS = new Set(['auto', 'draft', 'edit', 'off'])
const HERMES_CODE_EXECUTION_MODES = new Set(['project', 'strict'])
const HERMES_DISPLAY_TOOL_PROGRESS_VALUES = new Set(['off', 'new', 'all', 'verbose'])
const HERMES_DISPLAY_STREAMING_VALUES = new Set(['inherit', 'true', 'false'])
@@ -3382,6 +3383,13 @@ function normalizeHermesStreamingTransport(value, strict = false) {
return 'edit'
}
function normalizeHermesCodeExecutionMode(value, strict = false) {
const mode = String(value ?? '').trim().toLowerCase() || 'project'
if (HERMES_CODE_EXECUTION_MODES.has(mode)) return mode
if (strict) throw new Error('code_execution.mode 必须是 project 或 strict')
return 'project'
}
function normalizeHermesDisplayToolProgress(value, strict = false, key = 'display.tool_progress') {
const progress = String(value ?? '').trim().toLowerCase() || 'all'
if (HERMES_DISPLAY_TOOL_PROGRESS_VALUES.has(progress)) return progress
@@ -3585,6 +3593,53 @@ export function mergeHermesStreamingConfig(config = {}, form = {}) {
return next
}
export function buildHermesExecutionLimitsConfigValues(config = {}) {
const root = config && typeof config === 'object' && !Array.isArray(config) ? config : {}
const codeExecution = root.code_execution && typeof root.code_execution === 'object' && !Array.isArray(root.code_execution)
? root.code_execution
: {}
const delegation = root.delegation && typeof root.delegation === 'object' && !Array.isArray(root.delegation)
? root.delegation
: {}
return {
codeExecutionMode: normalizeHermesCodeExecutionMode(codeExecution.mode, false),
codeExecutionTimeout: parseHermesInteger(codeExecution.timeout, 'code_execution.timeout', 300, 1, 86400, false),
codeExecutionMaxToolCalls: parseHermesInteger(codeExecution.max_tool_calls, 'code_execution.max_tool_calls', 50, 1, 10000, false),
delegationMaxIterations: parseHermesInteger(delegation.max_iterations, 'delegation.max_iterations', 50, 1, 1000, false),
delegationChildTimeoutSeconds: parseHermesInteger(delegation.child_timeout_seconds, 'delegation.child_timeout_seconds', 600, 30, 86400, false),
delegationMaxConcurrentChildren: parseHermesInteger(delegation.max_concurrent_children, 'delegation.max_concurrent_children', 3, 1, 100, false),
delegationMaxSpawnDepth: parseHermesInteger(delegation.max_spawn_depth, 'delegation.max_spawn_depth', 1, 1, 3, false),
delegationOrchestratorEnabled: readHermesBool(delegation.orchestrator_enabled, true),
delegationSubagentAutoApprove: readHermesBool(delegation.subagent_auto_approve, false),
delegationInheritMcpToolsets: readHermesBool(delegation.inherit_mcp_toolsets, true),
}
}
export function mergeHermesExecutionLimitsConfig(config = {}, form = {}) {
const next = mergeConfigsPreservingFields({}, config && typeof config === 'object' && !Array.isArray(config) ? config : {})
const currentValues = buildHermesExecutionLimitsConfigValues(next)
const codeExecution = next.code_execution && typeof next.code_execution === 'object' && !Array.isArray(next.code_execution)
? mergeConfigsPreservingFields(next.code_execution, {})
: {}
const delegation = next.delegation && typeof next.delegation === 'object' && !Array.isArray(next.delegation)
? mergeConfigsPreservingFields(next.delegation, {})
: {}
codeExecution.mode = normalizeHermesCodeExecutionMode(Object.hasOwn(form, 'codeExecutionMode') ? form.codeExecutionMode : currentValues.codeExecutionMode, true)
codeExecution.timeout = parseHermesInteger(Object.hasOwn(form, 'codeExecutionTimeout') ? form.codeExecutionTimeout : currentValues.codeExecutionTimeout, 'code_execution.timeout', 300, 1, 86400, true)
codeExecution.max_tool_calls = parseHermesInteger(Object.hasOwn(form, 'codeExecutionMaxToolCalls') ? form.codeExecutionMaxToolCalls : currentValues.codeExecutionMaxToolCalls, 'code_execution.max_tool_calls', 50, 1, 10000, true)
delegation.max_iterations = parseHermesInteger(Object.hasOwn(form, 'delegationMaxIterations') ? form.delegationMaxIterations : currentValues.delegationMaxIterations, 'delegation.max_iterations', 50, 1, 1000, true)
delegation.child_timeout_seconds = parseHermesInteger(Object.hasOwn(form, 'delegationChildTimeoutSeconds') ? form.delegationChildTimeoutSeconds : currentValues.delegationChildTimeoutSeconds, 'delegation.child_timeout_seconds', 600, 30, 86400, true)
delegation.max_concurrent_children = parseHermesInteger(Object.hasOwn(form, 'delegationMaxConcurrentChildren') ? form.delegationMaxConcurrentChildren : currentValues.delegationMaxConcurrentChildren, 'delegation.max_concurrent_children', 3, 1, 100, true)
delegation.max_spawn_depth = parseHermesInteger(Object.hasOwn(form, 'delegationMaxSpawnDepth') ? form.delegationMaxSpawnDepth : currentValues.delegationMaxSpawnDepth, 'delegation.max_spawn_depth', 1, 1, 3, true)
delegation.orchestrator_enabled = formHermesBool(form, 'delegationOrchestratorEnabled', currentValues.delegationOrchestratorEnabled)
delegation.subagent_auto_approve = formHermesBool(form, 'delegationSubagentAutoApprove', currentValues.delegationSubagentAutoApprove)
delegation.inherit_mcp_toolsets = formHermesBool(form, 'delegationInheritMcpToolsets', currentValues.delegationInheritMcpToolsets)
next.code_execution = codeExecution
next.delegation = delegation
return next
}
export function buildHermesSessionRuntimeConfigValues(config = {}) {
const root = config && typeof config === 'object' && !Array.isArray(config) ? config : {}
const sessionReset = root.session_reset && typeof root.session_reset === 'object' && !Array.isArray(root.session_reset)
@@ -9955,6 +10010,27 @@ const handlers = {
}
},
hermes_execution_limits_config_read() {
const { configPath, exists, config } = readHermesConfigYamlObject()
return {
exists,
configPath,
values: buildHermesExecutionLimitsConfigValues(config),
}
},
hermes_execution_limits_config_save({ form } = {}) {
const { configPath, config } = readHermesConfigYamlObject()
const next = mergeHermesExecutionLimitsConfig(config, form || {})
const backup = writeHermesConfigYamlObject(configPath, next)
return {
ok: true,
configPath,
backup,
values: buildHermesExecutionLimitsConfigValues(next),
}
},
// P1-3 lazy_deps: Web 模式下不能调 venv python但仍提供 feature 列表 + 提示用户走桌面端装
hermes_lazy_deps_features() {
const features = [