← Back to home@intpfx

OpenFX

TypeScript monorepo — Deno × Perry × VitePlus × React × Nitro

Stars
0
Language
Swift
Created
May 15, 2026
Updated
Sep 14, 2026

Introduction

OpenFX

OpenFX 是一个以 TypeScript 为主的个人项目集合。当前主产品是使用 OPFS 的 Web 文件库, 并由 Perry 提供复用同一 Web 产品的 macOS 版本;仓库同时保留可独立运行的 domain、历史 项目和可复用能力模块。

当前产品

web/ 提供 VitePlus + React 客户端和 Nitro 服务端,部署目标为 Deno Deploy。首页不是可静默枚举硬盘的本机文件浏览器,也不是营销页,而是由应用自管理的文件库:

  • 用户可从默认空间 HUD 直接唤起系统照片选择器,也可通过通用文件选择器、拖放、PWA 文件处理器或系统分享入口显式导入内容;浏览器不会静默读取完整 Photos 图库;
  • 支持 File System Access API 的安全顶层浏览器可以由用户明确连接一个本地文件夹,以只读 内容墙查看并逐项复制到 OPFS;目录句柄保存在同源 IndexedDB,浏览器可能在重开后再次请求 授权。不支持该 API 时,Bloub 来源按钮直接退化为通用文件导入;
  • 原始字节和索引保存在当前 origin 的 /openfx-file-library/ OPFS 空间,不保留本机路径映射;
  • 图片、实况图片、视频、音频、文本和 PDF 可在应用内预览;音频导入后会在本机后台读取 曲名、歌手、专辑、内嵌封面与内嵌歌词;网格优先以专辑封面展示,无封面时使用稳定纯色 与大字号曲名,HUD 与全屏播放器沿用同一音乐视觉;音乐播放控件复用视频播放器的 Video.js 10 状态与皮肤体系,并通过音频预设适配为紧凑时间轴、前后跳转、倍速和音量控制; 无时间轴歌词以大字号滚动正文展示,不伪造逐字同步;
  • 不支持预览的格式仍保留原件并提供下载;
  • 音频标签/封面/歌词、视频缩略图、字幕关系、播放位置、观看状态和媒体智能视图由文件库 索引维护;
  • 照片在导入落盘后由可取消 Worker 解析 EXIF、位置和 Motion Photo;HEIC/HEIF 同时在本机 生成 JPEG 预览代理,原始字节保持不变;任务状态持久化,中断后可恢复、失败后可重试;
  • 照片可按拍摄日期、实况、收藏、位置和相册派生查看,不复制原始字节;
  • 20 个内置 App 作为只读虚拟条目合并到同一内容墙,不占用 OPFS 配额。
  • 用户可以在本机创建不依赖账号的私有设备网络,或生成一次性配对请求加入已有网络;成员 证书和网络密钥保存在本机 OPFS,设备私钥作为不可导出的 CryptoKey 保存在同源 IndexedDB 密钥保险库,Deno Deploy 不保存私有网络状态。

文件库内容墙使用无间距正方形网格。OPFS 文件与受限远程目录条目会显示在同一内容墙,格子 右下角以绿色圆点表示原件已在 OPFS、蓝色圆点表示原件在其他设备;切换到用户选择的本地 文件夹后,空心圆点是“复制到 OPFS”的 44 px 触控目标,并依次显示导入中、成功或失败状态。 本地文件夹条目不会进入索引、私有设备目录、指纹或缩略图后台任务,只有明确点按圆点后才由 session 复制为独立 OPFS 快照;每次切回文件夹会重新扫描只读视图,但外部原件后续变化不会 自动同步进已有 OPFS 副本。远程格只投影受限元数据和派生缩略图,点按后仍进入私有网络面板 按需读取,不会自动传输原件。少量内容只占需要的列,未占用区域保持磨砂背景。

触屏可像照片应用一样双指缩放,在 2–5 列之间切换并保存本机显示偏好。完全相同或视觉相似 的内容会自动合并为一个联系表式网格格子;点按组格后,页面顶部 HUD 同时列出全部成员, 再点按其中一个才进入单文件查看器。普通内容仍直接更新 HUD 预览,点按可打开内容的 HUD 任意空白或预览区域会进入全屏详情;收藏操作只保留无底色的心形线条图标。视频与实况照片 被选中后会在 HUD 中默认静音循环播放;实况照片格只在左下角保留类型标识,不再叠加右上角 LIVE 标签。尚未选择内容时,HUD 默认显示设备当前月份的完整月历,日期下方使用天气图标; 上下滑动、滚轮或键盘翻页键可逐月切换。浏览器取得定位权限后直接向 Open-Meteo 请求本地当前 天气和日级天气码,定位、网络或预报范围不可用时只显示中性占位,不伪造预测,也不经过 Deno Deploy 保存坐标。已用空间、浏览器估算配额、剩余配额、持久存储状态、设备数和文件数收缩为 月历下方的边缘文字控件,设备控件同时是打开私有网络面板的入口。默认背景由铺满 HUD 的动态 像素点阵构成,已用空间按照片、视频、音乐、文档和其他文件着色,剩余容量统一使用白色点。各 颜色的点数只按真实字节占配额的比例取整,不为极小类型人为补点;动画只改变位置、明暗和呼吸 尺度,不改变容量比例,并尊重系统减少动态效果设置。当前只有本机浏览器能提供真实 OPFS 配额,远端目录中可见或已缓存的文件字节不会伪装成远端设备总容量。再次点按已选内容或组格会 取消选择并回到该概览;App 若只是说明型项目,不再进入独立详情页,而是由 HUD 直接展示 catalog 的名称、技术栈、 项目说明、关键能力、来源路径和可用入口;只有真实同源预览或可操作组件保留打开入口。 摘要型 App 的 GitHub 链接不占用正文空间,而以 GitHub 线性图标显示在右下角收藏图标旁; Greasy Fork、Userscript 下载等其他入口仍保留在摘要内。 当前选中格不使用高亮描边,而是轻微放大上移并覆盖相邻网格,形成从内容墙中被拾起的层次反馈。 来源控制和搜索合并为未选择内容时 HUD 底部的无边框横条。Nebula-Orb 以呼吸、聆听、扫描和 无结果震荡表达真实搜索状态;Bloub 在支持 File System Access API 时连接并切换 OPFS/本地 文件夹,不支持时直接触发导入,并以待机、思考、轨道、涡旋和警觉表达真实来源状态。两个 渲染器各自暂停隐藏帧、尊重减少动态效果,不循环播放无关形态。上游项目、版权、MIT 许可及 Bloub 的设计权利边界保存在根 NOTICE。搜索命中组内任意成员时 会保留整个组。选中单项后不再显示独立的打开按钮;保存链接、新建文本和手动查重入口及其创建 功能均不再提供。所有操作使用轻量线性图标,悬停只高亮图标线条。当前网格项数直接 写入搜索占位文案;页面不提供手动明暗开关,只实时跟随系统主题。移动端竖屏时 HUD 预览固定在顶部;手机竖屏的完整月历模式占约 58% 视口高度,为日期、天气和底部控件保留可触摸 尺寸,横屏与宽屏使用 2fr / 3fr 的左右分栏。下方或右侧内容矩阵以直角边界无缝衔接并独立 滚动。单文件 查看器不再使用独立的底部文件胶囊,而是沿用播放器的黑色玻璃控件语言:非视频内容把返回与 文件身份固定在左上角,收藏、信息、编辑、下载和删除组成右上角动作组;视频的返回、编辑、 下载和删除直接进入播放器内部的左上控件组,并通过同源、当前 iframe 与条目 ID 三重校验的 消息交回文件库执行。非 App 条目可在编辑面板 修改文件名,图片与实况图片还可同时维护相册,保存只更新索引与下载名,不重写原始字节。

私有设备网络

OpenFX 不使用账号区分设备。首台设备创建 PrivateMesh 后成为所有者,并生成网络根密钥、 本机签名/加密密钥、根签名的成员证书和恢复码。新设备自行生成密钥和十分钟有效的一次性 请求码;所有者设备验证请求签名、核对双方一致的六位验证码并明确批准后,才签发成员证书。 网络密钥通过临时 ECDH P-256 与 AES-256-GCM 加密给新设备,不以明文放入配对响应。

网络描述、成员证书、网络密钥和本机密钥引用保存在当前 origin 的 /openfx-private-mesh/state.json OPFS 文件中,与文件原件索引分离;实际设备私钥以不可导出 CryptoKey 保存在同源 IndexedDB。刷新会重新验证根签名成员证书及本机公私钥匹配关系, 损坏或篡改的状态不会被静默覆盖。旧版 v1 OPFS 状态会先把 JWK 导入不可导出保险库,完整 校验后保留 state.v1-backup.json 原文备份,再写入不含私钥材料的 v2 状态;迁移失败不会 覆盖原身份。

普通成员默认可以存储文件但不能邀请新设备;只有持有根签名密钥引用且证书允许邀请的所有者 设备可以批准加入。恢复码包含所有者权限材料,使用用户设置的恢复口令经 PBKDF2-SHA-256 派生 AES-256-GCM 密钥后加密,创建后只在当前面板显示;恢复码与口令必须分别离线保存。 不可导出可以阻止脚本读取原始私钥字节,但不能阻止已在同源执行的恶意脚本调用密钥,后续仍需 把 CSP、依赖供应链和 origin 隔离作为联网前的安全门。

当前实现还提供首个同一局域网传输切片:成员可人工交换由设备签名、十五分钟有效的 openfx-rtc-v1 offer/answer,建立不经过服务器的 WebRTC DataChannel。连接后先按条目传输 文件名、类型、大小和更新时间;接收设备会在连接码有效期内保留待接管通道,页面刷新或 session 停止才会提前取消等待。只有用户点按“读取”时才以 12 KiB 分块取回不超过 4 MiB 的 单文件原件。接收端逐块校验 SHA-256、更新有序哈希链并写入未索引的 OPFS 源文件;当前块 完成 flush 且双槽检查点落盘后才确认发送下一块。只有声明长度、分块数与最终哈希链全部 一致,才登记文件库索引。读取前会按剩余字节与 256 KiB 安全余量预检浏览器估算配额。

读取期间按钮会切换为“取消”。用户明确取消或关闭面板会向提供设备发送取消消息并删除未完成 内容;意外断线、超时、暂存写入失败或 session 停止则保留最近一次已确认检查点 24 小时。 用户重新交换连接码并再次点按同一远端条目的“读取”后,提供设备会重算已确认前缀哈希链, 匹配同一原件才从下一块继续;崩溃后多写但未确认的尾部会先回滚。过期、缺失、元数据改变或 与原件不匹配的暂存不会进入索引。此切片不传本机 OPFS 路径,不自动复制文件,也暂不传 Live Photo 组合或超过 4 MiB 的文件。连接默认只收集本机候选地址; 用户可以在双方设备上明确允许公共 STUN 辅助寻址, 当前固定使用 Cloudflare STUN,只帮助 WebRTC 发现可直连地址,不传目录或文件,也不提供中继。若设备网络阻断 STUN UDP,公共模式 可能在候选收集阶段超时;同一局域网内可关闭该选项,继续使用本机候选直连。

每次成功读取的远端目录都会作为该设备的完整快照写入 /openfx-private-mesh/catalog.json。页面重开或设备离线后仍可显示最近一次受限元数据,但会 明确标成“离线缓存”并禁止读取原件;重新连线后的新快照会整体替换该设备旧快照。加载和成员 变更时只保留当前网络仍获授权的远端成员,撤销设备的缓存随即从展示和持久记录中移除。这个 缓存只是派生展示状态,不是成员权限、文件存在性或同步完成的事实来源;损坏缓存可以忽略, 不会覆盖本机文件索引或阻止打开已验证的网络身份。

在线连接期间,本机受限目录确实变化后只发送轻量失效事件,不把目录或原件塞进通知;接收端 仍通过 DataChannel 请求、校验并整体替换该设备的完整快照。同一设备在一次刷新期间连续产生 的失效事件会合并为至多一次补充刷新,避免导入和后台处理造成并发请求风暴。这个自动汇合只 覆盖当前仍在线的一跳连接,不会自动复制原件,也不等于离线传播或跨重启自动重连。

图片与已有视频预览还会在文件所在设备上按需生成最长边 320 px、不超过 128 KiB 的 WebP 派生缩略图。目录只保存缩略图版本描述,不内联图像字节;远程设备 连线时,文件面板通过同一端到端 DataChannel 自动按需读取,并在 /openfx-private-mesh/thumbnails/ 下单独缓存。每次 session 最多发起 32 个唯一远程 缩略图请求;损坏、超限、不支持或离线时只退回扩展名占位,不会请求、覆盖或丢弃原件。 HEIC/HEIF 仅使用已有 JPEG 代理生成派生缩略图,原始静态帧仍用于下载、指纹和 LIVP。 目录版本更换或成员被撤销时,不再可达的派生缩略图也会从本机缓存移除。

所有者设备可以撤销普通成员。撤销会先把网络 epoch 单调增加、生成新的 256 位网络密钥, 再由根密钥为全部保留成员重新签发当前代次证书;旧成员证书因此不能再与已更新设备建立新 连接。每台保留设备获得只用其 ECDH 私钥才能解开的 openfx-epoch-v1 更新码。已连接设备在 本机持久化新状态后通过 DataChannel 返回确认,离线设备则由用户手工粘贴专用更新码;未确认的 更新码会继续保存在所有者 OPFS,设备以新代次重新连接后才移除。由于没有中心状态源,撤销时 同时离线且尚未更新的旧代次设备之间仍可能暂时互通,不能把本机撤销误述为全网即时抹除。

当前还没有实现自动设备发现、跨重启自动重连、TURN 中继或 Iroh 公网连接、离线目录传播或 多跳汇合、全库缩略图收敛与容量策略、超过 4 MiB 的大文件传输、副本策略、恢复码导入、撤销状态 自动汇合或多所有者协作。即使允许公共 STUN,受 NAT 或防火墙限制的设备仍可能无法直连,刷新后也需要重新交换连接码。后续传输层 必须保持可替换,并把公共发现或中继视为不可信的端到端加密数据通道;Deno Deploy 继续只提供 Web 应用和既有公开产品入口,不新增账号、设备目录、信令、文件索引或网络密钥服务。

重复与相似文件

文件库会在导入完成后以可取消的后台任务生成版本化指纹:

  • 所有普通文件使用 SHA-256 检测字节完全一致的副本;
  • 图片使用 256 位 PDQ 感知哈希识别缩放、压缩或轻微调整后的相似内容;
  • 视频在 8%–92% 的相对时间位置抽取最多 8 帧,按 PDQ 序列、时长容差和多数帧匹配;
  • 实况图片必须同时满足静态图与动态片段相似;完全重复还要求两部分 SHA-256 均一致;
  • 旧索引升级后会自动补算指纹;失败项在每次会话启动时自动重试一次,单个文件失败不影响其 原件、下载和其他分析任务。

SHA-256 完全相同关系与视觉相似关系会共同形成互不重叠的连通组。只有组内所有成员的原始 字节指纹都相同时才标记为“完全相同”,否则标记为“相似内容”;每个组在内容墙只占一个格子, 组内原件仍各自保存在 OPFS。自动归组不会删除、覆盖或替用户保留某个版本,用户仍需从组 HUD 逐项打开确认并使用现有删除操作,避免感知哈希误判造成数据损失。

首页 HUD 还提供独立的“照片来源核对”面板,用于比较用户明确选择的两个临时只读来源:一侧 是从 Apple Photos 手动导出的普通文件夹,另一侧是 USB 上的文件夹。这个流程不会直读或枚举 iCloud 共享图库,不会把所选内容导入 OPFS,也不会保存目录句柄、清单或核对结果;关闭或清空 面板后即丢弃当前状态。不支持 File System Access API 时退化为用户明确选择文件夹内容的浏览器 输入。目录按顺序读取并保留来源类型与相对路径;同目录同名的图片与 MOV/MP4 先组成一个逻辑 Live Photo,OpenFX .livp 则解包后按原始静态帧与动态片段比较。只有两部分原始字节的 SHA-256 都一致才显示“完全重复”;PDQ 图片/视频相似结果只显示为人工审阅候选。该面板不提供 导入、移动、覆盖、删除或自动保留版本操作,原有 macOS 系统选择器的一次一张 Live Photo 导入 入口保持不变。

实况图片边界

当前文件库已经实现:

  1. 同名图片与 MOV/MP4 的导入配对;
  2. JPEG Motion Photo 的 XMP 检测、尾部 MP4 提取与 OPFS 保存;
  3. OpenFX 旧二进制与 ZIP .livp 双格式探测和导入,并以无压缩 UTF-8 ZIP 作为 canonical 导出格式;
  4. HEIC/HEIF 原片的本机 Worker 解码,以 JPEG 代理正常显示静态帧,同时保留原片用于下载、 SHA-256 和 LIVP;
  5. 静态图与动态片段的全窗口查看,包括桌面悬停、移动端长按、松手复位、静音和触觉反馈;
  6. 实况图片可下载为原片静态帧 + MOV/MP4 的 ZIP、JPEG + MOV/MP4 的兼容 ZIP,或包含原片 静态帧与动态片段的单文件 OpenFX LIVP;
  7. JPEG EXIF 的方向、尺寸、拍摄时间、相机、镜头、曝光、评分和 GPS 解析;
  8. 持久化照片分析队列,以及收藏、相册、日期和位置派生视图。

OpenFX 二进制 .livp 与 ZIP 容器不是同一格式,因此导入时先探测再解码。ZIP 读取支持 stored 和 deflate 条目;未知变体仍作为普通文件安全保存。这里的 .livp 是 OpenFX 交换格式,不应对外宣称已经支持无授权枚举 Apple Photos 图库、Quick Look 或所有第三方 变体。普通浏览器中的“Photos”入口仍由用户在系统文件选择器中明确授权具体文件,安装为 PWA 后也可接收系统分享;macOS App 则使用下面的原生 Photos 选择边界。

macOS 版本

domains/openfx-macos/ 使用 Perry 提供持久化 WKWebView,并在固定的 http://127.0.0.1:15501 origin 加载当前 Web 构建。原生桥接只监听 loopback;用户点按 “Photos”后,系统 PHPickerViewController 只允许选择一张 Live Photo,再通过 PhotoKit 读取该资产的原始静态帧与 paired video。两个资源以流式响应交给 Web,转换为同名 File[] 后继续调用 file-library-session.ts 的既有导入入口,由同一 OPFS store 完成配对、 落盘、预览代理和后台分析。选择器由独立的 AppKit 窗口承载,不依赖 Perry WebView 暴露的 contentViewController;取消后原生桥会释放窗口和请求状态,因此可以立即再次打开。 主窗口保留原生红绿灯和系统窗口行为,但隐藏标题与独立标题栏;WKWebView 延伸到窗口顶部, 让系统红绿灯直接嵌入文件库 HUD 的内容背景中,并在红绿灯右侧保留透明原生拖拽区。loopback 静态服务会把 /hlc/ 这类目录 URL 解析为目录内的 index.html,避免嵌入式 App 错误回退到 文件库根页面。

这实现了“一次选择完整导入”,但没有绕过系统授权,也不会枚举未选择的照片。原生资源接口 使用每次启动随机生成的 session token,不使用 base64 搬运大文件。WKWebView 与 Safari、 Chrome 各自拥有独立的物理网站数据容器,因此它们共享存储模型和代码,不共享同一份 OPFS 字节;macOS App 自身重启后会继续使用自己的持久库。

LivpExplorer 迁移与退役结论

原 domains/LivpExplorer/ 是从 ChronoFrame 导入并改名的独立自托管照片库,使用 Nuxt 4、Vue、SQLite/Drizzle 和独立 pnpm workspace。它从未成为 Web 首页的运行依赖。

可迁移的本地照片能力已经由 web/src/file-library/ 和 domains/_shared/livp-codec.ts 接管:同名配对、Motion Photo、Live Photo 交互、EXIF/GPS、 相册/收藏/派生视图、可恢复处理任务,以及 LIVP 双格式导入和 canonical 导出均不再依赖 原 Nuxt 应用。迁入实现使用浏览器 File、Worker 和 OPFS 边界,没有复制 Vue 页面、Drizzle 模型或 SQLite 服务。

分享/reaction、账号体系、SQLite、S3/OpenList、服务端公开 URL、反向地理编码供应商和 管理后台属于另一个多用户产品,不迁入本地优先文件库。若未来需要同步,应作为可选 适配器重新设计,而不是保留对 LivpExplorer 的依赖。

迁移回归验证完成后,domains/LivpExplorer/ 上游源码快照已于 2026-08-10 物理删除, deno.json 中仅用于跳过该独立工具链的两条排除项也已移除。迁入代码的 ChronoFrame MIT 归属继续固化在根 NOTICE,不依赖旧目录存在。

仓库结构

domains/          独立产品、历史项目和共享能力
  _shared/        运行时边界明确的共享算法与基础设施
  BewlyScript/    B 站桌面原站美化 userscript
  dsh-openfx/      DSH Web 五个能力包与一键组合包
  e/              运行时无关的 Agent 执行框架
  maci/            macOS 菜单栏内存、开发服务与窗口翻译
  media-player/   文件库专用最小播放器
  openink/        本地优先压感绘图工作台
  openfx-macos/   Perry WKWebView 与原生 Photos 导入桥
web/              OPFS 文件库与 React + Nitro Web 产品

主要 domain:

Domain定位与 Web 首页的关系
_shared文件库 LIVP 容器编解码边界被 Web 文件库引用
BewlyScriptVue userscript,输出单文件安装包内置 App 与安装入口
chinagas-wms-qrcodeWMS 物料二维码 userscript内置 App 介绍
costing-assistant浏览器本地工程计价助手动态预览 App
dsh-openfxDSH Web 主题、壳层、批注、用量与浏览器套件六个内置 App 介绍
eAgent core、reference runtime 与前台协议内置 App 介绍
finlyzer本地优先账单分析 Electron 应用动态预览 App
gasmap燃气工程单线图工具动态预览 App
hlc圣灯社区 PWA/CMS只读同源展示 App
how-much商品价格查询与地图报告Web API 与内置 App
map-posterOSM 地图海报生成器Web API 与内置 App
macimacOS 菜单栏工具、软件、容器与下载管理独立本机运维工具
media-playerOPFS 视频读取、Video.js 控件和播放引擎文件能力,不重复作为 App
openink本地优先压感绘图、OPFS 多画稿与导出动态预览 App
openfx-macosPerry macOS 壳与原生 Photos Live Photo复用完整 Web 文件库
wanone早期静态站点纪念项目动态预览 App

Web 文件库还索引 Smartisax、LiveSystem 和 WanderingPlan 等外部项目。App 的公开文案、 preview 和链接保存在 web/content/library-apps.json;ID、详情 renderer 与嵌入策略由 web/library-app-catalog.ts 统一校验。

文件库界面在手机竖屏让完整月历 HUD 占约 58% 视口并固定在顶部;手机横屏和桌面宽屏统一 切换为 2fr / 3fr 的左侧固定 HUD、右侧独立滚动矩阵。默认 HUD 以月历和本地天气为主体, 真实存储点阵位于月历背景,搜索与统一导入入口贴合底边;单项操作悬浮在所选内容预览内。 两种布局都保持内容格为正方形,并支持双指缩放调整列数。

Web 入口的几个深 Module 分别承担稳定边界:

  • src/file-library/file-library-session.ts 管理 OPFS 加载、用户 mutation、存储状态、 私有网络创建/配对、照片/音频标签/指纹/视频缩略图队列,以及文件处理器和播放器消息;React 首页 只订阅 snapshot;
  • src/file-library/private-mesh.ts 保存运行时无关的网络身份、根签名成员证书、一次性配对和 ECDH 密钥传递;private-mesh-key-vault.ts 保存不可导出密钥句柄并提供 IndexedDB adapter, private-mesh-recovery.ts 负责口令加密恢复材料,private-mesh-store.ts 只负责独立 OPFS 状态、v1 备份迁移和加载校验;private-mesh-catalog.ts 定义受限远端目录与成员过滤, private-mesh-catalog-store.ts 持久化派生目录与缩略图缓存,private-mesh-thumbnail.ts 在本机生成有界 WebP; private-mesh-transport.ts 负责成员签名的人工 WebRTC 信令和 DataChannel 生命周期, private-mesh-transfer.ts 负责目录元数据、目录失效事件、派生缩略图、带逐块确认/完整性校验与取消 协议的分块按需读取和已确认的在线 epoch 更新,private-mesh-staged-file.ts 负责把流式 sink 收束为可提交、可保留续传或可丢弃的暂存状态机;OPFS store 使用双槽持久检查点、 配额预检与 24 小时过期清理,private-mesh-catalog-sync.ts 合并同一设备的密集目录刷新;
  • library-app-catalog.ts 将 App 内容清单和 renderer 能力收成一份可校验 catalog;
  • publication-targets.ts 是 Nitro 静态资产、Vite 开发代理和构建前准备目标的共同事实源;
  • domains/openfx-macos/ 只负责 WKWebView 生命周期、loopback 静态服务和 PhotoKit I/O, 导入后的文件状态与 OPFS mutation 仍由 Web session 管理;
  • domains/map-poster/src/web-service.ts 管理地图海报输入与生成 use case, viewport.ts 管理纯 Web Mercator/瓦片计算,Web 服务层只注入 Nominatim adapter。
  • domains/openink/src/drawing-document.ts 保存版本化文档、原始压力点、不可变历史、变换纯函数与 perfect-freehand 派生轮廓命中;drawing-library.ts 以不可变正文修订和双槽目录管理多画稿、原子提交与旧 localStorage v1 迁移,opfs-text-store.ts 只适配同源 OPFS;stroke-renderer.ts 复用同一轮廓并收束 SVG 导出,React 页面只处理 Pointer Events、渲染、交互编排与下载。

开发

前置依赖为 Deno。根目录常用命令:

deno task dev
deno task dev:client
deno task dev:server
deno task build
deno task check
  • dev 先准备 HLC 与播放器静态资源,再同时启动客户端和服务端;
  • dev:client 只启动当前源码的 Vite 客户端:http://localhost:5501;
  • dev:server 只启动 Nitro API 与静态资源服务:http://localhost:3000;
  • 日常开发应进入 5501;3000 主要供 5501 的开发代理使用,不作为前端热更新入口;
  • 并行实例可分别用 OPENFX_VITE_DEV_PORT 与 Nitro 标准的 PORT 改写端口;
  • 根 deno.lock 管理 Web 与 Deno workspace 依赖。
  • 根目录和 web/ 只以各自 deno.json 为配置源;根 package.json 与 package-lock.json 已移除,并由 deno task guard:deno-only 防止回归。
  • Web 客户端通过 Deno 脚本调用 VitePlus Core,不依赖 vp 对 package.json workspace 的发现行为。

根 deno.json 同时保存 Deno Deploy 的构建与动态运行时配置。本机 Deno 2.9.5 可直接 上传当前 checkout 并创建预览 revision:

deno task deploy

命令从仓库根上传源码,在 Deploy 构建环境运行 deno task build,随后以 web/.output 为运行目录、server/index.ts 为动态入口。Nitro 使用 Deno 文件系统静态 资源处理器读取同目录下的 public/,避免把大型 Worker、WASM 和媒体资源内联进 server entry 而拖慢 Deploy warm-up。根配置固定发布到 universes/openfx;只有明确准备切换生产 流量时才追加 --prod。CI 或 Agent 使用 DENO_DEPLOY_TOKEN,并追加 --json --non-interactive。

domains/media-player/.openfx-public/ 保存最小播放器的确定性发布快照。普通开发和 GitHub CI 会从 domain 源码重新构建它,CI 同时检查快照无差异;Deno Deploy 直接复用该 快照,避免在 3 GiB builder 中再次运行独立 pnpm 安装。

这里的“统一”为根产品工具链收口,不是删除所有 domain 的独立构建边界。下列产品仍由其 自身配置和工具链构建;需要包清单或独立锁文件的上游项目继续保留:

独立工具链:

范围常用命令
domains/BewlyScriptbun install、bun run dev、bun run check:userscript
domains/dsh-openfxpnpm install、pnpm test、pnpm typecheck、pnpm build
domains/media-playerdeno run --no-config -A openfx/build.ts、deno run --no-config -A npm:pnpm@9.15.9 test
domains/map-posterbun test、bun run typecheck
domains/macideno task check、deno task install、deno task status
domains/finlyzerpnpm dev、pnpm dist:win
domains/openinkdeno task check、deno task build
domains/openfx-macosbun install、bun run check、bun run build

Web 服务边界

公开入口包括:

  • GET /api/health
  • /api/how-much/*
  • POST /api/map-poster/render
  • /media-player/*
  • /hlc/*
  • /openink/*

Map Poster 生产环境需要:

  • OPENFX_MAP_POSTER_NOMINATIM_SEARCH_URL
  • OPENFX_MAP_POSTER_NOMINATIM_REVERSE_URL

生产构建使用有界 Deno 入口:请求体在进入 Nitro 前限制为 64 KiB,并使用运行时真实远端 地址覆盖外部伪造的转发地址。

特殊模块

  • media-player 只保留 OPFS 读取、字幕、续播、Video.js 10 控件以及 playsvideo@0.4.7 的直通、解封装、分段和必要音频转码。完整 PlaysVideo domain 已物理删除;固定引擎保存在 vendor 包中。

  • HLC Web 展示只复制地图和艺术资产,不发布认证、内容工作流或写入接口。修改 domains/hlc/source/index.html 后运行:

    deno run --no-config --allow-read --allow-write domains/hlc/tools/build-display-app.ts
    
  • BewlyScript 只交付 userscript,不恢复 WebExtension popup/options/商店打包。 m.bilibili.com 只显示请求桌面站提示,不挂载主 Vue App。

  • domains/e 的 core 必须保持运行时无关;文件系统、模型、Git、MCP 和副作用通过接口 注入,危险动作经过 SafetyActionGate。

  • domains/openink 以原始压力点作为画稿事实,perfect-freehand 只负责生成可重算的轮廓;选择移动与缩放只修改变换。画稿库在同源 OPFS 中保存不可变正文修订与双槽目录,支持缩略图列表、新建、重命名、复制和原子恢复;首次打开 会在 OPFS 成功吸收后迁移并清除旧 localStorage v1 单画稿;兼容存储产生的新稿也会在 OPFS 恢复后先并入现有画稿库。用户显式选择的纸张照片会以原始字节留在本机,并通过手动 四角透视、背景/阴影清理、阈值、降噪和粗细控制生成可重建蒙版与 SDF;套索可整笔选择原生 笔画,并把圈内照片墨迹切成可统一移动、缩放和删除的片段。画稿 v3 用从底到顶的显式图层 组织原生笔画与照片墨迹,支持活动层、新建、重命名、排序、显隐、锁定和确认删除,旧 v1/v2 画稿会无损迁入默认层。“默认、黑板、蓝图、正文、纸张、像素、素描、沃霍尔”是八种画稿级 统一材质,分别使用粉笔颗粒、发光网格、凸版压痕、横线渗墨、整组栅格像素、石墨纹理与套色 网点等确定性 SVG 工艺;实时画布、画稿缩略图和导出保持一致。SVG 是 canonical 导出,PNG 由包含照片墨迹的 SVG 本机派生;尚未实现自动边缘 识别、旋转、逐图层材质、整张画稿删除、标签、云同步或 Carbo 专有格式读写。

  • domains/openfx-macos 的 bun run build 会先构建并暂存 Web 公共资源,校验 Perry 与 Swift/C ABI 桥,产出 ad-hoc Hardened Runtime 签名的 dist/OpenFX.app;正式分发仍需单独 配置 Developer ID、notarization 或 App Store 签名。

maci

原生 Agent 接口

maci 将可自动化操作作为原生接口维护。Agent 与面板调用同一套配置迁入、代理接管和恢复事务, 无须依靠界面坐标。入口为应用中的 Contents/MacOS/maci agent …,构建后也可用 domains/maci/bin/maci agent …。先读取 agent capabilities 获得当前版本的完整参数及读写影响; 能力的 available 表示该版本包含实现,实际后台是否运行、签名和许可是否满足仍以操作结果为准。 连接能力的 effects 会声明 vergeImportedProfileEnablesLoopbackTCP7897,供 Agent 在接管前识别固定兼容监听。

命令当前支持
agent capabilities当前构建的能力、协议版本和参数查询,不连接后台或启用可选功能
agent app status当前版本、版本类型、正式安装位置及 GUI 进程状态
agent app update-preview --source /absolute/maci.app只读验证界面更新候选、正式安装及后台保持条件,返回五分钟预览与状态令牌
agent app update-apply --source … --preview-token … --expect …复验候选与运行状态后更新正式 GUI,保持同一代理和显示后台,重开 GUI 并核验结果
agent app update-status只读查询更新回执及其 stateToken;未知结果不自动重放
agent app update-reconcile --expect …只确认已完整交换、实际 GUI 和保留后台均经重新核验的更新回执,不重放安装或重启进程
agent proxy profiles配置 ID、修订号、名称和功能开关;不返回订阅或配置原文
agent proxy status真实后台、接管方式、路由模式、运行代次、共享状态、本机兼容端口和恢复提示
agent proxy feature-status离线读取功能启用状态、恢复提示与前置令牌,不解析订阅或启动后台
agent proxy feature-enable --expect …显式启用功能,仅保存选择,不注册后台或连接网络
agent proxy feature-disable --expect …与面板共用锁和恢复事务,确认停止接管后停用;失败或未知保留处理入口
agent proxy import-preview --source verge只读预览当前 Verge 来源、现有迁入及五分钟提交令牌
agent proxy import-commit --preview-token … --expect …重验来源、当前手选、Geo 和目的库代次后迁入;拒绝重复覆盖
agent proxy connect --profile-id … --capture system|tun --expect …使用已批准且正在运行的代理后台接管,不自动注册或停用其他代理
agent proxy disconnect --expect …通过同一恢复事务断开并核验实际结果
agent proxy mode --mode rule|global|direct --expect …持久保存并读回路由模式
agent archive capabilities两个版本的归档格式与限制,不启动 Worker
agent archive preflight --intent-fd N读取有界 JSON 意图、建立匿名源快照并返回五分钟预检与状态令牌
agent archive create --intent-fd N --preview-token … --expect … [--password-fd N]重验完整意图、源内容、目标目录和期限后创建并回读发布结果
agent archive extract --intent-fd N --preview-token … --expect … [--password-fd N]经相同事务解压单包或所选分卷组,不执行包内程序
agent archive status [--job-id UUID] / agent archive result --job-id UUID读取有界作业回执与最终路径,遗留未结束作业显示为未知
agent archive cancel --job-id UUID --expect …比较作业状态后请求取消,等待执行器确认清理
agent archive recovery --destination /absolute/path只读检查指定目录的恢复记录与完整状态令牌
agent archive recover --destination … --record-id … --decision removePublishedRecord|discardInterrupted --expect …重验目录、记录与锁后,仅清理明确选中的自有记录或未发布暂存
agent software status / agent software list按实际软件来源读取本机清单、更新候选与操作回执
agent software preview --id … --operation upgrade|uninstall预览来源操作、依赖与影响,返回五分钟令牌
agent software apply --id … --operation … --preview-token … --expect …复验库存及回执,在同一来源执行并读回
agent software reconcile --expect …只核对未知操作是否已经完成,不重新升级或卸载
agent software acknowledge --id UUID --expect …人工核对当前状态后结束指定未知回执,保留未知结果与历史
agent containers status / list / images检测系统、Apple container 版本、容器及镜像,不启动运行时
agent containers logs --id … [--tail 100]显式读取指定容器的有界日志,不进入状态回执
agent containers preview --operation … / apply --operation … --preview-token … --expect …安装包准备、服务启停、容器创建及启停删除;完整选项由 capabilities 枚举
agent containers reconcile --expect …核对未知容器操作的实际结果,不重放操作
agent containers acknowledge --id UUID --expect …人工核对后结束未知回执,不重放容器操作或抹去历史
agent downloads status / agent downloads list读取任务、进度、速度、连接数和状态令牌,不启动下载进程
agent downloads preview --url … --destination /absolute/directory [--name …]校验目标与文件名,预览不覆盖的新任务
agent downloads add --url … --destination … --preview-token … --expect … [--name …]持久保存任务后启动独立下载进程
agent downloads pause|resume|cancel|retry|remove --job-id UUID --expect …经状态比较控制任务;移除历史不删除已完成文件
agent downloads reconcile --job-id UUID --expect …只在发布身份、长度和内容摘要重新匹配时确认已完成,不重放下载或重命名
agent displays status读取已运行后台的显示场景、能力与状态令牌,不注册或启动服务
agent displays preview --mode only|mirror|extended --display-id N [--mirror-target N]预览自有虚拟屏的唯一、镜像或扩展场景
agent displays apply --mode … --display-id … --preview-token … --expect … [--mirror-target …]复验实际布局后进入 15 秒显示试用
agent displays confirm|cancel --pending-id UUID --expect …核验保留试用或恢复之前布局,拒绝过期状态与重复操作

归档意图使用 UTF-8 JSON,最多 64 KiB,只接受已声明的字段,拒绝未知及重复键。例如创建 ZIP 的意图:

{
  "schemaVersion": 1,
  "operation": "create",
  "sources": ["/absolute/source.txt"],
  "destination": "/absolute/output",
  "outputName": "example.zip",
  "format": "zip"
}

可选字段为 level(0–9,默认 5)、solid、encryptHeaders、zipLegacyCrypto、preserveMac、 volumeBytes 和 requiresPassword;不适用于所选格式的组合会拒绝。解压使用 operation: "extract"、 一个所选归档路径和输出目录名,省略创建专用选项。预检只统计源条目或输入卷及其字节, 并未解码或验证压缩包内的全部成员。格式、加密与分卷的支持以实际能力表及验证结果为准。

调用方将 JSON 放入已打开的只读文件或管道 FD,例如 maci agent archive preflight --intent-fd 3 3<intent.json; 随后用同一意图重新打开 FD,传入返回的 previewToken 与 stateToken 执行 create 或 extract。 需要密码时,意图显式设置 requiresPassword: true,提交阶段另传 --password-fd。 密码是最多 4,096 字节的 UTF-8 原文,允许换行、不允许 NUL;FD 必须由调用方供应,不放进 argv、环境或 JSON 意图。 Service 仅在有界内存和私有管道中接收;自动化调用不弹出密码窗口,也不自动重试错误密码。

归档 Agent 通过自身包内已验签 Service 执行,无须安装或注册 Finder Services。发送私有请求前, 会验证当前应用的签名资源封装及 Service 的实际进程身份;仅保持相同 ID 的重签替换仍会被拒绝。Finder 与 Agent 共用准备、受限 XPC Worker、发布、恢复及完整事务租约;基础版不因此引入代理依赖。 作业回执位于本机 archive/jobs.json,最多保留 64 项;已确认终态超过 24 小时可在接受新作业时清理, 未确认作业不自动淘汰。回执不保存密码、源内容或完整意图;pending.json 仍仅保存原有请求 ID、动作和 URL。 读取缺失状态不会创建文件。取消标记可能已写入但同步或读回失败时返回 unknown,调用方不得自动重试。 创建与解压在 150 秒期限到达时取消,调用方等待有界清理; 停止仍未确认时返回 unknown,Service 保持租约直到获得真实停止证据。遗留请求必须由用户显式审阅, Agent 遇到未处理的 pending 记录返回 recoveryRequired,不自动重放;恢复暂存也不授权重跑原请求。

读取返回的 data.stateToken 是下一次写入的 --expect;配置迁入使用 profiles/preview 的令牌, 网络操作使用 proxy status 的令牌,不能混用。一个命令只执行一个事务,不自动重试。 例如先运行 maci agent proxy status,再以其令牌运行 maci agent proxy disconnect --expect '<stateToken>'。状态已变化时返回 conflict,应重新读取并决定下一步。 所有命令可附加 --api-version 1 和 UUID 格式的 --request-id;请求 ID 仅关联回执,不提供重复执行授权。

stdout 只有一份 JSON,包含 schemaVersion/requestID/domain/action/ok/outcome/data/error,最大 1 MiB。 outcome=applied 表示事务持久提交并读回验证;成功读取的 notApplied 表示没有业务写入。 unknown 表示可能已产生部分或全部效果,必须先检查状态及恢复材料,不能自动重放原命令。 退出码 0 表示成功,64 表示参数或协议版本错误,69 表示不可用/缺少前置条件,75 表示冲突或忙碌, 70 表示其他失败或结果未知;应以 JSON 中的错误代码和 outcome 为准。参数、响应和执行期限都有上限, 取消后等待事务清理,不能把进程退出当作网络已恢复。

普通读取与业务命令不会打开面板或新建终端;显示场景命令只连接已经运行的显示后台,显式界面更新会退出并重开 GUI。 基础版对代理返回 notIncluded。 代理状态仅尝试连接已存在的正式后台,后台未运行或未获批准时返回明确失败;系统授权仍由用户在 macOS 完成。 目前音乐、闪念、终端交互、翻译以及代理维护/共享设置尚未纳入这一统一协议;原有诊断入口仍保留, 不能把它们表述为完整的 Agent 接口覆盖。以后新增或变更功能必须按 AGENTS 中的同源事务、能力登记、 前置条件、结构化回执和自动化行为测试标准同步实现。

软件管理区分 Homebrew 工具、Homebrew 应用、App Store 与独立应用,按精确应用路径合并来源记录。 Homebrew 普通 formula/cask 可预览后升级或卸载;固定版本、含安装器或自定义卸载流程的应用会说明限制。 普通独立应用可预览后移到废纸篓,保留个人资料;系统应用、maci 自身和可能含后台或扩展的应用交由原来源管理。 App Store 使用本机收据与可选 mas JSON 清单,更新入口打开系统商店,不接管商店账户或管理员授权。 没有 Homebrew 或 mas 时保留本机应用清单,不自动安装软件源。状态与未知操作回执存于独立的 ~/Library/Application Support/maci/software/;GUI 与 Agent 共用库存复验和跨进程事务锁。 软件与容器操作的未知结果可先重新核验;仍无法证明完成时,用户可核对当前实际状态并明确结束该回执。 结束操作只记录人工确认,原业务结果仍为未知,保留历史并拒绝旧预览重放;后续操作必须重新预览。

容器管理适配 Apple container 1.4.1 的结构化接口,需要 Apple 芯片与 macOS 26 或更新版本。 未安装时可准备固定版本的官方签名 PKG,校验 SHA-256 和系统安装信任后,由用户点按交给系统 Installer; 管理员授权在系统安装器完成,安装后重新检测,启动服务是独立动作。其他版本明确显示待适配,不猜测 JSON 模型。 首轮提供镜像清单、单容器创建、启停、删除及日志;创建可设置名称、CPU、内存和 loopback TCP 端口映射。 删除前要求停止并预览,保留持久卷;容器可写层会随删除消失。服务停止、首次 Linux 环境准备也需显式选择。 这不是 Docker API 或 Compose 兼容层。操作回执和已验证安装包位于独立的 maci/containers/ 资料目录。

下载区是全宽矩形树图,位于开发服务与终端之间。任务面积按总字节比例分配,色相区分任务,色深表达进度; 较大块显示名称、大小、进度、速度及连接数,小块通过点按查看详情。新增入口也是树图内同纹理的小色块,只保留白色加号。 HTTP(S) 下载使用系统 URLSession 和独立的按需进程,面板隐藏或 GUI 退出不停止已启动的下载,不注册新的登录后台。 任务和续传检查点存于 ~/Library/Application Support/maci/downloads/,带查询参数的完整链接只保存在私有任务资料中, Agent 状态不返回它们。目标文件夹由用户选择;临时文件在目标卷,完成后校验并以不覆盖方式发布,保留 quarantine。 安全续传要求服务器支持 Range 和稳定的 ETag 或 Last-Modified;源变化会拒绝拼接。最多同时执行三个任务,每任务一个连接, 不宣称多连接提速、限速、BT/磁力、网页媒体解析或浏览器全局接管。重启系统后的中断任务需明确恢复。 界面更新在下载活跃或结果未知时延后;更新锁同时阻止新任务提交,避免更新期间出现下载竞态。 结果未知的任务可核对最终文件;只有目录、文件身份、长度和 SHA-256 全部匹配保存的检查点时才确认完成, 其他情况继续保留未知状态,不重新下载、不覆盖、不删除文件。 新增模块的行为验证入口为 deno task test:management,使用模拟软件源/容器与隔离的本机 HTTP 下载夹具。

domains/maci/ 是独立的 macOS 用户级菜单栏工具。内存监测只保留每 5 秒 显示一次 100 - 系统可用内存百分比,该数字是已用估算而不是剩余内存;菜单栏不再展示 压力等级、颜色状态、事件数量或诊断结果。

点开菜单栏面板会按当前用户的 TCP 监听进程扫描本机开发服务,显示项目/运行时和实际端口; 当前支持识别 Vite、Nitro、Nuxt、Next、Prisma Dev、常见本机开发服务器,以及位于用户项目 目录内的 Deno、Node、Bun 等运行时。每个服务名称左侧的停止方块会展开同格确认,确认后再次核对 PID、完整命令和监听端口,再只发送一次 SIGTERM。进程未按时退出时只提示失败,不会升级为 SIGKILL、终止整个进程组或删除项目文件。

内存子系统不订阅 Dispatch memory-pressure 事件,不保存新事件、快照、队列或报告,也不 调用模型。翻译是独立的用户触发工作流,不接入内存采样。

maci 常驻于菜单栏,无独立主窗口或 Dock 图标。默认按 ⌥T(Option + T),或点击 面板“翻译前台窗口”,通过 ScreenCaptureKit 截取当时前台应用最靠前的普通窗口,再用 Apple Vision OCR 与所选翻译引擎按文字块翻译。译文出现在原窗口位置的临时 翻译预览上,图片与界面布局保留在截图中;菜单面板提供终端区、闪念区、翻译入口、设置和服务控制。 面板紧贴菜单栏入口,保持顶部锚定,固定 340 点宽、28 点连续圆角。顶部为 maci 名称、单色形象锁定开关,以及窗口翻译、电影字幕、显示设置、翻译设置与退出图标。 软件管理与容器管理使用顶部显示器旁的网格、立方体图标,详情沿用面板内覆盖层。 这行工具栏默认隐藏,鼠标移入或在面板内移动时以 180 毫秒淡入,静止 1.5 秒后淡出; 停在工具栏上、键盘聚焦其中控件、展开详情或长按退出时保持显示。翻译/字幕运行时与 VoiceOver 开启时也保持可见;Tab 可在没有鼠标操作时唤出工具栏,减少动态效果时直接切换显隐。 工具栏覆盖在月面上,不挤动正文;状态反馈和显示试用确认独立可见。面板关闭时清理计时与输入监听。 悬停显示动作与快捷键;设置图标在面板内覆盖式展开目标语言、快捷键、窗口引擎、对白语言及模型下载;切换设置或权限详情不会改变面板尺寸或挤动终端。 翻译或字幕运行时图标高亮,状态和失败反馈收在顶部;正文依次呈现音乐、闪念、开发服务、下载树图和底部终端。 各区只用细分隔线区分,不显示区域标题和计数;没有开发服务时收起对应空白占位。 低频的显示设置收在顶部显示器图标中,与翻译和字幕控件并排;点击后在面板内展开可滚动的 玻璃覆盖层,不改变主体高度。显示试用确认始终独立可见,不被设置覆盖。 屏幕与系统音频共用一项授权,由顶部 maci 字标颜色表示:黄色表示待授权、正在检查或需重开应用, 绿色仅表示系统预检已授权。点击 maci 字标查看详情、主动授权或重新检查;打开面板和返回应用只读取 权限,不自动弹出授权请求,也不把麦克风、辅助功能或输入监控列为必需权限。 未授权时窗口翻译与电影字幕启动按钮置灰;已有任务的取消、停止入口仍可用。 本机开发构建默认临时签名,修改二进制后可能使旧屏幕授权失效。明确选择稳定本机签名时, 在 domain 内手动运行 deno task setup-signing,为 maci 创建专用身份;该步骤不能由构建或安装 自动触发。身份只保存在 ~/Library/Application Support/maci/signing/,不上传、不使用现有私钥; 后续构建固定使用该证书,签名失败时停止,不悄悄退回临时签名。配置脚本不修改证书信任; 自签名证书如需信任,必须另外明确授权,仅授予当前用户、该证书的代码签名用途。 签名工具临时将专用钥匙串加入搜索范围,结束时移除自身条目并重新上锁,不改变默认钥匙串。 首次从临时签名切换到固定证书仍需在 macOS 重新登记已安装应用并重开;后续版本以证书约束保持身份一致。

面板顶部保持水平;点击 maci 形象切换锁定,点亮后保持展开。默认点击外部收起,锁定后仍可按 Esc 或再次点击菜单栏百分比关闭。锁定状态仅保留在本次运行中,重启恢复未锁定;关闭菜单 不停止已启动的电影字幕。顶部退出入口是一个 16 点实心红点,保留 30×32 点点击范围;长按时放大到 20 点, 外围同步显示从顶部开始的进度环,让指针遮住圆内时仍能看到进度。按住 2 秒,进度环转满一圈后短暂微光并退出整个应用、结束终端和字幕。 提前松开或拖出按钮时进度环逐渐回退,圆点保持红色;切换应用、关闭面板或失去焦点取消长按。 键盘聚焦后也可按住空格;普通点击不退出。 LaunchAgent 仅在异常退出时恢复,正常退出后等待下次手动打开或登录。内核文件锁避免系统 “退出并重新打开”与后台恢复产生重复实例。安装时只刷新正式 App 的 LaunchServices 注册, 清理同 bundle ID 的构建目录旧注册,不全局清空图标缓存。开发服务使用 28 点高的连续单行, 小停止方块、名称与全部端口依次横排,服务间以短竖线区分,不设卡片底色或边框。 长名称、多端口及更多服务都不换行,超出面板宽度时在区内横向滚动,滚动条隐藏。 停止方块保留 22 点宽的点击范围;点击后左侧原位显示红色“停止”,条目末尾显示取消叉号, 再次点击“停止”才执行。确认预留固定位置,不改变条目尺寸或挤动其他服务;只有真实服务才占位。 不再提供手动刷新按钮:打开面板立即检查,面板显示时约每秒、隐藏时约每五秒自动扫描。 扫描在独立队列串行执行,只发布变化,不影响停止确认;退出时停止扫描,停止服务期间拒绝旧扫描结果。

音乐直接融入整块面板,移植 Gift 的流体月面着色器、手写字体与低语/手写/散字歌词场景。 月面铺满面板宽度并延伸至顶部工具栏背后,不设独立黑底或圆角卡片;歌词与歌名直接浮在玻璃上。 音乐底部用细线与闪念分隔,尚未选歌时不显示“音乐”占位标题。 封面主色形成的柔和光晕延伸至下方原生工具区,工具栏在固定位置自动显隐,音乐之后依次为闪念区、服务横排、下载树图和终端。 不另设搜索按钮或底部控制条:点击歌名前的灵动点展开透明径向搜索星盘,月面保留在背景; 输入后自动搜索,拖动、滚轮或聚焦星盘后按方向键旋转结果,松手惯性吸附到歌曲。 再次点击圆点、选择歌曲或按 Esc 返回播放画面;搜索关闭后 Esc 才收起整个面板。 短按月面产生触点波纹并播放/暂停,绕月面转动按累计角度调节进度,一圈对应整首歌曲。 月面边缘显示真实播放进度;拖动与长按不会误触播放。长按 520 ms 切换流体月面与专辑封面, 播放和暂停时行为一致,歌词、歌曲信息、进度和播放状态始终保留;无封面时保持原月面。 暂停冻结流体并缩至 84%,进度环保持原尺寸;拖动时流体纹理随歌曲进度转动, 封面模式使用 18 秒唱片旋转并释放流体 GPU 资源,切回时完成首帧后显影。 减少动态效果设置下停用运动; 键盘可聚焦月面,用空格播放/暂停、左右键调整 5 秒、Home/End 跳至首尾。

歌词沿用 Gift 的三幕结构与逐字显影,短面板内只缩放排版以保留完整歌词。 散字渐变为手写字体的外伸笔画预留绘制范围,字距与换行不随之扩大。 点击歌名缓存完整音频、封面和歌词,歌名按封面主色填色并在完成时发光;已缓存时再次点击仅删除 maci 的本地歌曲缓存。 搜索空白内容显示本机歌曲,搜索结果本地优先,网络失败仍可选择已缓存歌曲;重开 maci 后可以直接离线播放。 缓存位于 ~/Library/Application Support/maci/music-cache/,每首音频与封面合计最多 64 MiB、封面最多 8 MiB、 总缓存最多 512 MiB;先检查可用空间和下载完整性,使用临时目录及原子索引提交。 失败和取消不登记半首歌曲;索引损坏保留原件并阻止覆盖,删除不触碰其他应用或用户音乐文件。 正在播放本地缓存时删除会先释放该音源,之后可重新在线播放。

在线搜索使用 Gift 同款 GD Studio 公开音乐接口,音源固定为网易;仅主动搜索、选曲或缓存时请求网络, 不依赖 Gift 开发服务、账号或生日阶段。音频由原生 AVPlayer 播放,不申请麦克风或屏幕权限。 搜索与切歌取消旧请求并拒绝迟到结果。包内 WKWebView 承载视觉和月面/灵动点/歌名交互, 消息桥只接受这些明确动作,不允许网页指定音源或文件路径;隐藏面板暂停视觉动画,播放会话继续。 退出 maci 释放音源并取消未完成的缓存。Gift 字体作为用户本机资源迁入;源码中未附公开再分发许可, 公开分发前需核实字体授权。

显示设置与无屏常驻

点击顶部显示器图标打开显示设置;收起设置只隐藏控件,不断开虚拟屏。 设置沿用现有玻璃面板内的覆盖层,列出系统在线屏幕, 显示逻辑尺寸、HiDPI 与刷新率,悬停查看实际渲染像素;分辨率菜单只使用系统报告适合桌面的模式。 使用原生 CoreGraphics 切换分辨率或镜像,均为显示后台进程生命周期内的临时配置,不写永久显示器覆盖。 创建虚拟屏使用隔离的 CGVirtualDisplay 私有运行时桥,先校验类和方法签名;接口不可用时禁用新建, 保留现有屏幕管理。无需管理员服务、内核驱动、录屏或辅助功能权限,不会绕过 macOS 的接口限制。

首版最多保存两块虚拟屏,提供 16∶9、16∶10、3∶2、竖屏和自定逻辑尺寸;宽高各为 480–2560, HiDPI 将两维渲染像素翻倍,总量最多 16,384,000 像素。每块最多六种同比分辨率,固定 SDR、60 Hz。新建屏使用扩展桌面,自有虚拟屏的模式菜单提供“唯一 / 镜像 / 扩展”。 唯一模式把所选虚拟屏保留为有效桌面,其他显示通过隔离的 CGSConfigureDisplayEnabled 桥退出桌面; 接口不可用时明确禁用,不用黑屏或设主屏代替。镜像模式以所选自有屏为源,扩展模式解除该自有屏的镜像。 切回镜像或扩展先恢复进入唯一模式前的布局,再应用所选模式。不接管其他工具的虚拟屏对象; 普通镜像/扩展不会拆散与所选自有屏无关的镜像组,唯一模式的预览则明确列出停用其他桌面的影响。 断开只释放自有对象,删除在对应条目内确认。

新建、重连、分辨率和三模式切换均先试用 15 秒,顶部固定覆盖层确认保留;实际模式、启用状态或镜像未就绪时不能确认。 未确认自动恢复,关闭面板不取消倒计时;显示布局变化时确认层保持锚定。回退失败会保留错误与重试入口, 即使原屏恢复失败也独立尝试释放本次新建屏。菜单进程退出、GUI 连接失效或睡眠时撤销尚未确认的更改。 Agent 发起的场景试用由服务计时,不随单次 CLI 退出取消,仍须在 15 秒内另行 confirm。 已确认的唯一或镜像场景也只保留在服务会话中,睡眠、最后 GUI 退出、停止后台或断开自有屏前先恢复原桌面; 恢复无法核验时保留自有屏与恢复状态,不冒险释放最后桌面。不跨后台重启自动重放场景。 SIGTERM/SIGINT 也先恢复并核验;系统强杀、SIGKILL 或进程崩溃无法保证完成恢复。 保留场景恢复布局时,界面更新要求先切回扩展并确认,以免退出 GUI 时恢复布局破坏更新的显示保持条件。 ~/Library/Application Support/maci/displays.json 原子保存虚拟屏定义、启用意图、“登录后恢复”及“无屏常驻”偏好;旧版配置可直接读取。 创建确认后才保存,配置损坏时保留原件并禁止覆盖。默认不自动创建,开启恢复后重建已启用的自有虚拟屏。 启动、唤醒和意外离线的恢复最多尝试五次、二十秒截止;实际读回逻辑尺寸与 HiDPI 渲染像素后才报告成功, 失败后的布局通知不会无限重试。可在面板点击恢复或运行 bin/maci --restore-displays,重新尝试已保存且启用的屏幕。

虚拟屏、配置写入和试用倒计时由独立的 maci-display-service 用户级后台持有,面板通过本机 XPC 发送操作和接收状态;场景 Agent 使用同用户私有 Unix socket 连接已运行的后台,并调用相同 Host 与事务。 读取不会登记或唤醒服务。旧后台没有场景能力时需显式维护更新,日常 GUI 更新不会偷偷替换后台。 后台不加载音乐、终端或翻译。无屏常驻默认关闭,须先确认至少一块启用的虚拟屏。 开启后自动启用登录恢复,退出菜单应用会继续保留已确认的虚拟屏;关闭常驻时,退出菜单应用释放自有虚拟屏。 在常驻模式下断开或删除最后可用的自有虚拟桌面、关闭常驻保障,均需原位二次确认;后台停止也会重新核验屏幕。 手选分辨率和镜像关系仍不跨后台重启恢复,完整显示配置、主屏和排列预设尚未实现。

安装时通过 SMAppService.agent 登记包内的菜单与显示后台两个用户 LaunchAgent, 均在用户图形登录后启动,异常退出由 launchd 拉起。系统按所属 com.siaovon.maci 应用归组并读取自定义图标,不再依赖旧式外部 plist 的 AssociatedBundleIdentifiers 与 Team ID。注册状态只读检查;用户关闭后台许可后,重新打开或更新应用不会自动恢复许可, 须在系统设置的“登录项与扩展”中重新允许 maci。 更新完成前会核验菜单进程的实际路径与稳定运行状态;若系统明确报告旧启动签名约束失效, 安装器在重新验签和核验许可后仅重建一次菜单注册,再检查启动结果。其他失败保留诊断副本, 不会反复注册或重启未变化的显示后台。 正常退出不自动拉起,重新打开面板也不会重启已明确停止的显示后台,需主动点刷新。 这不提供 FileVault 解锁前或登录前的虚拟屏,不修改自动登录、系统信任、UU 远程或其他远程软件设置。 真实无实体显示器冷启动、睡眠唤醒和 UU 远程重连仍需在对应使用环境验收。

显示器逻辑与恢复测试使用注入 adapter,不改真实布局,包含在 deno task check 中,也可单独运行 deno task test:displays、deno task test:display-service 与 deno task test:display-modes。 bin/maci --list-displays-json 是只读枚举;bin/maci --display-service-status 读取后台状态,不启动已停止的后台。 deno task test:display-lifecycle 用临时 LaunchAgent 和模拟显示后端验证跨进程退出、崩溃重启及重连,结束移除测试任务。 显式加 --native 会临时创建一块 TEST 屏,在测试后台异常退出后核验其重建、HiDPI 和原有屏幕未改变; 该命令不读取用户显示配置,也不属于默认检查。另一显式硬件验证命令 xcrun swift run --scratch-path dist/swift-build --configuration release maci-display-integration --exercise-owned-displays 临时创建两块 TEST 屏,只对这两块进行模式、镜像、恢复和重连验证,结束清理并核验原有屏幕未改变; 不包含在默认检查中。HDR、画中画、串流和物理屏任意 HiDPI 解锁不属于首版。

终端位于现有面板最底部,始终展开,启动 maci 时预备一个本机 /bin/zsh -l -i 登录交互式 shell;关闭最后一个标签后自动补上新的待用会话,退出应用时不补建。点击标签末尾的纯加号可添加标签。 标签放在输出下方,组成 28 点高、全宽贴底的连续玻璃带;选中项使用轻微底色,标签间以细竖线分隔, 不再使用悬浮圆角方块。关闭按钮保留 24 点点击范围,加号紧跟标签;较多标签可横向滚动, 切换时显示选中项,选中末尾标签时同时露出加号。关闭确认和异常信息位于标签带上方。 底栏、选中背景与原生材质统一使用 28 点连续圆角遮罩;材质自己的 maskImage 随实际尺寸与缩放更新,并刷新窗口阴影。显式桌面合成测试在不同高度下检查边角亮块与保留阴影, 常规检查覆盖离屏遮罩及 1×/2× alpha;离屏检查不替代安装后的桌面实图验收。 视口默认预留五行,按真实字体行高计算,超过的输出在终端内部滚动;首次 PTY 尺寸与界面保持一致。竖向滚动条及右侧占位隐藏,滚轮、触控板回看输出与交互程序的鼠标行为保持可用。 不显示区域标题、会话计数、折叠、常驻操作提示或中断按钮,异常与退出状态仍显示。 shell 从用户主目录开始,加载用户自己的 shell 配置。PTY 在 shell 启动前按面板的实际尺寸初始化,避免首个提示符留下独立的 %; 命令未以换行结束时,zsh 正常的行尾标记仍保留。最多同时打开六个独立标签,分别保留工作目录、环境变量和 终端屏幕;支持彩色输出、中文、方向键、历史命令、交互式程序与 ⌘V 粘贴。保留上方全部工具和 340 点面板宽度,终端透明背景透出面板磨砂材质,内容过高时在面板内滚动;切换标签或关闭面板都不重启会话。 ⌃C 发送终端中断字符;关闭标签需面板内确认,随后挂断该 PTY 和前台任务。退出 maci 结束全部会话,显式脱离终端的守护进程遵循 shell 自身的生命周期。 每个标签保留最多 1,000 行回滚内容,maci 不额外写命令记录或输出日志、不在重启后重放命令; shell 自己的历史文件仍按用户配置工作。终端使用固定版本 SwiftTerm 1.20.0,许可证随 App 打包; 仅用户主动复制/粘贴访问剪贴板,不接受终端转义序列读取或修改剪贴板。

统一分发与可选代理模块:默认只构建一个完整版,deno task build 输出 dist/maci.app / bin/maci。代理默认关闭并隐藏;普通设置、工具栏和首次使用流程不显示代理入口。 未启用时只保留轻量功能状态读取,不创建代理面板、订阅刷新器或后台连接,也不注册代理服务。 build:proxy、install:proxy 和 bin/maci-proxy 保留为同一完整版的兼容入口。 内部裁剪验证仍可显式使用 MACI_FEATURE_PROXY=0 或 deno task build:base,输出隔离的 dist/base/maci.app / bin/maci-base,完整省略代理 domain、UI、Yams、mihomo 和 LaunchDaemon。 包内 MaciEdition=proxy/base 是更新协议兼容标记,不代表功能当前已启用。 构建从新暂存目录装配并核验实际包文件与二进制符号;旧 dist/proxy 不再作为输出。 两种内部构建保持同一显示后台构建路径与签名约束。

高级使用:打开翻译设置中的“关于 maci”,按住 Option 点击版本号,再点“启用网络代理功能”。 普通点击版本号没有副作用;关闭“关于”或收起面板后隐藏解锁项。也可先运行 maci agent proxy feature-status,再将返回的 stateToken 传给 maci agent proxy feature-enable --expect '<stateToken>'。启用只显示功能,不自动连接或请求系统授权。 代理设置内的“停用并隐藏”先等待自有工作取消、网络恢复和状态读回,完成后移除全部代理入口; 失败或结果未知保留状态与恢复操作,不能把隐藏当作停止成功。GUI 在重开面板和收到状态变更提示时重新读取, 不信任通知内容。独立 proxy/feature.json 保存选择,恢复检查点阻止未知结果自动重放; 旧代理资料只按已有启用字段迁入,显式关闭的意图保持关闭,不删除配置和订阅。 兼容发现会有界读取旧资料字节,但只解码启用元信息;已有独立功能状态时不再打开旧配置。 deno task test:proxy-feature 使用临时目录和模拟后台验证隐藏入口、延迟加载、恢复与跨进程状态重读, 不需要停止本机正在运行的代理;完整隔离内核回归仍要求测试端口可用。

代理构建默认使用上游标准内核。Apple Silicon 上可显式使用 MACI_PROXY_CORE_VARIANT=go122 deno task build:proxy 生成同版本兼容内核的诊断包; 两种内核各自固定下载摘要并隔离缓存,包内来源信息记录实际变体。该选项不安装应用、 不更改后台许可,也不代表已决定采用兼容内核分发;基础版不读取或携带这些内核。

启用后在终端底栏右侧提供状态入口,左侧标签单独横向滚动。控制面板向上展开, 配置、节点、规则、连接和 DNS 在覆盖层内滚动,不增加主面板高度。 首页只保留连接开关、线路入口和“更多”;关闭连接须原位确认,取消后继续运行。 底栏使用纯文字显示“探测出口地区 · 接管方式 · 路由模式”,不重复叠加模式图标; 接管方式来自实际状态,普通本机会话显示“本机”,不会把其他代理的 TUN 显示成 maci 接管。 展开后显示出口 IP、物理 Wi-Fi/以太网的局域网 IP、上下行速度、最近 60 秒共用刻度趋势、 本次内核运行累计量及当前连接数。LAN 地址可选择复制,多接口与 IPv6 信息可悬停查看; 展示地址不开放局域网代理共享。计量使用十进制 B/KB/MB,仅代表内核记录的接管流量, 包含经内核直连的流量,不是全机带宽、每日用量或订阅额度。 出口通过 maci 本机 SOCKS 端口访问固定的 Cloudflare trace HTTPS 端点, 服务端会看到该请求的出口 IP;不上传局域网地址、订阅或节点名,不绕过代理直连回退。 仅在自有内核运行且主面板可见时查询,最多每分钟一次,线路、模式、内核或本机网络变化后重新检测。 地区仅代表这一探测目标的出口,规则分流与 IPv4/IPv6 可能存在多个出口;读取失败显示未知, 旧探测不能覆盖新的线路。地址与最多 61 个图表采样只保留在内存,隐藏面板停止采样, 恢复后裁剪过期数据;缺测不补零,内核重启或累计值回退时清空旧代次。 配置、节点、规则、连接与 DNS 的完整现有控制收在“更多”中;界面简化不删除这些能力。 完整版本通过独立系统后台运行固定 mihomo 1.19.29, 本机混合端口为 127.0.0.1:17897。首次连接默认选择系统代理,可在断开时于“更多”切换为 TUN; 选择偏好单独持久保存,打开面板、重开功能或导入配置不会自动接管。 首次连接保留来源配置的路由模式;手动切换并读回成功后,按配置记住规则/全局/直连选择, 停止或重开功能不清除这项偏好。失败或结果未知的切换不保存为下次连接模式。 连接前先完成普通用户候选校验,随后才由显式连接动作登记后台;已存在其他代理内核时拒绝日常接管。 支持原始 YAML/部分节点链接导入、订阅更新与自动更新间隔、规则/全局/直连模式、 策略组选择与测速、连接断开、规则查询、DNS 查询及缓存清理。配置原文及选择保存在 ~/Library/Application Support/maci/proxy/profiles.json,原文不会被规范化后的运行配置替换。 订阅支持条件请求、流量/到期元数据和有界下载;自动更新原文后需重新应用生效。 节点链接目前支持 SS、Trojan、VLESS、HTTP(S)、SOCKS5;无法保真转换的参数或协议明确拒绝。

全局和单配置增强分别支持递归合并 YAML 与 main(config, name) JavaScript,按 全局合并、全局脚本、单配置合并、单配置脚本的顺序执行;最后重新覆盖应用拥有的控制端口、 鉴权、监听与 TUN 字段。脚本在独立 JavaScriptCore 子进程运行,限制输入、输出和时长, 超时/取消结束自有工作进程,不向脚本暴露本机文件、网络或 Objective-C 对象。 全局增强保存在同一私有目录的 enhancements.json。配置候选先由真实内核预检,启动并读回验证后 才提交活动配置;日常接管使用 root-session.json 和独立 root-session-recovery.json, 恢复标记覆盖元数据、最后可用配置与原子重命名后的写入失败。 旧普通用户会话的 session.json 独立保留。出现不确定结果时保留材料,不能自动重放连接或切换; 界面保持“状态未知”,确认后台停止后才能移除接管反馈。损坏、符号链接或归属不符的状态文件不被覆盖。 nameserver-policy、proxy-server-nameserver-policy 和 fallback-policy 保留声明顺序, 脚本输入和内核运行配置也不得重新排序。 显式迁入的应用 DNS 保留原始字节,在增强前整体替换 DNS,增强后恢复其 ipv6 设置。 配置页的“从 Verge 迁入”先显示只读摘要,确认迁入后保留原始订阅、完整增强链、规则/节点编辑、 启用的应用 DNS、应用层 TUN 等功能参数、有效手选线路和订阅更新方式;不改 Verge 文件或 maci 全局增强。 迁入时还通过 Verge 固定本机 socket 只读当前线路意图;预览后意图或源配置变化会拒绝提交并要求重新准备。 原索引的历史选择保留在来源附件中,实际配置分别保存普通手选组的当前选择与 URLTest 的 fixed 偏好, 不把自动测速的 now 当作手选,也不把过时历史选择重新固定。未固定的组继续自动选择;隐式 GLOBAL 与已确认偏好在重连、模式切换和回退时恢复。Fallback 的固定偏好具有不同失效行为,当前明确拒绝迁入该状态。 迁入还保留 Verge 显式的“切换线路时关闭旧连接”偏好;缺省不主动关闭。 选择成功读回并持久保存后,才限量清理连接链中经过旧线路的连接,其他连接不受影响。 清理失败或结果未知不回退已提交的线路,面板分别提示线路已切换与旧连接清理未完成。 Country.mmdb、geoip.dat、geosite.dat、ASN.mmdb 先作为内容摘要命名的不可变快照保存在私有 assets/, 再通过有界、按次序且逐文件核验 SHA-256 的通道交给 root;root 只接收固定文件类型,不接受路径或下载地址。 预检、启动、切换和内核恢复使用同一份快照。缺失或损坏依赖拒绝启动,不隐式下载 Geo 数据; 更多页可更新 Geo 与 Provider。Geo 更新只从 MetaCubeX 官方数据仓库解析一次 release commit, 四份文件固定到同一 commit,核对文件大小、Git blob 摘要和 SHA-256;先校验当前配置, 再通过两份固定的离线规则配置强制内核解析四类数据库,全部通过才发布快照。 每份大文件总时限为 15 分钟,连续 30 秒无数据则失败;更新可主动取消,旧配置继续生效。 普通用户下载失败、取消或内核校验失败均保留原配置;root 从不自行下载或接受外部文件路径。 root 最多保留四份完整 Geo 快照,回收时保护当前、上一份及事务/试用正在引用的快照。 上传取消与旧快照回收均可在写入中断后重试;未知或损坏材料保留并报告需恢复,不作为可删除的缓存处理。 Provider 在完整增强执行后由普通用户准备,保留名称、分组引用和健康检查设置,转换为 inline 内容。 支持 HTTPS 节点 YAML/JSON、规则 YAML/text 及条件更新;每份最多 2 MiB、总内容最多 4 MiB, 规则条目还须经隔离内核的实际 ruleCount 核对,防止解析器静默丢弃。 当前明确拒绝 provider 本机文件、MRS、加密/URI 内容、自定义下载代理及无法无损转换的字段。 缓存与来源声明绑定,存入私有 providers/ 的不可变快照;内容变化时按原接管事务应用, 仅校验元数据更新且运行配置相同时不重启内核。

更多页提供默认关闭的“局域网共享”。停止态开启只保存偏好,主动连接代理后才建立共享监听, 不自动登记后台或接管网络。共享地址仅来自本机 Wi-Fi/以太网的私有地址,固定端口 17897, 支持带独立用户名和密码的 HTTP / SOCKS5 TCP 代理;不提供局域网 UDP 转发。 控制器及本机混合监听继续限制在 loopback;普通本机代理访问不需要共享密码。 凭据由 root 随机生成,只有点按“查看连接信息”时才读取,复制前再次核验当前凭据; 收起面板、离开设置或状态未知时清除面板内缓存,代理配置备份不包含共享密码。 开启、关闭与更换凭据复用同一接管事务,监听、鉴权或持久保存失败时恢复原状态; 停止代理保留共享偏好和凭据,但不保留监听。旧后台缺少共享能力时不开启该开关。 局域网地址变化导致监听无法确认时显示未知或未生效,由用户检查后重新连接,不把旧地址当作仍可访问。

更多页支持 .maciproxy 本机备份,包含原始配置、完整增强、选择和引用的 Geo/Provider 资源, 不含 root 恢复日志、控制器鉴权、运行进程或流量地址记录。备份文件为 0600 的未加密包,包含订阅和节点凭据, 保存界面会明确提示;最大 256 MiB,以版本化清单、固定路径和逐文件摘要核验,损坏或未知版本拒绝恢复。 恢复先在独立私有目录中验证资源和真实内核配置,Provider 只能复用归档内容,不重新下载; 全部通过后追加新 ID 的配置,保留目的库原内容、启用状态与当前连接,由用户主动选择恢复的配置。 恢复的全局增强上下文单独保留,不与目的库全局脚本混合。包含新 Provider 引用或恢复上下文的资料使用 schema 2, 旧版读取会明确拒绝并保留文件,不能直接降级后忽略新增语义;基础版仍不读取代理资料。 显式修改全局合并或脚本前会自动保存一份完整代理备份,最多保留三份不同内容的历史版本; 取消后重试相同修改会复用相同备份。备份失败、原资料被并发修改或历史材料损坏时拒绝保存新增强。 自动备份位于代理私有目录的 auto-backups/,恢复选择器优先打开该目录。 “恢复全局增强”是独立动作,先备份当前内容,再恢复归档中的全局合并和脚本; 不改变当前连接,下次主动应用配置时生效。追加配置仍保留目的库的全局增强。

顶部设置的“代理功能”开关停止自有内核和订阅任务、保存关闭状态并移除底部入口; 重新打开功能不会自动启动代理。收起面板保持已启动会话;完整退出 GUI 只断开正式代理的客户端连接, 后台继续保持已确认的接管,重新打开面板读取实际后台及匹配的本机恢复记录,不重复启动内核。 正式连接从 Verge 迁入的配置时,额外提供固定 127.0.0.1:7897 的 HTTP CONNECT / SOCKS TCP 兼容入口,保留原本机 HTTP_PROXY/HTTPS_PROXY/ALL_PROXY 使用习惯;主端口仍是 17897。 这是固定的 Verge 兼容端口,不表示恢复任意自定义旧端口;普通配置和隔离试用不启用。 兼容入口只绑定本机 IPv4 回环,不开放 LAN 或 UDP。端口被其他进程占用时拒绝接管,不抢占监听。 启动、模式切换、失败回退及后台恢复共同保留这一状态,显式断开或关闭功能会释放监听。 agent proxy status 的 legacyLoopbackPort 只有在运行中的自有监听已核验时才为 7897,否则为 null; 代理尚未运行时,显式指向该端口的程序不能仅依靠系统 TUN 自动绕过它。 退出按钮与 SIGTERM 统一从主 RunLoop 发起退出,避免 AppKit 等待异步清理时阻塞主队列; 基础版和代理版检查均包含独立 AppKit 子进程的信号、控件请求退出回归。 关闭功能或显式断开仍等待自有普通用户内核和系统接管清理; 恢复失败时保留入口和错误反馈,不把关闭开关当作停止成功。 代理后台收到正常退出或拥有者离开图形登录会话时有界恢复网络、停止自有内核并保存 Fake-IP 检查点, 保留正式启用意图;拥有者再次进入图形会话后才能恢复。未知登录状态和其他用户会话不接管,重复事件不重启。 试用会话仍在客户端断开或原 60 秒期限到达时清理,后台重启不恢复试用。 上述生命周期已覆盖 fake adapter 行为测试;53 版本机正式接管通过了真实 GUI 退出与重开、 同一代理内核持续运行及 HTTPS/DNS 验证。Verge 内核停止后,7897 的 HTTP CONNECT / SOCKS TCP 请求均通过;已有 Codex 进程无需重启即可建立该端口的新连接,连续 60 秒未新增原来的连接拒绝错误。 这是短时连接回归;实际注销、重启、睡眠唤醒及长时间接管仍需独立验收。 bin/maci --show-proxy-panel 只展开已启用的代理面板,不解锁功能、启动代理或请求系统权限。 基础版不会读取已有代理资料,切换版本也不删除这些资料。

专用代理 LaunchDaemon、同签名/同用户 XPC 白名单、root 私有运行目录、完整候选/上一配置日志、 系统代理所有权恢复及遗留进程阻断已实现并以 fake OS adapter 验证; 它与显示后台完全独立。构建/安装不注册该系统后台;面板日常连接使用同一后台事务。 内核固定保存在 root 私有运行目录的 maci-mihomo,停止后保留已校验文件,避免每次连接都产生新的 防火墙应用名称。复用前重新核验文件归属、权限、摘要和签名;更新先暂存校验,再在目录锁与遗留进程 检查通过后原子替换。来源不明、签名失效或仍有活进程时保留原件并拒绝更新,不修改系统防火墙设置。 安装前同样检查包内代理后台及新旧路径的活内核;后台登记消失不能代替进程退出证据。 每次返回接通前,后台核验保留子进程的身份与其真实监听 FD、控制器配置及系统代理逐服务读回。 状态携带内核运行代次、源配置摘要和 Geo 快照 ID,跨切换或内核重启的迟到控制器响应会被拒绝。 fake-IP 内核正常退出后,后台保存自身地址池与分配进度;模式切换、重连及候选回退均继承最新映射, 避免向仍缓存旧地址的应用重新分配同一个地址。快照仅存于 root 私有目录,每份最多 64 MiB,最多保留当前与上一份; 不读取 Verge 的 DNS 历史缓存。异常退出、快照缺失/损坏、保存失败或已有映射时改变地址池会阻止重新接管并保留恢复材料, 不能用重置地址池或清除系统 DNS 缓存冒充恢复成功。 日常 DNS 页只清除解析缓存;Fake-IP 映射不提供重置按钮,后台也拒绝旧版客户端的重置请求, 防止仍持有旧地址的应用连接到另一个域名。 已安装代理版提供显式接通测试入口:--proxy-service-status 读取后台状态, --register-proxy-service 登记独立代理后台;首次运行仍须通过 macOS 的后台批准。 后台登记为已启用、codesign --verify 通过,都不代表 root 后台已获准执行。 默认固定本机身份使用自签证书;若系统日志同时出现 AMFI 证书链拒绝与启动约束不匹配, 须先解决签名身份问题,不能反复批准或把 XPC 超时归为未授权。 Apple 建议应用与嵌入后台使用同一 Apple 签发的代码签名身份。 改用其他证书及私钥必须另行授权;不自动修改系统信任,实际接管仍以后台运行读回和网络证据为准。 经授权后,代理版可使用 ~/Library/Application Support/maci/signing/proxy-signing.json: {"version":1,"kind":"appleDevelopment","certificateSHA256":"获授权证书的64位SHA256摘要"}。 该文件须由当前用户拥有且权限为 0600;签名工具只使用摘要精确匹配、有效且通过 Apple 代码签名证书链校验的现有身份,不创建证书、不导出私钥、不改系统信任。 代理 GUI、内核、配置工作进程与代理后台使用同一身份,基础版和显示后台保留原本机签名。 此配置存在但损坏、过期或缺少对应私钥时构建失败,不回退其他身份。 --unregister-proxy-service --repair-inactive-registration 仅供明确授权清理已退回待批准的 启动约束失效登记;仍逐项核验签名、同一失败任务、后台/内核不存在、端口空闲与全部网络服务无接管, 执行一次正式注销并读回,不恢复批准、不自动重新登记。 --prepare-proxy-connection --read-existing-subscription 可先独立完成普通用户预检和节点实测, 不登记后台或修改系统网络。接管测试使用固定 HTTPS 探测,原生请求最多下载 2 MiB, 系统代理按同一次 HTTPS 事务的本机地址/端口、内核连接链和系统代理标记关联; TUN 按同次事务的完整源/目标地址、端口、传输协议与内核 Tun 连接及节点链核对, 域名缺失不能单独作为失败或成功依据。每个成功的网络事务均须独立匹配,不能拼接不同事务的证据, 也不能混用系统代理和 TUN 的接管标记;缺少归属证据时不报告接管通过。 deno task test:proxy-connection --read-existing-subscription --capture system 使用现有订阅的 可用节点测试真实系统代理;--capture tun 仅在没有其他代理内核运行时允许进入。 测试不改正式配置库或 Verge。默认先在普通用户隔离目录预检原配置,再以全局节点配置验证接管链路; 这份基础候选不包含完整 Geo 规则,不能代替原规则/DNS 等价验收。 加 --full-configuration 时逐项比对原生效配置的完整节点、策略组、有序规则、DNS、策略声明顺序与其余功能参数, 仅允许明确的应用监听/控制器/接管归属字段差异;同时传入相同 Geo 字节和有效手选线路。 完整试用在规则模式下核验源摘要、全部运行规则、DNS 解析语义,以及原生请求经自有内核的直连/代理分支; 完整预检额外显式启动仅绑定 loopback 的临时 DNS 监听,先核验 TCP/UDP 端口空闲;普通运行默认不启用此监听。 TUN 再向固定文档保留地址发送有界 DNS 问题,与同一完整 DNS 处理链的隔离 UDP 基线核对,覆盖 hosts 与 fake-IP, 不把控制器解析器查询成功视为系统 DNS 已接管。与独立预检基线相比,fake-IP 分配只允许在原配置声明的同一地址池内变化, 普通 localhost 应答保留精确地址核对;A/AAAA 缺失、返回码或地址类别变化都不能通过。 fake-IP 连接在控制器目标已变为域名或解析后的真实地址时,必须额外绑定同一内核在请求前后返回的精确 DNS 地址集合, 并核验配置摘要、完整试用回执、fake-IP 模式、当前进程的新连接及请求时间窗;仅地址落在合成池内不能通过。 同次请求的源地址/端口、协议、目标端口、域名、规则链及正常 TLS 校验仍独立核验;该证据表示地址转换关联,不能冒充内核导出的原始目标元组。 全局节点 TUN 试用候选同时开启 IPv4/IPv6 与双栈 DNS;完整配置保留来源的 IPv6 设置, 来源启用 IPv6 时同样运行 IPv6 探测;仅明确关闭 IPv6 才可跳过,缺少 AAAA 地址视为未通过。 不能通过仅探测 IPv4 掩盖系统请求的 IPv6 绕行; 默认 HTTPS 请求后,再通过固定的 ipify IPv6 端点 单独探测 IPv6。 完整配置验收要求同一试用回执、同一网址的两道检查同时通过:系统 URLSession 自动选路请求正常完成且逐事务归属于自有 TUN, 以及独立 curl --ipv6 请求的客户端源/目标均为 IPv6、正常 TLS/HTTP 200、最多 4 KiB 的正文是单个非 mapped IPv6 地址。 自动请求可由 macOS 选择 IPv4 Fake-IP,但不能将它计作客户端原生 IPv6;强制请求不能用 IPv4 回退通过。 强制请求的每个候选连接还须是本次 curl 的新连接,起始时间落在请求窗口内,元数据、规则和连接链保持稳定; 完整元组只能对应一个合格连接,fake-IP 转换须具备同一 DNS 处理链的前后证据。正文仅在内存校验,结果不保存或输出出口地址。 两道检查及网络恢复全部完成才报告完整 IPv6 接管通过;全局节点候选仍要求系统请求本身使用 IPv6。 完整 TUN 的 IPv6 请求失败时,可在原 60 秒期限内追加固定 Cloudflare IPv6 字面地址的 HTTPS 诊断,以及同网址的传输与延后诊断; 字面地址诊断保留正常证书校验,并要求客户端与内核观测到同次连接的精确 IPv6 源/目标元组,不使用 fake-IP 转换例外。 自动组测速历史只作为排查信息,后续诊断成功也不覆盖首次失败或冒充接管验收通过。 单次系统请求的 DNS、控制器读取、HTTPS 与归属核验共用最多 23 秒预算,并在原试用期限前至少一秒取消; 取消时先阻止未启动请求,再等待自有网络操作结束,不因开始新探测而延长试用。 后台在接管前持久标记测试会话,60 秒后自动恢复系统代理并结束自有内核;客户端正常完成时提前恢复, 后台重启也不得恢复测试接管。只有原后台处于停止状态才可开始,测试期间不接受其他配置写入。 主动清理依据成功试用回执、完整状态代次/修订号和当前用户核验归属,不依赖节点列表或流量读取成功; 内核崩溃仍应尝试恢复,回执未知或状态已被其他操作改变时保留独立超时恢复边界。 成功清理后还原完整的原停止配置;试用期间的冗余停止日志写失败不应阻断实际回退, 但最终原配置必须成功落盘才能确认完成。恢复包含已禁用的网络服务,缺失服务不能被当作已恢复。 备份损坏或系统设置发生冲突时保留恢复材料并明确报告未完成, 不会将超时本身当作恢复成功,也不会关闭仍被系统设置引用的监听端口。 网络设置读回、HTTPS 连通与清理分别报告;现有 Verge TUN 仍运行时,不将结果表述为独立替代成功。 本机此前已完成全局节点候选在系统代理及独立 TUN 下 IPv4/IPv6 HTTPS 的逐事务归属与结束恢复验证; 完整配置和日常面板使用各自的显式测试结果,不复用此前全局候选结果作为验收。 2026-09-13 的 50 版在受控且具备 IPv6 出口的同一线路下,通过完整 621 条有序规则、DNS、 原生请求直连/代理分流及完整 IPv6 双请求门槛;原生客户端 IPv6 证据来自独立 curl --ipv6, 不把系统自动选择的 IPv4 fake-IP 请求算作原生 IPv6。固定内核获防火墙放行后,面板 TCP/UDP DNS、 三次模式切换后的映射连续性和结束恢复也通过。首次放行前的 TCP 超时仍保留为失败记录; 这些结果不代表所有订阅节点都有 IPv6 出口,也不代替正式常驻、重启或真实局域网设备验收。 受保护的切换测试在停止 Verge 前捕获当前固定/自动状态,以有界私有环境数据交给显式测试入口; 入口核验源摘要、时效、组与成员,正常面板不读取该测试环境数据。结束恢复同时核对 Verge 的固定/自动状态。 完整接通与面板测试需要切换测试驱动提供 MACI_PROXY_TEST_VERGE_INTENT(最多 64 KiB、有效期五分钟); 缺失时拒绝测试,不回退到索引中的历史选择。 --prepare-proxy-connection --read-existing-subscription --full-configuration 则在 Verge 仍运行时直接进行只读预检,不保存测试快照或接管网络。 --test-proxy-panel --read-existing-subscription --capture system|tun [--installed-backend] 通过真实面板模型在独立私有资料目录验证迁入、连接、图表/地址、三种模式、线路、隐藏、关闭功能和退出。 TUN 面板试用还在三次模式切换后重复 DNS 问题,要求已分配 fake-IP 的地址集合保持不变。 该入口先显式启用同一后台的固定 60 秒面板试用保护,测试连接仍走正常事务; 到期或客户端断开先取消并等待当前事务及回退,再恢复原停止配置,同一测试连接结束后不能再次接管或延长期限。 面板测试额外加 --disconnect-checkpoint 时,在接通后输出有界私有回执并固定等待十秒,供测试驱动终止其自身持有的诊断进程; 普通面板和显示后台不参与该故障注入。独立 --observe-proxy-panel-disconnect [--installed-backend] 从 MACI_PROXY_PANEL_DISCONNECT_WITNESS 读取这份 base64 回执,只读核验同代后台在原期限前停止、无接管且试用标记全部清除; 它不发送停止请求。驱动仍须另外核验内核退出、端口、系统网络及原配置恢复;等到六十秒后才停止不能证明断连恢复通过。 面板测试可另选 --maintenance-checkpoint,与断线故障注入互斥:连接前及停止后在独立私有库中, 调用与界面共用的备份、暂存和追加恢复流程,核对原配置与接管状态未变化;原 60 秒保护内验证 Provider 内容未变化的更新保持同一内核运行回执。该步骤不在保护期内下载 Geo,也不操作正式配置库。 TUN 面板试用可单独加 --dns-transport-checkpoint,与维护检查和断线故障注入互斥。 它在切换模式或线路前,分别经 UDP/TCP 向固定文档地址查询 localhost;每次请求前后均核对同一 后台代次、试用回执、源配置摘要和 Geo 快照,要求两种传输均返回成功的 A 答复且地址集合完全相同。 合法的 localhost fake-IP 答复不会被误判为传输故障;此处只比较同一内核的传输结果,不判定 DNS 语义等价。 TCP 的连接、发送与分帧读取共用三秒截止,取消关闭自有连接;整个面板试用仍受原六十秒保护。 失败先完成正常清理再报告失败。该检查仅用于定位 TUN DNS 传输,不能替代原生 HTTPS 或完整 IPv6 验收。 签名构建产物可在状态或连接测试命令末尾显式加入 --installed-backend,通过固定安装路径及 同证书 XPC 连接已有后台;此诊断路径不查询或写入 SMAppService,避免改变现有后台的应用归属。 登记和 --unregister-proxy-service 仍只允许正式安装实例;更新前应先确认后台停止,再显式注销。 已加载后台须由签名 XPC 核验停止和归属;已卸载后台须独立确认 launchd 任务不存在、自有内核退出、 本机 17897 端口空闲且全部网络服务无接管,不能把连接失败当作已卸载。注销后须读回未登记和任务不存在。 若系统明确报告代理后台因旧启动签名约束而无法执行,正式实例可在重新验签、确认许可仍开启, 并独立核验后台及内核进程均不存在、端口与网络设置均无接管后,显式注销该失效任务一次。 注销前再次核验同一任务;状态不明或变化时停止,不自动重放注销、重新登记或修改显示后台。 root 配置策略拒绝任意执行、外部文件引用、未审查字段及远程 HTTP proxy-provider; 远程内容必须先通过上述普通用户准备链,root 只接收已校验的 inline 配置。 后台保留旧版 provider 刷新请求的解码,但明确拒绝执行;inline provider 的更新时间变化不能冒充远程内容更新。 这不影响面板现有的主订阅更新或 provider 列表读取。 Geo/provider 更新、备份恢复、跨版本回退及长期运行均有独立验收边界, 不能据本机当前订阅的接通结果宣称 Clash Verge 全部功能已等价。公开分发与 GPL 对应源码义务另行核对。

deno task check:proxy 串行运行 domain、真实 YAML、迁移 fixture、脚本工作进程、HTTP/Unix socket、 隔离真实 mihomo、Provider/备份恢复组合、面板生命周期和后台 fake adapter 测试;不注册 root 服务、不改变系统代理/TUN, 不读取现有 Verge 的订阅凭据。deno task check:editions 检查两种实际 SwiftPM 依赖图。面板的真实内核夹具使用独立随机 loopback 端口,可与正在运行的本机代理并存;正式代理端口不变。 maci-proxy-network-tests --isolated-core-dns 已校验内核绝对路径 SHA256 可单独验证真实内核的 TCP/UDP DNS 传输:仅使用 localhost 配置与本机随机高端口,核验同一进程的监听与应答, 结束确认内核退出及端口释放;不接管网络、不使用订阅,也不代替 TUN 验收。 maci-proxy-sharing-tests --loopback-auth 已校验内核路径 SHA256 额外验证真实内核的共享鉴权、 凭据更换、兼容入口的 HTTP CONNECT / SOCKS TCP 转发、UDP 不转发及端口释放。 它仅使用随机高端口和本机 IPv4/IPv6 地址模拟本机、共享与兼容入口, 不开放物理局域网监听、不接管网络,也不能代替其他设备上的连通验收;默认检查不运行此选项。 额外的 maci-proxy-maintenance-tests SwiftPM 目标接收已校验内核路径;--public-provider-update 验证 MetaCubeX 公开规则的真实 HTTPS 下载和条件更新,--public-geo-update 验证官方四份 Geo 的完整下载与真实解析。 --read-existing-subscription 只读验证当前订阅的备份恢复;搭配 --stability-soak-seconds 60..3600 则单独运行指定时长的隔离内核测试,采样真实健康、规则、连接计数、HTTPS、内存和文件描述符,结束核验进程与端口释放。 持续测试不能与公开资源下载选项混用,不接管系统代理或 TUN;当前 Verge 可能仍承载其外层连接, 该报告不等同于日常系统接管、睡眠唤醒或跨日稳定性验收。所有这些联网/订阅读取选项均不属于默认检查。 Unix 控制器使用可取消、受总时限约束的非阻塞本机套接字,并复用有界 HTTP 解析; 测试覆盖完整响应后立即关闭、提前截断、超限、超时和取消,不自动重放请求。 独立的 deno task test:proxy-existing --read-existing-subscription --output 私有测试目录 需要用户明确授权读取本机订阅后才能运行。它只读准备当前 Verge 订阅、原始增强、选择、应用功能设置及已启用的 应用 DNS,核验源文件未变,并在测试目录保存私有副本;当前入口只接受裸 DNS mapping。 测试对齐当前生效的节点、策略组、规则及 DNS,使用 17897/17898 独立端口测试真实订阅下载、 节点测速、HTTPS 请求、配置回退与面板关闭清理,不改现有 Verge、TUN 或系统代理。 该入口不把资料导入正式 maci 配置目录;每次应使用新的测试目录。现有 TUN 保持运行时, 测试结果不能代替退出 Verge 后的系统网络接管验收。 首次安装使用 deno task install 安装默认完整版,代理保持未启用;安装只登记既有 GUI/显示后台。 正式位置已有完整版时,日常 install 默认构建并提交保留后台的界面更新。 旧基础版迁入完整版必须显式使用维护路径;安装资料损坏或更新失败均停止,不自动回退到停机替换。 只有主动维护后台、内核或迁移旧版本时才使用 zsh scripts/install.sh --maintenance-runtime(内部裁剪版显式设 MACI_FEATURE_PROXY=0), 并先通过自有控制入口停止接管、注销代理后台;此路径保留原有停机检查和显示保护。 旧基础版迁入前,由候选的原生功能接口确认停用状态,避免重新启用历史代理资料;确认失败、超时或未知时不交换应用。 此停用选择在后续安装失败时也不会自动恢复。旧基础版需要保持裁剪时,可显式使用 deno task install:base。 允许最后虚拟屏短暂断开须另加 --allow-last-display-loss,不能单独以该参数进入维护。

也可分步使用 deno task build:ui-update 和 deno task install:ui-update;默认准备完整版候选, 与正式安装版本类型不同则拒绝,不能绕过旧基础版的维护迁移。 后者调用候选二进制的原生 agent app update-preview/update-apply;不通过旧安装流程停用后台。也可直接向候选的 Contents/MacOS/maci agent app update-preview --source /absolute/maci.app 提交本机候选, 再将同次返回的 previewToken 和 stateToken 用于 apply。路径必须为规范绝对 .app 路径, 允许空格,不接受 URL、相对路径或 ./.. 路径段。

这条事务更新 GUI 与其附属资源,要求候选与正式安装的后台、内核、启动配置及其受保护资源字节和权限相同, 并在更新前后核验同一运行状态摘要。代理处于健康运行或明确停止状态才可继续;未知、试用、 待恢复状态均拒绝。存在自有虚拟屏时须已启用无屏常驻,否则退出 GUI 会释放屏幕,更新将拒绝。 它不会升级代理 daemon/core、重新登记代理或显示后台,也不会恢复用户关闭的系统许可。 旧版公共资料目录保持原权限;更新记录与暂存仍使用私有目录。 安装适配器与 Agent 共用原生更新事务、跨进程锁、候选复验和恢复记录;失败或回执未知时先读取 agent app update-status,不要自动重放 apply。若交换已完整完成,只是最终确认未收到,可用同次状态中的 stateToken 显式调用 agent app update-reconcile --expect …;它须重新核验安装、实际 GUI 及保留后台, 只提交确认回执,不重新交换文件、重启 GUI 或控制后台。部分交换、资料不符或无法读回的其他未知结果仍保留 恢复材料,须人工审阅,不能用 reconcile 强行标记成功。 后台或内核的维护更新不保证已有连接不断流。参数与 fake 事务测试不代表正式更新验收; 真实安装后仍须确认 GUI 版本、后台与内核原进程、显示及代理状态保持。 代理核心的下载归档 SHA-256、未签名前/包内签名后的二进制摘要和来源记录随包保存, 并保留 mihomo GPL-3.0 与 Yams 许可证。完整代理包目前用于本机开发;公开分发前仍需落实 对应源码与第三方许可证义务、正式签名和公证。基础版不携带该代理 payload。

音乐下方的闪念输入框用于随手记录灵感:支持 ⌘V 粘贴,以及系统剪切、复制、全选 快捷键;输入后按回车或点击加号保存,圆形勾选标记完成,已完成 事项默认折叠,可用输入框右侧的勾选圆图标展开恢复。列表最多显示三条(126 点),超出后在列表内部滚动,悬停查看完整文字;每行复制按钮将完整 内容写入剪贴板,并短暂显示成功勾号。删除后可撤销最近一次 删除,下一次修改或退出应用后撤销失效。每条最多 2,000 字,共最多 500 条。已保存事项写入 ~/Library/Application Support/maci/thoughts.json,仅保存在本机,不发送给翻译模型;未提交草稿 只在当前运行中保留。保存失败不清空草稿或更改已保存列表,读取失败不覆盖原文件。

预览是一张静态截图,需退出后才能操作原应用。按住空格查看原图,松开恢复译文;点击文字块 展开完整译文与原文,并可复制该段译文。文字过长时在原位置截尾,不缩小字号或自动盖住相邻 文字。再次按当前翻译快捷键或 Esc 退出并清除本次内容。切换应用、原窗口移动/缩放/关闭或 显示器布局变化时自动退出;预览期间仅检查窗口元数据,不持续截屏。截图、识别文本与译文 不写入文件或日志,旧任务的迟到结果不能进入新预览。

面板“快捷键”可改为 ⌃⌥T 或 ⌃⌥⌘T,选择后立即生效并在重启后保留;注册冲突时保留 原有快捷键。默认译为简体中文,可切换英语、日语和韩语。已识别为目标语言的块和纯数字保留 原样;未完成翻译的块保留原图,失败时显示提示。菜单可选择 Apple 高质量、Apple 快速或 腾讯 Hy-MT2 窗口翻译;高质量策略需要 macOS 26.4,未启用 Apple Intelligence 时系统可能 回退到传统模型,界面不保证实际使用了哪一种 Apple 模型。腾讯模式携带最近三段有限上下文, 同一窗口串行翻译,关闭预览时释放模型。未保存引擎偏好且腾讯模型已就绪时默认使用腾讯; 否则默认请求 Apple 高质量策略。

Apple 的两种策略均通过系统 TranslationSession 在设备上翻译;所需语言包未安装时需要联网下载。 腾讯模式加载本机模型,仅通过 loopback 调用本机推理进程;首次下载模型与运行时需要网络。 两者都可在所需资源准备完成后离线使用。

电影字幕(首版):macOS 26 及 Apple Silicon 上,将播放器切到前台,打开 maci,点击 “电影字幕 → 启动”。默认识别英语,在该行设置中可选日语、韩语或普通话;输出语言使用上方 “译为”。只读取目标应用的声音,不使用麦克风、不执行 OCR;SpeechAnalyzer 在本机产生 临时与最终识别结果,Hy-MT2-1.8B Q4 按短段翻译,底部字幕层不遮住整个画面、不抢焦点, 鼠标可操作播放器。临时结果会修订,并非逐字译文稳定不变;译文与对应原文成对更新。 菜单栏始终只显示内存百分比,面板内显示字幕准备、聆听或错误状态。点击“停止”或按当前翻译快捷键 停止;切换应用、源窗口关闭/更换或显示器布局变化也会停止,关闭菜单本身不停止电影字幕。 字幕随同一源窗口移动,停止后清空音频、字幕与上下文,并结束自有推理进程。

首次使用点击“下载腾讯翻译模型(约 1.1 GB)”,或在 domains/maci 执行 deno task setup-translation。脚本从官方来源下载固定版本运行时与模型,校验 SHA256、保留 许可证,安装在 ~/Library/Application Support/maci/translation/;不需要管理员权限。 语音语言包由系统 Speech 框架准备。模型首次启动可能需十几秒,准备完成后再开始播放。 该模式按应用捕获:浏览器其他标签的声音也可能被包含,不能宣称单标签隔离;不保证受保护 影片能取音。无音频时等待对白,长时间静音后清除旧字幕;配乐、口音和重叠说话会影响识别。 队列有界,跟不上播放速度时停止并提示,避免不断积压延迟。首版尚未接入字幕文件/字幕轨 读取、持续 OCR、播放器时间轴/拖动跳转同步或提前翻译,不能保证字幕与任意影片无延迟同步。

运行需要 macOS 15 或更新版本。窗口截取需要用户授予屏幕录制权限;不请求辅助功能或全局 键盘监听权限。首次使用语言对时,系统可能提示确认下载语言包;翻译在本机执行,语言包 可用后可离线使用。固定图片开发演示通过 --demo 执行真实 OCR 与所选引擎翻译,无需屏幕录制 权限。仅识别当前窗口画面,段落分组是保守的几何判断,复杂多栏、混合语言、小字、动态或受 保护画面仍可能识别或翻译失败;单次识别上限为 12,000 字符,超过上限明确提示,不静默 截断。固定图片 demo 使用菜单中选择的窗口翻译引擎。

应用图标采用银色模块化机器人、青色耳鳍与环绕能量带;菜单栏仅显示内存百分比,电影字幕 运行时也不添加图标。图稿保存在 domains/maci/Assets/AppIconArtwork.png,构建自动导出含透明圆角与留白的多尺寸 ICNS。

maci 的归档入口是独立、按需启动的 Finder Service,提供解压、解压到指定目录、ZIP、7z 和压缩选项。归档不占用菜单面板;参数、密码、进度与取消使用临时原生窗口。退出菜单栏 maci 不会停止服务已接收的任务。默认一次运行一个任务,最多等待十六个;同次多选归档分别 提取,同组分卷合并识别。源文件保留,结果先完整校验,再用新名称原子发布,不合并或覆盖 已有结果,不自动展开包内其他压缩包。完成后列出实际生成的位置,用户可以点按“在 Finder 中显示”;部分失败或取消的批次只列出已经发布的结果。 暂存初始化或首份事务记录写入失败时,清理会核验已创建目录的身份,再回收自有暂存。

归档能力表位于 Sources/MaciArchives/ArchiveCapabilities.swift,创建选项复用这张表。 创建支持 ZIP、7z、TAR、GZIP、BZIP2、XZ、LZIP、Brotli、Zstandard、LRZIP、WIM、ISO、 DMG 和 Apple Archive。提取还包括 RAR/RAR5、ZIPX、PAX、CPIO/CPGZ、LZMA、CAB/MSI、 JAR/WAR/IPA/APK/APPX/XPI/SPK、Compact Pro、InstallShield 3、WPRESS,以及已识别的 7z/RAR/ZIP 自解压容器。EXE/MSI 仅提取内容,绝不执行安装程序。扩展名只作路由提示,密码、 压缩方法、分卷和元数据分别验证:

  • ZIP 设置密码时默认 AES-256,可明确选择传统兼容加密;7z 支持固实和加密文件名。ZIP/7z 可创建分卷, 数字分卷与传统 ZIP/RAR 卷组分别识别;保留 Mac 属性暂不能与加密同时使用。
  • ZIPX 验证 BZIP2/LZMA/PPMd8/XZ/Zstd。WPRESS 支持 v1/v2、raw/zlib/bzip2 与 AES-256-CBC, 密码先通过备份格式的校验块验证;CBC 和旧版无 CRC 内容不被表述为认证加密。
  • DMG 创建未压缩 UDRO,内含 ISO9660/Rock Ridge/Joliet;不创建 APFS 或加密镜像。 提取可以读取已验证的 APFS/HFS/ISO 内容,全程不挂载镜像。
  • Apple Archive 支持 AA01 与有界 LZFSE,.aar 中的 Android ZIP 按内容区分;不支持 AEA。 AAR 的单条属性块和磁盘镜像的单个属性目前各限 128 KiB。
  • Compact Pro 验证 RLE/LZH、CRC、资源叉、FinderInfo 与 MacBinary 包装;加密和多卷尚不支持。 InstallShield 3 验证 Fast/Medium/High/No 历史 .Z 归档,不泛指所有 InstallShield 安装器。 SFX 只查找有界前缀中已识别的载荷,不宣称所有 EXE、加密或多卷 SFX 兼容。

XIP 已实现系统信任检查及 XAR→PBZX→XZ→CPIO 解码链;因尚无有效 Apple 签名正例完成 签名 Worker 的全链验收,仍不开放产品入口。当前还不能称为完整 Keka 平替。

7-Zip 26.03 使用完整归档回调接口;固定 libarchive 3.7.4、liblzma 5.8.4、Brotli 1.2.0 和 Zstd 1.5.7 通过有界分配器运行;LRZIP 0.7.2 使用继承同一沙箱的包内 helper,CPT/IS3 使用固定内存的专用解码器。解码只在无网络权限的 App Sandbox XPC Worker 内执行, 它接收只读匿名输入快照和输出管道,不能得到最终目录的写权限。宿主逐项校验路径、链接、 大小写和 Unicode 冲突,以目录描述符写出;默认最多十万实际节点、16 GiB 实际输出,并保留 至少 64 MiB 空间。密码只存在本次内存;下载来源的 quarantine 继续传给结果。兼容分享与 保留 Mac 属性是显式选项,格式不能表达的属性不会被冒充为已保留。

已接收请求的 ID、动作和来源 URL 保存在权限为 0600 的 ~/Library/Application Support/maci/archive/pending.json;内容和密码不写入该文件。 重启时明确选择稍后处理、重新排队或放弃记录,自定义参数需要重新输入。目录内的私有事务 记录用于核对是否已经发布;无法确认旧引擎停止时,服务保留队列和租约。损坏记录保留原件, 不依赖旧 PID 清理进程、不盲目重跑,也不宣称支持断点续解。目标卷不支持 原子且不覆盖的发布时明确失败。引擎使用包内固定产物,不依赖 Keka 或 Homebrew 运行时; 许可证、来源 SHA-256 和对应源码归档随 Service 打包。

恢复弹窗可以保留记录、清理已发布记录或放弃已确认中断的暂存。清理会重新核对目录锁、 inode、记录原文与发布阶段;已发布结果始终保留。活跃事务、不确定状态和没有目录锁协议的 旧版记录只保留,不提供删除操作。

cd domains/maci
deno task build:archives
deno task check:archives
python3 scripts/install-archives.py  # 仅显示安装计划

归档构建需要 Xcode Command Line Tools、CMake 和 Python 3.12 或更新版本;脚本优先选择 满足版本要求的现有解释器,也可通过 MACI_ARCHIVE_PYTHON 指定。旧版 macOS 系统 Python 不提供所需的受限 tar 解包过滤器,构建不会为兼容它而降低源码提取检查。 检查同时覆盖空缓存中的固定来源解包:接受合法根目录,拒绝越界、未知链接和特殊条目, 并确认拒绝时尚未写入源码目录。 真实 XPC 检查会将已验签产物原样暂存到专用临时目录,并核对文件、权限和签名,避免 macOS 受保护目录限制沙箱初始化;不重签、不安装,也不修改系统权限。 归档检查会在专用临时目录创建 32 MiB HFS+ 测试映像,核验真实满盘和只读错误,再正常卸载 并清理该映像;这项检查不能替代外置卷拔出、ExFAT 或网络卷验收。

Finder 一级 maci 菜单由包内 Contents/PlugIns/maciFinder.appex 提供;需在 macOS 中启用该 Finder 扩展,并安装下述独立归档服务。扩展仅保存本次菜单的有界文件选择,通过私有 pasteboard 调用既有服务,不枚举目录、不读取原件、不访问代理资料。五个菜单动作仍由同一归档事务执行,Agent 使用既有 archive 接口。归档服务仅向 maci Finder 扩展声明菜单上下文,Finder 的“服务”中不再重复显示这五个命令;未启用扩展时需先启用,或使用“打开方式”与 Agent 接口。

独立产物为 dist/archive/maci Archive.service。只有明确选择后才执行安装脚本的 --install,安装至 ~/Library/Services/maci Archive.service 并刷新 Services;NSRequiredContext.NSApplicationIdentifier 固定为 com.siaovon.maci.finder,保留扩展调用而隐藏 Finder 中的重复服务入口。 --uninstall 只移除自己的服务。运行中的任务持有租约,更新会延后。安装不设置默认文件关联、不卸载 Keka,也不启动菜单面板。同一服务声明能力表中的文件类型为 Viewer/Alternate,并通过打开 文件事件进入相同队列;用户可自行选择“打开方式”及默认应用。Finder 菜单的位置、打开方式 发现以及是否需要在系统设置开启 Services,由 macOS 决定。隔离探针和本地构建不能替代 真实安装后的 Finder、外置卷和系统文件关联验收。

deno task build 使用 SwiftPM 与 Package.resolved 锁定依赖,首次构建需要联网获取依赖, 缓存位于 domains/maci/dist/swift-build/;生成 dist/maci.app(默认 ad-hoc,配置专用身份后使用稳定本机签名)及 bin/maci 入口,并携带独立归档 Service;不安装或修改登录启动项。设置 MACI_SIGNING_MODE=adhoc-validation 可做明确的本地临时签名验证,不读取已配置的私有证书; 普通构建仍遵循已有固定签名配置。ad-hoc 构建更新会改变代码签名;若旧屏幕录制授权失效, 需在系统设置重新登记已安装的 maci 并重启,不能仅依据开关状态判断权限。 deno task install 才安装至 ~/Applications/maci.app,停用旧 Memory Guardian LaunchAgent 并启用新服务;旧 plist、helper 和 ~/Library/Application Support/CodexMemoryGuardian/ 内历史数据完整保留。 更新先暂存并校验签名;已使用包内注册且后台二进制、启动配置未变化时保持其运行,只替换菜单界面。 旧外部 LaunchAgent 迁入包内注册必须受控停止并卸载旧任务后再注册;新任务分别使用 com.siaovon.maci.menu-agent 与 com.siaovon.maci.display-agent,避免旧式后台活动记录 阻碍应用归组。显示 XPC 接口仍为 com.siaovon.maci.display-service。旧 plist 归档保留; 显示后台迁移同样经过最后一屏保护。 旧版虚拟屏由菜单进程持有,首次迁移无法直接转交对象:检测到可能仅有旧版虚拟屏时,安装会在停止服务之前退出。 应接入备用屏幕,或明确接受短暂断屏后运行 deno task install --maintenance-runtime --allow-last-display-loss。 显示后台自身升级或卸载同样经过最后一屏保护;失败时保留配置和回退副本,不强制杀死真实服务。

cd domains/maci
deno task build
deno task check
deno task install
deno task status

deno task test:movie 是显式的真实模型集成验证:先完成 setup-translation,测试通过 系统语音合成生成已知英语音频,运行真实 SpeechAnalyzer 与 Hy-MT2,检查识别、翻译、取消和 进程清理;不采集播放器或麦克风。首次可能需要系统准备语音语言包。它独立于常规 check, 不能替代授权后的真实播放器取音与字幕层验收。

deno task benchmark:movie <Safari PID> <15–120 秒> 对用户当前选择播放的 Safari 音频做 显式短段评测:看到 CAPTURE_READY 后播放影片,看到 CAPTURE_FINISHED 后暂停。 采集期间只保留有界内存,最终取前八个完整识别句段,以相同原文、无历史上下文比较 Apple 快速、Apple 高质量请求与 Hy-MT2;每段每引擎重复三次、轮换顺序,另计模型启动和预热。 结果仅输出到调用终端,不写录音、字幕或报告文件;不要把控制台重定向到日志,除非明确需要 保存评测原文。识别最终化延迟是基于音频时间戳的近似值,翻译耗时是接口完成时间;二者不能 冒充已实测的播放到字幕显示延迟。Apple 实际使用的高质量模型无法由该接口确认。

同一发现与停止边界也提供给自动化验收:

bin/maci --sample-memory-percentage
bin/maci --list-dev-services-json
bin/maci --stop-dev-service <PID> <PORT>
bin/maci --display-service-status
bin/maci --set-display-headless on
bin/maci --restore-displays
~/Applications/maci.app/Contents/MacOS/maci --startup-status

安装后由 ~/Applications/maci.app/Contents/Library/LaunchAgents/ 内两个启动项 在用户登录时启动,主程序与独立签名的显示后台均位于 Contents/MacOS/。 新日志保存于 ~/Library/Application Support/maci/。status 分别核对包内注册状态、真实进程与 launchd 监管 PID;已安装 App 的 --startup-status 不启动后台。未安装的构建产物返回 notInstalled,不查询系统注册,以免系统把正式后台的 App 路径改指向构建目录。 安装和卸载脚本调用已安装 App 的 --register-startup gui|display 与 --unregister-startup gui|display,后者停止运行中的显示后台必须先获得其停止确认。 uninstall 只停止并注销这两个服务,保留 App 和所有历史运行数据,不自动恢复旧服务。 bin/maci --stop-display-service 会释放后台持有的虚拟屏;涉及最后一屏时拒绝执行,只有明确接受断屏后 才可加 --allow-last-display-loss。这不会删除已保存的屏幕定义。

构建后可直接运行 open dist/maci.app --args --demo 试用固定图片翻译,或使用 open dist/maci.app --args --show-panel 打开菜单栏面板。重复打开已运行的 App 不会重新传递 启动参数,但会重新打开菜单栏面板;日常使用也可点击菜单栏入口。

文档约定

项目源码只维护两份 Markdown 文档:

  • README.md:面向人的产品、架构、运行和迁移说明;
  • AGENTS.md:面向开发 Agent 的工作约束与验证规则。

不要新增 domain 级 README、AGENTS、SKILL、历史计划或设计 QA 文档;相关有效信息应归并 到上述两份文件。LICENSE、NOTICE、代码注释、API 类型和测试不属于此限制。

清理记录

  • 历史 Perry 桌面端、Proxy、Downip、LivpExplorer 与完整 PlaysVideo domain 已移除;新的 openfx-macos 只承载当前文件库的 WKWebView 和原生 Photos 导入,不恢复旧桌面产品;
  • PlaysVideo 仍被使用的最小发布引擎已固定在 domains/media-player/vendor/;
  • _shared 中没有产品调用的历史工具已删除;只服务 how-much 的 KV adapter 已回归其 domain,livp-codec.ts 按文件库事实边界保留;
  • 历史设计稿、重复上游说明和旧清理报告已在文档收口时删除。

协议与来源

仓库主体使用 Apache-2.0,见 LICENSE 与 NOTICE。包含独立许可证的 domain 继续以各自目录中的 LICENSE 为准。主要上游来源包括 BewlyCat/BewlyBewly、 ChronoFrame、maptoposter 和 playsvideo;保留其源码许可与第三方声明。