mirror of
https://gitcode.com/JianFeeeee/homeagent-sdk.git
synced 2026-09-20 00:48:12 +00:00
feat(sdk): 通道方向契约落地 + 模板工程/示例插件显式登记 inputch + 生成器两处修正
## 背景:内核侧发现的真问题
在真实二进制压力测试里发现:插件只调 `RegisterOutputChannel("cli", ...)`,
却用同一个通道名 `InjectTextSync("cli", ...)` 注入输入 ⇒ 内核 inputch 登记表里
**没有**这个通道,"把 inputch 划给驻留子"直接失败(`划入 inputch cli: inputch 未注册`)。
根因是**契约没有落到插件与 SDK 面上**:inputch 是内核最基本的**输入路由单位**,
"谁会往这个通道注入输入"必须显式声明,而 SDK 文档没说清它与 RegisterOutputChannel
的分工,示例与模板工程也没有示范。
## SDK 面
- `RegisterInputChannel` / `RegisterOutputChannel` 的文档补齐**方向契约**:
入站(谁会注入)与出站(output_send__<name> 的回复发给谁)是分开登记的两件事;
凡是用 `InjectText*/InjectInput*/InjectInterrupt*(source, "<name>", ...)` 注入的
通道名都要 RegisterInputChannel。README 同步补了一段契约说明。
## 示例插件(全部补齐,之前只有 qq/weather 是对的)
`a2a`、`acp`、`browser`、`memo`:注入用 `p.name` ⇒ 登记 `p.name`;
`calendar`、`rss`:注入用字面量通道名 ⇒ 登记同名通道。
(这些插件此前是"能注入、但通道不在登记表里",与 cli 同类问题。)
## 模板工程(生成器 templates.go)
- `tmplPluginGo`:示范入站+出站两个方向(含 ChannelDef/NoMemory 说明与 `inputch 未注册` 的成因)。
- `tmplMainLua`:同样两个方向(`register_input_channel` / `register_output_channel`)。
- `tmplReadme`:新增 "Channels" 一节(方向对照表 + 兜底告警说明)。
- 实测:`hmapdev init` 生成的 Go/Lua 工程都含通道代码,Go 工程可构建打包出 `.hmap`;
`--lua` 工程同样生成通道代码。
## 生成器两处修正(都是实测踩出来的)
1. `sdk install --from <dir>`:install 原本只能从 Release 归档下载,而 SDK 开发期的新能力
(如 proc 桥要透传的 `InjectOptions.Priority`)还没发版 ⇒ 生成的工程必然编译失败
(`z_proc_gen.go: opts.Priority undefined`)。现在可用本地源码装一个版本并激活。
实测:`hmapdev sdk install --from <local sdk>` → 装成 v1.3.0 并激活 → 工程构建通过。
2. 构建前置校验 `sdkHasInjectPriority`:proc 桥模板需要 `InjectOptions.Priority`,
旧 SDK 没有时应给出**可执行**的报错(升级 SDK 或用 `--from`),
而不是把两条 `opts.Priority undefined` 编译错误甩给用户(那些错误指向生成物,
完全看不出是 SDK 版本问题)。实测:声明 sdk=1.2.0 的工程构建时正确命中该提示。
## 未决(发布期事项)
`InjectOptions.Priority` 属本特性线新增能力,**已发布的 SDK v1.2.0 不含它**;
发版时 SDK 版本需随之内含该能力(当前源码 meta 已是 1.3.0),否则外部开发者
按文档生成的工程会撞上上面那条守卫。
This commit is contained in:
@ -58,6 +58,27 @@ func cmdSDK(args []string) {
|
||||
sdkHelp()
|
||||
return
|
||||
}
|
||||
// install --from <本地目录> [version]:用本地 SDK 源码装一个版本并激活。
|
||||
if args[0] == "install" {
|
||||
from := ""
|
||||
rest := []string{}
|
||||
for i := 1; i < len(args); i++ {
|
||||
if args[i] == "--from" && i+1 < len(args) {
|
||||
from = args[i+1]
|
||||
i++
|
||||
continue
|
||||
}
|
||||
rest = append(rest, args[i])
|
||||
}
|
||||
if from != "" {
|
||||
version := ""
|
||||
if len(rest) > 0 && rest[0] != "latest" {
|
||||
version = rest[0]
|
||||
}
|
||||
cmdSDKInstallFromDir(from, version)
|
||||
return
|
||||
}
|
||||
}
|
||||
switch args[0] {
|
||||
case "list":
|
||||
cmdSDKList()
|
||||
@ -100,7 +121,8 @@ Commands:
|
||||
Examples:
|
||||
hmapdev sdk install v0.7.1
|
||||
hmapdev sdk install latest
|
||||
hmapdev sdk use v0.7.1
|
||||
hmapdev sdk install v0.7.1
|
||||
hmapdev sdk install --from /path/to/homeagent-sdk # 用本地源码(SDK 开发时用)sdk use v0.7.1
|
||||
`)
|
||||
}
|
||||
|
||||
@ -144,6 +166,51 @@ func cmdSDKList() {
|
||||
}
|
||||
}
|
||||
|
||||
// cmdSDKInstallFromDir 从**本地 SDK 源码目录**安装一个版本。
|
||||
//
|
||||
// 为什么需要它:`install` 只能从 Release 归档下载,而 SDK 开发时的新能力
|
||||
// (例如 `InjectOptions.Priority` 这类 proc 桥要透传的字段)往往还没发版 ——
|
||||
// 此时生成出来的插件工程会因为"引用的 SDK 还没有该字段"直接编译失败。
|
||||
// 有 --from 才能"用本地源码当这个版本的 SDK",边改 SDK 边验证模板工程。
|
||||
func cmdSDKInstallFromDir(src, version string) {
|
||||
store := sdkStore()
|
||||
if err := os.MkdirAll(store, 0755); err != nil {
|
||||
fmt.Printf("error: create SDK store %s: %v\n", store, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if version == "" {
|
||||
version = readMetaVersion(src)
|
||||
}
|
||||
if version == "" {
|
||||
fmt.Printf("error: cannot determine version from %s/meta/meta.go\n", src)
|
||||
os.Exit(1)
|
||||
}
|
||||
if !strings.HasPrefix(version, "v") {
|
||||
version = "v" + version
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(src, "go.mod")); err != nil {
|
||||
fmt.Printf("error: %s 看起来不是 SDK 源码目录(缺 go.mod)\n", src)
|
||||
os.Exit(1)
|
||||
}
|
||||
dest := sdkVersionDir(version)
|
||||
_ = os.RemoveAll(dest)
|
||||
if err := copyDir(src, dest); err != nil {
|
||||
fmt.Printf("error: copy %s -> %s: %v\n", src, dest, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
// 源码目录里的开发产物不该带进 store。
|
||||
for _, junk := range []string{".git", "dist", "build"} {
|
||||
_ = os.RemoveAll(filepath.Join(dest, junk))
|
||||
}
|
||||
fmt.Printf("Installed SDK %s from %s\n", version, src)
|
||||
fmt.Printf(" %s\n", dest)
|
||||
if err := os.WriteFile(filepath.Join(store, "current"), []byte(version), 0644); err != nil {
|
||||
fmt.Printf("error: activate %s: %v\n", version, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("Activated SDK %s\n", version)
|
||||
}
|
||||
|
||||
// cmdSDKInstall downloads and installs an SDK version from Release archive.
|
||||
func cmdSDKInstall(version string) {
|
||||
store := sdkStore()
|
||||
@ -520,5 +587,3 @@ func readMetaVersion(sdkRoot string) string {
|
||||
}
|
||||
return "0.0.0"
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user