mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-10-26 21:26:39 +00:00
* fix(community): reserve Browserless capture names before publishing Name selection and publication were two separate operations: `_dedupe_output_name` probed with `Path.exists()` and then `publish_bytes_atomically` ran `os.replace`, so two `web_capture` calls in the same thread outputs directory could both settle on `report.png` before either wrote, and the second publication replaced the first capture while both reported success for the same artifact path (#6883). `web_capture_tool` runs the writer through `asyncio.to_thread`, and same-second default names collide the same way because the generated stem's timestamp has second resolution. Claim the name instead of checking for it: an `O_CREAT | O_EXCL` open either creates an empty placeholder or reports the name held, so the probe walk (-1, -2, ... then the microsecond timestamp) is race-free. `_write_capture_output` releases the placeholder when publication fails, catching BaseException so an interruption also frees the name, and a failing unlink is logged rather than allowed to mask the original error - the same error-masking family #6871 is addressing in the shared publisher, which this change deliberately does not touch. When even the timestamped names are held, the function now raises instead of returning a name it cannot own; returning one would reintroduce the silent overwrite. `tests/test_browser_outputs_atomic.py` pins the publisher call as source text, so its expectation moved to the new call shape in the same commit. Refs #6883 * fix(community): open the reserved capture name with new-file permissions An `os.open` without an explicit mode creates the file with `0o777 & ~umask`, and `publish_bytes_atomically` preserves an existing destination's mode, so the reservation added in the previous commit made every capture executable (`0o755` under the usual umask) where main produced `0o666 & ~umask` (`0o644`) through the publisher's new-file branch. Pass `0o666` explicitly and pin the mode against a `Path.write_bytes` reference in the same directory, which is the permission the publisher documents for new files. Refs #6883 * fix(browserless): warn when capture reservation cleanup fails --------- Co-authored-by: Willem Jiang <willem.jiang@gmail.com>