Commit 88f967bb by Archer Committed by GitHub

fix: tool connection (#6919)

* fix: tool connection

* doc
parent c3dd66e9
...@@ -9,6 +9,8 @@ description: 'FastGPT V4.15.0-beta2 更新说明' ...@@ -9,6 +9,8 @@ description: 'FastGPT V4.15.0-beta2 更新说明'
1. 优化 OTEL 日志采集格式。 1. 优化 OTEL 日志采集格式。
2. 增加 workflow zod 检查鲁棒性。 2. 增加 workflow zod 检查鲁棒性。
3. 禁用工作流无效连接模式。
4. 增加工作流节点,名字超长适配。
## 🐛 修复 ## 🐛 修复
......
...@@ -272,6 +272,7 @@ ...@@ -272,6 +272,7 @@
"content/self-host/upgrading/4-14/4149.en.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/4-14/4149.en.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/upgrading/4-14/4149.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/4-14/4149.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/upgrading/4-15/4150.mdx": "2026-05-09T16:13:01+08:00", "content/self-host/upgrading/4-15/4150.mdx": "2026-05-09T16:13:01+08:00",
"content/self-host/upgrading/4-15/41502.mdx": "2026-05-12T11:14:32+08:00",
"content/self-host/upgrading/outdated/40.en.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/outdated/40.en.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/upgrading/outdated/40.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/outdated/40.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/upgrading/outdated/41.en.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/outdated/41.en.mdx": "2026-04-26T21:08:47+08:00",
...@@ -413,7 +414,7 @@ ...@@ -413,7 +414,7 @@
"content/self-host/upgrading/upgrade-intruction.en.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/upgrade-intruction.en.mdx": "2026-04-26T21:08:47+08:00",
"content/self-host/upgrading/upgrade-intruction.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/upgrade-intruction.mdx": "2026-04-26T21:08:47+08:00",
"content/toc.en.mdx": "2026-05-09T15:25:23+08:00", "content/toc.en.mdx": "2026-05-09T15:25:23+08:00",
"content/toc.mdx": "2026-05-09T15:25:23+08:00", "content/toc.mdx": "2026-05-12T11:14:32+08:00",
"content/use-cases/app-cases/dalle3.en.mdx": "2026-04-26T21:08:47+08:00", "content/use-cases/app-cases/dalle3.en.mdx": "2026-04-26T21:08:47+08:00",
"content/use-cases/app-cases/dalle3.mdx": "2026-04-26T21:08:47+08:00", "content/use-cases/app-cases/dalle3.mdx": "2026-04-26T21:08:47+08:00",
"content/use-cases/app-cases/english_essay_correction_bot.en.mdx": "2026-04-26T21:08:47+08:00", "content/use-cases/app-cases/english_essay_correction_bot.en.mdx": "2026-04-26T21:08:47+08:00",
......
...@@ -15,6 +15,8 @@ export const createClientAbortTracker = ({ ...@@ -15,6 +15,8 @@ export const createClientAbortTracker = ({
let clientAborted = false; let clientAborted = false;
let responseCompleted = !!(res?.writableEnded || res?.writableFinished); let responseCompleted = !!(res?.writableEnded || res?.writableFinished);
// For workflow stopping, "client aborted" means the current response can no longer be written.
// It is intentionally broader than a strict user-initiated cancel audit signal.
const responseFinished = () => const responseFinished = () =>
responseCompleted || !!(res?.writableEnded || res?.writableFinished); responseCompleted || !!(res?.writableEnded || res?.writableFinished);
const responseWritableAborted = () => const responseWritableAborted = () =>
...@@ -22,6 +24,7 @@ export const createClientAbortTracker = ({ ...@@ -22,6 +24,7 @@ export const createClientAbortTracker = ({
const hasExplicitAbort = () => !!(req?.aborted || responseWritableAborted()); const hasExplicitAbort = () => !!(req?.aborted || responseWritableAborted());
const hasBrokenConnection = () => !!(req?.socket?.destroyed || res?.destroyed || res?.errored); const hasBrokenConnection = () => !!(req?.socket?.destroyed || res?.destroyed || res?.errored);
const isAbortedSnapshot = () => { const isAbortedSnapshot = () => {
// A normal completed response may also emit close later. Do not treat that as abort.
if (responseFinished()) return false; if (responseFinished()) return false;
return hasExplicitAbort() || hasBrokenConnection(); return hasExplicitAbort() || hasBrokenConnection();
......
...@@ -51,7 +51,7 @@ export const ToolTargetHandle = ({ show, nodeId }: ToolHandleProps) => { ...@@ -51,7 +51,7 @@ export const ToolTargetHandle = ({ show, nodeId }: ToolHandleProps) => {
type="target" type="target"
id={handleId} id={handleId}
position={Position.Top} position={Position.Top}
isConnectableEnd={showHandle} isConnectableEnd={active}
> >
<Box <Box
className="flow-handle" className="flow-handle"
...@@ -65,7 +65,7 @@ export const ToolTargetHandle = ({ show, nodeId }: ToolHandleProps) => { ...@@ -65,7 +65,7 @@ export const ToolTargetHandle = ({ show, nodeId }: ToolHandleProps) => {
/> />
</Handle> </Handle>
); );
}, [showHandle, size]); }, [active, showHandle, size]);
return Render; return Render;
}; };
...@@ -130,7 +130,7 @@ export const ToolSourceHandle = ({ nodeId }: { nodeId: string }) => { ...@@ -130,7 +130,7 @@ export const ToolSourceHandle = ({ nodeId }: { nodeId: string }) => {
</Handle> </Handle>
</MyTooltip> </MyTooltip>
); );
}, [onConnect, size, t]); }, [active, onConnect, size, t]);
return Render; return Render;
}; };
......
...@@ -354,7 +354,7 @@ const NodeCard = (props: Props) => { ...@@ -354,7 +354,7 @@ const NodeCard = (props: Props) => {
appId={pluginId} appId={pluginId}
/> />
<Box flex={1} mr={1} /> <Box mr={1} />
{showVersion && <NodeVersion node={node!} />} {showVersion && <NodeVersion node={node!} />}
...@@ -428,6 +428,8 @@ const NodeCard = (props: Props) => { ...@@ -428,6 +428,8 @@ const NodeCard = (props: Props) => {
export default React.memo(NodeCard); export default React.memo(NodeCard);
const NODE_NAME_MAX_LENGTH = 50;
// 节点标题区域组件 // 节点标题区域组件
const NodeTitleSection = React.memo<{ const NodeTitleSection = React.memo<{
nodeId: string; nodeId: string;
...@@ -490,9 +492,25 @@ const NodeTitleSection = React.memo<{ ...@@ -490,9 +492,25 @@ const NodeTitleSection = React.memo<{
}); });
return ( return (
<Flex alignItems={'center'}> <Flex alignItems={'center'} flex={'1 1 0'} minW={0}>
<Avatar src={avatar} borderRadius={'sm'} objectFit={'contain'} w={'24px'} h={'24px'} /> <Avatar src={avatar} borderRadius={'sm'} objectFit={'contain'} w={'24px'} h={'24px'} />
<Box ml={2} fontSize={'18px'} fontWeight={'medium'} color={'myGray.900'}> <Box
ml={2}
flex={1}
minW={0}
fontSize={'18px'}
fontWeight={'medium'}
color={'myGray.900'}
overflow={'hidden'}
textOverflow={'ellipsis'}
whiteSpace={'nowrap'}
title={t(name as any)}
sx={{
'& > div': {
display: 'inline'
}
}}
>
<HighlightText <HighlightText
rawText={t(name as any)} rawText={t(name as any)}
matchText={searchedText ?? ''} matchText={searchedText ?? ''}
...@@ -500,11 +518,11 @@ const NodeTitleSection = React.memo<{ ...@@ -500,11 +518,11 @@ const NodeTitleSection = React.memo<{
color={'#ffe82d'} color={'#ffe82d'}
/> />
</Box> </Box>
<Box ml={1} visibility={'hidden'}> <Box ml={1} flexShrink={0} visibility={'hidden'}>
<MyIconButton className="node-hover-controller" icon="edit" onClick={handleRenameClick} /> <MyIconButton className="node-hover-controller" icon="edit" onClick={handleRenameClick} />
</Box> </Box>
{childAppId && ( {childAppId && (
<Box ml={1} visibility={'hidden'}> <Box ml={1} flexShrink={0} visibility={'hidden'}>
<MyIconButton <MyIconButton
className="node-hover-controller" className="node-hover-controller"
icon="common/link" icon="common/link"
...@@ -514,7 +532,7 @@ const NodeTitleSection = React.memo<{ ...@@ -514,7 +532,7 @@ const NodeTitleSection = React.memo<{
</Box> </Box>
)} )}
<EditTitleModal maxLength={100} /> <EditTitleModal maxLength={NODE_NAME_MAX_LENGTH} />
</Flex> </Flex>
); );
}); });
...@@ -653,7 +671,7 @@ const NodeVersion = React.memo(function NodeVersion({ node }: { node: FlowNodeIt ...@@ -653,7 +671,7 @@ const NodeVersion = React.memo(function NodeVersion({ node }: { node: FlowNodeIt
)} )}
</Flex> </Flex>
); );
}, [node.isLatestVersion, node?.version, node?.versionLabel, t]); }, [node.isLatestVersion, node.version, node.versionLabel, t]);
const ScrollDataWrapper = useCallback( const ScrollDataWrapper = useCallback(
(props: { children: React.ReactNode }) => ( (props: { children: React.ReactNode }) => (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment