diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/__tests__/index.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/__tests__/index.spec.tsx index 77a9530d9d8..5594dbf1146 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/__tests__/index.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/__tests__/index.spec.tsx @@ -388,6 +388,23 @@ describe('ModelParameterModal', () => { expect(screen.getByText(/debugAsSingleModel/i)).toBeInTheDocument() }) + it('should append the first token timeout parameter only in workflow advanced mode', () => { + render() + + openSettings() + + expect(screen.getByTestId('param-first_token_timeout')).toBeInTheDocument() + }) + + it('should not append the first token timeout parameter outside workflow', () => { + render() + + openSettings() + + expect(screen.getByTestId('param-stop')).toBeInTheDocument() + expect(screen.queryByTestId('param-first_token_timeout')).not.toBeInTheDocument() + }) + it('should render the empty loading fallback when rules resolve to an empty list', () => { parameterRules = [] isRulesLoading = true diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/index.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/index.tsx index afa0bad04dc..1d30756a1f9 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/index.tsx @@ -9,7 +9,11 @@ import { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { ArrowNarrowLeft } from '@/app/components/base/icons/src/vender/line/arrows' import Loading from '@/app/components/base/loading' -import { PROVIDER_WITH_PRESET_TONE, STOP_PARAMETER_RULE } from '@/config' +import { + FIRST_TOKEN_TIMEOUT_PARAMETER_RULE, + PROVIDER_WITH_PRESET_TONE, + STOP_PARAMETER_RULE, +} from '@/config' import { useModelParameterRules } from '@/service/use-common' import { useTextGenerationCurrentProviderAndModelAndModelList } from '../hooks' import ModelSelector from '../model-selector' @@ -216,22 +220,24 @@ const ModelParameterModal: FC = ({ ) : ( - [...parameterRules, ...(isAdvancedMode ? [STOP_PARAMETER_RULE] : [])].map( - (parameter) => ( - handleParamChange(parameter.name, v)} - onSwitch={(checked, assignValue) => - handleSwitch(parameter.name, checked, assignValue) - } - isInWorkflow={isInWorkflow} - nodesOutputVars={nodesOutputVars} - availableNodes={availableNodes} - /> - ), - ) + [ + ...parameterRules, + ...(isAdvancedMode ? [STOP_PARAMETER_RULE] : []), + ...(isAdvancedMode && isInWorkflow ? [FIRST_TOKEN_TIMEOUT_PARAMETER_RULE] : []), + ].map((parameter) => ( + handleParamChange(parameter.name, v)} + onSwitch={(checked, assignValue) => + handleSwitch(parameter.name, checked, assignValue) + } + isInWorkflow={isInWorkflow} + nodesOutputVars={nodesOutputVars} + availableNodes={availableNodes} + /> + )) )} )} diff --git a/web/config/index.ts b/web/config/index.ts index 4a1cad99164..eb10270bad5 100644 --- a/web/config/index.ts +++ b/web/config/index.ts @@ -328,6 +328,27 @@ export const STOP_PARAMETER_RULE: ModelParameterRule = { }, } +// Synthetic rule consumed by the Dify backend before the request reaches the +// model provider; only enforced for workflow LLM-compatible nodes. +export const FIRST_TOKEN_TIMEOUT_PARAMETER_RULE: ModelParameterRule = { + default: 60, + min: 1, + max: 1800, + precision: 0, + help: { + en_US: + 'Max seconds to wait for the first streamed token. On timeout the node fails; combine with node retry to re-run it automatically.', + zh_Hans: '等待首个流式 Token 的最长秒数。超时后节点失败,可配合节点重试自动重跑。', + }, + label: { + en_US: 'First token timeout', + zh_Hans: '首个 Token 超时', + }, + name: 'first_token_timeout', + required: false, + type: 'int', +} + export const PARTNER_STACK_CONFIG = { cookieName: 'partner_stack_info', saveCookieDays: 90,