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,