Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
86758af5
authored
Mar 24, 2026
by
Archer
Committed by
GitHub
Mar 24, 2026
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feishu stream (#6629)
parent
25d6bb7d
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
44 additions
and
39 deletions
+44
-39
.claude/design/wechat-file-support.md
+0
-0
document/content/docs/self-host/upgrading/4-14/41410.mdx
+1
-0
document/data/doc-last-modified.json
+3
-2
packages/global/common/error/utils.ts
+4
-0
packages/service/common/api/axios.ts
+4
-0
packages/service/support/outLink/runtime/utils.ts
+31
-35
packages/service/support/outLink/wechat/mq.ts
+1
-2
No files found.
.claude/design/wechat-file-support.md
0 → 100644
View file @
86758af5
This diff is collapsed.
Click to expand it.
document/content/docs/self-host/upgrading/4-14/41410.mdx
View file @
86758af5
...
...
@@ -6,6 +6,7 @@ description: 'FastGPT V4.14.10 更新说明'
## 🚀 新增内容
1. 飞书发布渠道,支持流输出。
## ⚙️ 优化
...
...
document/data/doc-last-modified.json
View file @
86758af5
...
...
@@ -220,6 +220,7 @@
"document/content/docs/self-host/upgrading/4-14/4140.mdx"
:
"2026-03-03T17:39:47+08:00"
,
"document/content/docs/self-host/upgrading/4-14/4141.en.mdx"
:
"2026-03-03T17:39:47+08:00"
,
"document/content/docs/self-host/upgrading/4-14/4141.mdx"
:
"2026-03-03T17:39:47+08:00"
,
"document/content/docs/self-host/upgrading/4-14/41410.mdx"
:
"2026-03-24T09:59:30+08:00"
,
"document/content/docs/self-host/upgrading/4-14/4142.en.mdx"
:
"2026-03-03T17:39:47+08:00"
,
"document/content/docs/self-host/upgrading/4-14/4142.mdx"
:
"2026-03-03T17:39:47+08:00"
,
"document/content/docs/self-host/upgrading/4-14/4143.en.mdx"
:
"2026-03-03T17:39:47+08:00"
,
...
...
@@ -239,7 +240,7 @@
"document/content/docs/self-host/upgrading/4-14/41481.en.mdx"
:
"2026-03-09T12:02:02+08:00"
,
"document/content/docs/self-host/upgrading/4-14/41481.mdx"
:
"2026-03-09T17:39:53+08:00"
,
"document/content/docs/self-host/upgrading/4-14/4149.en.mdx"
:
"2026-03-23T12:17:04+08:00"
,
"document/content/docs/self-host/upgrading/4-14/4149.mdx"
:
"2026-03-23T23:3
6:27
+08:00"
,
"document/content/docs/self-host/upgrading/4-14/4149.mdx"
:
"2026-03-23T23:3
7:12
+08:00"
,
"document/content/docs/self-host/upgrading/outdated/40.en.mdx"
:
"2026-03-03T17:39:47+08:00"
,
"document/content/docs/self-host/upgrading/outdated/40.mdx"
:
"2026-03-03T17:39:47+08:00"
,
"document/content/docs/self-host/upgrading/outdated/41.en.mdx"
:
"2026-03-03T17:39:47+08:00"
,
...
...
@@ -381,7 +382,7 @@
"document/content/docs/self-host/upgrading/upgrade-intruction.en.mdx"
:
"2026-03-03T17:39:47+08:00"
,
"document/content/docs/self-host/upgrading/upgrade-intruction.mdx"
:
"2026-03-03T17:39:47+08:00"
,
"document/content/docs/toc.en.mdx"
:
"2026-03-23T12:10:44+08:00"
,
"document/content/docs/toc.mdx"
:
"2026-03-2
3T11:57:05
+08:00"
,
"document/content/docs/toc.mdx"
:
"2026-03-2
4T09:59:30
+08:00"
,
"document/content/docs/use-cases/app-cases/dalle3.en.mdx"
:
"2026-02-26T22:14:30+08:00"
,
"document/content/docs/use-cases/app-cases/dalle3.mdx"
:
"2025-07-23T21:35:03+08:00"
,
"document/content/docs/use-cases/app-cases/english_essay_correction_bot.en.mdx"
:
"2026-02-26T22:14:30+08:00"
,
...
...
packages/global/common/error/utils.ts
View file @
86758af5
...
...
@@ -28,6 +28,10 @@ export const getErrText = (err: any, def = ''): any => {
return
replaceSensitiveText
(
msg
);
};
export
const
getErrResponse
=
(
err
:
any
):
any
=>
{
return
err
?.
response
?.
data
||
err
?.
response
||
err
;
};
export
class
UserError
extends
Error
{
constructor
(
message
:
string
)
{
super
(
message
);
...
...
packages/service/common/api/axios.ts
View file @
86758af5
import
_
,
{
type
AxiosRequestConfig
}
from
'axios'
;
import
{
ProxyAgent
}
from
'proxy-agent'
;
import
{
isDevEnv
}
from
'@fastgpt/global/common/system/constants'
;
export
function
createProxyAxios
(
config
?:
AxiosRequestConfig
)
{
if
(
isDevEnv
)
{
return
_
.
create
(
config
);
}
const
agent
=
new
ProxyAgent
();
return
_
.
create
({
...
...
packages/service/support/outLink/runtime/utils.ts
View file @
86758af5
...
...
@@ -21,7 +21,7 @@ import { authOutLinkLimit } from './auth';
import
{
addOutLinkUsage
}
from
'../../../support/outLink/tools'
;
import
{
getLogger
,
LogCategories
}
from
'../../../common/logger'
;
import
{
appendRedisCache
}
from
'../../../common/redis/cache'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
import
{
getErr
Response
,
getErr
Text
}
from
'@fastgpt/global/common/error/utils'
;
import
{
getUsageSourceByPublishChannel
}
from
'@fastgpt/global/support/wallet/usage/tools'
;
import
{
getChatSourceByPublishChannel
}
from
'@fastgpt/global/core/chat/utils'
;
import
{
WORKFLOW_MAX_RUN_TIMES
}
from
'../../../core/workflow/constants'
;
...
...
@@ -75,7 +75,10 @@ export type outLinkInvokeChatProps<T extends OutlinkAppType> = {
res
?:
NextApiResponse
;
messageId
:
string
;
chatUserId
:
string
;
replyCallback
?:
(
replyContent
:
string
)
=>
Promise
<
any
>
;
// Called once with complete response content (all channels except wecom)
onReply
?:
(
replyContent
:
string
)
=>
Promise
<
void
>
;
// Called for each streaming chunk (feishu and other push channels)
onStreamChunk
?:
(
text
:
string
)
=>
Promise
<
void
>
;
streamId
?:
string
;
};
...
...
@@ -91,7 +94,8 @@ export async function outlinkInvokeChat<T extends OutlinkAppType>({
res
,
messageId
,
chatUserId
,
replyCallback
,
onReply
,
onStreamChunk
,
streamId
}:
outLinkInvokeChatProps
<
T
>
)
{
const
streamResKey
=
`
${
STREAM_CACHE_KEY_PREFIX
}${
streamId
}
`
;
...
...
@@ -112,7 +116,7 @@ export async function outlinkInvokeChat<T extends OutlinkAppType>({
const
userQuestion
=
query
.
find
((
item
)
=>
item
.
text
)?.
text
?.
content
||
''
;
if
(
RESET_CHAT_INPUT
[
userQuestion
])
{
await
resetChat
({
appId
:
outLinkConfig
.
appId
,
chatId
});
await
replyCallback
?.(
RESET_CHAT_REPLY
);
await
onReply
?.(
RESET_CHAT_REPLY
);
if
(
streamId
)
{
await
appendRedisCache
(
streamResKey
,
RESET_CHAT_REPLY
,
60
);
await
appendRedisCache
(
streamResKey
,
STREAM_END_FLAG
,
60
);
...
...
@@ -144,7 +148,9 @@ export async function outlinkInvokeChat<T extends OutlinkAppType>({
ip
:
chatId
});
const
workflowStreamResponse
=
streamId
const
enableStreaming
=
!!
streamId
||
!!
onStreamChunk
;
const
workflowStreamResponse
=
enableStreaming
?
async
({
write
,
event
,
...
...
@@ -158,7 +164,12 @@ export async function outlinkInvokeChat<T extends OutlinkAppType>({
try
{
const
text
=
data
.
choices
?.[
0
]?.
delta
?.
content
;
if
(
text
)
{
await
appendRedisCache
(
streamResKey
,
text
,
60
);
if
(
streamId
)
{
await
appendRedisCache
(
streamResKey
,
text
,
60
);
}
if
(
onStreamChunk
)
{
await
onStreamChunk
(
text
);
}
}
}
catch
(
error
)
{
logger
.
error
(
'Outlink real-time streaming failed'
,
{
...
...
@@ -171,8 +182,10 @@ export async function outlinkInvokeChat<T extends OutlinkAppType>({
}
:
undefined
;
// Append first
await
appendRedisCache
(
streamResKey
,
''
,
120
);
// Initialize Redis key only when needed
if
(
streamId
)
{
await
appendRedisCache
(
streamResKey
,
''
,
120
);
}
// Merge global variables from database
const
variables
=
chatDetail
?.
variables
??
{};
...
...
@@ -202,7 +215,7 @@ export async function outlinkInvokeChat<T extends OutlinkAppType>({
histories
,
query
:
query
,
chatConfig
,
stream
:
streamId
?
true
:
false
,
stream
:
enableStreaming
,
workflowStreamResponse
,
runtimeEdges
:
storeEdges2RuntimeEdges
(
edges
),
runtimeNodes
:
storeNodes2RuntimeNodes
(
nodes
,
getWorkflowEntryNodeIds
(
nodes
)),
...
...
@@ -225,31 +238,13 @@ export async function outlinkInvokeChat<T extends OutlinkAppType>({
const
replyResult
=
await
(
async
()
=>
{
try
{
if
(
streamId
)
{
//
if streamId is provided, do not reply
return
;
//
wecom model: Redis handles streaming, no reply needed
return
{
success
:
true
}
;
}
const
result
=
await
replyCallback
?.(
responseContent
);
if
(
result
.
errcode
!==
0
)
{
logger
.
error
(
'Outlink official account reply failed'
,
{
errmsg
:
result
.
errmsg
});
return
{
success
:
false
,
errmsg
:
result
.
errmsg
};
}
logger
.
debug
(
'Outlink official account reply success'
,
{
responseContent
,
result
});
return
{
success
:
true
,
data
:
result
};
await
onReply
?.(
responseContent
);
return
{
success
:
true
};
}
catch
(
error
)
{
logger
.
error
(
'Outlink reply callback failed'
,
{
error
});
logger
.
error
(
'Outlink reply callback failed'
,
{
error
:
getErrResponse
(
error
)
});
return
{
success
:
false
,
errmsg
:
getErrText
(
error
)
...
...
@@ -306,9 +301,10 @@ export async function outlinkInvokeChat<T extends OutlinkAppType>({
});
try
{
await
appendRedisCache
(
streamResKey
,
STREAM_END_FLAG
,
60
);
await
replyCallback
?.(
`App run error:
${
getErrText
(
error
)}
`
);
if
(
streamId
)
{
await
appendRedisCache
(
streamResKey
,
STREAM_END_FLAG
,
60
);
}
await
onReply
?.(
`App run error:
${
getErrText
(
error
)}
`
);
}
catch
(
error
)
{
logger
.
error
(
'Outlink invoke chat fallback reply failed'
,
{
shareId
:
outLinkConfig
.
shareId
,
...
...
packages/service/support/outLink/wechat/mq.ts
View file @
86758af5
...
...
@@ -126,13 +126,12 @@ async function processUserGroup(
query
:
[{
text
:
{
content
:
group
.
text
}
}],
messageId
:
group
.
msgIds
[
group
.
msgIds
.
length
-
1
],
chatUserId
:
group
.
userId
,
replyCallback
:
async
(
replyContent
:
string
)
=>
{
onReply
:
async
(
replyContent
:
string
)
=>
{
await
client
.
sendMessage
({
to_user_id
:
group
.
userId
,
text
:
replyContent
,
context_token
:
group
.
contextToken
});
return
{
errcode
:
0
};
}
});
}
catch
(
error
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment