refactor(toolchain)!: 工具链 plugindev 更名为 hmapdev,module path 改回 gitcode

- 目录 tools/plugindev → tools/hmapdev,可执行文件名/平台产物名同步
  (hmapdev_linux_amd64 等;包格式仍叫 .hmap)
- module path github.com/JianFeeeee/homeagent-sdk/tools/... → gitcode.com/...
  (与仓库实际托管一致;核心仓不依赖该 path,改动无外部影响)
- SDK 存储目录 ~/.homeagent/plugindev/sdk → ~/.homeagent/hmapdev/sdk
  新目录不存在而旧目录存在时沿用旧目录 → 已装 SDK 版本不会丢失
- 命令表/usage/--help/生成项目 README/示例 README/NSIS 安装器/
  package/build.sh/build-examples.sh 全部同步;PLUGINDEV 环境变量保留兼容
- sdk/ 目录零改动(公开接口不变)

验证:
- go build ./... ok;go test ./tools/hmapdev/ ok(含模板接线守卫 TestProcTemplate_CoversAllCoreMethods)
- bash -n package/{build,build-examples}.sh ok
- 端到端:hmapdev init demo && hmapdev build → dist/demo_bundle.hmap(linux+darwin)
- 本机安装 /usr/local/bin/hmapdev,旧名以软链保留;sdk list/current 正常
This commit is contained in:
JianFeeeee
2026-09-12 12:30:20 +08:00
parent 69ff3089a4
commit b237787c90
33 changed files with 135 additions and 122 deletions

View File

@ -25,8 +25,8 @@ HomeAgent 插件开发 SDK用于构建与 HomeAgent 平台交互的智能插
**1.1.x 插件升到 1.2.x接口纯追加但必须重编。** 公开接口没有签名变更(新增 **1.1.x 插件升到 1.2.x接口纯追加但必须重编。** 公开接口没有签名变更(新增
`InjectOptions` 与六个 `*Opts` 变体、`ChannelDef.ContextPolicy`),不调新能力就不受影响; `InjectOptions` 与六个 `*Opts` 变体、`ChannelDef.ContextPolicy`),不调新能力就不受影响;
但内核的**插件运行协议升到了 2**(统一共享内存区的 fd3 布局改变,**不支持滚动升级** 但内核的**插件运行协议升到了 2**(统一共享内存区的 fd3 布局改变,**不支持滚动升级**
所以 `plugin.bin` 必须用配套的 `plugindev` 重编后与内核**同批**安装——否则握手时协议版本 所以 `plugin.bin` 必须用配套的 `hmapdev` 重编后与内核**同批**安装——否则握手时协议版本
不匹配会被拒绝(错误信息会明确提示用配套 plugindev 重编,不会静默降级)。 不匹配会被拒绝(错误信息会明确提示用配套 hmapdev 重编,不会静默降级)。
## 注入行为与上下文裁剪1.2.0 ## 注入行为与上下文裁剪1.2.0
@ -284,18 +284,23 @@ func New(name string, sett SettingsAPI, regTool ToolRegistrar, regStage StageReg
插件开发者只需实现 `Plugin` 接口并导出 `NewPluginFactory()` 入口函数。 插件开发者只需实现 `Plugin` 接口并导出 `NewPluginFactory()` 入口函数。
## plugindev 工具链 ## hmapdev 工具链
`plugindev` 提供插件开发全流程支持。预编译二进制作为 **release 附件**分发linux/darwin/windows × amd64/arm64 `hmapdev` 提供插件开发全流程支持,最终产出 `.hmap` 插件包(工具名即来自该包格式)。
预编译二进制作为 **release 附件**分发linux/darwin/windows × amd64/arm64
[Releases](https://gitcode.com/JianFeeeee/homeagent-sdk/releases) 下载后加入 PATH 即可: [Releases](https://gitcode.com/JianFeeeee/homeagent-sdk/releases) 下载后加入 PATH 即可:
> 改名说明:工具链原名 `plugindev`,自 1.2.0 起更名 `hmapdev`。
> SDK 存储目录同时由 `~/.homeagent/plugindev/sdk` 迁到 `~/.homeagent/hmapdev/sdk`
> (旧目录会被自动沿用,不会丢已装版本)。
```bash ```bash
# 从 release 附件下载(以 v1.1.0 / linux amd64 为例) # 从 release 附件下载(以最新 SDK 发布 / linux amd64 为例)
curl -Lo plugindev https://gitcode.com/JianFeeeee/homeagent-sdk/releases/download/v1.1.0/plugindev_linux_amd64 curl -Lo hmapdev https://gitcode.com/JianFeeeee/homeagent-sdk/releases/download/<版本>/hmapdev_linux_amd64
chmod +x plugindev chmod +x hmapdev
# 或从源码自己编 # 或从源码自己编
cd tools/plugindev && go build -o plugindev . cd tools/hmapdev && go build -o hmapdev .
``` ```
> 二进制不再随仓库分发(旧的 `bin/` 目录已停用5 个平台各 26-28MB > 二进制不再随仓库分发(旧的 `bin/` 目录已停用5 个平台各 26-28MB
@ -303,11 +308,11 @@ cd tools/plugindev && go build -o plugindev .
| 命令 | 说明 | | 命令 | 说明 |
|------|------| |------|------|
| `plugindev init <name> [--lua]` | 初始化插件项目(生成 plg.json、plugin.go 或 main.lua、go.mod、README.md | | `hmapdev init <name> [--lua]` | 初始化插件项目(生成 plg.json、plugin.go 或 main.lua、go.mod、README.md |
| `plugindev build [flags]` | 编译并打包为 `.hmap` 包(支持跨平台编译和 bundle 模式) | | `hmapdev build [flags]` | 编译并打包为 `.hmap` 包(支持跨平台编译和 bundle 模式) |
| `plugindev clean` | 清理 `build/``dist/` 目录及生成文件plugin.json、z_bridge_gen.go | | `hmapdev clean` | 清理 `build/``dist/` 目录及生成文件plugin.json、z_bridge_gen.go |
| `plugindev debug [dir]` | 通过 Yaegi Go 解释器加载插件源码,启动交互式 REPL 调试 | | `hmapdev debug [dir]` | 通过 Yaegi Go 解释器加载插件源码,启动交互式 REPL 调试 |
| `plugindev sdk <command>` | SDK 版本管理子命令list/install/use/path/current/latest | | `hmapdev sdk <command>` | SDK 版本管理子命令list/install/use/path/current/latest |
支持 **Go****Lua** 两种插件语言。 支持 **Go****Lua** 两种插件语言。
@ -414,7 +419,7 @@ return plugin
- `sdk.RegisterOnRemoveHandler(fn func())` — 注册删除清理回调。内核在 `RemovePlugin` 流程中、插件 `Stop()` **之后**执行(后注册先执行,执行后清空、幂等)。用于删除插件自身创建的持久化文件(数据/缓存/状态文件)。 - `sdk.RegisterOnRemoveHandler(fn func())` — 注册删除清理回调。内核在 `RemovePlugin` 流程中、插件 `Stop()` **之后**执行(后注册先执行,执行后清空、幂等)。用于删除插件自身创建的持久化文件(数据/缓存/状态文件)。
- 内核卸载时一并清理:工具注册、`disabled_plugins` 记录、插件配置项定义(`plugin.<name>.*`)与插件配置表(`config_<name>`),卸载后插件配置区完全消失。 - 内核卸载时一并清理:工具注册、`disabled_plugins` 记录、插件配置项定义(`plugin.<name>.*`)与插件配置表(`config_<name>`),卸载后插件配置区完全消失。
- 示例:`example/calendar`(删 events.json`example/memo`(删 memos.json`example/rss`(删订阅数据目录)、`example/weather`(删缓存目录);`plugindev` 模板含 onRemove 演示。 - 示例:`example/calendar`(删 events.json`example/memo`(删 memos.json`example/rss`(删订阅数据目录)、`example/weather`(删缓存目录);`hmapdev` 模板含 onRemove 演示。
```go ```go
sdk.RegisterOnRemoveHandler(func() { sdk.RegisterOnRemoveHandler(func() {
@ -488,7 +493,7 @@ ctx.Unlock()
| [rss](example/rss) | Go | RSS 订阅 | | [rss](example/rss) | Go | RSS 订阅 |
| [sanitizer](example/sanitizer) | Go | 内容清洗/安全过滤 | | [sanitizer](example/sanitizer) | Go | 内容清洗/安全过滤 |
**发版时附带预编译示例产物**SDK 的 release 除 5 平台 `plugindev` 外,还包含各示例插件的 **发版时附带预编译示例产物**SDK 的 release 除 5 平台 `hmapdev` 外,还包含各示例插件的
`.hmap``SHA256SUMS`/`MANIFEST.txt`。原因是插件二进制与内核**协议绑定**`ProtocolVersion` `.hmap``SHA256SUMS`/`MANIFEST.txt`。原因是插件二进制与内核**协议绑定**`ProtocolVersion`
+ 共享内存区魔数),只发工具链不发示例产物,很容易拿旧产物去装而握手失败——那看起来像 + 共享内存区魔数),只发工具链不发示例产物,很容易拿旧产物去装而握手失败——那看起来像
「插件坏了」而不是「版本不配套」。 「插件坏了」而不是「版本不配套」。
@ -594,10 +599,10 @@ ha_transport_t my_transport = {
### 使用方式 ### 使用方式
通过 `plugindev` 工具链初始化项目: 通过 `hmapdev` 工具链初始化项目:
```bash ```bash
plugindev init my-adapter --type remotedevice hmapdev init my-adapter --type remotedevice
``` ```
生成 `main.c` + `CMakeLists.txt`,可直接编译或作为三方库引入: 生成 `main.c` + `CMakeLists.txt`,可直接编译或作为三方库引入:
@ -809,17 +814,17 @@ curl -X POST http://<homeagent-server>:8080/api/v1/device/esp32-cam-1/cmd \
### 位置 ### 位置
- **SDK 源码**: `remotedevice/` - **SDK 源码**: `remotedevice/`
- **plugindev 模板**: `plugindev init --type remotedevice` - **hmapdev 模板**: `hmapdev init --type remotedevice`
## 构建与安装 ## 构建与安装
### 构建 ### 构建
```bash ```bash
plugindev build hmapdev build
``` ```
输出 `.hmap` 包到 `dist/` 目录(默认 bundle 多平台合集;单平台构建使用 `plugindev build --no-bundle`)。 输出 `.hmap` 包到 `dist/` 目录(默认 bundle 多平台合集;单平台构建使用 `hmapdev build --no-bundle`)。
### 安装 ### 安装

View File

@ -30,8 +30,8 @@ No public signature changed (the SDK adds `InjectOptions`, six `*Opts` variants
`ChannelDef.ContextPolicy`), so not calling the new capabilities means not being affected — but the `ChannelDef.ContextPolicy`), so not calling the new capabilities means not being affected — but the
kernel's **plugin protocol went to 2** (the fd3 layout of the unified shared-memory region changed, kernel's **plugin protocol went to 2** (the fd3 layout of the unified shared-memory region changed,
and **rolling upgrades are not supported**). `plugin.bin` must therefore be rebuilt with the matching and **rolling upgrades are not supported**). `plugin.bin` must therefore be rebuilt with the matching
`plugindev` and installed **together with** the kernel; otherwise the handshake fails on protocol `hmapdev` and installed **together with** the kernel; otherwise the handshake fails on protocol
version mismatch (the error says explicitly to rebuild with the matching plugindev — it never version mismatch (the error says explicitly to rebuild with the matching hmapdev — it never
degrades silently). degrades silently).
## Injection Behaviour and Context Pruning (1.2.0) ## Injection Behaviour and Context Pruning (1.2.0)
@ -303,19 +303,24 @@ func New(name string, sett SettingsAPI, regTool ToolRegistrar, regStage StageReg
Plugin developers only need to implement the `Plugin` interface and export a `NewPlugin()` entry function. Plugin developers only need to implement the `Plugin` interface and export a `NewPlugin()` entry function.
## plugindev Toolchain ## hmapdev Toolchain
`plugindev` provides full development workflow support. Prebuilt binaries ship as **release assets** `hmapdev` provides full development workflow support and produces `.hmap` plugin bundles (the tool is
named after that package format). Prebuilt binaries ship as **release assets**
(linux/darwin/windows × amd64/arm64); download from (linux/darwin/windows × amd64/arm64); download from
[Releases](https://gitcode.com/JianFeeeee/homeagent-sdk/releases) and put it on your PATH: [Releases](https://gitcode.com/JianFeeeee/homeagent-sdk/releases) and put it on your PATH:
> Rename note: the toolchain was called `plugindev` and is `hmapdev` since 1.2.0.
> The SDK store moved from `~/.homeagent/plugindev/sdk` to `~/.homeagent/hmapdev/sdk`
> (the old directory is still honored, so installed versions are not lost).
```bash ```bash
# From release assets (v1.1.0 / linux amd64 shown) # From release assets (latest SDK release / linux amd64 shown)
curl -Lo plugindev https://gitcode.com/JianFeeeee/homeagent-sdk/releases/download/v1.1.0/plugindev_linux_amd64 curl -Lo hmapdev https://gitcode.com/JianFeeeee/homeagent-sdk/releases/download/<version>/hmapdev_linux_amd64
chmod +x plugindev chmod +x hmapdev
# Or build from source # Or build from source
cd tools/plugindev && go build -o plugindev . cd tools/hmapdev && go build -o hmapdev .
``` ```
> Binaries no longer ship inside the repository (the old `bin/` directory is retired): five > Binaries no longer ship inside the repository (the old `bin/` directory is retired): five
@ -324,11 +329,11 @@ cd tools/plugindev && go build -o plugindev .
| Command | Description | | Command | Description |
|---------|-------------| |---------|-------------|
| `plugindev init <name> [--lua]` | Initialize plugin project (generates plg.json, plugin.go or main.lua, go.mod, README.md) | | `hmapdev init <name> [--lua]` | Initialize plugin project (generates plg.json, plugin.go or main.lua, go.mod, README.md) |
| `plugindev build [flags]` | Build and package into a `.hmap` (supports cross-compilation and bundle mode) | | `hmapdev build [flags]` | Build and package into a `.hmap` (supports cross-compilation and bundle mode) |
| `plugindev clean` | Clean `build/` and `dist/` plus generated files | | `hmapdev clean` | Clean `build/` and `dist/` plus generated files |
| `plugindev debug [dir]` | Load plugin source through the Yaegi Go interpreter and start an interactive REPL | | `hmapdev debug [dir]` | Load plugin source through the Yaegi Go interpreter and start an interactive REPL |
| `plugindev sdk <command>` | SDK version management (list/install/use/path/current/latest) | | `hmapdev sdk <command>` | SDK version management (list/install/use/path/current/latest) |
Supports both **Go** and **Lua** plugin languages. Supports both **Go** and **Lua** plugin languages.
@ -400,7 +405,7 @@ Supports both **Go** and **Lua** plugin languages.
- `sdk.RegisterOnRemoveHandler(fn func())` — Register a remove cleanup callback. The kernel runs it **after** the plugin's `Stop()` in the `RemovePlugin` flow (LIFO order, cleared after running — idempotent). Use it to delete persistent files the plugin created itself (data/cache/state files). - `sdk.RegisterOnRemoveHandler(fn func())` — Register a remove cleanup callback. The kernel runs it **after** the plugin's `Stop()` in the `RemovePlugin` flow (LIFO order, cleared after running — idempotent). Use it to delete persistent files the plugin created itself (data/cache/state files).
- The kernel also cleans up on uninstall: tool registrations, the `disabled_plugins` record, the plugin's config definitions (`plugin.<name>.*`) and its config table (`config_<name>`) — the plugin's config section disappears completely after removal. - The kernel also cleans up on uninstall: tool registrations, the `disabled_plugins` record, the plugin's config definitions (`plugin.<name>.*`) and its config table (`config_<name>`) — the plugin's config section disappears completely after removal.
- Examples: `example/calendar` (removes events.json), `example/memo` (removes memos.json), `example/rss` (removes the subscription data dir), `example/weather` (removes the cache dir); the `plugindev` template includes an onRemove demo. - Examples: `example/calendar` (removes events.json), `example/memo` (removes memos.json), `example/rss` (removes the subscription data dir), `example/weather` (removes the cache dir); the `hmapdev` template includes an onRemove demo.
```go ```go
sdk.RegisterOnRemoveHandler(func() { sdk.RegisterOnRemoveHandler(func() {
@ -476,7 +481,7 @@ Internal plugins (platform built-in) have full SDK access including SocialAPI wr
| [rss](example/rss) | Go | RSS subscriptions | | [rss](example/rss) | Go | RSS subscriptions |
| [sanitizer](example/sanitizer) | Go | Content sanitization / safety filtering | | [sanitizer](example/sanitizer) | Go | Content sanitization / safety filtering |
**Prebuilt example artifacts ship with every release**: besides the 5-platform `plugindev`, an SDK **Prebuilt example artifacts ship with every release**: besides the 5-platform `hmapdev`, an SDK
release contains the example plugins' `.hmap` files plus `SHA256SUMS`/`MANIFEST.txt`. The reason is release contains the example plugins' `.hmap` files plus `SHA256SUMS`/`MANIFEST.txt`. The reason is
that plugin binaries are **protocol-bound** to the kernel (`ProtocolVersion` + the shared-memory that plugin binaries are **protocol-bound** to the kernel (`ProtocolVersion` + the shared-memory
magic), so shipping the toolchain without matching artifacts invites installing an old artifact — magic), so shipping the toolchain without matching artifacts invites installing an old artifact —
@ -567,10 +572,10 @@ ha_transport_t my_transport = {
### Usage ### Usage
Initialize a project via the `plugindev` toolchain: Initialize a project via the `hmapdev` toolchain:
```bash ```bash
plugindev init my-adapter --type remotedevice hmapdev init my-adapter --type remotedevice
``` ```
Generates `main.c` + `CMakeLists.txt`, can be built directly or used as a third-party library: Generates `main.c` + `CMakeLists.txt`, can be built directly or used as a third-party library:
@ -780,17 +785,17 @@ curl -X POST http://<homeagent-server>:8080/api/v1/device/esp32-cam-1/cmd \
### Location ### Location
- **SDK Source**: `remotedevice/` - **SDK Source**: `remotedevice/`
- **plugindev template**: `plugindev init --type remotedevice` - **hmapdev template**: `hmapdev init --type remotedevice`
## Building & Installing ## Building & Installing
### Build ### Build
```bash ```bash
plugindev build hmapdev build
``` ```
Outputs a `.hmap` package to the `dist/` directory (default is the multi-platform bundle; use `plugindev build --no-bundle` for a single-target build). Outputs a `.hmap` package to the `dist/` directory (default is the multi-platform bundle; use `hmapdev build --no-bundle` for a single-target build).
### Install ### Install

View File

@ -5,7 +5,7 @@ ai_image plugin
## Build ## Build
```bash ```bash
plugindev build hmapdev build
``` ```
## Install ## Install

View File

@ -5,7 +5,7 @@ calendar plugin
## Build ## Build
```bash ```bash
plugindev build hmapdev build
``` ```
## Install ## Install

View File

@ -17,7 +17,7 @@ lua main.lua # 使用 sdk.lua mock不依赖内核
## 构建 ## 构建
```bash ```bash
plugindev build hmapdev build
``` ```
## 安装 ## 安装

View File

@ -5,7 +5,7 @@ rss plugin
## Build ## Build
```bash ```bash
plugindev build hmapdev build
``` ```
## Install ## Install

View File

@ -5,7 +5,7 @@ weather plugin
## Build ## Build
```bash ```bash
plugindev build hmapdev build
``` ```
## Install ## Install

View File

@ -61,7 +61,7 @@ var (
// SDKName 是 SDK 名称。 // SDKName 是 SDK 名称。
SDKName = "HomeAgent SDK" SDKName = "HomeAgent SDK"
// CoreModule 是核心仓的 Go module pathplugindev 生成 go.mod 时使用。 // CoreModule 是核心仓的 Go module pathhmapdev 生成 go.mod 时使用。
CoreModule = "gitcode.com/JianFeeeee/HomeAgent" CoreModule = "gitcode.com/JianFeeeee/HomeAgent"
// CoreVersion 是此 SDK 所兼容的最低核心版本。 // CoreVersion 是此 SDK 所兼容的最低核心版本。

View File

@ -20,7 +20,7 @@
# <OUT_DIR>/MANIFEST.txt 版本、协议版本、产自哪个 commit # <OUT_DIR>/MANIFEST.txt 版本、协议版本、产自哪个 commit
# #
# 纪律(与本项目其它构建脚本一致): # 纪律(与本项目其它构建脚本一致):
# 1. 判成功看**产物是否存在**,不看退出码——plugindev 对部分错误只打印不退出。 # 1. 判成功看**产物是否存在**,不看退出码——hmapdev 对部分错误只打印不退出。
# 2. SHA256SUMS 必须在全部产物生成完毕后一次算完,边打边算会漏掉后生成的包。 # 2. SHA256SUMS 必须在全部产物生成完毕后一次算完,边打边算会漏掉后生成的包。
set -uo pipefail set -uo pipefail
@ -67,14 +67,15 @@ fi
# 1) 先保证工具链可用:示例必须用**本仓当前源码**构建,否则产物协议与这一版 SDK 不符。 # 1) 先保证工具链可用:示例必须用**本仓当前源码**构建,否则产物协议与这一版 SDK 不符。
# 允许外部指定(发版脚本会在跨平台构建后把刚产出的工具链路径传进来)。 # 允许外部指定(发版脚本会在跨平台构建后把刚产出的工具链路径传进来)。
PLUGINDEV="${PLUGINDEV:-$SDK_ROOT/build/plugindev}" # 工具链二进制名由 plugindev 改为 hmapdev旧变量名 PLUGINDEV 仍兼容。
HMAPDEV="${HMAPDEV:-${PLUGINDEV:-$SDK_ROOT/build/hmapdev}}"
if [ ! -x "$PLUGINDEV" ]; then if [ ! -x "$PLUGINDEV" ]; then
echo "[examples] 先构建 plugindev ..." echo "[examples] 先构建 hmapdev ..."
( cd "$SDK_ROOT/tools/plugindev" && "$GO" build -o "$PLUGINDEV" . ) || { ( cd "$SDK_ROOT/tools/hmapdev" && "$GO" build -o "$HMAPDEV" . ) || {
echo "[examples] plugindev 构建失败,无法继续" >&2; exit 1; } echo "[examples] hmapdev 构建失败,无法继续" >&2; exit 1; }
fi fi
if [ ! -x "$PLUGINDEV" ]; then if [ ! -x "$PLUGINDEV" ]; then
echo "[examples] plugindev 不存在或不可执行:$PLUGINDEV" >&2 echo "[examples] hmapdev 不存在或不可执行:$HMAPDEV" >&2
exit 1 exit 1
fi fi
@ -100,7 +101,7 @@ for dir in "$SDK_ROOT"/example/*/; do
rc=$? rc=$?
# 判据是**退出码 + 产物存在**,两者都要。 # 判据是**退出码 + 产物存在**,两者都要。
# 只看退出码:plugindev 曾经出错也退 0已修但脚本不该依赖它「现在」是对的 # 只看退出码:hmapdev 曾经出错也退 0已修但脚本不该依赖它「现在」是对的
# 只看产物:部分平台失败时会留下上一次的产物,看起来像成功。 # 只看产物:部分平台失败时会留下上一次的产物,看起来像成功。
hmap="$(ls "$dir"/dist/*.hmap 2>/dev/null | head -1)" hmap="$(ls "$dir"/dist/*.hmap 2>/dev/null | head -1)"
if [ $rc -eq 0 ] && [ -n "$hmap" ]; then if [ $rc -eq 0 ] && [ -n "$hmap" ]; then

View File

@ -28,7 +28,7 @@ case "$TARGET" in
;; ;;
*) *)
echo "Unknown target: $TARGET" echo "Unknown target: $TARGET"
echo "Usage: $0 [native|linux/amd64|linux/arm64|darwin/amd64|darwin/arm64|windows/amd64|all] [all|plugindev|examples]" echo "Usage: $0 [native|linux/amd64|linux/arm64|darwin/amd64|darwin/arm64|windows/amd64|all] [all|hmapdev|examples]"
exit 1 exit 1
esac esac
@ -42,12 +42,12 @@ export CGO_ENABLED=0
mkdir -p "$BUILD_DIR" mkdir -p "$BUILD_DIR"
build_plugindev() { build_hmapdev() {
local src="tools/plugindev" local src="tools/hmapdev"
local out="$BUILD_DIR/plugindev${SUFFIX:+_$SUFFIX}" local out="$BUILD_DIR/hmapdev${SUFFIX:+_$SUFFIX}"
if [ "$GOOS" = "windows" ]; then out="${out}.exe"; fi if [ "$GOOS" = "windows" ]; then out="${out}.exe"; fi
echo "[BUILD] plugindev ${GOOS:-linux}/${GOARCH:-amd64}$out" echo "[BUILD] hmapdev ${GOOS:-linux}/${GOARCH:-amd64}$out"
cd "$PROJECT_ROOT/$src" cd "$PROJECT_ROOT/$src"
"$GO" build -trimpath -ldflags "-X gitcode.com/JianFeeeee/homeagent-sdk/meta.Version=${VERSION}" \ "$GO" build -trimpath -ldflags "-X gitcode.com/JianFeeeee/homeagent-sdk/meta.Version=${VERSION}" \
-o "$out" . -o "$out" .
@ -64,7 +64,7 @@ build_plugindev() {
# #
# 用刚构建出来的那把工具链(而非 PATH 里的),保证产物与本次发版同源。 # 用刚构建出来的那把工具链(而非 PATH 里的),保证产物与本次发版同源。
build_examples() { build_examples() {
local dev="$BUILD_DIR/plugindev${SUFFIX:+_$SUFFIX}" local dev="$BUILD_DIR/hmapdev${SUFFIX:+_$SUFFIX}"
[ "$GOOS" = "windows" ] && dev="${dev}.exe" [ "$GOOS" = "windows" ] && dev="${dev}.exe"
echo "[BUILD] example plugins ${GOOS:-linux}/${GOARCH:-amd64}$BUILD_DIR/examples" echo "[BUILD] example plugins ${GOOS:-linux}/${GOARCH:-amd64}$BUILD_DIR/examples"
PLUGINDEV="$dev" VERSION="$VERSION" bash "$PROJECT_ROOT/package/build-examples.sh" "$TARGET" "$BUILD_DIR/examples" PLUGINDEV="$dev" VERSION="$VERSION" bash "$PROJECT_ROOT/package/build-examples.sh" "$TARGET" "$BUILD_DIR/examples"
@ -74,10 +74,10 @@ build_examples() {
case "$COMPONENT" in case "$COMPONENT" in
all) all)
# 工具链必须先建完:示例用它来构建(同源保证协议一致)。 # 工具链必须先建完:示例用它来构建(同源保证协议一致)。
build_plugindev build_hmapdev
build_examples build_examples
;; ;;
plugindev) build_plugindev ;; hmapdev) build_hmapdev ;;
examples) build_examples ;; examples) build_examples ;;
*) *)
echo "Unknown component: $COMPONENT" echo "Unknown component: $COMPONENT"

View File

@ -48,7 +48,7 @@ Function pageConfirm
${EndIf} ${EndIf}
${NSD_CreateLabel} 0 5u 100% 12u "将安装以下组件:" ${NSD_CreateLabel} 0 5u 100% 12u "将安装以下组件:"
Pop $0 Pop $0
${NSD_CreateLabel} 15u 20u 100% 12u "plugindev.exe — 插件开发工具" ${NSD_CreateLabel} 15u 20u 100% 12u "hmapdev.exe — 插件开发工具"
Pop $0 Pop $0
${NSD_CreateLabel} 15u 35u 100% 12u "• SDK ${SDK_VERSION} — 将从远程仓库自动下载" ${NSD_CreateLabel} 15u 35u 100% 12u "• SDK ${SDK_VERSION} — 将从远程仓库自动下载"
Pop $0 Pop $0
@ -64,11 +64,11 @@ Section "Install" SEC_INSTALL
SetOutPath "$INSTDIR" SetOutPath "$INSTDIR"
DetailPrint "复制工具链文件..." DetailPrint "复制工具链文件..."
File "plugindev.exe" File "hmapdev.exe"
DetailPrint "创建快捷方式..." DetailPrint "创建快捷方式..."
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}" CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\plugindev.lnk" "$INSTDIR\plugindev.exe" "" "$INSTDIR\plugindev.exe" 0 CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\hmapdev.lnk" "$INSTDIR\hmapdev.exe" "" "$INSTDIR\hmapdev.exe" 0
DetailPrint "配置环境变量..." DetailPrint "配置环境变量..."
; Add to system PATH ; Add to system PATH
@ -93,23 +93,23 @@ Section "Install" SEC_INSTALL
DetailPrint "Git 已安装: $1" DetailPrint "Git 已安装: $1"
${Else} ${Else}
DetailPrint "未检测到 Git将跳过 SDK 自动下载" DetailPrint "未检测到 Git将跳过 SDK 自动下载"
DetailPrint "安装完成后请手动运行: plugindev sdk install ${SDK_VERSION}" DetailPrint "安装完成后请手动运行: hmapdev sdk install ${SDK_VERSION}"
${EndIf} ${EndIf}
${If} $hasGit == "1" ${If} $hasGit == "1"
DetailPrint "正在下载 SDK ${SDK_VERSION}..." DetailPrint "正在下载 SDK ${SDK_VERSION}..."
nsExec::ExecToStack '"$INSTDIR\plugindev.exe" sdk install ${SDK_VERSION}' nsExec::ExecToStack '"$INSTDIR\hmapdev.exe" sdk install ${SDK_VERSION}'
Pop $0 Pop $0
Pop $1 Pop $1
${If} $0 == 0 ${If} $0 == 0
StrCpy $sdkInstallOk "1" StrCpy $sdkInstallOk "1"
DetailPrint "SDK ${SDK_VERSION} 下载完成" DetailPrint "SDK ${SDK_VERSION} 下载完成"
DetailPrint "正在激活 SDK ${SDK_VERSION}..." DetailPrint "正在激活 SDK ${SDK_VERSION}..."
nsExec::Exec '"$INSTDIR\plugindev.exe" sdk use ${SDK_VERSION}' nsExec::Exec '"$INSTDIR\hmapdev.exe" sdk use ${SDK_VERSION}'
Pop $0 Pop $0
${Else} ${Else}
DetailPrint "SDK 下载失败 (错误码: $0)" DetailPrint "SDK 下载失败 (错误码: $0)"
DetailPrint "请手动运行: plugindev sdk install ${SDK_VERSION}" DetailPrint "请手动运行: hmapdev sdk install ${SDK_VERSION}"
${EndIf} ${EndIf}
${EndIf} ${EndIf}
@ -126,10 +126,10 @@ SectionEnd
Section "Uninstall" Section "Uninstall"
Delete "$INSTDIR\Uninstall.exe" Delete "$INSTDIR\Uninstall.exe"
Delete "$INSTDIR\plugindev.exe" Delete "$INSTDIR\hmapdev.exe"
RMDir /r "$INSTDIR\sdk" RMDir /r "$INSTDIR\sdk"
RMDir "$INSTDIR" RMDir "$INSTDIR"
Delete "$SMPROGRAMS\${PRODUCT_NAME}\plugindev.lnk" Delete "$SMPROGRAMS\${PRODUCT_NAME}\hmapdev.lnk"
RMDir "$SMPROGRAMS\${PRODUCT_NAME}" RMDir "$SMPROGRAMS\${PRODUCT_NAME}"
DeleteRegValue HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "HOMEAGENT_SDK_DIR" DeleteRegValue HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "HOMEAGENT_SDK_DIR"
DeleteRegKey HKLM "Software\Microsoft\CurrentVersion\Uninstall\${PRODUCT_NAME}" DeleteRegKey HKLM "Software\Microsoft\CurrentVersion\Uninstall\${PRODUCT_NAME}"

View File

@ -441,8 +441,8 @@ func ensureSDKResolvable(plg *PlgConfig, sdkModule, sdkPath string) {
fmt.Printf(" %s\n", strings.TrimSpace(string(out))) fmt.Printf(" %s\n", strings.TrimSpace(string(out)))
} }
fmt.Printf(" 提示:%s 不在公共 proxy 上。用以下任一方式指向本机 SDK\n", sdkModule) fmt.Printf(" 提示:%s 不在公共 proxy 上。用以下任一方式指向本机 SDK\n", sdkModule)
fmt.Printf(" plugindev sdk install latest # 装一份到 ~/.homeagent/plugindev/sdk\n") fmt.Printf(" hmapdev sdk install latest # 装一份到 ~/.homeagent/hmapdev/sdk\n")
fmt.Printf(" plugindev build --sdk-path <路径> # 或直接指定源码目录\n") fmt.Printf(" hmapdev build --sdk-path <路径> # 或直接指定源码目录\n")
} }
} }
@ -457,17 +457,12 @@ func findLocalSDK(sdkPath string) string {
candidates = append(candidates, abs) candidates = append(candidates, abs)
} }
} }
// plugindev 自身所在位置往上三级tools/plugindev/plugindev → SDK 根) // hmapdev 自身所在位置往上三级tools/hmapdev/hmapdev → SDK 根)
if self, err := os.Executable(); err == nil { if self, err := os.Executable(); err == nil {
candidates = append(candidates, filepath.Dir(filepath.Dir(filepath.Dir(self)))) candidates = append(candidates, filepath.Dir(filepath.Dir(filepath.Dir(self))))
} }
// plugindev sdk use 选定的版本 // hmapdev sdk use 选定的版本(复用 sdkStore(),含改名前的旧目录回退)
store := os.Getenv("HOMEAGENT_SDK_DIR") store := sdkStore()
if store == "" {
if home, err := os.UserHomeDir(); err == nil {
store = filepath.Join(home, ".homeagent", "plugindev", "sdk")
}
}
if store != "" { if store != "" {
if d, err := os.ReadFile(filepath.Join(store, "current")); err == nil { if d, err := os.ReadFile(filepath.Join(store, "current")); err == nil {
if ver := strings.TrimSpace(string(d)); ver != "" { if ver := strings.TrimSpace(string(d)); ver != "" {
@ -511,7 +506,7 @@ func resolveSDKPath(sdkPath string) string {
fmt.Printf("error: --sdk-path %q not a valid SDK\n", sdkPath) fmt.Printf("error: --sdk-path %q not a valid SDK\n", sdkPath)
os.Exit(1) os.Exit(1)
} }
// Detect from plugindev's own location (internal dev) // Detect from hmapdev's own location (internal dev)
self, err := os.Executable() self, err := os.Executable()
if err == nil { if err == nil {
cand := filepath.Dir(filepath.Dir(filepath.Dir(self))) cand := filepath.Dir(filepath.Dir(filepath.Dir(self)))
@ -519,14 +514,8 @@ func resolveSDKPath(sdkPath string) string {
return cand return cand
} }
} }
// Active SDK via plugindev sdk use // Active SDK via hmapdev sdk use
store := os.Getenv("HOMEAGENT_SDK_DIR") store := sdkStore()
if store == "" {
home, _ := os.UserHomeDir()
if home != "" {
store = filepath.Join(home, ".homeagent", "plugindev", "sdk")
}
}
if store != "" { if store != "" {
if d, err := os.ReadFile(filepath.Join(store, "current")); err == nil { if d, err := os.ReadFile(filepath.Join(store, "current")); err == nil {
ver := strings.TrimSpace(string(d)) ver := strings.TrimSpace(string(d))
@ -538,7 +527,7 @@ func resolveSDKPath(sdkPath string) string {
} }
} }
} }
fmt.Printf("error: cannot locate SDK. Use --sdk-path or 'plugindev sdk use'\n") fmt.Printf("error: cannot locate SDK. Use --sdk-path or 'hmapdev sdk use'\n")
os.Exit(1) os.Exit(1)
return "" return ""
} }

View File

@ -7,12 +7,12 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/JianFeeeee/homeagent-sdk/tools/plugindev/yaegi" "gitcode.com/JianFeeeee/homeagent-sdk/tools/hmapdev/yaegi"
) )
// tmplLuaDebug is the temporary Lua debug script template // tmplLuaDebug is the temporary Lua debug script template
const tmplLuaDebug = `-- HomeAgent Lua Plugin Debug const tmplLuaDebug = `-- HomeAgent Lua Plugin Debug
-- Generated by plugindev debug --lua -- Generated by hmapdev debug --lua
sdk = require("sdk") sdk = require("sdk")
local ok, plugin = pcall(dofile, "main.lua") local ok, plugin = pcall(dofile, "main.lua")
if not ok then if not ok then
@ -115,7 +115,7 @@ func debugLua(dir, sdkPath, luaPath string) {
luaBin, err := exec.LookPath("lua") luaBin, err := exec.LookPath("lua")
if err != nil { if err != nil {
fmt.Println("error: lua interpreter not found in PATH") fmt.Println("error: lua interpreter not found in PATH")
fmt.Println(" install Lua 5.1+ or use plugindev build to compile your plugin") fmt.Println(" install Lua 5.1+ or use hmapdev build to compile your plugin")
os.Exit(1) os.Exit(1)
} }

View File

@ -63,7 +63,7 @@ type TemplateData struct {
// SDKLocalPath 是本机 SDK 源码绝对路径,写入生成的 go.mod 作为 replace 目标。 // SDKLocalPath 是本机 SDK 源码绝对路径,写入生成的 go.mod 作为 replace 目标。
// //
// 为何必须写gitcode 的模块不在 proxy.golang.org 上,只 require 一个 // 为何必须写gitcode 的模块不在 proxy.golang.org 上,只 require 一个
// 版本号的 go.mod 配上缺失的 go.sum新用户第一次 `plugindev build` // 版本号的 go.mod 配上缺失的 go.sum新用户第一次 `hmapdev build`
// 必定死在 "missing go.sum entry",而 `go mod tidy` 又会去公共 proxy 拉 // 必定死在 "missing go.sum entry",而 `go mod tidy` 又会去公共 proxy 拉
// 一个不存在的条目。有了本地 replacego 完全不需要 go.sum 条目。 // 一个不存在的条目。有了本地 replacego 完全不需要 go.sum 条目。
SDKLocalPath string SDKLocalPath string
@ -71,7 +71,7 @@ type TemplateData struct {
func cmdInit(args []string) { func cmdInit(args []string) {
if len(args) < 1 { if len(args) < 1 {
fmt.Println("Usage: plugindev init <name> [--lua] [--type remotedevice]") fmt.Println("Usage: hmapdev init <name> [--lua] [--type remotedevice]")
os.Exit(1) os.Exit(1)
} }
@ -192,7 +192,7 @@ func cmdInit(args []string) {
if isLua { if isLua {
fmt.Printf(" cd %s && lua main.lua (standalone test)\n", dir) fmt.Printf(" cd %s && lua main.lua (standalone test)\n", dir)
} }
fmt.Printf(" cd %s && plugindev build\n", dir) fmt.Printf(" cd %s && hmapdev build\n", dir)
} }
// detectSDKInfo reads the HomeAgent SDK's go.mod and meta to get module path, go version, and SDK version. // detectSDKInfo reads the HomeAgent SDK's go.mod and meta to get module path, go version, and SDK version.

View File

@ -14,7 +14,12 @@ import (
"time" "time"
) )
const sdkDirName = "plugindev/sdk" const sdkDirName = "hmapdev/sdk"
// legacySDKDirName 是改名前的存储目录。工具链在 1.2.0 从 plugindev 改名 hmapdev
// 已装过旧版的机器上 SDK 仍在旧路径,直接换名会让它找不到已装 SDK
// (表现为「没有活动版本」)。新目录不存在而旧目录存在时沿用旧目录。
const legacySDKDirName = "plugindev/sdk"
// sdkStore returns the root directory for stored SDK versions. // sdkStore returns the root directory for stored SDK versions.
func sdkStore() string { func sdkStore() string {
@ -26,7 +31,15 @@ func sdkStore() string {
fmt.Printf("error: cannot determine home directory: %v\n", err) fmt.Printf("error: cannot determine home directory: %v\n", err)
os.Exit(1) os.Exit(1)
} }
return filepath.Join(home, ".homeagent", sdkDirName) dir := filepath.Join(home, ".homeagent", sdkDirName)
if _, err := os.Stat(dir); err != nil {
if legacy := filepath.Join(home, ".homeagent", legacySDKDirName); legacy != "" {
if _, err := os.Stat(legacy); err == nil {
return legacy
}
}
}
return dir
} }
func sdkCurrentDir() string { func sdkCurrentDir() string {
@ -50,13 +63,13 @@ func cmdSDK(args []string) {
cmdSDKList() cmdSDKList()
case "install": case "install":
if len(args) < 2 { if len(args) < 2 {
fmt.Println("Usage: plugindev sdk install <version>") fmt.Println("Usage: hmapdev sdk install <version>")
os.Exit(1) os.Exit(1)
} }
cmdSDKInstall(args[1]) cmdSDKInstall(args[1])
case "use": case "use":
if len(args) < 2 { if len(args) < 2 {
fmt.Println("Usage: plugindev sdk use <version>") fmt.Println("Usage: hmapdev sdk use <version>")
os.Exit(1) os.Exit(1)
} }
cmdSDKUse(args[1]) cmdSDKUse(args[1])
@ -72,7 +85,7 @@ func cmdSDK(args []string) {
} }
func sdkHelp() { func sdkHelp() {
fmt.Print(`Usage: plugindev sdk <command> fmt.Print(`Usage: hmapdev sdk <command>
Manage installed HomeAgent SDK versions. Manage installed HomeAgent SDK versions.
@ -85,9 +98,9 @@ Commands:
latest Show the latest available version from remote latest Show the latest available version from remote
Examples: Examples:
plugindev sdk install v0.7.1 hmapdev sdk install v0.7.1
plugindev sdk install latest hmapdev sdk install latest
plugindev sdk use v0.7.1 hmapdev sdk use v0.7.1
`) `)
} }
@ -127,7 +140,7 @@ func cmdSDKList() {
fmt.Printf(" %s %s\n", mark, v) fmt.Printf(" %s %s\n", mark, v)
} }
if current == "" { if current == "" {
fmt.Println("\nNo version active. Use 'plugindev sdk use <version>' to set one.") fmt.Println("\nNo version active. Use 'hmapdev sdk use <version>' to set one.")
} }
} }
@ -292,7 +305,7 @@ func cmdSDKUse(version string) {
verDir := sdkVersionDir(version) verDir := sdkVersionDir(version)
if _, err := os.Stat(verDir); os.IsNotExist(err) { if _, err := os.Stat(verDir); os.IsNotExist(err) {
fmt.Printf("SDK version %s is not installed.\n", version) fmt.Printf("SDK version %s is not installed.\n", version)
fmt.Printf("Install it first: plugindev sdk install %s\n", version) fmt.Printf("Install it first: hmapdev sdk install %s\n", version)
os.Exit(1) os.Exit(1)
} }
setCurrentVersion(store, version) setCurrentVersion(store, version)
@ -305,7 +318,7 @@ func cmdSDKPath() {
current := resolveCurrentVersion(store) current := resolveCurrentVersion(store)
if current == "" { if current == "" {
fmt.Println("No active SDK version set.") fmt.Println("No active SDK version set.")
fmt.Println("Use 'plugindev sdk use <version>' to set one.") fmt.Println("Use 'hmapdev sdk use <version>' to set one.")
os.Exit(1) os.Exit(1)
} }
fmt.Println(sdkVersionDir(current)) fmt.Println(sdkVersionDir(current))
@ -440,21 +453,21 @@ func parseSemver(tag string) [3]int {
} }
// activeSDKRoot returns the path to the active SDK root. // activeSDKRoot returns the path to the active SDK root.
// It replaces the old runtime.Caller(0) approach so plugindev can work // It replaces the old runtime.Caller(0) approach so hmapdev can work
// independently of its own build location. // independently of its own build location.
func activeSDKRoot() string { func activeSDKRoot() string {
store := sdkStore() store := sdkStore()
current := resolveCurrentVersion(store) current := resolveCurrentVersion(store)
if current == "" { if current == "" {
fmt.Printf("error: no active SDK version set\n") fmt.Printf("error: no active SDK version set\n")
fmt.Printf(" Install one: plugindev sdk install latest\n") fmt.Printf(" Install one: hmapdev sdk install latest\n")
fmt.Printf(" Or set one: plugindev sdk use <version>\n") fmt.Printf(" Or set one: hmapdev sdk use <version>\n")
os.Exit(1) os.Exit(1)
} }
root := sdkVersionDir(current) root := sdkVersionDir(current)
if _, err := os.Stat(root); os.IsNotExist(err) { if _, err := os.Stat(root); os.IsNotExist(err) {
fmt.Printf("error: active SDK version %s not found at %s\n", current, root) fmt.Printf("error: active SDK version %s not found at %s\n", current, root)
fmt.Printf(" Reinstall: plugindev sdk install %s\n", current) fmt.Printf(" Reinstall: hmapdev sdk install %s\n", current)
os.Exit(1) os.Exit(1)
} }
return root return root

View File

@ -1,4 +1,4 @@
module github.com/JianFeeeee/homeagent-sdk/tools/plugindev module gitcode.com/JianFeeeee/homeagent-sdk/tools/hmapdev
go 1.21.0 go 1.21.0

View File

@ -30,14 +30,14 @@ func help() {
fmt.Print(`HomeAgent Plugin Dev Tool fmt.Print(`HomeAgent Plugin Dev Tool
Usage: Usage:
plugindev init <name> Scaffold a new plugin project hmapdev init <name> Scaffold a new plugin project
plugindev init <name> --lua Create Lua plugin hmapdev init <name> --lua Create Lua plugin
plugindev init <name> --type remotedevice hmapdev init <name> --type remotedevice
Create C remote device adapter Create C remote device adapter
plugindev build [flags] Compile and package plugin hmapdev build [flags] Compile and package plugin
plugindev clean Clean build/dist artifacts hmapdev clean Clean build/dist artifacts
plugindev debug [dir] Interpret and debug plugin source hmapdev debug [dir] Interpret and debug plugin source
plugindev sdk <command> Manage SDK versions hmapdev sdk <command> Manage SDK versions
Flags: Flags:
--outdir Output directory (default: dist) --outdir Output directory (default: dist)

View File

@ -56,7 +56,7 @@ const procGenFile = "z_proc_gen.go"
// generateProcRuntime 把子进程运行时(平台无关主体 + 两个平台挂载实现) // generateProcRuntime 把子进程运行时(平台无关主体 + 两个平台挂载实现)
// 写入插件目录,返回清理函数。 // 写入插件目录,返回清理函数。
func generateProcRuntime() (func(), error) { func generateProcRuntime() (func(), error) {
// 清理历史 C ABI 产物:旧版 plugindev 生成过这两个文件,残留下来会与 // 清理历史 C ABI 产物:旧版 hmapdev原名 plugindev生成过这两个文件,残留下来会与
// 本模板的 main 冲突。无需人工清理就能从旧版升级。 // 本模板的 main 冲突。无需人工清理就能从旧版升级。
for _, stale := range []string{"z_bridge_gen.go", "z_entry.c"} { for _, stale := range []string{"z_bridge_gen.go", "z_entry.c"} {
os.Remove(stale) os.Remove(stale)

View File

@ -511,7 +511,7 @@ const tmplReadme = `# {{.Plg.Name}}
## Build ## Build
` + "```bash" + ` ` + "```bash" + `
plugindev build hmapdev build
` + "```" + ` ` + "```" + `
## Install ## Install

View File

@ -13,7 +13,7 @@ import (
"github.com/traefik/yaegi/interp" "github.com/traefik/yaegi/interp"
"github.com/traefik/yaegi/stdlib" "github.com/traefik/yaegi/stdlib"
"github.com/JianFeeeee/homeagent-sdk/tools/plugindev/yaegi/mocksdk" "gitcode.com/JianFeeeee/homeagent-sdk/tools/hmapdev/yaegi/mocksdk"
) )
type YaegiDebugger struct { type YaegiDebugger struct {