Skip to content

Commit 1aaf487

Browse files
committed
build synchronized macOS Electron releases
1 parent 80156fc commit 1aaf487

9 files changed

Lines changed: 228 additions & 31 deletions

File tree

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
name: Release macOS
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
tag:
7+
description: Existing GitHub release tag
8+
required: true
9+
default: v0.9.0-preview.29
10+
11+
permissions:
12+
contents: write
13+
14+
jobs:
15+
build:
16+
name: Build macOS ${{ matrix.arch }}
17+
runs-on: macos-latest
18+
strategy:
19+
fail-fast: false
20+
matrix:
21+
arch:
22+
- arm64
23+
- x64
24+
25+
steps:
26+
- name: Check out source
27+
uses: actions/checkout@v4
28+
29+
- name: Set up .NET
30+
uses: actions/setup-dotnet@v4
31+
with:
32+
dotnet-version: 8.0.x
33+
34+
- name: Set up Node.js
35+
uses: actions/setup-node@v4
36+
with:
37+
node-version: 22
38+
cache: npm
39+
cache-dependency-path: NovaDesktop.Electron/package-lock.json
40+
41+
- name: Install Electron dependencies
42+
working-directory: NovaDesktop.Electron
43+
run: npm ci
44+
45+
- name: Build renderer
46+
working-directory: NovaDesktop.Electron
47+
run: npm run build:renderer
48+
49+
- name: Publish AgentOS bridge
50+
shell: bash
51+
run: |
52+
rm -rf NovaDesktop.Electron/resources/bridge
53+
dotnet publish Nova.AgentOS.Bridge/Nova.AgentOS.Bridge.csproj \
54+
--configuration Release \
55+
--runtime "osx-${{ matrix.arch }}" \
56+
--self-contained true \
57+
-p:PublishSingleFile=false \
58+
--output NovaDesktop.Electron/resources/bridge
59+
test -x NovaDesktop.Electron/resources/bridge/Nova.AgentOS.Bridge
60+
61+
- name: Package Electron application
62+
working-directory: NovaDesktop.Electron
63+
env:
64+
CSC_IDENTITY_AUTO_DISCOVERY: "false"
65+
run: >-
66+
npx electron-builder
67+
--mac zip
68+
--${{ matrix.arch }}
69+
--config.directories.output=dist-electron-mac
70+
71+
- name: Verify application payload
72+
working-directory: NovaDesktop.Electron
73+
shell: bash
74+
run: |
75+
package="$(find dist-electron-mac -maxdepth 1 -name '*.zip' -print -quit)"
76+
test -n "$package"
77+
unzip -Z1 "$package" | grep -q 'NOVA AgentOS.app/Contents/MacOS/NOVA AgentOS'
78+
unzip -Z1 "$package" | grep -q 'NOVA AgentOS.app/Contents/Resources/bridge/Nova.AgentOS.Bridge'
79+
shasum -a 256 "$package"
80+
81+
- name: Upload workflow artifact
82+
uses: actions/upload-artifact@v4
83+
with:
84+
name: NOVA-AgentOS-mac-${{ matrix.arch }}
85+
path: NovaDesktop.Electron/dist-electron-mac/*.zip
86+
if-no-files-found: error
87+
88+
publish:
89+
name: Publish macOS assets
90+
needs: build
91+
runs-on: ubuntu-latest
92+
93+
steps:
94+
- name: Download macOS packages
95+
uses: actions/download-artifact@v4
96+
with:
97+
pattern: NOVA-AgentOS-mac-*
98+
path: release-assets
99+
merge-multiple: true
100+
101+
- name: Upload packages to GitHub Release
102+
env:
103+
GH_TOKEN: ${{ github.token }}
104+
GH_REPO: ${{ github.repository }}
105+
run: gh release upload "${{ inputs.tag }}" release-assets/*.zip --clobber

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
### Added
88

99
- Electron / React 主交互壳与 .NET 8 AgentOS Bridge;
10+
- Windows 与 macOS 共用 Electron UI、跨平台 AgentOS Bridge/Core,并提供 macOS arm64/x64 原生构建流水线;
1011
- OpenAI、DeepSeek、Kimi、Ollama 与兼容模型端点;
1112
- 输入附件、图片理解、Markdown 渲染与多轮 Threadspace;
1213
- Ask、Plan、Build、Autopilot、Goal 模式;
@@ -25,6 +26,6 @@
2526
### Known limitations
2627

2728
- Preview 未签名,自动更新关闭;
28-
- Mac Preview 未完成签名、公证和 Windows 功能对等
29+
- Mac Preview 未完成 Developer ID 签名、公证和 macOS 原生桌面控制
2930
- 复杂编码质量仍依赖底层模型、上下文编译和工具链成熟度;
3031
- 1.0 GA 所需的 30×3 真实端到端基准尚未完成。
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<OutputType>Exe</OutputType>
4-
<TargetFramework>net8.0-windows</TargetFramework>
4+
<TargetFramework>net8.0</TargetFramework>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77
<AssemblyName>Nova.AgentOS.Bridge</AssemblyName>
88
<RootNamespace>Nova.AgentOS.Bridge</RootNamespace>
99
<Version>0.9.0-preview.29</Version>
1010
</PropertyGroup>
1111
<ItemGroup>
12-
<ProjectReference Include="..\NovaDesktop\NovaDesktop.csproj" />
12+
<ProjectReference Include="..\Nova.AgentOS\Nova.AgentOS.csproj" />
1313
</ItemGroup>
1414
</Project>

Nova.AgentOS/Nova.AgentOS.csproj

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,7 @@
1111
</PropertyGroup>
1212

1313
<ItemGroup>
14-
<Compile Include="..\NovaDesktop\Models\ActivityEntry.cs" Link="Models\ActivityEntry.cs" />
15-
<Compile Include="..\NovaDesktop\Models\AgentInputAttachment.cs" Link="Models\AgentInputAttachment.cs" />
16-
<Compile Include="..\NovaDesktop\Models\AgentOsModels.cs" Link="Models\AgentOsModels.cs" />
17-
<Compile Include="..\NovaDesktop\Models\AgentSupervisorModels.cs" Link="Models\AgentSupervisorModels.cs" />
18-
<Compile Include="..\NovaDesktop\Models\TaskFailureModels.cs" Link="Models\TaskFailureModels.cs" />
19-
<Compile Include="..\NovaDesktop\Models\TaskItem.cs" Link="Models\TaskItem.cs" />
20-
21-
<Compile Include="..\NovaDesktop\Services\AgentExecutionPolicy.cs" Link="Services\AgentExecutionPolicy.cs" />
22-
<Compile Include="..\NovaDesktop\Services\AgentOsKernel.cs" Link="Services\AgentOsKernel.cs" />
23-
<Compile Include="..\NovaDesktop\Services\AgentResourceGovernor.cs" Link="Services\AgentResourceGovernor.cs" />
24-
<Compile Include="..\NovaDesktop\Services\AgentRuntimeContracts.cs" Link="Services\AgentRuntimeContracts.cs" />
25-
<Compile Include="..\NovaDesktop\Services\AgentSupervisorService.cs" Link="Services\AgentSupervisorService.cs" />
26-
<Compile Include="..\NovaDesktop\Services\AgentTaskGraphService.cs" Link="Services\AgentTaskGraphService.cs" />
27-
<Compile Include="..\NovaDesktop\Services\NovaProductVersion.cs" Link="Services\NovaProductVersion.cs" />
28-
<Compile Include="..\NovaDesktop\Services\SideEffectReceiptService.cs" Link="Services\SideEffectReceiptService.cs" />
29-
<Compile Include="..\NovaDesktop\Services\TaskFailureService.cs" Link="Services\TaskFailureService.cs" />
30-
<Compile Include="..\NovaDesktop\Services\TaskJournalService.cs" Link="Services\TaskJournalService.cs" />
31-
<Compile Include="..\NovaDesktop\Services\TaskSnapshotService.cs" Link="Services\TaskSnapshotService.cs" />
14+
<Compile Include="..\NovaDesktop\Models\*.cs" Link="Models\%(Filename)%(Extension)" />
15+
<Compile Include="..\NovaDesktop\Services\*.cs" Link="Services\%(Filename)%(Extension)" />
3216
</ItemGroup>
3317
</Project>

NovaDesktop.Electron/electron/main.cjs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,12 @@ class BridgeClient {
3636
start() {
3737
if (this.process) return;
3838

39+
const bridgeExecutable =
40+
process.platform === "win32"
41+
? "Nova.AgentOS.Bridge.exe"
42+
: "Nova.AgentOS.Bridge";
3943
const executable = app.isPackaged
40-
? path.join(process.resourcesPath, "bridge", "Nova.AgentOS.Bridge.exe")
44+
? path.join(process.resourcesPath, "bridge", bridgeExecutable)
4145
: "dotnet";
4246
const args = app.isPackaged
4347
? []
@@ -62,7 +66,7 @@ class BridgeClient {
6266
}
6367

6468
this.process = spawn(executable, args, {
65-
windowsHide: true,
69+
windowsHide: process.platform === "win32",
6670
stdio: ["pipe", "pipe", "pipe"]
6771
});
6872

NovaDesktop.Electron/package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"build": "npm run build:renderer && npm run build:bridge",
1414
"package:win": "npm run build && electron-builder --win dir",
1515
"package:win:zip": "npm run build && electron-builder --win zip",
16+
"package:mac": "node scripts/build-mac.mjs",
1617
"smoke": "electron . --smoke",
1718
"smoke:bridge": "node scripts/smoke-bridge.mjs"
1819
},
@@ -67,6 +68,19 @@
6768
}
6869
],
6970
"artifactName": "NOVA-AgentOS-Electron-${version}-${arch}.${ext}"
71+
},
72+
"mac": {
73+
"category": "public.app-category.developer-tools",
74+
"target": [
75+
{
76+
"target": "zip",
77+
"arch": [
78+
"arm64",
79+
"x64"
80+
]
81+
}
82+
],
83+
"artifactName": "NOVA-AgentOS-Electron-${version}-mac-${arch}.${ext}"
7084
}
7185
}
7286
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { existsSync, mkdirSync, rmSync } from "node:fs";
2+
import { dirname, join, resolve } from "node:path";
3+
import { fileURLToPath } from "node:url";
4+
import { spawnSync } from "node:child_process";
5+
6+
if (process.platform !== "darwin") {
7+
throw new Error(
8+
"macOS application bundles must be built on macOS. Run the Release macOS GitHub Actions workflow."
9+
);
10+
}
11+
12+
const scriptRoot = dirname(fileURLToPath(import.meta.url));
13+
const projectRoot = resolve(scriptRoot, "..");
14+
const repositoryRoot = resolve(projectRoot, "..");
15+
const bridgeProject = join(
16+
repositoryRoot,
17+
"Nova.AgentOS.Bridge",
18+
"Nova.AgentOS.Bridge.csproj"
19+
);
20+
const bridgeOutput = join(projectRoot, "resources", "bridge");
21+
const packageOutput = join(projectRoot, "dist-electron-mac");
22+
const builder = join(
23+
projectRoot,
24+
"node_modules",
25+
".bin",
26+
"electron-builder"
27+
);
28+
29+
function run(command, args, cwd = projectRoot) {
30+
const result = spawnSync(command, args, {
31+
cwd,
32+
stdio: "inherit",
33+
env: {
34+
...process.env,
35+
CSC_IDENTITY_AUTO_DISCOVERY: "false"
36+
}
37+
});
38+
if (result.error) throw result.error;
39+
if (result.status !== 0) {
40+
throw new Error(`${command} failed with exit code ${result.status}.`);
41+
}
42+
}
43+
44+
if (!existsSync(builder)) {
45+
throw new Error("electron-builder is not installed. Run npm install first.");
46+
}
47+
48+
run("npm", ["run", "build:renderer"]);
49+
50+
for (const architecture of ["arm64", "x64"]) {
51+
rmSync(bridgeOutput, { recursive: true, force: true });
52+
mkdirSync(bridgeOutput, { recursive: true });
53+
54+
run("dotnet", [
55+
"publish",
56+
bridgeProject,
57+
"--configuration",
58+
"Release",
59+
"--runtime",
60+
`osx-${architecture}`,
61+
"--self-contained",
62+
"true",
63+
"-p:PublishSingleFile=false",
64+
"--output",
65+
bridgeOutput
66+
]);
67+
68+
const bridgeExecutable = join(bridgeOutput, "Nova.AgentOS.Bridge");
69+
if (!existsSync(bridgeExecutable)) {
70+
throw new Error(`AgentOS bridge publish did not produce ${bridgeExecutable}.`);
71+
}
72+
73+
run(builder, [
74+
"--mac",
75+
"zip",
76+
`--${architecture}`,
77+
`--config.directories.output=${packageOutput}`
78+
]);
79+
}
80+
81+
console.log(`macOS packages ready: ${packageOutput}`);

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@ flowchart LR
5757
Fabric --> Truth
5858
```
5959

60-
当前 Electron 是主要交互验证壳,复用 `.NET 8` AgentOS Bridge/Core。仓库仍保留成熟的 WPF Windows 实现和独立 Avalonia Mac Preview;1.0 前需要冻结正式桌面主线和迁移边界,避免长期形成两套状态真值
60+
当前 Electron 是 Windows 与 macOS 共用的主要交互壳,复用同一套跨平台 `.NET 8` AgentOS Bridge/Core。仓库仍保留成熟的 WPF Windows 实现和早期 Avalonia Mac Preview,作为迁移与回归参考
6161

6262
## 快速开始
6363

6464
### 环境
6565

66-
- Windows 10/11 x64
66+
- Windows 10/11 x64,或 macOS 13+
6767
- .NET 8 SDK
6868
- Node.js 20+
6969
- PowerShell 7 或 Windows PowerShell 5.1
@@ -76,6 +76,14 @@ npm ci
7676
npm run build
7777
```
7878

79+
在 macOS 上构建 Apple Silicon 与 Intel 发布包:
80+
81+
```bash
82+
cd NovaDesktop.Electron
83+
npm ci
84+
npm run package:mac
85+
```
86+
7987
### 启动开发环境
8088

8189
```powershell
@@ -123,7 +131,7 @@ Ollama 与自定义兼容端点可配置 Base URL。本地和局域网地址允
123131
|---|---|---|
124132
| Windows Electron x64 | 主体验 Preview | 连接 .NET 8 AgentOS Bridge/Core |
125133
| Windows WPF x64 | 成熟参考实现 | 功能较完整,保留用于服务与迁移验证 |
126-
| macOS arm64 / x64 | 独立 Preview | 未签名、未公证,尚未与 Windows 功能完全对等 |
134+
| macOS Electron arm64 / x64 | 同步体验 Preview | 与 Windows 共用 Electron UI 和 AgentOS Bridge/Core;未签名、未公证,Windows 专属桌面控制能力除外 |
127135

128136
## 项目结构
129137

@@ -134,7 +142,7 @@ Ollama 与自定义兼容端点可配置 Base URL。本地和局域网地址允
134142
| `NovaDesktop` | WPF 壳与主要服务实现 |
135143
| `Nova.AgentOS` | Kernel、Supervisor、任务图和治理模型 |
136144
| `Nova.Core` | 跨平台基础模型与 Provider 协议 |
137-
| `NovaDesktop.Mac` | Avalonia Mac Preview |
145+
| `NovaDesktop.Mac` | 早期 Avalonia Mac Preview,保留用于迁移参考 |
138146
| `NovaDesktop.SmokeTests` | AgentOS 自动烟雾测试 |
139147
| `ga` / `tools` | GA 基准、验证和发布工具 |
140148

RELEASE_NOTES.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55
## 下载选择
66

77
- `NOVA-AgentOS-Electron-0.9.0-preview.29-...-win-x64.zip`:Windows x64 Electron 主体验;
8-
- `NOVA-Mac-0.1.0-preview.4-osx-arm64.zip`:Apple Silicon Mac Preview
9-
- `NOVA-Mac-0.1.0-preview.4-osx-x64.zip`:Intel Mac Preview
8+
- `NOVA-AgentOS-Electron-0.9.0-preview.29-mac-arm64.zip`:Apple Silicon Electron 主体验
9+
- `NOVA-AgentOS-Electron-0.9.0-preview.29-mac-x64.zip`:Intel Electron 主体验
1010
- 项目介绍 PPT 与项目说明书:产品、架构和 1.0 发布边界。
1111

1212
## 重要说明
1313

1414
- 所有安装包当前均未签名;
1515
- Windows 自动更新默认关闭;
16-
- Mac 构建为跨平台打包的 Preview,未完成 Developer ID 签名与 Apple 公证
17-
- Mac 版本尚未与 Windows 功能完全对等
16+
- Mac 构建由 macOS 原生 CI 生成,与 Windows 共用 Electron UI 和 AgentOS Bridge/Core
17+
- Mac 包尚未完成 Developer ID 签名与 Apple 公证,Windows 专属桌面控制能力不可用
1818
- 请只从本仓库 Release 页面下载,并核对发布页面上的 SHA-256。
1919

2020
## 主要能力

0 commit comments

Comments
 (0)