diff --git a/docs/getting-started/install-options.md b/docs/getting-started/install-options.md index 574ab8799..258175e69 100644 --- a/docs/getting-started/install-options.md +++ b/docs/getting-started/install-options.md @@ -82,7 +82,7 @@ Stop with `docker compose stop` using the same files and environment. Back up th The installer downloads release files from GitHub Releases with this shell's network settings, including `HTTPS_PROXY`. Docker pulls the images through its daemon, which does not read the shell's proxy variables. Every image, PostgreSQL included, comes from GHCR (`ghcr.io`); Docker Hub is not needed. When GHCR is reachable only through a proxy or mirror, configure [the daemon's proxy](https://docs.docker.com/engine/daemon/proxy/) or a [registry mirror](https://docs.docker.com/docker-hub/image-library/mirror/), then rerun the installer. -A Linux amd64 host without that access installs from the release asset `oac--linux-amd64-offline.tar.gz`, which contains every image and node artifact. Copy it to the host, extract it and run its `install.py` with Python 3.9 or newer and Docker. No checkout, Go, Node or pnpm is needed on that host. Keep the extracted bundle until installation completes; the installed services and node downloads do not depend on its original location afterward. The same archive is what [Develop OpenAgentCore](../development.md#install-a-checkout-without-publishing-a-release) builds from a checkout. +A Linux amd64 host without that access installs from the release asset `oac--linux-amd64-offline.tar.gz`, which contains every image and node artifact and the Linux amd64 self-hosted installer. Self-hosted machines on macOS and Windows download their installer from GitHub Releases. Copy it to the host, extract it and run its `install.py` with Python 3.9 or newer and Docker. No checkout, Go, Node or pnpm is needed on that host. Keep the extracted bundle until installation completes; the installed services and node downloads do not depend on its original location afterward. The same archive is what [Develop OpenAgentCore](../development.md#install-a-checkout-without-publishing-a-release) builds from a checkout. ### `install.py` options diff --git a/docs/getting-started/self-hosted.md b/docs/getting-started/self-hosted.md index 0e89f0caf..40ecb6590 100644 --- a/docs/getting-started/self-hosted.md +++ b/docs/getting-started/self-hosted.md @@ -32,7 +32,7 @@ With one Harness, the peak is the archive (316 MiB), the unpacked installer (907 The machine needs: -- HTTP or HTTPS access to Core, and to the release download host unless Core carries an offline copy of the installers; +- HTTP or HTTPS access to Core, and to the release download host unless Core carries an offline copy of this platform's installer (an offline installation carries only Linux amd64); - Bash for environment setup and MiniMax Code tools; on Windows, Git Bash, which Claude Code also requires; - Python and pip when the Session's packages need them; - any system packages your setup needs. The daemon never runs apt, sudo or another elevation command, so install them through the host's normal administration. diff --git a/docs/maintainers.md b/docs/maintainers.md index 956d888e8..a07d422f1 100644 --- a/docs/maintainers.md +++ b/docs/maintainers.md @@ -54,7 +54,7 @@ node scripts/build-native-catalog.mjs INPUT_DIR OUTPUT_DIR export OAC_NATIVE_INSTALLER_BUILD_DIR=OUTPUT_DIR ``` -The catalog records the commit, the Runtime protocol version, each archive's SHA-256 and, with a release base, its versioned URL. The control archive and Core image carry only `native-installers/catalog.json`; the archives become separate `oac-native--.tar.gz` release assets, and the offline archive holds one copy of each outside the Core image, which its `install.py` copies into the installation for Core to serve. Without a catalog, Sessions report the install command as unavailable, and the release workflow refuses to publish. +The catalog records the commit, the Runtime protocol version, each archive's SHA-256 and, with a release base, its versioned URL. The control archive and Core image carry only `native-installers/catalog.json`; the archives become separate `oac-native--.tar.gz` release assets, and the offline archive holds a copy of the Linux amd64 archive outside the Core image, which its `install.py` copies into the installation for Core to serve. Core redirects the other platforms to their release assets; a catalog without a release base has no such URL, so its offline archive holds every archive. Without a catalog, Sessions report the install command as unavailable, and the release workflow refuses to publish. ### Runtime images and helpers diff --git a/docs/zh/getting-started/install-options.md b/docs/zh/getting-started/install-options.md index 3d62e9724..86e13c33d 100644 --- a/docs/zh/getting-started/install-options.md +++ b/docs/zh/getting-started/install-options.md @@ -1,7 +1,7 @@ --- title: "安装选项" source: docs/getting-started/install-options.md -source_hash: 432e372bf9bb4729edf27df889d4e45526c87fc39b9baa43c9b0e16d3fa54036 +source_hash: d8df8f9bacd4a7ee2246ae0878d2139108a06079d0a6d0245f98a67972839b3e --- 本页是安装程序参数的参考,并说明如何用默认方式以外的方式安装:在已有反向代理之后、在托管平台上使用 Docker Compose,或在无法访问互联网的主机上。[默认安装](./install.md)无需任何选项。 @@ -84,7 +84,7 @@ docker compose exec web oac-web core-key 安装程序使用当前 shell 的网络设置(包括 `HTTPS_PROXY`)从 GitHub Releases 下载发行文件。Docker 通过其守护进程拉取镜像,守护进程不读取 shell 的代理变量。所有镜像(包括 PostgreSQL)都来自 GHCR(`ghcr.io`),不需要 Docker Hub。如果只能经代理或镜像加速器访问 GHCR,请配置[守护进程代理](https://docs.docker.com/engine/daemon/proxy/)或[镜像加速器](https://docs.docker.com/docker-hub/image-library/mirror/),然后重新运行安装程序。 -无法访问这些地址的 Linux amd64 主机可使用发行资产 `oac--linux-amd64-offline.tar.gz` 安装,其中包含所有镜像和节点制品。将其复制到该主机并解压,然后用 Python 3.9 或更高版本和 Docker 运行其中的 `install.py`。该主机上不需要检出代码、Go、Node 或 pnpm。安装完成前请保留解压后的安装包;之后已安装的服务和节点下载不再依赖它原来的位置。[开发 OpenAgentCore](../development.md#install-a-checkout-without-publishing-a-release)从检出代码构建的就是同一个归档。 +无法访问这些地址的 Linux amd64 主机可使用发行资产 `oac--linux-amd64-offline.tar.gz` 安装,其中包含所有镜像、节点制品和 Linux amd64 自托管安装程序。macOS 和 Windows 上的自托管机器从 GitHub Releases 下载各自的安装程序。将其复制到该主机并解压,然后用 Python 3.9 或更高版本和 Docker 运行其中的 `install.py`。该主机上不需要检出代码、Go、Node 或 pnpm。安装完成前请保留解压后的安装包;之后已安装的服务和节点下载不再依赖它原来的位置。[开发 OpenAgentCore](../development.md#install-a-checkout-without-publishing-a-release)从检出代码构建的就是同一个归档。 ### `install.py` 选项 {#install-py-options} diff --git a/docs/zh/getting-started/self-hosted.md b/docs/zh/getting-started/self-hosted.md index 6fc451246..34591f2dd 100644 --- a/docs/zh/getting-started/self-hosted.md +++ b/docs/zh/getting-started/self-hosted.md @@ -1,7 +1,7 @@ --- title: "运行自托管 Session" source: docs/getting-started/self-hosted.md -source_hash: 01c815bcb2a5c7c9eee05574e949cd391a0188be8dc5b3fcfdc84c828071134e +source_hash: ed3a04fb0421631c5633fc1b46d455d2c50c77d696bab09855b19d1c6d8ee92f --- `self_hosted` Session 在应用拥有的机器上运行,例如工作站、虚拟机或容器,而不是 Core 管理的沙箱。本指南面向用 `oac-daemon` 连接此类机器并保持其运行的应用开发者。 @@ -34,7 +34,7 @@ Session 自带模型提供商;安装默认模型不适用([原因](../../../ 机器需要: -- 通过 HTTP 或 HTTPS 访问 Core,以及访问发布下载主机;如果 Core 已有安装程序的离线副本,则无需后者; +- 通过 HTTP 或 HTTPS 访问 Core,以及访问发布下载主机;如果 Core 已有本平台安装程序的离线副本,则无需后者(离线安装只带有 Linux amd64 的安装程序); - 用于环境设置和 MiniMax Code 工具的 Bash;Windows 上需要 Git Bash,Claude Code 也要求它; - Session 的软件包需要时,安装 Python 和 pip; - 环境设置所需的系统软件包。守护进程不运行 apt、sudo 或其他提权命令,请通过主机的常规管理方式安装。 diff --git a/docs/zh/maintainers.md b/docs/zh/maintainers.md index e3e4ab639..101cd5613 100644 --- a/docs/zh/maintainers.md +++ b/docs/zh/maintainers.md @@ -1,7 +1,7 @@ --- title: "构建并发布 OpenAgentCore" source: docs/maintainers.md -source_hash: 16d591f49202d2f08b26e296ceccbaed72dfe6f706658cef6a11238de1f78d7c +source_hash: 0180ec977dbb3efee2d1af237420d133ca972426cf8d3b873b80ca45a4387e4c --- 本指南面向负责构建和发布 OpenAgentCore 的维护者。要安装 Core 和 Web,请按 [安装 Core 和 Web](getting-started/install.md) 操作。安装程序代码遵循的规则见 [部署](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/deploy/README.md) 和 [节点安装程序](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/deploy/node/README.md);必需检查见 [CONTRIBUTING](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/CONTRIBUTING.md#required-checks)。 @@ -56,7 +56,7 @@ node scripts/build-native-catalog.mjs INPUT_DIR OUTPUT_DIR export OAC_NATIVE_INSTALLER_BUILD_DIR=OUTPUT_DIR ``` -该目录会记录提交、Runtime 协议版本、每个归档的 SHA-256,并在提供发布基址时记录其带版本号的 URL。控制归档和 Core 镜像仅携带 `native-installers/catalog.json`;这些归档会成为独立的 `oac-native--.tar.gz` 发布资源,离线归档则会在 Core 镜像之外为每个平台保留一份副本,由其 `install.py` 复制到安装目录中供 Core 提供下载。如果没有目录,Sessions 会将安装命令报告为不可用,并且发布工作流会拒绝发布。 +该目录会记录提交、Runtime 协议版本、每个归档的 SHA-256,并在提供发布基址时记录其带版本号的 URL。控制归档和 Core 镜像仅携带 `native-installers/catalog.json`;这些归档会成为独立的 `oac-native--.tar.gz` 发布资源,离线归档则会在 Core 镜像之外保留 Linux amd64 归档的一份副本,由其 `install.py` 复制到安装目录中供 Core 提供下载。其他平台由 Core 重定向到对应的发布资源;没有发布基址的目录没有这类 URL,因此其离线归档会保留所有归档。如果没有目录,Sessions 会将安装命令报告为不可用,并且发布工作流会拒绝发布。 ### Runtime 镜像和辅助程序 {#runtime-images-and-helpers} diff --git a/scripts/core-distribution-manifest.py b/scripts/core-distribution-manifest.py index 18d0ec015..7aa2b3857 100644 --- a/scripts/core-distribution-manifest.py +++ b/scripts/core-distribution-manifest.py @@ -265,14 +265,16 @@ def native_catalog(bundle, stage, revision, source, artifact_base_url=""): def native_offline(bundle, stage): + """Carry the offline host's own platform; Core redirects the others to their release URL.""" bundle, stage = pathlib.Path(bundle), pathlib.Path(stage) path = bundle / "native-installers/catalog.json" if not path.exists(): return catalog = json.loads(path.read_text()) - for platform in catalog["artifacts"]: - source = stage / "native-artifacts" / f"oac-native-{catalog['version']}-{platform}.tar.gz" - os.link(source, path.parent / (platform + ".tar.gz")) + for platform, entry in catalog["artifacts"].items(): + if platform == "linux-amd64" or "url" not in entry: + source = stage / "native-artifacts" / f"oac-native-{catalog['version']}-{platform}.tar.gz" + os.link(source, path.parent / (platform + ".tar.gz")) @contextmanager diff --git a/scripts/core-distribution-manifest.test.py b/scripts/core-distribution-manifest.test.py index cb4b78ce8..4f2ec7901 100644 --- a/scripts/core-distribution-manifest.test.py +++ b/scripts/core-distribution-manifest.test.py @@ -51,7 +51,7 @@ def descriptor(data, media_type, label): class DistributionTests(unittest.TestCase): - def test_native_payload_is_independent_and_offline_has_one_copy(self): + def test_native_payload_is_independent_and_offline_has_only_linux(self): source = self.stage / "qualified-native" source.mkdir() catalog = {"version": REVISION, "protocol_version": "fixture", "artifacts": {}} @@ -74,16 +74,27 @@ def test_native_payload_is_independent_and_offline_has_one_copy(self): distribution.archive(self.bundle, "1", "offline") with tarfile.open(self.bundle.with_name(self.bundle.name + "-offline.tar.gz")) as archive: native = [p for p in archive.getmembers() if "native-installers/" in p.name and p.name.endswith(".tar.gz")] - self.assertEqual(len(native), 3) - for member in native: - platform = pathlib.Path(member.name).name.removesuffix(".tar.gz") - self.assertEqual(archive.extractfile(member).read(), (source / (platform + ".tar.gz")).read_bytes()) + self.assertEqual([pathlib.Path(p.name).name for p in native], ["linux-amd64.tar.gz"]) + self.assertEqual(archive.extractfile(native[0]).read(), (source / "linux-amd64.tar.gz").read_bytes()) metadata = json.loads((self.bundle / "native-installers/catalog.json").read_text()) for platform, entry in metadata["artifacts"].items(): filename = f"oac-native-{REVISION}-{platform}.tar.gz" self.assertEqual(entry["url"], RELEASE_BASE + "/" + filename) self.assertEqual(distribution.sha256(self.stage / "native-artifacts" / filename), entry["sha256"]) + def test_offline_without_release_urls_keeps_every_native_installer(self): + source = self.stage / "qualified-native" + source.mkdir() + catalog = {"version": REVISION, "protocol_version": "fixture", "artifacts": {}} + for platform in ("linux-amd64", "darwin-arm64", "windows-amd64"): + (source / (platform + ".tar.gz")).write_bytes(platform.encode()) + catalog["artifacts"][platform] = {"sha256": hashlib.sha256(platform.encode()).hexdigest()} + (source / "catalog.json").write_text(json.dumps(catalog)) + distribution.native_catalog(self.bundle, self.stage, REVISION, source) + distribution.native_offline(self.bundle, self.stage) + self.assertEqual(sorted(p.name for p in (self.bundle / "native-installers").iterdir()), + ["catalog.json", "darwin-arm64.tar.gz", "linux-amd64.tar.gz", "windows-amd64.tar.gz"]) + def setUp(self): self.temporary = tempfile.TemporaryDirectory() self.addCleanup(self.temporary.cleanup)