Skip to content

Releases

v0.5.1

Choose a tag to compare

@huangfuren huangfuren released this 06 Nov 09:49
  • 补 dsh.compatibility.dshReleases 声明:0.1.7-rc.2 / 0.2.0-rc.2 / 0.2.1-rc.5 /
    0.2.2-rc.1。依据:0.1.7-rc.2 上七插件实测加载;0.2.2-rc.1 的三条客户端断代 API
    (EntryTree.write()→commit(change)、MenuTarget→ContextMenuTarget、
    useAnchoredPosition / Menu.getAnchorRect 移除)本仓引用数为 0。该字段供插件市场与
    兼容性阅读器查看,不参与宿主加载判定 —— 宿主强校验的仍是 peerDependencies。

  • 修复 SMB 推送复制步骤从未成功过的致命 bug:robocopy 的参数被手工加了引号。
    execFile 不经 shell,参数里的引号会被原样交给程序,而 robocopy 自己不做引号剥离 ——
    带引号的路径让它直接以 exit 16(语法/参数错误)拒绝执行,一个文件都不会复制
    (实测:带引号 exit=16、目标目录为空;裸参数 exit=1、文件正确落盘)。现改为传裸参数。
    这条通道此前「挂载修好了、复制仍必然失败」,与 0.5.0 修的挂载 bug 是同一类的只在真机
    才暴露
    的问题。

  • 新增两条 robocopy 实机用例与一条引号回归用例:单测过去只断言「参数构造」,证明不了
    「文件落到了哪」。现在在 Windows 上真跑一次 robocopy(纯本地临时目录,不联网),断言
    落盘位置;CI 的 ubuntu / macos 组合自动跳过。

  • 修复 SMB 推送单文件会多出一层同名目录:robocopy 的「目标」参数恒为目录,而单文件
    分支把目标写成了 <destDir>\<leaf>,于是文件实际落到 …\<leaf>\<leaf>。现在单文件的目标
    就是 destDir 本身、文件名作为第三个位置参数;目录分支不变(目标即 <destDir>\<leaf>)。

  • 设置项 sharePort / shareExpiresIn / sharePassword 真正生效:三者此前只定义了 schema、
    渲染了设置卡片、写进了 README,但 host 端引用数为 0 —— 改了不生效。现新增纯函数
    resolveShareOptions()(显式参数优先 → 设置项兜底 → 内置默认),localsend_share 与
    localsend_send_plugin 均改用它,并在入口配置里补齐三者默认值。

  • 修复 expiresIn: 0(无有效期)在参数层不可达:旧实现写 Number(x) || 3600,把显式传入
    的 0 当成假值吞成了 3600,与 README / 工具描述里「0 = no expiry」的承诺矛盾;port 同理。
    现在只有「未提供」才回落默认,0 与空串按原样生效。

  • 修复分享通道「调用后永久挂起」的致命 bug —— localsend_share / localsend_send_plugin
    此前从未真正可用过
    :createShareSession() 用 resolve({url,token,port,expires,files,close})
    返回了一个新建的对象字面量,而 closed / downloaded / onDone / temps 只存在于内部
    会话对象上。两个工具都写 session.onDone = fn 等下载结束 —— 回调落在另一个对象上,
    shutdown() 永远读不到,于是 await 永不返回。宿主侧也没有兜底:timeoutMs 在 DSH 里
    仅作声明、不强制执行,所以工具会一直挂到用户手动取消,而取消又会关掉服务器、只拿回一条死链。
    实测:expiresIn: 5 在 8 秒后 onDone 仍未触发,且返回对象上 closed === undefined。
    现在 createShareSession() 直接 resolve 会话本身;两个工具改为生成链接后立即返回,
    服务器在后台继续服务直到过期或全部下载完成;临时 zip 改由会话持有、在会话关闭时清理
    (此前由工具在 finally 里删除 —— 一旦改为立即返回,链接就会指向已被删掉的文件);
    工具也不再绑定 exec.signal,否则对话一结束服务器就被关掉。

  • 分享链接改为根路径:多文件时 /dl/<token> 只会给出第 1 个文件(实测响应体只含第 1 个),
    现在对外给 http://<ip>:<port>/ —— 多文件渲染列表页,单文件自动 302 跳转到下载。

  • 新增 6 条分享会话契约测试(test/share-session.test.js):锁住「返回的是会话本身」、
    onDone 在「下载完成 / 到期 / 手动 close」三种情形下都会触发、临时文件随会话清理、
    根路径渲染多文件列表页。此前 grep onDone test/ 零命中 —— 50 个用例全绿也测不出这个 bug。

  • 大目录打包改为流式写入,内存占用降一个数量级:packDirectory() 过去先由
    collectDirectory() 把每个文件的内容读进内存攒成数组,再交给 createZip() 一次性
    concat 出完整 zip —— 整个过程中「全部原始数据 + 全部压缩结果 + 最终 buffer」同时驻留。
    实测打包 60 MB 目录(20 个 3 MB 不可压缩文件)后仍驻留 375 MB。现在新增
    writeZipFile()(lib/zip.js)逐文件「读入 → 压缩 → 写盘 → 释放」,collectDirectory()
    只收集文件清单(stat,不读内容),同样输入驻留降到 21.5 MB。createZip() 保留给
    插件包等小体量输入。

  • zip 写入改用 FileHandle 顺序写:先前的 WriteStream 版在「首个文件读取即失败」时,
    异步 open 会在调用方结束之后才落地并抛 ENOENT(实测触发 uncaughtException);
    改用 fs.promises.open() + 顺序 write() 后收尾干净,失败时也不会在磁盘上留下半截 zip。

  • 分享链接不再指向虚拟网卡:getLocalIp() 旧实现取「第一个非内部 IPv4」—— 装了
    WSL / Hyper-V / VirtualBox / Docker 时枚举顺序常把虚拟网卡排在前面,链接于是指向对端
    根本访问不到的地址。现在新增 getLocalIps() 返回全部候选,getLocalIp() 优先物理网卡、
    跳过链路本地 169.254.x,全是虚拟网卡时才退回第一个候选;localsend_share 在多网卡时
    会把所有候选地址打进日志,便于手动替换。

  • 发送前增加可达性预检 —— 失败从 4 分钟降到 3 秒,并给出下一步:localsend_send_files
    过去对 IP 目标不做任何探测就直接进入 prepare-upload,于是「IP 打错一位」要等满
    acceptTimeoutMs(默认 240 秒)才换来一句 network error: timeout after 240000ms ——
    既没说哪一步失败,也没说下一步该做什么(实测确认失败耗时完全等于超时值)。
    现在 lib/discovery.js 新增 probeDevice():发送前对目标打一次 /info,不通就立刻报错并
    列出三条可操作路径(① 确认 LocalSend 已安装且正在运行 ② 确认两台机器在同一局域网
    ③ 改用 localsend_share,接收方用浏览器即可,无需安装任何东西)。
    实测不可达地址 3082 ms 返回,对比修复前的 240 秒。

  • 协议不再硬编码 https:probeDevice() 先试 https 再试 http,并把探到的协议传给
    sendFiles() —— LocalSend 默认用自签名 https,但 tailnet / 反向代理等环境可能只暴露
    http,旧实现遇到这类接收端必然失败。实测「只开 HTTP 的接收端」8 ms 即被探到并正确
    判定协议。

  • prepare 超时的错误文案改为说明真实原因:预检通过后对端必然在线,此时超时基本只剩
    「接收端没点接受」一种解释,报错直接说明这一点并提示 LocalSend 可开启自动接受。


完整变更:CHANGELOG.md

兼容性:已验证 DeepSeek Harness 0.1.7-rc.2 / 0.2.0-rc.2 / 0.2.1-rc.5 / 0.2.2-rc.1。声明见 package.json 的 dsh.compatibility.dshReleases;宿主强校验的仍是 peerDependencies。

v0.5.0

Choose a tag to compare

@huangfuren huangfuren released this 06 Nov 09:53
  • 新增「目标机档案」(smbProfiles):设置卡片里可为每台目标机保存一条档案
    (档案名 / 目标 IP / 共享名 / 共享下子目录 / 账户 / 密码),localsend_smb_push 只需
    profile="<名>" + files 直推;任何显式参数(target/share/destDir/username/password)
    按字段覆盖档案。把「无软件推送」从"每次重填 5 个参数"变成"配一次 + 一条命令"。
    新增 lib/smb.js 的 findProfile()(按名查找,找不到时列出已配置的档案名)与
    mergeProfile()(显式参数优先、空值回落到档案)。
  • 设置卡片新增档案编辑器:可增删档案行,六字段(密码用 password 输入框);
    保存前校验「档案名与主机必填、档案名唯一」,两端文案均双语。
  • 修复 localsend_smb_push 从未成功挂载的致命 bug:mountShare() 曾把 targetDir 单独
    拼一次,而 buildNetUseArgs() 的返回值里已含它 —— net 因此收到两个 devicename 加上凭据
    共 4 个位置参数,直接打印用法说明(语法错误)。带凭据与来宾登录两条路径都必然失败,
    即该通道此前从未真正跑通。现改为 net use <buildNetUseArgs 返回的完整参数>,并新增
    「目标只出现一次」的回归用例;同时把 net 错误 67(找不到网络名)并入「找不到网络路径」提示。
  • 安全约定更新:档案中的凭据(含密码)以明文保存在本机 DSH settings 文件里,会随该文件
    被同步/备份而流转 —— 这是为「自己的多台机器之间推送」做的取舍。README 中英两版均已标注
    「勿在共享/多人机器上启用」,并修正原先"不存储任何凭据"的无条件表述。
  • 文档:README 默认语言改为中文并同步中英两版内容。 语言约定统一为 README.md(中文,默认入口)+
    README.en.md(英文),两版顶部互链;README.zh-CN.md 已并入 README.md 并删除。
    同时修正中文版遗留的版本号、补齐 localsend_smb_push 与 peer 范围的准确描述,
    使中英两版与当前包状态一致。files 改为分发 README.en.md。
  • 脱敏:清除 lib/tools/smb.js 参数示例与 test/smb.test.js 中的真实内网 IP 与主机名
    (统一改用文档专用网段 192.0.2.10 与占位主机名 TARGET-PC),并把 test/unit.test.js 中
    疑似本机网卡地址归一为通用示例 192.168.1.66。

完整变更:CHANGELOG.md

本条为历史版本补录:tag 早已存在,Release 于 2026-11-06 补建。

v0.4.1

Choose a tag to compare

@huangfuren huangfuren released this 06 Nov 09:53
  • 修复设置卡片崩溃导致「内置插件」页签空白:卡片在 useEffect 里调用 face.localePreference(),
    但注入的 face 只提供了 readValues / saveValues,调用即抛 TypeError,
    整张卡片连同面板被 React 摘掉 —— 表现为在 设置 → 内置插件 里选中「LocalSend 局域网传输」后下方全空。
    现在 face 提供 localePreference()(优先宿主 locale 服务,缺失时回退浏览器语言),
    调用侧同时加能力探测 + try/catch:旧版 face 缺这个方法时只损失语言切换,不再影响卡片渲染。
  • 兼容性:不新增宿主 API 依赖,对 dsh 0.1.x 与 0.2.0-rc.1 均安全。

完整变更:CHANGELOG.md

本条为历史版本补录:tag 早已存在,Release 于 2026-11-06 补建。

v0.4.0

Choose a tag to compare

@huangfuren huangfuren released this 12 Sep 13:07
dsh-localsend 0.4.0: SMB push channel

v0.3.1

Choose a tag to compare

@huangfuren huangfuren released this 06 Nov 09:53
  • 修复 dsh web 启动失败:localsend_share 与 localsend_send_plugin 的 output schema 用了 required: [...] 数组,
    宿主 dsh 的 value schema DSL 只接受逐属性 required: true,插件树加载因此报
    unsupported JSON schema: schema.required is not supported by the value schema DSL 并中断启动。已改为逐属性声明。
  • 修复会话历史损坏(resume 失败):localsend_list_devices 与 localsend_send_files 的 output.render 返回裸字符串,
    而 dsh 契约要求返回内容块数组(ContentBlock[])。裸字符串被原样写进 tool/result 事件,导致该会话此后每次加载都报
    SessionPersistenceCorruptionError: session event at seq N message must contain one tool-result block。
    现已改为 [{ type: 'text', text: String(value) }],与其余工具一致。
  • 升级提示:0.3.0 及更早版本产生的历史会话若调用过上述两个工具,需先修复 tool-result.content(字符串包装为文本块)才能恢复加载。

完整变更:CHANGELOG.md

本条为历史版本补录:tag 早已存在,Release 于 2026-11-06 补建。

v0.3.0

v0.3.0 Pre-release
Pre-release

Choose a tag to compare

@huangfuren huangfuren released this 11 Sep 04:59
feat: 0.3.0 - localsend_send_plugin (self-contained plugin package ov…