mirror of
https://github.com/TencentCloud/Octop.git
synced 2026-10-21 06:29:24 +08:00
* feat(browser): support real remote drag with shared canvas pointer Forward CDP mousedown/mousemove/mouseup (with clickCount) so remote browser and desktop can drag instead of pan-to-scroll, and share a connecting indicator while the stream starts. * fix(chat): restore loading earlier messages on scroll up Keep the load-older gate armed across virtual list updates, release the in-flight latch when history declines to start, and expose a clickable fallback when the list does not overflow. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(workspace): clarify path semantics with from_workspace Add from_workspace so workspace UI keeps leading-slash relative paths while chat/tool downloads can pass host-absolute send_file paths through BackendWorkspace, with a host download allowlist. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(workspace): preserve chat document path semantics * fix(workspace): harden file URL and host path checks on Windows Preserve Unix-style file:// paths instead of url2pathname backslashes, decode percent-encoded segments, and deny POSIX system roots like /etc before Path.resolve() on Windows. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(workspace): decode Windows file URLs to native paths Unquote percent-encoded segments in file:///C:/… URLs and normalize via Path so send_file enrichment matches str(Path.resolve()) on Windows. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: jubaoliang <jubaoliang@tencent.com> Co-authored-by: Cursor <cursoragent@cursor.com>
44 lines
1.5 KiB
Python
44 lines
1.5 KiB
Python
"""Workspace I/O path resolution for download / file APIs."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from octop.api.routers.workspace import _workspace_io_path
|
|
|
|
|
|
def test_from_workspace_false_slash_is_host_absolute() -> None:
|
|
abs_path = "/Users/jubaoliang/Desktop/IronMan_PPT/钢铁侠.pptx"
|
|
assert _workspace_io_path(abs_path, from_workspace=False) == abs_path
|
|
assert _workspace_io_path("/logo.png", from_workspace=False) == "/logo.png"
|
|
|
|
|
|
def test_from_workspace_true_slash_is_workspace_relative() -> None:
|
|
assert _workspace_io_path("/logo.png", from_workspace=True) == "logo.png"
|
|
assert _workspace_io_path("/outbound/a.pptx", from_workspace=True) == "outbound/a.pptx"
|
|
assert _workspace_io_path("/", from_workspace=True) == "."
|
|
|
|
|
|
def test_relative_without_slash_always_workspace() -> None:
|
|
assert (
|
|
_workspace_io_path("generated/water-ppt/a.pptx", from_workspace=False)
|
|
== "generated/water-ppt/a.pptx"
|
|
)
|
|
assert (
|
|
_workspace_io_path("generated/water-ppt/a.pptx", from_workspace=True)
|
|
== "generated/water-ppt/a.pptx"
|
|
)
|
|
|
|
|
|
def test_file_url_always_host_absolute() -> None:
|
|
assert (
|
|
_workspace_io_path("file:///Users/me/report.pptx", from_workspace=False)
|
|
== "/Users/me/report.pptx"
|
|
)
|
|
assert (
|
|
_workspace_io_path("file:///Users/me/report.pptx", from_workspace=True)
|
|
== "/Users/me/report.pptx"
|
|
)
|
|
|
|
|
|
def test_default_from_workspace_is_false() -> None:
|
|
assert _workspace_io_path("/Users/me/a.pptx") == "/Users/me/a.pptx"
|