feat: Add mutual exclusion between structured output and tools in LLM

node
This commit is contained in:
zhsama 2026-02-04 22:28:26 +08:00
parent e0082dbf18
commit 9bd714623e
22 changed files with 314 additions and 105 deletions

View File

@ -151,6 +151,7 @@ export type PromptEditorProps = {
agentBlock?: AgentBlockType
isSupportFileVar?: boolean
isSupportSandbox?: boolean
disableToolBlocks?: boolean
}
const PromptEditor: FC<PromptEditorProps> = ({
@ -180,6 +181,7 @@ const PromptEditor: FC<PromptEditorProps> = ({
agentBlock,
isSupportFileVar,
isSupportSandbox,
disableToolBlocks,
}) => {
const { eventEmitter } = useEventEmitterContextContext()
const initialConfig = {
@ -239,36 +241,49 @@ const PromptEditor: FC<PromptEditorProps> = ({
}
}, [onToolMetadataChange, toolMetadata])
const sandboxPlaceHolder = React.useMemo(
() => {
return isSupportSandbox && (
<Trans
i18nKey="promptEditor.placeholderSandbox"
ns="common"
components={[
<span
key="slash"
className="system-kbd inline-flex h-5 min-w-5 items-center justify-center rounded-[4px] bg-components-kbd-bg-gray px-1 text-text-tertiary"
/>,
<span
key="insert"
className="border-b border-dotted border-current"
/>,
<span
key="at"
className="system-kbd inline-flex h-5 min-w-5 items-center justify-center rounded-[4px] bg-components-kbd-bg-gray px-1 text-text-tertiary"
/>,
<span
key="tools"
className="border-b border-dotted border-current"
/>,
]}
/>
)
},
[isSupportSandbox],
)
const sandboxPlaceHolder = React.useMemo(() => {
if (!isSupportSandbox)
return null
const i18nKey = disableToolBlocks
? 'promptEditor.placeholderSandboxNoTools'
: 'promptEditor.placeholderSandbox'
const components = disableToolBlocks
? [
<span
key="slash"
className="system-kbd inline-flex h-5 min-w-5 items-center justify-center rounded-[4px] bg-components-kbd-bg-gray px-1 text-text-tertiary"
/>,
<span
key="insert"
className="border-b border-dotted border-current"
/>,
]
: [
<span
key="slash"
className="system-kbd inline-flex h-5 min-w-5 items-center justify-center rounded-[4px] bg-components-kbd-bg-gray px-1 text-text-tertiary"
/>,
<span
key="insert"
className="border-b border-dotted border-current"
/>,
<span
key="at"
className="system-kbd inline-flex h-5 min-w-5 items-center justify-center rounded-[4px] bg-components-kbd-bg-gray px-1 text-text-tertiary"
/>,
<span
key="tools"
className="border-b border-dotted border-current"
/>,
]
return (
<Trans
i18nKey={i18nKey}
ns="common"
components={components}
/>
)
}, [disableToolBlocks, isSupportSandbox])
return (
<LexicalComposer initialConfig={{ ...initialConfig, editable }}>
@ -332,7 +347,7 @@ const PromptEditor: FC<PromptEditorProps> = ({
<ToolBlock />
<ToolGroupBlockReplacementBlock />
<ToolBlockReplacementBlock />
{editable && <ToolPickerBlock />}
{editable && !disableToolBlocks && <ToolPickerBlock />}
</>
)}
<ComponentPickerBlock

View File

@ -85,6 +85,7 @@ type Props = {
required?: boolean
onBlur?: () => void
onFocus?: () => void
disableToolBlocks?: boolean
}
const Editor: FC<Props> = ({
@ -129,6 +130,7 @@ const Editor: FC<Props> = ({
required,
onBlur,
onFocus,
disableToolBlocks,
}) => {
const { t } = useTranslation()
const { eventEmitter } = useEventEmitterContextContext()
@ -312,6 +314,7 @@ const Editor: FC<Props> = ({
editable={!readOnly}
isSupportFileVar={isSupportFileVar}
isSupportSandbox={isSupportSandbox}
disableToolBlocks={disableToolBlocks}
toolMetadata={promptMetadata}
onToolMetadataChange={onPromptMetadataChange}
/>

View File

@ -13,6 +13,9 @@ const i18nPrefix = 'nodes.llm.computerUse'
type Props = {
readonly: boolean
isDisabledByStructuredOutput?: boolean
disabled?: boolean
disabledTip?: string
enabled: boolean
onChange: (enabled: boolean) => void
nodeId: string
@ -22,6 +25,9 @@ type Props = {
const ComputerUseConfig: FC<Props> = ({
readonly,
isDisabledByStructuredOutput,
disabled,
disabledTip,
enabled,
onChange,
nodeId,
@ -29,6 +35,8 @@ const ComputerUseConfig: FC<Props> = ({
promptTemplateKey,
}) => {
const { t } = useTranslation()
const disabledByStructuredOutput = isDisabledByStructuredOutput ?? disabled ?? false
const isDisabled = readonly || disabledByStructuredOutput
return (
<div>
@ -46,12 +54,17 @@ const ComputerUseConfig: FC<Props> = ({
noXSpacing
operations={(
<div>
<Switch
size="md"
disabled={readonly}
defaultValue={enabled}
onChange={onChange}
/>
<Tooltip
disabled={!disabledTip}
popupContent={disabledTip}
>
<Switch
size="md"
disabled={isDisabled}
defaultValue={enabled}
onChange={onChange}
/>
</Tooltip>
</div>
)}
>
@ -63,7 +76,8 @@ const ComputerUseConfig: FC<Props> = ({
</div>
<ReferenceToolConfig
readonly={readonly}
enabled={enabled}
isDisabledByStructuredOutput={disabledByStructuredOutput}
isComputerUseEnabled={enabled}
nodeId={nodeId}
toolSettings={toolSettings}
promptTemplateKey={promptTemplateKey}

View File

@ -43,6 +43,7 @@ type Props = {
modelConfig?: ModelConfig
isSupportSandbox?: boolean
onPromptEditorBlur?: () => void
disableToolBlocks?: boolean
}
const roleOptions = [
@ -88,6 +89,7 @@ const ConfigPromptItem: FC<Props> = ({
modelConfig,
isSupportSandbox,
onPromptEditorBlur,
disableToolBlocks,
}) => {
const { t } = useTranslation()
const workflowStore = useWorkflowStore()
@ -158,6 +160,7 @@ const ConfigPromptItem: FC<Props> = ({
handleAddVariable={handleAddVariable}
isSupportFileVar
isSupportSandbox={isSupportSandbox}
disableToolBlocks={disableToolBlocks}
onBlur={onPromptEditorBlur}
/>
)

View File

@ -66,6 +66,7 @@ type Props = {
handleAddVariable: (payload: any) => void
modelConfig: ModelConfig
onPromptEditorBlur?: () => void
disableToolBlocks?: boolean
}
const ConfigPrompt: FC<Props> = ({
@ -82,6 +83,7 @@ const ConfigPrompt: FC<Props> = ({
handleAddVariable,
modelConfig,
onPromptEditorBlur,
disableToolBlocks,
}) => {
const { t } = useTranslation()
const workflowStore = useWorkflowStore()
@ -361,6 +363,7 @@ const ConfigPrompt: FC<Props> = ({
modelConfig={modelConfig}
isSupportSandbox={isSupportSandbox}
onPromptEditorBlur={onPromptEditorBlur}
disableToolBlocks={disableToolBlocks}
/>
</div>
)
@ -438,6 +441,7 @@ const ConfigPrompt: FC<Props> = ({
modelConfig={modelConfig}
isSupportSandbox={isSupportSandbox}
onBlur={onPromptEditorBlur}
disableToolBlocks={disableToolBlocks}
/>
</div>
)}

View File

@ -1,40 +1,36 @@
'use client'
import type { FC } from 'react'
import type { LLMNodeType, ToolSetting } from '../types'
import type { ToolDependency } from '@/app/components/workflow/nodes/llm/use-node-skills'
import type { ToolWithProvider } from '@/app/components/workflow/types'
import type { Locale } from '@/i18n-config/language'
import { useQuery } from '@tanstack/react-query'
import * as React from 'react'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useStore as useAppStore } from '@/app/components/app/store'
import AppIcon from '@/app/components/base/app-icon'
import { DefaultToolIcon } from '@/app/components/base/icons/src/public/other'
import { ArrowDownRoundFill } from '@/app/components/base/icons/src/vender/solid/general'
import { SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton'
import Switch from '@/app/components/base/switch'
import { useNodeCurdKit } from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
import { useNodeSkills } from '@/app/components/workflow/nodes/llm/use-node-skills'
import useTheme from '@/hooks/use-theme'
import { getLanguage } from '@/i18n-config/language'
import { consoleClient, consoleQuery } from '@/service/client'
import { useAllBuiltInTools, useAllCustomTools, useAllMCPTools, useAllWorkflowTools } from '@/service/use-tools'
import { cn } from '@/utils/classnames'
import { getIconFromMarketPlace } from '@/utils/get-icon'
type ReferenceToolConfigProps = {
readonly: boolean
enabled: boolean
isDisabledByStructuredOutput?: boolean
isComputerUseEnabled?: boolean
disabledByStructuredOutput?: boolean
computerUseEnabled?: boolean
nodeId: string
toolSettings?: ToolSetting[]
promptTemplateKey: string
}
type ToolDependency = {
type: string
provider: string
tool_name: string
}
type ToolProviderGroup = {
id: string
actions: ToolDependency[]
@ -42,14 +38,18 @@ type ToolProviderGroup = {
const ReferenceToolConfig: FC<ReferenceToolConfigProps> = ({
readonly,
enabled,
isDisabledByStructuredOutput,
isComputerUseEnabled,
disabledByStructuredOutput,
computerUseEnabled,
nodeId,
toolSettings,
promptTemplateKey,
}) => {
const isDisabled = readonly || !enabled
const resolvedIsComputerUseEnabled = isComputerUseEnabled ?? computerUseEnabled ?? false
const resolvedIsDisabledByStructuredOutput = isDisabledByStructuredOutput ?? disabledByStructuredOutput ?? false
const isReferenceToolsDisabled = readonly || !resolvedIsComputerUseEnabled || resolvedIsDisabledByStructuredOutput
const { i18n, t } = useTranslation()
const appId = useAppStore(s => s.appDetail?.id)
const { handleNodeDataUpdate } = useNodeCurdKit<LLMNodeType>(nodeId)
const { theme } = useTheme()
const { data: buildInTools } = useAllBuiltInTools()
@ -58,34 +58,11 @@ const ReferenceToolConfig: FC<ReferenceToolConfigProps> = ({
const { data: mcpTools } = useAllMCPTools()
const locale = useMemo(() => getLanguage(i18n.language as Locale), [i18n.language])
const queryKey = useMemo(() => {
return [
...consoleQuery.workflowDraft.nodeSkills.queryKey({
input: {
params: {
appId: appId ?? '',
nodeId,
},
},
}),
promptTemplateKey,
]
}, [appId, nodeId, promptTemplateKey])
const { data, isLoading } = useQuery({
queryKey,
queryFn: () => consoleClient.workflowDraft.nodeSkills({
params: {
appId: appId ?? '',
nodeId,
},
}),
enabled: !!appId && !!nodeId,
placeholderData: previous => previous,
const { toolDependencies, isLoading, isQueryEnabled, hasData } = useNodeSkills({
nodeId,
promptTemplateKey,
})
const toolDependencies = useMemo<ToolDependency[]>(() => data?.tool_dependencies ?? [], [data?.tool_dependencies])
const providers = useMemo<ToolProviderGroup[]>(() => {
const map = new Map<string, ToolDependency[]>()
toolDependencies.forEach((tool) => {
@ -214,8 +191,7 @@ const ReferenceToolConfig: FC<ReferenceToolConfigProps> = ({
}))
}, [])
const isQueryEnabled = !!appId && !!nodeId
const isInitialLoading = isQueryEnabled && isLoading && !data
const isInitialLoading = isQueryEnabled && isLoading && !hasData
const showNoData = !isInitialLoading && providers.length === 0
const renderProviderIcon = useCallback((providerId: string) => {
@ -244,7 +220,7 @@ const ReferenceToolConfig: FC<ReferenceToolConfigProps> = ({
}, [iconErrorMap, providerIcons])
return (
<div className={cn('flex flex-col gap-2', isDisabled && 'opacity-50')}>
<div className={cn('flex flex-col gap-2', isReferenceToolsDisabled && 'opacity-50')}>
{isInitialLoading && [0, 1].map(index => (
<div
key={`loading-provider-${index}`}
@ -296,7 +272,7 @@ const ReferenceToolConfig: FC<ReferenceToolConfigProps> = ({
key={`${action.type}-${action.provider}-${action.tool_name}`}
className={cn(
'relative flex h-7 items-center justify-between rounded-md pl-9 pr-2',
!isDisabled && 'hover:bg-state-base-hover',
!isReferenceToolsDisabled && 'hover:bg-state-base-hover',
)}
>
<div className="absolute left-[15px] top-0 h-full w-[2px] bg-divider-subtle" />
@ -307,7 +283,7 @@ const ReferenceToolConfig: FC<ReferenceToolConfigProps> = ({
</div>
<Switch
size="md"
disabled={isDisabled}
disabled={isReferenceToolsDisabled}
defaultValue={resolveToolEnabled(action)}
onChange={value => handleToolEnabledChange(action, value)}
/>

View File

@ -1,8 +1,10 @@
import type { ToolValue } from '@/app/components/workflow/block-selector/types'
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
import Tooltip from '@/app/components/base/tooltip'
import MultipleToolSelector from '@/app/components/plugins/plugin-detail-panel/multiple-tool-selector'
import { BoxGroup } from '@/app/components/workflow/nodes/_base/components/layout'
import { cn } from '@/utils/classnames'
import MaxIterations from './max-iterations'
import { useNodeTools } from './use-node-tools'
@ -11,14 +13,19 @@ type ToolsProps = {
tools?: ToolValue[]
maxIterations?: number
hideMaxIterations?: boolean
disabled?: boolean
disabledTip?: string
}
const Tools = ({
nodeId,
tools = [],
maxIterations = 10,
hideMaxIterations = false,
disabled,
disabledTip,
}: ToolsProps) => {
const { t } = useTranslation()
const isDisabled = !!disabled
const {
handleToolsChange,
handleMaxIterationsChange,
@ -34,22 +41,32 @@ const Tools = ({
className: 'px-0',
}}
>
<MultipleToolSelector
nodeId={nodeId}
nodeOutputVars={[]}
availableNodes={[]}
value={tools}
label={t(`nodes.llm.tools.title`, { ns: 'workflow' })}
tooltip={t(`nodes.llm.tools.title`, { ns: 'workflow' })}
onChange={handleToolsChange}
supportCollapse
/>
{!hideMaxIterations && (
<MaxIterations
value={maxIterations}
onChange={handleMaxIterationsChange}
/>
)}
<Tooltip
disabled={!disabledTip}
popupContent={disabledTip}
>
<div className={cn(isDisabled && 'opacity-50')}>
<div className={cn(isDisabled && 'pointer-events-none')}>
<MultipleToolSelector
nodeId={nodeId}
nodeOutputVars={[]}
availableNodes={[]}
value={tools}
label={t('nodes.llm.tools.title', { ns: 'workflow' })}
tooltip={t('nodes.llm.tools.title', { ns: 'workflow' })}
onChange={handleToolsChange}
supportCollapse
disabled={isDisabled}
/>
{!hideMaxIterations && (
<MaxIterations
value={maxIterations}
onChange={handleMaxIterationsChange}
/>
)}
</div>
</div>
</Tooltip>
</BoxGroup>
)
}

View File

@ -29,6 +29,8 @@ import Tools from './components/tools'
import MaxIterations from './components/tools/max-iterations'
import { useNodeTools } from './components/tools/use-node-tools'
import useConfig from './use-config'
import { useNodeSkills } from './use-node-skills'
import { useStructuredOutputMutualExclusion } from './use-structured-output-mutual-exclusion'
const i18nPrefix = 'nodes.llm'
@ -91,6 +93,27 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
scheduleSkillsRefresh(promptTemplateKey)
}, [promptTemplateKey, scheduleSkillsRefresh])
const { toolDependencies } = useNodeSkills({
nodeId: id,
promptTemplateKey: skillsRefreshKey,
enabled: isSupportSandbox,
})
const {
isStructuredOutputBlocked,
isComputerUseBlocked,
isToolsBlocked,
disableToolBlocks,
structuredOutputDisabledTip,
computerUseDisabledTip,
toolsDisabledTip,
} = useStructuredOutputMutualExclusion({
inputs,
readOnly,
isSupportSandbox,
toolDependencies,
})
const {
handleMaxIterationsChange,
} = useNodeTools(id)
@ -162,6 +185,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
handleAddVariable={handleAddVariable}
modelConfig={model}
onPromptEditorBlur={handlePromptEditorBlur}
disableToolBlocks={disableToolBlocks}
/>
)}
@ -248,6 +272,8 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
<>
<ComputerUseConfig
readonly={readOnly}
isDisabledByStructuredOutput={isComputerUseBlocked}
disabledTip={computerUseDisabledTip}
enabled={!!inputs.computer_use}
onChange={handleComputerUseChange}
nodeId={id}
@ -262,6 +288,8 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
tools={inputs.tools}
maxIterations={inputs.max_iterations}
hideMaxIterations
disabled={isToolsBlocked}
disabledTip={toolsDisabledTip}
/>
)}
</div>
@ -364,13 +392,19 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
<RiQuestionLine className="size-3.5 text-text-quaternary" />
</div>
</Tooltip>
<Switch
className="ml-2"
defaultValue={!!inputs.structured_output_enabled}
onChange={handleStructureOutputEnableChange}
size="md"
disabled={readOnly}
/>
<Tooltip
disabled={!structuredOutputDisabledTip}
popupContent={structuredOutputDisabledTip}
>
<div className="ml-2">
<Switch
defaultValue={!!inputs.structured_output_enabled}
onChange={handleStructureOutputEnableChange}
size="md"
disabled={isStructuredOutputBlocked}
/>
</div>
</Tooltip>
</div>
)}
>

View File

@ -0,0 +1,63 @@
'use client'
import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'
import { useStore as useAppStore } from '@/app/components/app/store'
import { consoleClient, consoleQuery } from '@/service/client'
export type ToolDependency = {
type: string
provider: string
tool_name: string
}
type UseNodeSkillsParams = {
nodeId: string
promptTemplateKey: string
enabled?: boolean
}
export function useNodeSkills({ nodeId, promptTemplateKey, enabled = true }: UseNodeSkillsParams) {
const appId = useAppStore(s => s.appDetail?.id)
const isQueryEnabled = enabled && !!appId && !!nodeId
const queryKey = useMemo(() => {
return [
...consoleQuery.workflowDraft.nodeSkills.queryKey({
input: {
params: {
appId: appId ?? '',
nodeId,
},
},
}),
promptTemplateKey,
]
}, [appId, nodeId, promptTemplateKey])
const { data, isLoading } = useQuery({
queryKey,
queryFn: () => consoleClient.workflowDraft.nodeSkills({
params: {
appId: appId ?? '',
nodeId,
},
}),
enabled: isQueryEnabled,
placeholderData: previous => previous,
})
const toolDependencies = useMemo<ToolDependency[]>(
() => data?.tool_dependencies ?? [],
[data?.tool_dependencies],
)
const hasData = !!data
return {
toolDependencies,
isLoading,
isQueryEnabled,
hasData,
}
}

View File

@ -0,0 +1,59 @@
import type { LLMNodeType } from './types'
import type { ToolDependency } from './use-node-skills'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
type Params = {
inputs: LLMNodeType
readOnly: boolean
isSupportSandbox: boolean
toolDependencies: ToolDependency[]
}
export const useStructuredOutputMutualExclusion = ({
inputs,
readOnly,
isSupportSandbox,
toolDependencies,
}: Params) => {
const { t } = useTranslation()
const isStructuredOutputEnabled = !!inputs.structured_output_enabled
const hasToolDependencies = isSupportSandbox && toolDependencies.length > 0
const hasEnabledTools = (inputs.tools?.length ?? 0) > 0
const hasToolConflict = !!inputs.computer_use || hasToolDependencies || hasEnabledTools
const isStructuredOutputBlocked = readOnly || (hasToolConflict && !isStructuredOutputEnabled)
const isComputerUseBlocked = readOnly || (isStructuredOutputEnabled && !inputs.computer_use)
const isToolsBlocked = readOnly || isStructuredOutputEnabled
const disableToolBlocks = isStructuredOutputEnabled
const structuredOutputDisabledTip = useMemo(() => {
if (readOnly || !isStructuredOutputBlocked)
return ''
return inputs.computer_use
? t('structOutput.disabledByComputerUse', { ns: 'app' })
: t('structOutput.disabledByTools', { ns: 'app' })
}, [inputs.computer_use, isStructuredOutputBlocked, readOnly, t])
const computerUseDisabledTip = useMemo(() => {
if (readOnly || !isComputerUseBlocked)
return ''
return t('nodes.llm.computerUse.disabledByStructuredOutput', { ns: 'workflow' })
}, [isComputerUseBlocked, readOnly, t])
const toolsDisabledTip = useMemo(() => {
if (readOnly || !isToolsBlocked)
return ''
return t('nodes.llm.tools.disabledByStructuredOutput', { ns: 'workflow' })
}, [isToolsBlocked, readOnly, t])
return {
isStructuredOutputBlocked,
isComputerUseBlocked,
isToolsBlocked,
disableToolBlocks,
structuredOutputDisabledTip,
computerUseDisabledTip,
toolsDisabledTip,
}
}

View File

@ -210,6 +210,8 @@
"showMyCreatedAppsOnly": "Created by me",
"structOutput.LLMResponse": "LLM Response",
"structOutput.configure": "Configure",
"structOutput.disabledByComputerUse": "Structured Output is disabled when Computer Use is enabled.",
"structOutput.disabledByTools": "Structured Output is disabled when tools are enabled.",
"structOutput.modelNotSupported": "Model not supported",
"structOutput.modelNotSupportedTip": "The current model does not support this feature and is automatically downgraded to prompt injection.",
"structOutput.moreFillTip": "Showing max 10 levels of nesting",

View File

@ -510,6 +510,7 @@
"promptEditor.history.modal.user": "Hello",
"promptEditor.placeholder": "Write your prompt word here, enter '{' to insert a variable, enter '/' to insert a prompt content block",
"promptEditor.placeholderSandbox": "Write instructions here, <0>/</0> <1>insert</1>, <2>@</2> <3>tools</3>",
"promptEditor.placeholderSandboxNoTools": "Write instructions here, <0>/</0> <1>insert</1>",
"promptEditor.query.item.desc": "Insert user query template",
"promptEditor.query.item.title": "Query",
"promptEditor.skillMarkdown.placeholderPrefix": "Type to write,",

View File

@ -673,6 +673,7 @@
"nodes.llm.addContext": "Add Context",
"nodes.llm.addMessage": "Add Message",
"nodes.llm.advancedSettings": "Advanced Settings",
"nodes.llm.computerUse.disabledByStructuredOutput": "Computer Use is disabled when Structured Output is enabled.",
"nodes.llm.computerUse.referenceTools": "Reference Tools",
"nodes.llm.computerUse.referenceToolsEmpty": "Tools referenced in the prompt will appear here",
"nodes.llm.computerUse.title": "Computer Use",
@ -727,6 +728,7 @@
"nodes.llm.roleDescription.user": "Provide instructions, queries, or any text-based input to the model",
"nodes.llm.singleRun.variable": "Variable",
"nodes.llm.sysQueryInUser": "sys.query in user message is required",
"nodes.llm.tools.disabledByStructuredOutput": "Tools are disabled when Structured Output is enabled.",
"nodes.llm.tools.title": "Tools",
"nodes.llm.variables": "variables",
"nodes.llm.vision": "vision",

View File

@ -207,6 +207,8 @@
"showMyCreatedAppsOnly": "自分が作成したアプリ",
"structOutput.LLMResponse": "LLM のレスポンス",
"structOutput.configure": "設定",
"structOutput.disabledByComputerUse": "Computer Use を有効にすると、構造化出力は無効になります。",
"structOutput.disabledByTools": "ツールを有効にすると、構造化出力は無効になります。",
"structOutput.modelNotSupported": "モデルが対応していません",
"structOutput.modelNotSupportedTip": "現在のモデルはこの機能に対応しておらず、自動的にプロンプトインジェクションに切り替わります。",
"structOutput.moreFillTip": "最大 10 レベルのネストを表示します",

View File

@ -509,6 +509,8 @@
"promptEditor.history.modal.title": "例",
"promptEditor.history.modal.user": "こんにちは",
"promptEditor.placeholder": "ここにプロンプトワードを入力してください。変数を挿入するには「{」を、プロンプトコンテンツブロックを挿入するには「/」を入力します。",
"promptEditor.placeholderSandbox": "ここに指示を書いて、<0>/</0> <1>挿入</1>、<2>@</2> <3>ツール</3>",
"promptEditor.placeholderSandboxNoTools": "ここに指示を書いて、<0>/</0> <1>挿入</1>",
"promptEditor.query.item.desc": "ユーザークエリテンプレートを挿入",
"promptEditor.query.item.title": "クエリ",
"promptEditor.variable.item.desc": "変数&外部ツールを挿入",

View File

@ -648,6 +648,7 @@
"nodes.listFilter.selectVariableKeyPlaceholder": "サブ変数キーを選択する",
"nodes.llm.addContext": "コンテキスト追加",
"nodes.llm.addMessage": "メッセージ追加",
"nodes.llm.computerUse.disabledByStructuredOutput": "構造化出力を有効にすると、コンピュータ使用は無効になります。",
"nodes.llm.context": "コンテキスト",
"nodes.llm.contextBlock": "コンテキストブロック",
"nodes.llm.contextMissing": "ノード「{{nodeName}}」のコンテキストがありません。コンテキスト変数を選択してください。",
@ -697,6 +698,7 @@
"nodes.llm.roleDescription.user": "指示/質問を入力",
"nodes.llm.singleRun.variable": "変数",
"nodes.llm.sysQueryInUser": "ユーザーメッセージに sys.query を含めてください",
"nodes.llm.tools.disabledByStructuredOutput": "構造化出力を有効にすると、ツールは無効になります。",
"nodes.llm.variables": "変数",
"nodes.llm.vision": "ビジョン",
"nodes.loop.ErrorMethod.continueOnError": "エラーを無視して継続",

View File

@ -208,6 +208,8 @@
"showMyCreatedAppsOnly": "我创建的",
"structOutput.LLMResponse": "LLM 的响应",
"structOutput.configure": "配置",
"structOutput.disabledByComputerUse": "启用计算机使用时,将禁用结构化输出。",
"structOutput.disabledByTools": "启用工具时,将禁用结构化输出。",
"structOutput.modelNotSupported": "模型不支持",
"structOutput.modelNotSupportedTip": "当前模型不支持此功能,将自动降级为提示注入。",
"structOutput.moreFillTip": "最多显示 10 级嵌套",

View File

@ -510,6 +510,7 @@
"promptEditor.history.modal.user": "你好",
"promptEditor.placeholder": "在这里写你的提示词,输入'{' 插入变量、输入'/' 插入提示内容块",
"promptEditor.placeholderSandbox": "在这里写你的指令,<0>/</0> <1>插入</1><2>@</2> <3>工具</3>",
"promptEditor.placeholderSandboxNoTools": "在这里写你的指令,<0>/</0> <1>插入</1>",
"promptEditor.query.item.desc": "插入用户查询模板",
"promptEditor.query.item.title": "查询内容",
"promptEditor.skillMarkdown.placeholderPrefix": "输入",

View File

@ -666,6 +666,7 @@
"nodes.listFilter.selectVariableKeyPlaceholder": "选择子变量的 Key",
"nodes.llm.addContext": "添加上下文",
"nodes.llm.addMessage": "添加消息",
"nodes.llm.computerUse.disabledByStructuredOutput": "启用结构化输出时,将禁用计算机使用。",
"nodes.llm.computerUse.referenceTools": "引用工具",
"nodes.llm.computerUse.referenceToolsEmpty": "提示词中引用的工具会显示在这里",
"nodes.llm.computerUse.title": "计算机使用",
@ -720,6 +721,7 @@
"nodes.llm.roleDescription.user": "向模型提供指令、查询或任何基于文本的输入",
"nodes.llm.singleRun.variable": "变量",
"nodes.llm.sysQueryInUser": "user message 中必须包含 sys.query",
"nodes.llm.tools.disabledByStructuredOutput": "启用结构化输出时,将禁用工具。",
"nodes.llm.variables": "变量",
"nodes.llm.vision": "视觉",
"nodes.loop.ErrorMethod.continueOnError": "忽略错误并继续",

View File

@ -201,6 +201,8 @@
"showMyCreatedAppsOnly": "我建立的",
"structOutput.LLMResponse": "LLM 回應",
"structOutput.configure": "配置",
"structOutput.disabledByComputerUse": "啟用電腦使用時,將停用結構化輸出。",
"structOutput.disabledByTools": "啟用工具時,將停用結構化輸出。",
"structOutput.modelNotSupported": "模型不支持",
"structOutput.modelNotSupportedTip": "當前模型不支持此功能,並自動降級為提示注入。",
"structOutput.moreFillTip": "顯示最多 10 層的嵌套",

View File

@ -510,6 +510,7 @@
"promptEditor.history.modal.user": "你好",
"promptEditor.placeholder": "在這裡寫你的提示詞,輸入'{' 插入變數、輸入'/' 插入提示內容塊",
"promptEditor.placeholderSandbox": "在這裡寫你的指令,<0>/</0> <1>插入</1><2>@</2> <3>工具</3>",
"promptEditor.placeholderSandboxNoTools": "在這裡寫你的指令,<0>/</0> <1>插入</1>",
"promptEditor.query.item.desc": "插入使用者查詢模板",
"promptEditor.query.item.title": "查詢內容",
"promptEditor.skillMarkdown.placeholderPrefix": "輸入",

View File

@ -648,6 +648,7 @@
"nodes.listFilter.selectVariableKeyPlaceholder": "Select sub variable key選擇子變數鍵",
"nodes.llm.addContext": "新增上下文",
"nodes.llm.addMessage": "新增消息",
"nodes.llm.computerUse.disabledByStructuredOutput": "啟用結構化輸出時,將停用電腦使用。",
"nodes.llm.computerUse.referenceToolsEmpty": "提示詞中引用的工具會顯示在這裡",
"nodes.llm.context": "上下文",
"nodes.llm.contextBlock": "上下文區塊",
@ -698,6 +699,7 @@
"nodes.llm.roleDescription.user": "向模型提供指令、查詢或任何基於文本的輸入",
"nodes.llm.singleRun.variable": "變數",
"nodes.llm.sysQueryInUser": "user message 中必須包含 sys.query",
"nodes.llm.tools.disabledByStructuredOutput": "啟用結構化輸出時,將停用工具。",
"nodes.llm.variables": "變數",
"nodes.llm.vision": "視覺",
"nodes.loop.ErrorMethod.continueOnError": "繼續出錯",