Skip to content

Commit b8f81e9

Browse files
authored
fix: support older browsers for share page (#6903) (#6904)
* fix: support older browsers for share page (#6903) * fix: support older browsers for share page * chore: remove local compatibility note * pick * remove * doc
1 parent d068d65 commit b8f81e9

10 files changed

Lines changed: 104 additions & 38 deletions

File tree

.vscode/extensions.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"recommendations": [
3+
"dbaeumer.vscode-eslint",
4+
"alexcvzz.vscode-sqlite"
5+
]
6+
}

.vscode/settings.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,22 @@
22
"editor.formatOnSave": true,
33
"editor.mouseWheelZoom": true,
44
"editor.defaultFormatter": "esbenp.prettier-vscode",
5+
"editor.codeActionsOnSave": {
6+
"source.fixAll.eslint": "explicit"
7+
},
58
"prettier.prettierPath": "node_modules/prettier",
9+
"eslint.useFlatConfig": true,
10+
"eslint.workingDirectories": [
11+
{
12+
"mode": "auto"
13+
}
14+
],
15+
"eslint.validate": [
16+
"javascript",
17+
"javascriptreact",
18+
"typescript",
19+
"typescriptreact"
20+
],
621
"i18n-ally.localesPaths": [
722
"packages/web/i18n",
823
],

document/data/doc-last-modified.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,4 +425,4 @@
425425
"document/content/docs/use-cases/external-integration/wecom.mdx": "2025-12-10T20:07:05+08:00",
426426
"document/content/docs/use-cases/index.en.mdx": "2026-02-26T22:14:30+08:00",
427427
"document/content/docs/use-cases/index.mdx": "2025-07-24T14:23:04+08:00"
428-
}
428+
}

packages/global/core/chat/utils.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ ${stepText}`;
9898
// Concat 2 -> 1, and sort by role
9999
export const concatHistories = (histories1: ChatItemMiniType[], histories2: ChatItemMiniType[]) => {
100100
const newHistories = [...histories1, ...histories2];
101-
return newHistories.sort((a, b) => {
101+
return newHistories.sort((a) => {
102102
if (a.obj === ChatRoleEnum.System) {
103103
return -1;
104104
}
@@ -110,7 +110,6 @@ export const getChatTitleFromChatMessage = (
110110
message?: ChatItemMiniType,
111111
defaultValue = '新对话'
112112
) => {
113-
// @ts-ignore
114113
const textMsg = message?.value.find((item) => 'text' in item && item.text);
115114

116115
if (textMsg?.text?.content) {
@@ -185,32 +184,32 @@ export const filterPublicNodeResponseData = ({
185184
[FlowNodeTypeEnum.agent]: true,
186185
[FlowNodeTypeEnum.pluginOutput]: true,
187186
[FlowNodeTypeEnum.runApp]: true,
188-
[FlowNodeTypeEnum.toolCall]: true
187+
[FlowNodeTypeEnum.toolCall]: true,
188+
[FlowNodeTypeEnum.tool]: true
189189
};
190190

191+
const commonFields = {
192+
moduleType: true,
193+
pluginOutput: true,
194+
runningTime: true,
195+
toolId: true
196+
};
191197
const filedMap: Record<string, boolean> = responseDetail
192198
? {
193199
quoteList: true,
194-
moduleType: true,
195-
pluginOutput: true,
196-
runningTime: true
200+
...commonFields
197201
}
198-
: {
199-
moduleType: true,
200-
pluginOutput: true,
201-
runningTime: true
202-
};
202+
: commonFields;
203203

204204
return nodeRespones
205205
.filter((item) => publicNodeMap[item.moduleType])
206206
.map((item) => {
207207
const obj: DispatchNodeResponseType = {};
208-
for (let key in item) {
208+
for (const key in item) {
209209
if (key === 'toolDetail' || key === 'pluginDetail') {
210-
// @ts-ignore
211210
obj[key] = filterPublicNodeResponseData({ nodeRespones: item[key], responseDetail });
212211
} else if (filedMap[key]) {
213-
// @ts-ignore
212+
// @ts-expect-error Dynamic public field copy is constrained by filedMap.
214213
obj[key] = item[key];
215214
}
216215
}

packages/global/test/core/chat/chatUtils.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
88
import { PublishChannelEnum } from '@fastgpt/global/support/outLink/constant';
99
import type { ChatItemMiniType, ChatHistoryItemResType } from '@fastgpt/global/core/chat/type';
10+
import { SANDBOX_TOOL_NAME } from '@fastgpt/global/core/ai/sandbox/constants';
1011
import {
1112
concatHistories,
1213
getChatTitleFromChatMessage,
@@ -180,6 +181,33 @@ describe('filterPublicNodeResponseData', () => {
180181

181182
expect(result[0].quoteList).toBeDefined();
182183
});
184+
185+
it('should keep tool node type and toolId without exposing tool details', () => {
186+
const nodeResponses: ChatHistoryItemResType[] = [
187+
{
188+
id: '1',
189+
nodeId: 'node1',
190+
moduleName: 'Sandbox',
191+
moduleType: FlowNodeTypeEnum.tool,
192+
runningTime: 0.8,
193+
toolId: SANDBOX_TOOL_NAME,
194+
toolInput: {
195+
command: 'ls'
196+
},
197+
toolRes: 'file.txt'
198+
}
199+
];
200+
201+
const result = filterPublicNodeResponseData({ nodeRespones: nodeResponses });
202+
203+
expect(result).toEqual([
204+
{
205+
moduleType: FlowNodeTypeEnum.tool,
206+
runningTime: 0.8,
207+
toolId: SANDBOX_TOOL_NAME
208+
}
209+
]);
210+
});
183211
});
184212

185213
describe('removeEmptyUserInput', () => {

pro

Submodule pro updated from eb6ef1b to 9af17ea

projects/app/package.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
"name": "@fastgpt/app",
33
"version": "4.14.19",
44
"private": false,
5+
"browserslist": [
6+
"Chrome >= 80",
7+
"Edge >= 80",
8+
"Firefox >= 74",
9+
"Safari >= 13",
10+
"ios_saf >= 13"
11+
],
512
"scripts": {
613
"dev": "pnpm run build:workers && next dev",
714
"dev:pro": "pnpm run dev",

projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ResponseTags.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,8 @@ const ResponseTags = ({
8888
outLinkAuthData
8989
});
9090

91-
useSize(quoteListRef);
92-
const quoteIsOverflow = quoteListRef.current
93-
? quoteListRef.current.scrollHeight > (isPc ? 50 : 55)
94-
: true;
91+
const quoteListSize = useSize(quoteListRef);
92+
const quoteIsOverflow = quoteListSize ? quoteListSize.height >= (isPc ? 50 : 55) : true;
9593

9694
const citationRenderList: CitationRenderItem[] = useMemo(() => {
9795
if (!isShowCite) return [];
@@ -136,7 +134,8 @@ const ResponseTags = ({
136134
return [...datasetItems, ...linkItems];
137135
}, [quoteList, toolCiteLinks, onOpenCiteModal, isShowCite]);
138136

139-
const notEmptyTags = notSharePage || quoteList.length > 0 || (isPc && durationSeconds > 0);
137+
const notEmptyTags =
138+
notSharePage || quoteList.length > 0 || useAgentSandbox || (isPc && durationSeconds > 0);
140139

141140
return !showTags ? null : (
142141
<>

projects/app/src/pageComponents/chat/SandboxEditor/hook.tsx

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback, useEffect, useMemo, useState, useRef } from 'react';
1+
import { useCallback, useEffect, useMemo, useState } from 'react';
22
import SandboxEditorModal from '@/pageComponents/chat/SandboxEditor/modal';
33
import type { IconButtonProps } from '@chakra-ui/react';
44
import { IconButton } from '@chakra-ui/react';
@@ -62,8 +62,8 @@ export const useSandboxEditor = ({
6262
* 职责:负责 checkSandboxExist 的网络同步及 SandboxEntryIcon 的显示控制。
6363
* 同步模式:
6464
* 1. 历史记录(ChatRecordContext):useMemo 派生,无副作用。
65-
* 2. chatId 切换:渲染周期利用 useRef 确认 ID 变化并同步重置状态,防止 UI 闪烁
66-
* 3. 网络请求:单一 useEffect,在参数变化时触发 1 次
65+
* 2. 网络请求:单一 useEffect,在参数变化时触发 1 次
66+
* 3. API 结果已返回时以 API 为准;未返回前才使用历史记录兜底
6767
*/
6868
export const useSandboxStatus = ({
6969
appId,
@@ -75,13 +75,11 @@ export const useSandboxStatus = ({
7575
outLinkAuthData?: OutLinkChatAuthProps;
7676
}) => {
7777
const { t } = useTranslation();
78-
const [apiSandboxExists, setApiSandboxExists] = useState(false);
79-
const lastChatIdRef = useRef(chatId);
80-
81-
if (lastChatIdRef.current !== chatId) {
82-
lastChatIdRef.current = chatId;
83-
setApiSandboxExists(false);
84-
}
78+
const [apiSandboxStatus, setApiSandboxStatus] = useState({
79+
appId: '',
80+
chatId: '',
81+
exists: false
82+
});
8583

8684
const chatRecords = useContextSelector(ChatRecordContext, (v) => {
8785
return v.chatRecords;
@@ -97,22 +95,33 @@ export const useSandboxStatus = ({
9795
}, [chatRecords, isChatRecordsLoaded]);
9896

9997
useEffect(() => {
100-
if (!chatId) return;
98+
if (!appId || !chatId) return;
10199
let cancelled = false;
102100
checkSandboxExist({ appId, chatId, outLinkAuthData })
103101
.then((result) => {
104-
if (!cancelled) setApiSandboxExists(result.exists);
102+
if (!cancelled) setApiSandboxStatus({ appId, chatId, exists: result.exists });
105103
})
106104
.catch((error) => {
107105
console.error('Failed to check sandbox status:', error);
108106
});
109107
return () => {
110108
cancelled = true;
111109
};
112-
}, [appId, chatId]);
110+
}, [appId, chatId, outLinkAuthData]);
113111

112+
const apiSandboxExists =
113+
apiSandboxStatus.appId === appId &&
114+
apiSandboxStatus.chatId === chatId &&
115+
apiSandboxStatus.exists;
114116
const sandboxExists = hasSandboxInHistory || apiSandboxExists;
115117

118+
const setSandboxExists = useCallback(
119+
(exists: boolean) => {
120+
setApiSandboxStatus({ appId, chatId, exists });
121+
},
122+
[appId, chatId]
123+
);
124+
116125
const SandboxEntryIcon = useCallback(
117126
({
118127
onOpen,
@@ -138,7 +147,7 @@ export const useSandboxStatus = ({
138147

139148
return {
140149
sandboxExists,
141-
setSandboxExists: setApiSandboxExists,
150+
setSandboxExists,
142151
SandboxEntryIcon
143152
};
144153
};

projects/app/src/pageComponents/chat/ToolMenu.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,21 @@ const ToolMenu = ({
2525

2626
const onChangeChatId = useContextSelector(ChatContext, (v) => v.onChangeChatId);
2727
const chatData = useContextSelector(ChatItemContext, (v) => v.chatBoxData);
28-
const { chatId, outLinkAuthData } = useChatStore();
28+
const { chatId, outLinkAuthData, appId, source } = useChatStore();
29+
const currentAppId = chatData.appId || appId;
30+
const isShareAuthReady =
31+
source !== 'share' || (!!outLinkAuthData.shareId && !!outLinkAuthData.outLinkUid);
2932

3033
// Status Hook: 顶层单例,负责网络同步与入口图标显示
3134
const { sandboxExists, setSandboxExists, SandboxEntryIcon } = useSandboxStatus({
32-
appId: chatData.appId,
35+
appId: isShareAuthReady ? currentAppId : '',
3336
chatId,
3437
outLinkAuthData
3538
});
3639

3740
// UI Hook: 负责弹窗渲染
3841
const { SandboxEditorModal, onOpenSandboxModal } = useSandboxEditor({
39-
appId: chatData.appId,
42+
appId: currentAppId,
4043
chatId,
4144
outLinkAuthData
4245
});

0 commit comments

Comments
 (0)