fix(feishu): decode URL-encoded filenames when receiving files#43916
fix(feishu): decode URL-encoded filenames when receiving files#43916ccsang wants to merge 12 commits into
Conversation
Greptile SummaryThis PR fixes non-ASCII filename display in Feishu by adding Key findings:
Confidence Score: 2/5
Prompt To Fix All With AIThis is a comment left during a code review.
Path: ui/src/ui/chat/tool-cards.ts
Line: 65-84
Comment:
**Double-shift consumes two queue entries per queue-fallback result**
When `args` is `null`/`undefined` and the queue-fallback branch is taken (line 70: `args = queue.shift()`), the "always consume" block immediately shifts the queue a second time (line 82: `queue.shift()`). This means two entries are consumed for a single result card whenever the queue-fallback path is used.
Concretely: if two same-named tool calls exist and their result blocks carry no `toolCallId` and no own args, the second result will incorrectly receive the *third* call's args (or `undefined` if there is no third call).
The "always consume" block is only needed when the first block matched via `toolCallId` (which does not shift) or when the result already has its own args (which also does not shift). For the queue-fallback path, the shift was already performed on line 70 and should not be repeated.
Fix — only run the "always consume" block when the queue-fallback path was *not* already taken:
```
// Always consume matching queue entry to keep queue in sync
// Skip if we already consumed via queue fallback above
const usedQueueFallback = (args !== undefined && args !== null) &&
!(toolCallId && argsByToolCallId.has(toolCallId)) &&
!(coerceArgs(item.arguments ?? item.args) !== undefined && coerceArgs(item.arguments ?? item.args) !== null);
```
Or more clearly, track whether the first block already called `shift`:
```typescript
let args = coerceArgs(item.arguments ?? item.args);
const toolCallId = ...;
let usedQueueFallback = false;
if (toolCallId && argsByToolCallId.has(toolCallId)) {
args = argsByToolCallId.get(toolCallId);
} else if (args === undefined || args === null) {
if (argsQueueByName.has(name)) {
const queue = argsQueueByName.get(name)!;
if (queue.length > 0) {
args = queue.shift();
usedQueueFallback = true;
}
}
}
// Consume queue entry to keep it in sync — but only if we haven't already done so
if (!usedQueueFallback && argsQueueByName.has(name)) {
const queue = argsQueueByName.get(name)!;
if (queue.length > 0) {
queue.shift();
}
}
```
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/media.ts
Line: 243-258
Comment:
**Return type does not match implementation**
The function is declared as `(fileName: string): string`, but the early-return on line 244 returns `fileName` as-is — meaning `null` or `undefined` will be returned when a falsy non-string value is passed. The tests confirm this by using `as any` to bypass the type checker.
The callers pass `parsed.file_name` (JSON-parsed `any`), so `null`/`undefined` is a realistic input. The type signature should reflect this to avoid silent type errors elsewhere:
```suggestion
export function decodeFileNameFromFeishu(fileName: string | null | undefined): string | null | undefined {
```
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/media.ts
Line: 241
Comment:
**Stray asterisk in JSDoc comment**
There is an extra `*` mid-sentence, likely a copy-paste artifact.
```suggestion
* This is used when receiving filenames from Feishu messages
* to ensure proper display of non-ASCII characters.
```
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: 3250356 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 325035697f
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@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: b14ebd1255
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@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: 7118d3fa3e
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@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: e9e468dd29
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Add formatToolArgsForSidebar to render untruncated command and sibling args - Preserve truncated in-card detail while sidebar shows full fidelity - Sidebar now includes Command section plus Args section when extra fields exist - Add browser tests for sidebar content (full command, args, no-output case) Closes openclaw#43153
- Defer args serialization until sidebar is opened (P2) - Populate result-card args from paired tool call (P1) - Choose fence length from longest backtick run (P2)
- Keep markdown fences at minimum 3 backticks (P2) - Use FIFO queue for same-name tool call arg pairing (P2)
When sending files with non-ASCII filenames (Chinese, Japanese, emoji), the filename is URL-encoded via sanitizeFileNameForUpload for safe multipart/form-data transmission. However, when receiving files from Feishu messages, the filename was not decoded, causing display issues like '%E6%B5%8B%E8%AF%95.txt' instead of '测试.txt'. This PR adds decodeFileNameFromFeishu() to decode URL-encoded filenames when parsing Feishu message content, ensuring proper display of non-ASCII filenames in the [File: ...] placeholder and mediaKeys.fileName field. Fixes openclaw#43840
- Use more precise regex to only match valid percent-encoded sequences - Avoids false positives for filenames like report-100%.pdf
Return type now matches implementation (string | null | undefined) Only decode UTF-8 percent-encoded sequences to avoid false positives Add test for literal percent sequences
e9e468d to
e11efb9
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e11efb9b4d
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Closing due to extensive merge conflicts (500+ files). This PR mixed UI and feishu changes that became difficult to reconcile with main branch refactoring. The feishu filename decoding fix can be re-submitted as a clean, focused PR if needed. |
Fixes #43840
Summary
When sending files with non-ASCII filenames (Chinese, Japanese, emoji), the filename is URL-encoded via sanitizeFileNameForUpload for safe multipart/form-data transmission. However, when receiving files from Feishu messages, the filename was not decoded, causing display issues like
%E6%B5%8B%E8%AF%95.txtinstead of测试.txt.Changes
decodeFileNameFromFeishu()function to decode URL-encoded filenamesparseMediaKeys()andformatSubMessageContent()when parsing Feishu message contentTest Plan
decodeFileNameFromFeishufunction