From 830c28606295d817a9ad235ff85826383c84713a Mon Sep 17 00:00:00 2001 From: Joel Date: Mon, 26 Jan 2026 15:54:59 +0800 Subject: [PATCH] feat: support credical --- .../plugins/tool-block/component.tsx | 47 ++++++++++++++- .../tool-block/tool-group-block-component.tsx | 58 ++++++++++++++++++- 2 files changed, 101 insertions(+), 4 deletions(-) diff --git a/web/app/components/workflow/skill/editor/skill-editor/plugins/tool-block/component.tsx b/web/app/components/workflow/skill/editor/skill-editor/plugins/tool-block/component.tsx index 0b861e73be..43ce78476e 100644 --- a/web/app/components/workflow/skill/editor/skill-editor/plugins/tool-block/component.tsx +++ b/web/app/components/workflow/skill/editor/skill-editor/plugins/tool-block/component.tsx @@ -67,6 +67,7 @@ type ToolConfigMetadata = { fields: ToolConfigField[] } enabled?: boolean + credential_id?: string } type SkillFileMetadata = { @@ -83,6 +84,12 @@ const getVarKindType = (type: FormTypeEnum | string) => { return VarKindType.constant } +const normalizeCredentialId = (credentialId?: string) => { + if (!credentialId || credentialId === '__workspace_default__') + return undefined + return credentialId +} + type ToolFormSchema = { variable: string type: string @@ -242,6 +249,7 @@ const ToolBlockComponent: FC = ({ ...(defaultToolValue.parameters || {}), ...applyFields(paramsSchemas), }, + credential_id: toolConfigFromMetadata?.credential_id ?? defaultToolValue.credential_id, } }, [currentTool, defaultToolValue, toolConfigFromMetadata]) @@ -341,6 +349,7 @@ const ToolBlockComponent: FC = ({ setToolValue(nextValue) if (!currentProvider || !currentTool) return + const credentialId = normalizeCredentialId(nextValue.credential_id) if (isUsingExternalMetadata) { const metadata = (toolBlockContext?.metadata || {}) as SkillFileMetadata const toolType = currentProvider.type === CollectionType.mcp ? 'mcp' : 'builtin' @@ -365,6 +374,7 @@ const ToolBlockComponent: FC = ({ [configId]: { type: toolType, configuration: { fields }, + ...(credentialId ? { credential_id: credentialId } : {}), }, }, } @@ -396,6 +406,7 @@ const ToolBlockComponent: FC = ({ [configId]: { type: toolType, configuration: { fields }, + ...(credentialId ? { credential_id: credentialId } : {}), }, }, } @@ -404,7 +415,41 @@ const ToolBlockComponent: FC = ({ } const handleAuthorizationItemClick = (id: string) => { - setToolValue(prev => (prev ? { ...prev, credential_id: id } : prev)) + const credentialId = normalizeCredentialId(id) + setToolValue(prev => (prev ? { ...prev, credential_id: credentialId } : prev)) + if (!currentProvider) + return + const applyCredential = (metadata: SkillFileMetadata | undefined) => { + const nextMetadata: SkillFileMetadata = { + ...(metadata || {}), + tools: { + ...(metadata?.tools || {}), + }, + } + const existing = nextMetadata.tools?.[configId] + const toolType = existing?.type || (currentProvider.type === CollectionType.mcp ? 'mcp' : 'builtin') + const nextEntry: ToolConfigMetadata = { + type: toolType, + configuration: existing?.configuration || { fields: [] }, + ...(existing?.enabled !== undefined ? { enabled: existing.enabled } : {}), + } + if (credentialId) + nextEntry.credential_id = credentialId + if (!nextMetadata.tools) + nextMetadata.tools = {} + nextMetadata.tools[configId] = nextEntry + return nextMetadata + } + if (isUsingExternalMetadata) { + toolBlockContext?.onMetadataChange?.(applyCredential(toolBlockContext?.metadata as SkillFileMetadata | undefined)) + return + } + if (!activeTabId || activeTabId === START_TAB_ID) + return + const metadata = fileMetadata.get(activeTabId) as SkillFileMetadata | undefined + const nextMetadata = applyCredential(metadata) + storeApi.getState().setDraftMetadata(activeTabId, nextMetadata) + storeApi.getState().pinTab(activeTabId) } const needAuthorization = useMemo(() => { diff --git a/web/app/components/workflow/skill/editor/skill-editor/plugins/tool-block/tool-group-block-component.tsx b/web/app/components/workflow/skill/editor/skill-editor/plugins/tool-block/tool-group-block-component.tsx index e94b255b63..c3849f0adb 100644 --- a/web/app/components/workflow/skill/editor/skill-editor/plugins/tool-block/tool-group-block-component.tsx +++ b/web/app/components/workflow/skill/editor/skill-editor/plugins/tool-block/tool-group-block-component.tsx @@ -56,6 +56,7 @@ type ToolConfigMetadata = { fields: ToolConfigField[] } enabled?: boolean + credential_id?: string [key: string]: string | boolean | number | undefined | object// Add index signature to allow string keys } @@ -219,6 +220,12 @@ const ToolGroupBlockComponent: FC = ({ return VarKindType.constant } + const normalizeCredentialId = (credentialId?: string) => { + if (!credentialId || credentialId === '__workspace_default__') + return undefined + return credentialId + } + const defaultToolValue = useMemo(() => { if (!currentProvider || !currentTool || !activeToolItem) return null @@ -282,6 +289,7 @@ const ToolGroupBlockComponent: FC = ({ ...(defaultToolValue.parameters || {}), ...applyFields(paramsSchemas), }, + credential_id: toolConfigFromMetadata?.credential_id ?? defaultToolValue.credential_id, } }, [currentTool, defaultToolValue, toolConfigFromMetadata]) @@ -393,6 +401,7 @@ const ToolGroupBlockComponent: FC = ({ if (!activeToolItem || !currentProvider || !currentTool) return setToolValue(nextValue) + const credentialId = normalizeCredentialId(nextValue.credential_id) if (isUsingExternalMetadata) { const metadata = (toolBlockContext?.metadata || {}) as SkillFileMetadata const toolType = currentProvider.type === CollectionType.mcp ? 'mcp' : 'builtin' @@ -419,6 +428,7 @@ const ToolGroupBlockComponent: FC = ({ type: toolType, configuration: { fields }, enabled: currentToolMetadata?.enabled ?? resolvedEnabledByConfigId[activeToolItem.configId] ?? true, + ...(credentialId ? { credential_id: credentialId } : {}), }, }, } @@ -452,6 +462,7 @@ const ToolGroupBlockComponent: FC = ({ type: toolType, configuration: { fields }, enabled: currentToolMetadata?.enabled ?? resolvedEnabledByConfigId[activeToolItem.configId] ?? true, + ...(credentialId ? { credential_id: credentialId } : {}), }, }, } @@ -476,6 +487,7 @@ const ToolGroupBlockComponent: FC = ({ type: toolType, configuration: existing?.configuration || { fields: [] }, enabled: nextValue, + ...(existing?.credential_id ? { credential_id: existing.credential_id } : {}), } return nextMetadata } @@ -585,7 +597,10 @@ const ToolGroupBlockComponent: FC = ({ currentProvider={currentProvider} credentialId={toolValue.credential_id} onAuthorizationItemClick={(id) => { - setToolValue(prev => (prev ? { ...prev, credential_id: id } : prev)) + const credentialId = normalizeCredentialId(id) + setToolValue(prev => (prev ? { ...prev, credential_id: credentialId } : prev)) + if (activeToolItem) + handleToolValueChange({ ...(toolValue as ToolValue), credential_id: credentialId }) }} noDivider /> @@ -636,9 +651,46 @@ const ToolGroupBlockComponent: FC = ({
{ - setToolValue(prev => (prev ? { ...prev, credential_id: id } : prev)) + const credentialId = normalizeCredentialId(id) + if (!toolItems.length) + return + if (activeToolItem && toolValue) + handleToolValueChange({ ...toolValue, credential_id: credentialId }) + const applyCredential = (metadata: SkillFileMetadata | undefined) => { + const nextMetadata: SkillFileMetadata = { + ...(metadata || {}), + tools: { + ...(metadata?.tools || {}), + }, + } + toolItems.forEach((item) => { + const existing = nextMetadata.tools?.[item.configId] + const toolType = existing?.type || (currentProvider?.type === CollectionType.mcp ? 'mcp' : 'builtin') + const nextEntry: ToolConfigMetadata = { + type: toolType, + configuration: existing?.configuration || { fields: [] }, + ...(existing?.enabled !== undefined ? { enabled: existing.enabled } : {}), + } + if (credentialId) + nextEntry.credential_id = credentialId + if (!nextMetadata.tools) + nextMetadata.tools = {} + nextMetadata.tools[item.configId] = nextEntry + }) + return nextMetadata + } + if (isUsingExternalMetadata) { + toolBlockContext?.onMetadataChange?.(applyCredential(toolBlockContext?.metadata as SkillFileMetadata | undefined)) + return + } + if (!activeTabId || activeTabId === START_TAB_ID) + return + const metadata = fileMetadata.get(activeTabId) as SkillFileMetadata | undefined + const nextMetadata = applyCredential(metadata) + storeApi.getState().setDraftMetadata(activeTabId, nextMetadata) + storeApi.getState().pinTab(activeTabId) }} noDivider />