Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .claude/scripts/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,11 +256,14 @@ def generate(args):
from datetime import date
today = date.today().isoformat()

report_url = (args.report_url or "").strip() or update_url.rstrip('/').rstrip('/check').rstrip('/Verification').rstrip('/') + "/Report"

bowl_lower = "yes" if with_bowl else "no"
variables = {
"PROJECT_NAME": project_name,
"APP_SECRET_KEY": app_secret,
"UPDATE_URL": update_url,
"REPORT_URL": report_url,
"CLIENT_VERSION": version,
"PRODUCT_ID": product_id,
"STRATEGY": strategy,
Expand Down Expand Up @@ -329,6 +332,7 @@ def generate(args):
help="Project name (default: MyApp)")
parser.add_argument("--app-secret-key", help="AppSecretKey (min 32 chars)")
parser.add_argument("--update-url", help="Update API URL")
parser.add_argument("--report-url", help="Report API URL (default: derived from update-url)")
parser.add_argument("--version", "-v", default="1.0.0.0",
help="Client version (default: 1.0.0.0)")
parser.add_argument("--product-id", help="Product ID (default: <project-name>-001)")
Expand Down
19 changes: 8 additions & 11 deletions .claude/scripts/generate/templates/Bootstrap.cs.template
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
using GeneralUpdate.Core;
using GeneralUpdate.Core.Configuration;
using GeneralUpdate.Core.Event;
using GeneralUpdate.Core.Download;

var config = new UpdateRequest
// Only 3 secrets needed in code. Identity fields (MainAppName, ClientVersion,
// ProductId, etc.) are auto-discovered from generalupdate.manifest.json.
var request = new UpdateRequest
{
// === 必需 ===
UpdateUrl = "{{UPDATE_URL}}",
UpdateUrl = "{{UPDATE_URL}}",
ReportUrl = "{{REPORT_URL}}",
AppSecretKey = "{{APP_SECRET_KEY}}",
MainAppName = "{{PROJECT_NAME}}.exe",
ClientVersion = "{{CLIENT_VERSION}}",
ProductId = "{{PRODUCT_ID}}",
InstallPath = {{INSTALL_PATH}},
{{#BOWL}}
// Bowl 配置(仅包含 GeneralUpdate.Bowl 包,不重复添加 Core)
{{/BOWL}}
};

{{STRATEGY_WARNING}}
{{BOWL_NOTICE}}
await new GeneralUpdateBootstrap()
.SetConfig(config)
.SetConfig(request)
.SetOption(Option.AppType, AppType.Client)
{{LISTENERS}}
.LaunchAsync();
20 changes: 17 additions & 3 deletions .claude/scripts/generate/templates/UpgradeProgram.cs.template
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
using GeneralUpdate.Core;
using GeneralUpdate.Core.Configuration;
using GeneralUpdate.Core.Event;

// Upgrade 进程入口 — 从 IPC 文件读取配置,无需 SetConfig
// 注意: Upgrade 项目的 AppType 设为 2 (UpgradeApp)
// ================================================================
// Upgrade — standalone upgrade process
// No SetConfig() needed — parameters come via encrypted IPC from Client
// ================================================================

await new GeneralUpdateBootstrap()
.SetOption(Option.AppType, AppType.Upgrade)
.AddListenerMultiDownloadStatistics((_, e) =>
{
System.Console.WriteLine($"\rApplying: {e.ProgressPercentage:F0}%");
})
.AddListenerMultiDownloadCompleted((_, e) =>
{
System.Console.WriteLine();
System.Console.WriteLine($"Patch {(e.IsCompleted ? "✓ done" : "✗ failed")}");
})
.AddListenerException((_, e) =>
{
System.Console.Error.WriteLine($"升级错误: {e.Message}");
System.Console.Error.WriteLine($"Error: {e.Exception.Message}");
})
.LaunchAsync();
4 changes: 2 additions & 2 deletions .claude/scripts/generate/templates/manifest.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"mainAppName": "{{PROJECT_NAME}}.exe",
"updateAppName": "Upgrade{{PROJECT_NAME}}.exe",
"updatePath": "./update/",
"appType": 1,
"version": "{{CLIENT_VERSION}}",
"appType": "Client",
"clientVersion": "{{CLIENT_VERSION}}",
"productId": "{{PRODUCT_ID}}"
}
14 changes: 7 additions & 7 deletions .claude/skills/generalupdate-init/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: generalupdate-init
description: |
Integrate GeneralUpdate auto-update into any .NET application. Generates Bootstrap
configuration code, manifest files, and dual-project (Client+Upgrade) scaffolding.
Covers 4 update scenes, Configinfo configuration, appsettings.json, HTTP auth (HMAC/Basic/Bearer),
Covers 4 update scenes, UpdateRequest configuration, appsettings.json, HTTP auth (HMAC/Basic/Bearer),
and complete deployment checklist. Triggers on: "add auto update", "integrate GeneralUpdate",
"configure bootstrap", "我需要自动更新", "配置更新", "初始化GeneralUpdate", "添加更新功能",
"接入更新", "升级框架". Also triggers when user mentions their project type + update.
Expand All @@ -13,7 +13,7 @@ when_to_use: |
- First-time integration of GeneralUpdate into a .NET project
- User wants Bootstrap configuration code (Minimal or Full)
- User needs the Client + Upgrade dual-project structure explained
- User asks about manifest.json, Configinfo, or generalupdate.manifest.json
- User asks about manifest.json, UpdateRequest, or generalupdate.manifest.json
- User mentions their specific .NET framework (WPF/WinForms/Avalonia/MAUI/console)
- User asks about deployment considerations or CI/CD integration
- Best used as the entry point; guide to other skills as needed
Expand Down Expand Up @@ -47,7 +47,7 @@ allowed-tools: "Bash, Read, Write, Edit, Glob, Grep, WebSearch"

### 已有配置(如果存在)
- 是否已安装 NuGet: ______(是/否,版本号)
- 是否已有 Configinfo 配置: ______(是/否)
- 是否已有 UpdateRequest 配置: ______(是/否)
- 是否已有 manifest.json: ______(是/否)
```

Expand All @@ -60,7 +60,7 @@ allowed-tools: "Bash, Read, Write, Edit, Glob, Grep, WebSearch"
```
├── 检查 .csproj → 目标框架、UI 类型、是否有 NuGet 引用
├── 检查是否存在 generalupdate.manifest.json
├── 检查是否存在 Configinfo/Bootstrap 配置代码
├── 检查是否存在 UpdateRequest/Bootstrap 配置代码
└── 检查项目结构 → 是否已有独立的 Upgrade 项目
```

Expand All @@ -71,7 +71,7 @@ allowed-tools: "Bash, Read, Write, Edit, Glob, Grep, WebSearch"
| 模式 | 适用场景 | 产出 |
|------|---------|------|
| **[Minimal]** | 新用户快速上手,控制台/服务应用 | 3 行 Bootstrap 代码 |
| **[Standard]** | 需要精确控制更新过程 | Configinfo + 完整事件监听 |
| **[Standard]** | 需要精确控制更新过程 | UpdateRequest + 完整事件监听 |
| **[Scaffold]** | 团队项目,从零开始 | 完整 Client + Upgrade 双项目结构 |

### Step 3:生成输出
Expand Down Expand Up @@ -345,7 +345,7 @@ v10.5.0-beta.4 新增以下功能:
## ✅ 集成验证清单(交付前逐项检查)

### Bootstrap 配置
- [ ] `Configinfo` 的 6 个必填字段都已设置(UpdateUrl, AppSecretKey, AppName, MainAppName, ClientVersion, ProductId, InstallPath)
- [ ] `UpdateRequest` 的 6 个必填字段都已设置(UpdateUrl, AppSecretKey, MainAppName, ClientVersion, ProductId, InstallPath)
- [ ] `UpdateUrl` 指向的服务端 API 可正常返回版本信息
- [ ] `AppSecretKey` 长度 ≥ 16 字符,与服务端一致
- [ ] `AppType` 设置正确(Client = 1, Upgrade = 2)
Expand All @@ -358,7 +358,7 @@ v10.5.0-beta.4 新增以下功能:
- [ ] 无需额外引用 `GeneralUpdate.Differential`(已嵌入 Core)

### 部署结构
- [ ] UpgradeApp.exe 存在于发布目录(首个版本就必须有)
- [ ] UpgradeApp.exe 存在于发布目录 update/ 子目录中(首个版本就必须有)
- [ ] `generalupdate.manifest.json` 的 `UpdateAppName` 包含 `.exe`
- [ ] IPC 文件(`UpdateInfo.msg`)路径在 Client/Upgrade 间一致
- [ ] `Encoding` 设置为 `Encoding.UTF8`(防止 Linux/macOS 中文乱码)
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/generalupdate-troubleshoot/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ reference.md 中的问题按严重度分级:
- [ ] `AppType` 设置正确(Client = 1, Upgrade = 2)

### 配置检查
- [ ] `Configinfo` 的 6 个必填字段都已设置
- [ ] `UpdateRequest` 的 6 个必填字段都已设置
- [ ] `UpdateUrl` 可通过 HTTP GET 访问并返回合法 JSON
- [ ] `AppSecretKey` 与服务端配置一致(长度 ≥ 16 字符)
- [ ] UpgradeApp.exe 存在于发布目录的 `update/` 子目录中
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/generalupdate-ui/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ GeneralUpdateBootstrap.AddListenerException

### 事件桥接
- [ ] 所有 6 个事件都已绑定(UpdateInfo, MultiDownloadStatistics, MultiDownloadCompleted, MultiDownloadError, MultiAllDownloadCompleted, Exception)
- [ ] 桥接代码使用正确的 EventArgs 类型(检查命名空间 `GeneralUpdate.Common.Download`)
- [ ] `IsComplated` 注意拼写(v10.4.6 API 中的实际拼写,不是 `IsCompleted`)
- [ ] 桥接代码使用正确的 EventArgs 类型(检查命名空间 `GeneralUpdate.Core.Download` / `GeneralUpdate.Core.Event`)
- [ ] `IsCompleted` 属性名正确(v10.5.0-beta.4 使用 `IsCompleted`)

### 线程安全
- [ ] UI 更新操作在正确的线程上执行(WPF/Avalonia 用 `Dispatcher`,WinForms 用 `Invoke`,MAUI 用 `MainThread`)
Expand Down
4 changes: 4 additions & 0 deletions cli/assets/scripts/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,11 +256,14 @@ def generate(args):
from datetime import date
today = date.today().isoformat()

report_url = (args.report_url or "").strip() or update_url.rstrip('/').rstrip('/check').rstrip('/Verification').rstrip('/') + "/Report"

bowl_lower = "yes" if with_bowl else "no"
variables = {
"PROJECT_NAME": project_name,
"APP_SECRET_KEY": app_secret,
"UPDATE_URL": update_url,
"REPORT_URL": report_url,
"CLIENT_VERSION": version,
"PRODUCT_ID": product_id,
"STRATEGY": strategy,
Expand Down Expand Up @@ -329,6 +332,7 @@ def generate(args):
help="Project name (default: MyApp)")
parser.add_argument("--app-secret-key", help="AppSecretKey (min 32 chars)")
parser.add_argument("--update-url", help="Update API URL")
parser.add_argument("--report-url", help="Report API URL (default: derived from update-url)")
parser.add_argument("--version", "-v", default="1.0.0.0",
help="Client version (default: 1.0.0.0)")
parser.add_argument("--product-id", help="Product ID (default: <project-name>-001)")
Expand Down
19 changes: 8 additions & 11 deletions cli/assets/scripts/generate/templates/Bootstrap.cs.template
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
using GeneralUpdate.Core;
using GeneralUpdate.Core.Configuration;
using GeneralUpdate.Core.Event;
using GeneralUpdate.Core.Download;

var config = new UpdateRequest
// Only 3 secrets needed in code. Identity fields (MainAppName, ClientVersion,
// ProductId, etc.) are auto-discovered from generalupdate.manifest.json.
var request = new UpdateRequest
{
// === 必需 ===
UpdateUrl = "{{UPDATE_URL}}",
UpdateUrl = "{{UPDATE_URL}}",
ReportUrl = "{{REPORT_URL}}",
AppSecretKey = "{{APP_SECRET_KEY}}",
MainAppName = "{{PROJECT_NAME}}.exe",
ClientVersion = "{{CLIENT_VERSION}}",
ProductId = "{{PRODUCT_ID}}",
InstallPath = {{INSTALL_PATH}},
{{#BOWL}}
// Bowl 配置(仅包含 GeneralUpdate.Bowl 包,不重复添加 Core)
{{/BOWL}}
};

{{STRATEGY_WARNING}}
{{BOWL_NOTICE}}
await new GeneralUpdateBootstrap()
.SetConfig(config)
.SetConfig(request)
.SetOption(Option.AppType, AppType.Client)
{{LISTENERS}}
.LaunchAsync();
20 changes: 17 additions & 3 deletions cli/assets/scripts/generate/templates/UpgradeProgram.cs.template
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
using GeneralUpdate.Core;
using GeneralUpdate.Core.Configuration;
using GeneralUpdate.Core.Event;

// Upgrade 进程入口 — 从 IPC 文件读取配置,无需 SetConfig
// 注意: Upgrade 项目的 AppType 设为 2 (UpgradeApp)
// ================================================================
// Upgrade — standalone upgrade process
// No SetConfig() needed — parameters come via encrypted IPC from Client
// ================================================================

await new GeneralUpdateBootstrap()
.SetOption(Option.AppType, AppType.Upgrade)
.AddListenerMultiDownloadStatistics((_, e) =>
{
System.Console.WriteLine($"\rApplying: {e.ProgressPercentage:F0}%");
})
.AddListenerMultiDownloadCompleted((_, e) =>
{
System.Console.WriteLine();
System.Console.WriteLine($"Patch {(e.IsCompleted ? "✓ done" : "✗ failed")}");
})
.AddListenerException((_, e) =>
{
System.Console.Error.WriteLine($"升级错误: {e.Message}");
System.Console.Error.WriteLine($"Error: {e.Exception.Message}");
})
.LaunchAsync();
4 changes: 2 additions & 2 deletions cli/assets/scripts/generate/templates/manifest.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"mainAppName": "{{PROJECT_NAME}}.exe",
"updateAppName": "Upgrade{{PROJECT_NAME}}.exe",
"updatePath": "./update/",
"appType": 1,
"version": "{{CLIENT_VERSION}}",
"appType": "Client",
"clientVersion": "{{CLIENT_VERSION}}",
"productId": "{{PRODUCT_ID}}"
}
14 changes: 7 additions & 7 deletions cli/assets/skills/generalupdate-init/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: generalupdate-init
description: |
Integrate GeneralUpdate auto-update into any .NET application. Generates Bootstrap
configuration code, manifest files, and dual-project (Client+Upgrade) scaffolding.
Covers 4 update scenes, Configinfo configuration, appsettings.json, HTTP auth (HMAC/Basic/Bearer),
Covers 4 update scenes, UpdateRequest configuration, appsettings.json, HTTP auth (HMAC/Basic/Bearer),
and complete deployment checklist. Triggers on: "add auto update", "integrate GeneralUpdate",
"configure bootstrap", "我需要自动更新", "配置更新", "初始化GeneralUpdate", "添加更新功能",
"接入更新", "升级框架". Also triggers when user mentions their project type + update.
Expand All @@ -13,7 +13,7 @@ when_to_use: |
- First-time integration of GeneralUpdate into a .NET project
- User wants Bootstrap configuration code (Minimal or Full)
- User needs the Client + Upgrade dual-project structure explained
- User asks about manifest.json, Configinfo, or generalupdate.manifest.json
- User asks about manifest.json, UpdateRequest, or generalupdate.manifest.json
- User mentions their specific .NET framework (WPF/WinForms/Avalonia/MAUI/console)
- User asks about deployment considerations or CI/CD integration
- Best used as the entry point; guide to other skills as needed
Expand Down Expand Up @@ -47,7 +47,7 @@ allowed-tools: "Bash, Read, Write, Edit, Glob, Grep, WebSearch"

### 已有配置(如果存在)
- 是否已安装 NuGet: ______(是/否,版本号)
- 是否已有 Configinfo 配置: ______(是/否)
- 是否已有 UpdateRequest 配置: ______(是/否)
- 是否已有 manifest.json: ______(是/否)
```

Expand All @@ -60,7 +60,7 @@ allowed-tools: "Bash, Read, Write, Edit, Glob, Grep, WebSearch"
```
├── 检查 .csproj → 目标框架、UI 类型、是否有 NuGet 引用
├── 检查是否存在 generalupdate.manifest.json
├── 检查是否存在 Configinfo/Bootstrap 配置代码
├── 检查是否存在 UpdateRequest/Bootstrap 配置代码
└── 检查项目结构 → 是否已有独立的 Upgrade 项目
```

Expand All @@ -71,7 +71,7 @@ allowed-tools: "Bash, Read, Write, Edit, Glob, Grep, WebSearch"
| 模式 | 适用场景 | 产出 |
|------|---------|------|
| **[Minimal]** | 新用户快速上手,控制台/服务应用 | 3 行 Bootstrap 代码 |
| **[Standard]** | 需要精确控制更新过程 | Configinfo + 完整事件监听 |
| **[Standard]** | 需要精确控制更新过程 | UpdateRequest + 完整事件监听 |
| **[Scaffold]** | 团队项目,从零开始 | 完整 Client + Upgrade 双项目结构 |

### Step 3:生成输出
Expand Down Expand Up @@ -345,7 +345,7 @@ v10.5.0-beta.4 新增以下功能:
## ✅ 集成验证清单(交付前逐项检查)

### Bootstrap 配置
- [ ] `Configinfo` 的 6 个必填字段都已设置(UpdateUrl, AppSecretKey, AppName, MainAppName, ClientVersion, ProductId, InstallPath)
- [ ] `UpdateRequest` 的 6 个必填字段都已设置(UpdateUrl, AppSecretKey, MainAppName, ClientVersion, ProductId, InstallPath)
- [ ] `UpdateUrl` 指向的服务端 API 可正常返回版本信息
- [ ] `AppSecretKey` 长度 ≥ 16 字符,与服务端一致
- [ ] `AppType` 设置正确(Client = 1, Upgrade = 2)
Expand All @@ -358,7 +358,7 @@ v10.5.0-beta.4 新增以下功能:
- [ ] 无需额外引用 `GeneralUpdate.Differential`(已嵌入 Core)

### 部署结构
- [ ] UpgradeApp.exe 存在于发布目录(首个版本就必须有)
- [ ] UpgradeApp.exe 存在于发布目录 update/ 子目录中(首个版本就必须有)
- [ ] `generalupdate.manifest.json` 的 `UpdateAppName` 包含 `.exe`
- [ ] IPC 文件(`UpdateInfo.msg`)路径在 Client/Upgrade 间一致
- [ ] `Encoding` 设置为 `Encoding.UTF8`(防止 Linux/macOS 中文乱码)
Expand Down
2 changes: 1 addition & 1 deletion cli/assets/skills/generalupdate-troubleshoot/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ reference.md 中的问题按严重度分级:
- [ ] `AppType` 设置正确(Client = 1, Upgrade = 2)

### 配置检查
- [ ] `Configinfo` 的 6 个必填字段都已设置
- [ ] `UpdateRequest` 的 6 个必填字段都已设置
- [ ] `UpdateUrl` 可通过 HTTP GET 访问并返回合法 JSON
- [ ] `AppSecretKey` 与服务端配置一致(长度 ≥ 16 字符)
- [ ] UpgradeApp.exe 存在于发布目录的 `update/` 子目录中
Expand Down
4 changes: 2 additions & 2 deletions cli/assets/skills/generalupdate-ui/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ GeneralUpdateBootstrap.AddListenerException

### 事件桥接
- [ ] 所有 6 个事件都已绑定(UpdateInfo, MultiDownloadStatistics, MultiDownloadCompleted, MultiDownloadError, MultiAllDownloadCompleted, Exception)
- [ ] 桥接代码使用正确的 EventArgs 类型(检查命名空间 `GeneralUpdate.Common.Download`)
- [ ] `IsComplated` 注意拼写(v10.4.6 API 中的实际拼写,不是 `IsCompleted`)
- [ ] 桥接代码使用正确的 EventArgs 类型(检查命名空间 `GeneralUpdate.Core.Download` / `GeneralUpdate.Core.Event`)
- [ ] `IsCompleted` 属性名正确(v10.5.0-beta.4 使用 `IsCompleted`)

### 线程安全
- [ ] UI 更新操作在正确的线程上执行(WPF/Avalonia 用 `Dispatcher`,WinForms 用 `Invoke`,MAUI 用 `MainThread`)
Expand Down