mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-22 22:48:11 +00:00
fix(feishu): address third-round codex bot review feedback
P2 - Throw ENOENT for non-existing absolute image paths (docx.ts):
Previously a non-existing absolute path like /tmp/missing.png fell
through to Buffer.from(..., 'base64') and uploaded garbage bytes.
Now throws a descriptive ENOENT error and hints at data URI format
for callers intending to pass JPEG binary data (which starts with /9j/).
P2 - Fail clearly when insert anchor block is not found (docx.ts):
insertDoc previously set insertIndex to -1 (append) when after_block_id
was absent from the parent's child list, silently inserting at the wrong
position. Two fixes:
1. Paginate through all children (documentBlockChildren.get returns up to
200 per page) before searching for the anchor.
2. Throw a descriptive error if after_block_id is still not found after
full pagination, instead of silently falling back to append.
This commit is contained in:
@@ -420,22 +420,28 @@ async function resolveUploadInput(
|
||||
}
|
||||
|
||||
// local path: ~, ./ and ../ are unambiguous (not in base64 alphabet).
|
||||
// Absolute paths (/...) are supported but must exist on disk.
|
||||
// Absolute paths (/...) are supported but must exist on disk. If an absolute
|
||||
// path does not exist we throw immediately rather than falling through to
|
||||
// base64 decoding, which would silently upload garbage bytes.
|
||||
// Note: JPEG base64 starts with "/9j/" — pass as data:image/jpeg;base64,...
|
||||
// to avoid ambiguity with absolute paths.
|
||||
if (imageInput) {
|
||||
const resolved = imageInput.startsWith("~") ? imageInput.replace(/^~/, homedir()) : imageInput;
|
||||
const candidate = imageInput.startsWith("~") ? imageInput.replace(/^~/, homedir()) : imageInput;
|
||||
const unambiguousPath =
|
||||
imageInput.startsWith("~") || imageInput.startsWith("./") || imageInput.startsWith("../");
|
||||
const absolutePath = isAbsolute(imageInput);
|
||||
if (unambiguousPath || (absolutePath && existsSync(resolved))) {
|
||||
const buffer = await fs.readFile(resolved);
|
||||
|
||||
if (unambiguousPath || (absolutePath && existsSync(candidate))) {
|
||||
const buffer = await fs.readFile(candidate);
|
||||
if (buffer.length > maxBytes) {
|
||||
throw new Error(`Local file exceeds limit: ${buffer.length} bytes > ${maxBytes} bytes`);
|
||||
}
|
||||
return { buffer, fileName: explicitFileName ?? basename(resolved) };
|
||||
return { buffer, fileName: explicitFileName ?? basename(candidate) };
|
||||
}
|
||||
if (absolutePath && !existsSync(resolved)) {
|
||||
|
||||
if (absolutePath && !existsSync(candidate)) {
|
||||
throw new Error(
|
||||
`File not found: "${resolved}". ` +
|
||||
`File not found: "${candidate}". ` +
|
||||
`If you intended to pass image binary data, use a data URI instead: data:image/jpeg;base64,...`,
|
||||
);
|
||||
}
|
||||
@@ -836,8 +842,9 @@ async function insertDoc(
|
||||
|
||||
const parentId = blockInfo.data?.block?.parent_id ?? docToken;
|
||||
|
||||
// documentBlockChildren.get pages at 200 entries; scan all pages so insert
|
||||
// works when parent has lots of children.
|
||||
// Paginate through all children to reliably locate after_block_id.
|
||||
// documentBlockChildren.get returns up to 200 children per page; large
|
||||
// parents require multiple requests.
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- SDK block type
|
||||
const items: any[] = [];
|
||||
let pageToken: string | undefined;
|
||||
|
||||
Reference in New Issue
Block a user