fix(feishu): refine streaming card delivery#53534
fix(feishu): refine streaming card delivery#53534allan0509 wants to merge 5 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR refines Feishu streaming-card delivery in two ways: it improves the throttle logic in
As a result, the updated tests in Confidence Score: 2/5
Prompt To Fix All With AIThis is a comment left during a code review.
Path: extensions/feishu/src/reply-dispatcher.test.ts
Line: 17-20
Comment:
**`sendStructuredCardFeishu` removed from mock but still used in implementation**
`sendStructuredCardFeishu` has been removed from the `vi.mock("./send.js", ...)` factory, yet `reply-dispatcher.ts` (line 424) still calls it:
```ts
await sendStructuredCardFeishu({ cfg, to: chatId, text: chunk, ... });
```
Because the module mock now only exports `sendMessageFeishu` and `sendMarkdownCardFeishu`, `sendStructuredCardFeishu` will resolve to `undefined` in tests. Any test that hits a non-streaming card path — such as "passes replyInThread to sendMarkdownCardFeishu for card text" (`renderMode: "card", streaming: false`) and "disables streaming for thread replies and keeps reply metadata" (`threadReply: true`) — will throw `TypeError: sendStructuredCardFeishu is not a function`.
The test assertions expect `sendMarkdownCardFeishuMock` to have been called, but the production code hasn't been updated to call `sendMarkdownCardFeishu`. `reply-dispatcher.ts` needs to be updated alongside these test changes for them to pass.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: extensions/feishu/src/reply-dispatcher.test.ts
Line: 357-361
Comment:
**Test assertions diverge from actual `streaming.start()` call arguments**
The test now asserts `streaming.start` is called with exactly `{ replyToMessageId, replyInThread, rootId }`, but `reply-dispatcher.ts` (lines 275–282) still passes `header` and `note` as well:
```ts
await streaming.start(chatId, resolveReceiveIdType(chatId), {
replyToMessageId,
replyInThread: effectiveReplyInThread,
rootId,
header: cardHeader, // still present
note: cardNote, // still present (also removed from StreamingStartOptions)
});
```
`toHaveBeenCalledWith` uses deep equality, so these tests will fail because the actual third argument has two extra keys. The same mismatch applies to the "passes replyToMessageId and replyInThread to streaming.start()" test at line 691.
`reply-dispatcher.ts` must drop `header` and `note` from the `start()` call (matching the removed `StreamingCardOptions`) for these assertions to hold.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: extensions/feishu/src/streaming-card.ts
Line: 415-416
Comment:
**`this.state` not cleared after `close()` completes**
The previous code explicitly nulled `this.state` and `this.pendingText` at the end of `close()`:
```ts
// old
const finalState = this.state;
this.state = null;
this.pendingText = null;
this.log?.(`Closed streaming: cardId=${finalState.cardId}`);
```
The new code removed those assignments, so after `close()` returns the instance continues to hold `cardId`, `messageId`, `currentText`, and any remaining `pendingText` in memory indefinitely. `this.closed = true` correctly prevents any further API calls, but the heap references linger until the session object itself is GC'd. Consider adding `this.pendingText = null` (and optionally `this.state = null`) after the final log line so closed sessions release their data promptly.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "Feishu: refine streaming card delivery" | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eddbc04de5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 132792daf8
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: afb251c035
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| import type { Client } from "@larksuiteoapi/node-sdk"; | ||
| import { fetchWithSsrFGuard } from "../runtime-api.js"; | ||
| import { resolveFeishuCardTemplate, type CardHeaderConfig } from "./send.js"; | ||
| import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/feishu"; |
There was a problem hiding this comment.
Restore local runtime import to avoid self-referential SDK load
Importing fetchWithSsrFGuard from openclaw/plugin-sdk/feishu inside extensions/feishu creates a self-import through the extension’s public SDK facade, which eagerly pulls in unrelated Feishu re-exports (including ../../extensions/feishu/setup-api.js and ../../extensions/feishu/api.js from src/plugin-sdk/feishu.ts) during normal reply streaming. That increases circular-initialization risk and couples runtime message delivery to setup surfaces; it also violates the explicit root guideline in AGENTS.md (“inside an extension package, do not import that same extension via openclaw/plugin-sdk/<extension> from production files”). This should keep using the local runtime barrel instead of the SDK self-import.
Useful? React with 👍 / 👎.
|
The latest PR head I attempted to merge from this account, but GitHub rejected This one looks ready for a maintainer to merge. |
|
Thanks for pushing this. I landed the current canonical version in #71523, with the changelog credit preserving your representative streaming-card delivery path. I’m closing this PR as superseded because the new PR rebases the throttle/pending-flush behavior onto current main and adds current dispatcher coverage for one-card final delivery. If there’s a gap from your original branch that I missed, tell me and I can reopen/re-check it. |
Summary
Testing
Notes