- 人工智能
- 大模型
- AI Agent
- 交互助手
- 工具调用
- MCP 服务
- Agent 记忆
- RAG
【免费下载链接】opensquilla
OpenSquilla — Token-Efficient AI Agent with same budget, higher intelligence density
导读
本文围绕 OpenSquilla 的 docs/release-oss-mirror.md 展开,完整解读它如何把 GitHub Release 产物镜像到阿里云 OSS,为中国大陆用户提供更快的安装包与更新下载链路。你会掌握这套镜像系统的完整工作流(触发方式、仓库迁移边界、配置项、目标目录布局、手动回填、失败模型),并深入到 .github/workflows/mirror-release-to-oss.yml、scripts/release_channel_manifest.py 与桌面端 desktop/electron/src/update-channel.ts 的源码实现,理解"版本化对象写一次、移动别名与渠道清单可回滚"这套设计如何同时保障下载速度与更新安全。
一、为什么需要 OSS 发布镜像
OpenSquilla 的官方发布源是 GitHub Releases,但 GitHub 下载节点在国内大陆网络环境下并不总是稳定、快速。为了在不改变发布流程的前提下缩短大陆用户的下载耗时,项目把每个已发布的 Release 产物同步到阿里云 OSS:
- 安装包(macOS DMG、Windows EXE、Python wheel)按版本放在版本化路径下;
- 同时维护
latest/移动别名与channels/渠道清单,供桌面端更新客户端消费; - 所有上传产物在写入前都经过
SHA256SUMS校验,保证镜像内容与 GitHub 原版字节一致。
镜像链路以 GitHub Release 为唯一事实来源(source of truth),OSS 只是它的加速副本,这一点贯穿了后面所有章节的设计取舍。
二、工作流与仓库迁移边界
2.1 触发方式
镜像工作流定义在 .github/workflows/mirror-release-to-oss.yml:
on: release: types: [published] workflow_dispatch: inputs: tag: description: Release tag to mirror, for example v0.5.0rc3 required: true- 自动触发:GitHub Release 被发布(
published)时自动运行; - 手动触发(workflow_dispatch):通过
tag输入指定已发布的标签,用于回填历史版本。
工作流通过concurrency.group: oss-release-mirror-latest-aliases(cancel-in-progress: false)把所有发布任务放在同一个并发组,串行执行,避免两个任务同时推进移动对象。
2.2 标签解析与规范化
工作流第一步会解析并校验标签,只接受v0.5.0rc3、v0.5.0这类规范写法:
if [[ ! "${tag}" =~ ^v[0-9]+[.][0-9]+[.][0-9]+[A-Za-z0-9._+-]*$ ]]; then echo "Release tag must look like v0.5.0rc3 or v0.5.0: ${tag}" >&2 exit 1 fi对应的版本解析逻辑在 scripts/release_channel_manifest.py 中由_TAG_RE承担,它把标签拆解为major.minor.patch与可选的rc号,并定义了完整的排序语义(见下文"渠道晋升"小节)。
2.3 仓库迁移边界:从opensquilla到TokenRhythm
项目经历了 GitHub 组织迁移。新的发布源固定在规范化仓库TokenRhythm/opensquilla(工作流环境变量CANONICAL_GITHUB_REPOSITORY)。迁移不改变 OSS 侧的任何布局:
- 继续使用
ALIYUN_OSS_BUCKET、releases前缀、latest/与channels/对象; - 工作流在非规范化仓库中运行会fail closed——即立即失败退出:
if [[ "${GITHUB_REPOSITORY}" != "${CANONICAL_GITHUB_REPOSITORY}" ]]; then echo "Refusing to mirror from non-canonical GitHub repository: ${GITHUB_REPOSITORY}" >&2 exit 1 fi这样迁移前的仓库即使被误触发,也无法悄悄往镜像写入内容。
一个关键的兼容细节:渠道清单中故意保留旧版 v1 客户端需要的releaseUrl拼写(github.com/opensquilla/opensquilla),而已发布的客户端在 desktop/electron/src/update-channel.ts 中也同样保留了LEGACY_V1_RELEASE_PAGE_ROOT常量来校验这一拼写;GitHub API 与下载操作则使用新仓库TokenRhythm/opensquilla。文档明确要求:不要仅仅因为 GitHub 归属方变了就重写 OSS 对象键或移动别名。
三、仓库级配置:Secrets、Variables 与权限模型
3.1 必须配置的 Secret 与 Variable
| 配置项 | 类型 | 说明 |
|---|---|---|
ALIYUN_OSS_ACCESS_KEY_ID | Secret | 阿里云 RAM 用户 AccessKey ID |
ALIYUN_OSS_ACCESS_KEY_SECRET | Secret | 阿里云 RAM 用户 AccessKey Secret |
ALIYUN_OSS_BUCKET | Variable | OSS Bucket 名称,例如opensquilla-downloads |
ALIYUN_OSS_REGION | Variable | OSS Region ID,例如cn-hangzhou |
ALIYUN_OSS_PREFIX | Variable | 可选对象前缀,默认releases |
ALIYUN_OSS_ENDPOINT | Variable | 可选自定义 Endpoint 或 CNAME Endpoint |
ALIYUN_OSS_ADDRESSING_STYLE | Variable | 可选 ossutil 寻址方式:virtual/path/cname |
工作流的 "Validate OSS configuration" 步骤会先检查ALIYUN_OSS_BUCKET、OSS_REGION与两个 Secret 是否齐全,缺失即失败;随后对前缀做规范化处理(去掉首尾/,空则回退为releases)。
3.2 Addressing Style 的自动选择
寻址方式决定 ossutil 构造请求时 Bucket 的放法,源码中有一整套自动推导逻辑:
endpoint_host="${OSS_ENDPOINT#http://}" endpoint_host="${endpoint_host#https://}" endpoint_host="${endpoint_host%%/*}" addressing_style="${OSS_ADDRESSING_STYLE:-}" if [[ -z "${addressing_style}" ]]; then if [[ -n "${endpoint_host}" && ! "${endpoint_host}" =~ (^|[.])aliyuncs[.]com$ ]]; then addressing_style="cname" else addressing_style="virtual" fi fi case "${addressing_style}" in virtual|path|cname) ;; *) echo "ALIYUN_OSS_ADDRESSING_STYLE must be virtual, path, or cname: ${addressing_style}" >&2; exit 1 ;; esac- 未设置且 Endpoint 主机名以
aliyuncs.com结尾(如oss-cn-hangzhou.aliyuncs.com)→ 默认virtual; - Endpoint 指向绑定的自定义上传域名(CNAME)→ 自动
cname; - 显式设置则只接受
virtual/path/cname三者之一。
3.3 最小权限 RAM 策略
文档明确建议使用专用的 RAM 用户或角色,权限范围限定到镜像 Bucket/前缀,需要的权限包括:
oss:ListObjectsoss:GetObjectoss:PutObjectoss:DeleteObject- Bucket 级
oss:GetBucketVersioning(工作流需要查询 Bucket 的版本化状态)
不要使用全权限账号密钥。这是因为工作流需要:列出已有对象、把现有别名复制到短期备份、上传版本化产物/别名/渠道清单,最后删除备份与遗留的latest.html。
四、目标目录布局:版本化对象、移动别名与渠道清单
以标签v0.5.0rc4与默认前缀为例,工作流先写入版本化产物:
oss://<bucket>/releases/v0.5.0rc4/OpenSquilla-0.5.0-rc4-win-x64.exe oss://<bucket>/releases/v0.5.0rc4/OpenSquilla-0.5.0-rc4-mac-arm64.dmg oss://<bucket>/releases/v0.5.0rc4/opensquilla-0.5.0rc4-py3-none-any.whl oss://<bucket>/releases/v0.5.0rc4/SHA256SUMS然后替换两个移动安装器别名:
oss://<bucket>/releases/latest/OpenSquilla-win-x64.exe oss://<bucket>/releases/latest/OpenSquilla-mac-arm64.dmg最后发布渠道清单:
oss://<bucket>/releases/channels/latest.json oss://<bucket>/releases/channels/stable.json oss://<bucket>/releases/channels/preview/0.5.0.json4.1 版本化路径 vs 移动别名:各自的用途
- 版本化路径:需要把下载钉在某个发布标签上时使用(例如用户要精确下载
v0.5.0rc4); latest别名:只面向用户界面上的"下载最新桌面应用"链接,且仅在镜像版本是该渠道最高可用版本时才推进——更早版本的手动回填不能顶替它们。
4.2 更新客户端如何消费渠道清单
桌面端更新客户端不使用移动安装器别名,也不用latest.json之外的所谓固定链接行为:
- Stable 客户端读
stable.json; - Preview 客户端读对应 release line 的清单,如
preview/0.5.0.json。
清单提供经过校验的 tag 与版本化文件名,让"发现与下载"始终停留在同一个版本上。对应关系在 desktop/electron/src/update-channel.ts 中实现:
export function updateChannelPathForVersion(currentVersion: string): string | null { const parsed = parseOpenSquillaReleaseTag(currentVersion) if (!parsed) return null return parsed.rc === null ? 'stable.json' : `preview/${parsed.base}.json` }即:最终版本走stable.json,RC 版本走preview/<base>.json。清单 URL 拼装见 updateChannelManifestUrl,默认根为https://opensquilla-releases.oss-cn-beijing.aliyuncs.com/releases(同文件UPDATE_OSS_RELEASE_ROOT常量)。
4.3 渠道晋升规则:谁可以推进谁
晋升决策由 scripts/release_channel_manifest.py 中的版本排序与should_promote实现,核心规则如下:
stable.json只被最终版本(final release)推进;- preview 清单被更高 RC 或同一 base 版本的最终版推进,例如
0.5.0rc4可以前进到0.5.0rc5或0.5.0,但绝不可能跳到0.6.0rc1; latest.json记录既有固定链接行为、跨 release line 存在,只用于提交与回滚latest/别名。
版本排序在ReleaseVersion数据类中体现:final_rank(0 表示 RC、1 表示最终版)保证同一 base 下最终版排在所有 RC 之后:
@dataclass(frozen=True, order=True) class ReleaseVersion: major: int minor: int patch: int final_rank: int # 0 = rc, 1 = final rc: int4.4 渠道清单的 JSON 契约
清单由release_channel_manifest.py build子命令从 GitHub Release 元数据(release.json)与已下载产物目录生成,桌面端在 validateUpdateChannelManifest 中做同样的严格校验。清单结构(schemaVersion 1)关键字段:
{ "schemaVersion": 1, "tag": "v0.5.0rc4", "version": "0.5.0-rc4", "baseVersion": "0.5.0", "prerelease": true, "publishedAt": "<RFC3339 时间戳>", "releaseUrl": "https://github.com/opensquilla/opensquilla/releases/tag/v0.5.0rc4", "sha256sums": "SHA256SUMS", "platforms": { "darwin-arm64": { "feed": "latest-mac.yml", "archive": "OpenSquilla-0.5.0-rc4-mac-arm64.zip", "installer": "OpenSquilla-0.5.0-rc4-mac-arm64.dmg" }, "win32-x64": { "feed": "latest.yml", "installer": "OpenSquilla-0.5.0-rc4-win-x64.exe" } } }校验要点:tag 与 version 必须一致且规范;prerelease必须与 tag 的 rc 后缀一致;publishedAt必须是带时区的 RFC3339;releaseUrl只接受新仓库规范拼写或旧版 v1 拼写;platforms中的文件名必须与版本完全匹配且为单段安全文件名。
4.5 缓存策略:版本化不可变 vs 移动可重校验
- 版本化对象:写一次(write-once),使用不可变缓存策略
public,max-age=31536000,immutable(一年 + immutable); - 渠道 JSON:要求缓存重新校验,
no-cache,max-age=0,must-revalidate,保证客户端总能拿到最新渠道头; - 移动别名:同样使用
no-cache,max-age=0,must-revalidate,因为别名指向会变。
以上缓存头分别对应工作流中的versioned_cache_control与moving_cache_control变量。
五、下载路径与 Windows 客户端的校验链
5.1 公共 Endpoint 直链
使用默认公共 Endpoint 时,下载地址为:
https://<bucket>.oss-<region>.aliyuncs.com/releases/latest/OpenSquilla-win-x64.exe https://<bucket>.oss-<region>.aliyuncs.com/releases/latest/OpenSquilla-mac-arm64.dmgOSS 默认域名会对这些文件强制浏览器下载行为,这对安装包链接来说是符合预期的,无需自定义域名。也因此,工作流不发布 HTML 的 latest-release 落地页——因为 OSS 默认域名的安全策略同样会把 HTML 强制为下载而不是页面渲染。
5.2 Windows 客户端:先校验、再流式下载、失败即删
Windows 客户端不会直接执行 OSS 上的对象,而是执行一条严格的校验链:
- 先从 OSS 镜像拉取对应版本 release 的
SHA256SUMS(镜像时已与 GitHub Release 字节比对过),若镜像对象缺失或不可读则回退到 GitHub Release 原版; - 从选定的 GitHub 或 OSS 源,把精确的版本化 EXE 流式下载到应用自有的目录;
- 校验其 SHA-256 摘要;
- 只有校验通过后才暴露该文件供用户显式手动安装。
如果校验源不可达或摘要不匹配,客户端fail closed:删除部分下载或摘要不匹配的下载文件,绝不带着未经验证的安装包继续执行。这一点在桌面端主进程中有对应的下载与发布逻辑(见 desktop/electron/src/main.ts 与publishVerifiedWindowsInstaller相关调用)。
5.3 更新源的排序策略
桌面端在 orderedUpdateSources 中决定 OSS/GitHub 的尝试顺序:
- 用户显式覆盖
oss/china→['oss', 'github'];github/global→['github', 'oss']; - 上次成功来源优先;
- 否则按系统 locale 推断:大陆地区(
CNregion,或简体中文语言标签)→ OSS 优先,其余 → GitHub 优先。
这解释了镜像存在的直接价值:大陆用户默认从 OSS 拉取更新,链路更稳、更快。
六、大文件上传:分片暂存 + 服务端条件拷贝
大产物(>= 8 MB,对应--bigfile-threshold 8388608)走并行分片上传流程:
- 先上传到本次 attempt 专属的临时前缀:
<prefix>/.upload-staging/<GITHUB_RUN_ID>-<GITHUB_RUN_ATTEMPT>/; - 下载暂存字节并校验其 SHA-256 与本地一致(防止链路损坏);
- 重新检查最终对象是否已存在(防并发写入);
- 用条件服务端拷贝(
copy-object+--forbid-overwrite true)提交版本化对象; - 提交后再校验一次,确认字节一致。
这样做的好处是:小分片失败不必重启整个安装包传输;而版本化对象在未验证通过前,channels/清单不会被推进。每次 attempt 的暂存内容只会被当前 attempt 清理(见工作流末尾 "Remove this attempt's temporary multipart staging" 步骤,always()执行,且同时清理版本化残留与未完成的分片上传)。
移动别名则直接在 OSS 内部从已验证的版本化对象服务端拷贝而来(upload_installer_alias读取channel-assets/<name>.source记录的真实版本文件名),不需要二次上传安装包字节。
七、写一次语义:校验、拒绝覆盖与并发安全
7.1 版本化对象是不可变的
工作流在写每个版本化对象前:
- 先
ossutil ls检查对象是否已存在; - 若存在,逐字节下载比对 SHA-256;
- 字节一致才跳过(幂等重跑安全),不一致则拒绝替换,提示"用新标签发布修正后的产物":
Refusing to replace immutable OSS release object: oss://... local SHA256: ... remote SHA256: ... Publish corrected release assets under a new release tag.x-oss-forbid-overwrite条件用于缩小"检查到写入"之间的竞态窗口;但 OSS 在 Bucket 开启或挂起版本化时会忽略该条件,所以真正不可变性的保障始终落在"存在性检查 + SHA-256 验证"上,而不是服务器条件。
7.2 Bucket 版本化状态只记录、不修改
工作流通过ossutil api get-bucket-versioning查询并记录Bucket 版本化状态(enabled/suspended/ 未配置),不修改它。测试 tests/test_release_oss_mirror_workflow.py 用 fake ossutil 验证了Enabled/Suspended两种状态下的行为:
- 相同字节重跑保持幂等(不触发任何
put-object/copy-object); - 已被镜像的对象出现不同字节时,即使在版本化 Bucket 上也先拒绝再上传("Refusing to replace immutable OSS release object");
- 并发写入者(fake 模拟的 race 对象)的字节原样保留,工作流失败。
7.3 竞态下的最终裁决
put_immutable_asset在写入失败后会再查一次对象是否存在并做字节验证:
if ! put_immutable_asset ...; then if object_exists "${object}" && verify_immutable_asset ...; then echo "Concurrent immutable OSS release object already matches: ${object}" return 0 fi ... fi如果竞态中别的写入者提交了相同字节,视为成功;提交了不同字节则失败——从而在任何版本化/未版本化场景下都保持"写一次、不可篡改"的契约。
八、移动对象推进:备份、晋升、回滚
8.1 晋升前双重守卫
在推进任何移动对象(别名与渠道清单)之前,工作流做两层检查:
- 认证的 GitHub Release 清单比对:候选版本必须是该渠道的 head(最高发布版本)——
is-release-head检查基于 release_is_channel_head,独立于 OSS 状态,专门堵住"首次引入清单后的回填覆盖已有别名"的 bootstrap 缺口:即使latest.json尚不存在,回填v0.5.0rc3也不能替换已在线的 rc4 别名; - 现有 OSS 清单单调性比对:
should-promote比较 current 与 candidate 的版本排序,候选不得低于 OSS 当前状态。
两个检查不通过时工作流以退出码 3 表示"跳过"而非失败(如Skipping non-head release .../Skipping older channel candidate ...)。
8.2 备份前缀:每次 attempt 独立
晋升前把现有对象备份到:
<prefix>/.promotion-backups/<GITHUB_RUN_ID>-<GITHUB_RUN_ATTEMPT>/GitHub Actions 重跑时GITHUB_RUN_ID不变、GITHUB_RUN_ATTEMPT递增,因此重跑不会覆盖上一次失败留下的恢复快照。
8.3 晋升顺序与失败回滚
推进顺序是精心设计的:
- 备份现有渠道清单;
- 需要推进
latest.json时:备份并删除遗留的latest.html,备份现有别名,再拷贝新别名(拷贝前先记录promoted_aliases,保证元数据更新失败也能回滚字节); - 最后发布渠道清单——此时所有引用的版本化对象与别名都已就位;
- 删除
latest.html(仅当本次推进了别名且做过备份)。
整个移动组(别名 + 渠道清单 + 被移除的latest.html)作为一个 promotion group 备份与回滚。失败时rollback_promotions从备份前缀恢复字节或删除本次新增对象。成功后清理备份;若清理失败只报::warning::,不会把已提交的镜像误标为失败。
测试 test_release_oss_mirror_workflow.py 还验证了别名推进只发生两次 ossutil 调用(一次服务端拷贝 + 一次set-props更新缓存头),且不依赖本地存在安装包文件;set-props失败时整个推进失败并触发回滚。
九、手动回填(Manual Backfill)
要镜像一个已经发布的 release,直接在 GitHub Actions 页面手动运行工作流并填入标签,例如v0.5.0rc4。手动回填的行为:
- 上传缺失的版本化对象,并对已存在对象逐字节校验;
- 绝不会在同一标签下用不同字节替换已存在的对象;
- 改变任何移动对象前,先用 GitHub Release 认证清单与既有 OSS 清单做单调性校验:候选必须是该渠道最高版本,且不得早于 OSS 当前状态;
- 如果回填无法推进
latest.json,则latest/别名与被退役的latest.html对象都保持原样不动。
这保证了历史版本补镜像不会意外破坏当前在线的"最新"指针。
十、失败模型(Failure Model)
镜像工作流在以下任一情况发生时整体失败:
- 缺少必需的 OSS 配置(Bucket/Region/AccessKey);
- GitHub Release 没有可下载产物;
- 缺少
SHA256SUMS; - 某个 release 产物未列入
SHA256SUMS(或反向:清单列出的文件不存在); - 校验和验证失败;
- 无法恰好找到一个 macOS DMG 与一个 Windows EXE 安装器;
- 既有渠道清单格式非法;
- 既有版本化对象与已验证的 GitHub 产物字节不一致。
在这些情况下:
- GitHub 仍然是唯一事实来源;
- 移动对象不会被部分更新——渠道清单与别名作为一个 promotion group 备份并回滚;
- 每次 attempt 使用独立备份前缀,重跑失败工作流不会覆盖手动恢复用的快照;
- 成功且验证通过后,若临时备份清理失败,仅记录为工作流警告,而不是把已提交的发布镜像误标为失败。
十一、测试与契约保障
该镜像系统有完整的契约测试支撑,最核心的是 tests/test_release_oss_mirror_workflow.py:
test_aliyun_oss_release_mirror_workflow_contract:静态断言工作流 YAML 的每个关键行为(规范化仓库检查、gh release download、sha256sum --strict -c、--forbid-overwrite true、备份/回滚顺序、先验证版本化对象再推进清单等);test_version_scoped_oss_objects_are_write_once_and_race_safe:用 fake ossutil 验证幂等重跑、篡改拒绝、并发写入者保护、版本化 Bucket 行为;test_large_assets_are_verified_before_server_side_commit:验证大文件必须先经暂存分片上传 + 字节验证,损坏的暂存对象不会被提交,服务端拷贝只在验证通过后发生;test_installer_alias_uses_verified_oss_object_without_local_reupload:别名推进只做一次服务端拷贝加元数据更新,失败即回滚。
此外,.github/scripts/prestage-release-to-oss.sh 提供了 Draft 发布前的预暂存路径(配套测试 tests/test_scripts/test_prestage_release_to_oss.py):它把 Draft 期产物以版本化写一次的方式预先上传到 OSS,但刻意不含任何渠道/别名代码——直到人工发布该 Draft 后,镜像工作流才会推进 stable/latest 清单。这一分离避免了未发布版本污染更新渠道。
十二、把镜像系统接入自己的仓库:一份可操作清单
- 准备 RAM 凭据:创建只含镜像 Bucket/前缀最小权限的 RAM 用户,配置两个 Secret 与四个 Variable(Bucket、Region、Prefix、可选 Endpoint/Addressing Style);
- 确认仓库归属:工作流只接受
TokenRhythm/opensquilla运行;其他仓库应复制后自行修改CANONICAL_GITHUB_REPOSITORY; - 发布流程对齐:确保每个 Release 都携带
SHA256SUMS、恰好一个 macOS DMG 与一个 Windows EXE 安装器,并遵循vX.Y.Z[rcN]标签规范; - 首次镜像:直接用 workflow_dispatch 回填首个版本,观察
channels/与latest/对象创建; - 持续验证:依赖 tests/test_release_oss_mirror_workflow.py 的契约测试守卫工作流修改,桌面端更新链路由 desktop/electron/src/update-channel.ts 的清单校验兜底。
延伸阅读
- 镜像工作流实现:.github/workflows/mirror-release-to-oss.yml
- 渠道清单生成与晋升决策:scripts/release_channel_manifest.py
- Draft 预暂存脚本:.github/scripts/prestage-release-to-oss.sh
- 工作流契约测试:tests/test_release_oss_mirror_workflow.py、tests/test_scripts/test_prestage_release_to_oss.py
- 桌面端渠道消费与校验:desktop/electron/src/update-channel.ts
- 本文档的原始说明:docs/release-oss-mirror.md
- 人工智能
- 大模型
- AI Agent
- 交互助手
- 工具调用
- MCP 服务
- Agent 记忆
- RAG
【免费下载链接】opensquilla
OpenSquilla — Token-Efficient AI Agent with same budget, higher intelligence density
相关推荐
GitHub镜像云同步工具:github-mirror
GitHub镜像云同步工具:github mirror 项目基础介绍及编程语言 github mirror 是一个由CSDN公司开发的InsCode AI大模型
后端开发工具【免费下载】 GitHub镜像云同步工具:github-mirror
GitHub镜像云同步工具:github mirror 项目基础介绍及编程语言 github mirror 是一个由CSDN公司开发的InsCode AI大模型
后端开发工具Robocode机器人类型对比:从Robot到AdvancedRobot的进化之路
Robocode机器人类型对比:从Robot到AdvancedRobot的进化之路 Robocode是一款极具挑战性的编程游戏,玩家通过编写Java代码控制虚拟
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考