Files
homeagent-sdk/README_EN.md
root bc1a005885 docs: fix plugindev install endpoint and build output; examples table; fix NewPluginFactory in bridge template
- README 构建与安装:输出目录为 dist/,安装端点为 pluginmgr POST /plugins(JSON 或 raw body),删除不存在的 /api/plugins/install
- 示例表:weather/luademo 新增、qq 更新 17 工具(补入 2b54814 未提交部分)
- templates.go: go_init_plugin 调用 NewPluginFactory(模板插件仅导出该函数)
2026-07-31 13:00:09 +08:00

279 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# HomeAgent SDK
Plugin development SDK for building intelligent plugins that interact with the HomeAgent platform.
## SDK API Surface
### Plugin Interface
Plugins implement the `Plugin` interface:
```go
type Plugin interface {
Name() string
Start(sdk *PluginSDK) error
Stop() error
}
```
### PluginSDK Methods
The SDK instance injected via `Start(sdk *PluginSDK)` provides:
| Category | Method | Description |
|----------|--------|-------------|
| Stage Hooks | `RegisterStage(stage, handler, scope...)` | Register stage callback; scope: `StageScopeGlobal` (all, default) or `StageScopeOwnTools` (own tools only) |
| Input Channel | `RegisterInputChannel(name, def)` | Register input channel with `ChannelDef` (NoMemory/Cleaner) |
| Output Channel | `RegisterOutputChannel(name, caps, desc, def, handler)` | Register output channel with `ChannelDef` and capability bitmask |
| Tool Registration | `RegisterTool(name, def, handler)` | Register a tool for LLM invocation |
| Plugin API | `RegisterPluginAPI(name)` | Register plugin API for inter-plugin access |
| Graph Memory | `Memory()` | Access graph memory API (entity-relation store) |
| Text Memory | `TextMemory()` | Access text memory API (chronological events) |
| Doc Memory | `DocMemory()` | Access document memory API (vector store) |
| Social Graph | `Social()` | Access social graph API (read-only for external plugins) |
| Knowledge | `Knowledge()` | Access knowledge base API |
| LLM | `LLM()` | Access LLM provider manager API |
| Settings | `Settings()` | Access settings API |
| Events | `Events()` | Access event subscriber (subscribe-only for external plugins) |
| Inject | `InjectText(source, channel, text)` / `InjectInterruptText(source, channel, text)` / `InjectTextNoMemory(source, channel, text)` | Inject text into the agent pipeline |
| Auto-Restart | `SetAutoRestart(enabled)` / `AutoRestart()` | Control automatic restart on crash |
### Stage Hooks
```go
// Listen to all stage events globally
sdk.RegisterStage(StagePreAction, func(ctx *StageContext) error { return nil })
// Listen only to this plugin's own tool calls (before_toolcall / after_toolcall only)
sdk.RegisterStage(StageBeforeToolcall, myHandler, StageScopeOwnTools)
```
### ChannelDef
```go
type ChannelDef struct {
NoMemory bool // Channel input/output skips memory computation (vector/keyword/distill), original text preserved
Cleaner func(string) string // Optional: computation layer filter (does not modify original text)
}
```
`ChannelDef` controls channel behavior in the memory computation layer, with the same semantics as `ToolDef.NoMemory`/`Cleaner`.
### Input Channels
```go
sdk.RegisterInputChannel("qq", ChannelDef{
NoMemory: true,
Cleaner: func(text string) string { return strings.TrimSpace(text) },
})
```
### Output Channels
```go
sdk.RegisterOutputChannel("my-channel", CapText|CapFile, "channel description", ChannelDef{}, handler)
```
The handler receives three arguments:
- `payload` (string) — message content. For `type=text` it's plain text, for `type=file/image` it's a URL
- `meta` (string) — optional JSON routing metadata (e.g. `{"group_id":123,"user_id":456}`)
- `type` (string) — content type enum (see below)
Capability flags:
| Flag | Value | Description |
|------|-------|-------------|
| `CapText` | 1 | Plain text output |
| `CapFile` | 2 | File output |
| `CapImage` | 4 | Image output |
| `CapAudio` | 8 | Audio output |
| `CapStructured` | 16 | Structured data output |
Type enum values:
| Value | Description |
|-------|-------------|
| `text` | plain text |
| `voice` / `audio` | audio/voice |
| `image` | image |
| `file` | file |
### IOInjector Channel Routing
| Method | Description |
|--------|-------------|
| `InjectText(source, channel, text)` | Inject text, record to memory, route to specified channel |
| `InjectInterruptText(source, channel, text)` | Inject interrupt text, interrupt current processing, route to specified channel |
| `InjectTextNoMemory(source, channel, text)` | Inject text without memory recording, route to specified channel |
`source` identifies the origin, `channel` specifies the target output channel.
### Triple Extended Fields
The Triple data structure includes additional fields:
- `Confidence` — confidence score (0.01.0)
- `SubjectType` — subject type
- `ObjectType` — object type
### ToolDef Field Reference
The `def` parameter of `RegisterTool` is of type `sdk.ToolDef`, with the following fields:
| Field | Type | Description |
|-------|------|-------------|
| `Name` | `string` | Tool name, use plugin name prefix to avoid conflicts |
| `Description` | `string` | Tool description, LLM uses this for tool selection |
| `Parameters` | `map[string]interface{}` | JSON Schema parameter definition |
| `NoMemory` | `bool` | Default `false`; when `true`, output skips vector/jieba/distill computation (original text preserved) |
| `Cleaner` | `func(string) string` | Optional, filters output before computation layer (e.g., extract `.content` from JSON) |
For detailed design rationale of `NoMemory` and `Cleaner`, see `docs/en/PLUGIN_DEV.md` in the core repository.
### New Constructor
`New()` is called by the kernel when loading a plugin. Plugin developers do not need to construct PluginSDK manually:
```go
func New(name string, sett SettingsAPI, regTool ToolRegistrar, regStage StageRegistrar, regAPI APIRegistrar, regOutput OutputChannelRegistrar) *PluginSDK
```
Plugin developers only need to implement the `Plugin` interface and export a `NewPlugin()` entry function.
## plugindev Toolchain
`plugindev` provides full development workflow support:
| Command | Description |
|---------|-------------|
| `plugindev init` | Initialize plugin project (generates plg.json, entry template) |
| `plugindev build` | Build plugin, output .hmap package |
| `plugindev clean` | Clean build artifacts |
| `plugindev debug` | Run plugin in local debug mode |
Supports both **Go** and **Lua** plugin languages.
### plg.json Manifest Format
```json
{
"name": "weather",
"name_zh": "天气查询",
"name_en": "Weather",
"version": "1.0.0",
"description": "Weather plugin",
"author": "HomeAgent",
"entry": "plugin.so",
"tags": ["weather", "forecast"],
"targets": "linux/amd64,windows/amd64",
"outdir": "dist",
"bundle": true,
"replaces": {
"github.com/example/pkg": "../local/pkg"
},
"source_dirs": [
"../shared-lib"
]
}
```
| Field | Type | Description |
|-------|------|-------------|
| `name` | string | Plugin identifier |
| `name_zh` | string | Chinese name |
| `name_en` | string | English name |
| `version` | string | Version |
| `description` | string | Plugin description |
| `author` | string | Author |
| `entry` | string | Entry file (`plugin.so` / `main.lua`) |
| `tags` | string[] | Tags |
| `targets` | string | Build targets, comma-separated (e.g. `linux/amd64,windows/amd64`) |
| `outdir` | string | Output directory (default `dist`) |
| `bundle` | bool | Bundle mode (build all platforms at once) |
| `replaces` | object | Go module replacements, key=module path, value=local path |
| `source_dirs` | string[] | Additional source search paths (auto-imported at build time) |
### .hmap Package Format
`.hmap` is a ZIP archive containing:
- `plugin.json` — plugin metadata
- `plugin.so` — Go compiled artifact (Linux)
- `plugin.dll` — Go compiled artifact (Windows)
- `main.lua` — Lua plugin entry (for Lua plugins)
## Plugin Lifecycle
### Start & Stop
- `Start(sdk *PluginSDK) error` — Plugin startup, receives SDK instance
- `Stop() error` — Plugin shutdown, release resources
### Auto-Restart
```go
sdk.SetAutoRestart(true)
// Query state
enabled := sdk.AutoRestart()
```
The platform automatically restarts the plugin on crash, ensuring service availability.
## Restricted SDK vs Full SDK
External plugins (third-party distribution) use a **restricted SDK** that only exposes a safe subset:
| Restricted API | Allowed Operations |
|----------------|-------------------|
| `SocialAPI` | Read-only: `GetPerson`, `GetTrait`, `GetRelations`, `GetNetwork`, `ListPersons` |
| `EventSubscriber` | Subscribe-only: `Subscribe` (no `Publish`) |
Internal plugins (platform built-in) have full SDK access including SocialAPI write operations and EventPublisher.
## Example Plugins
| Plugin | Type | Description |
|--------|------|-------------|
| [weather](example/weather) | Go | Weather queries (wttr.in); demonstrates NoMemory/Cleaner/stage hooks/channels/text memory |
| [luademo](example/luademo) | Lua | Full-featured Lua example covering the whole v0.8.0 Lua SDK surface |
| [qq](example/qq) | Go | QQ messaging integration (NapCat), 17 tools, full input/output channel wiring |
| [a2a](example/a2a) | Go | Agent-to-Agent protocol communication |
| [ai_image](example/ai_image) | Go | AI image generation |
| [bili](example/bili) | Go | Bilibili video downloading |
| [browser](example/browser) | Go | Web search, page fetching, browser rendering |
| [calendar](example/calendar) | Go | Calendar management |
| [editdoc](example/editdoc) | Go | Document editing |
| [files](example/files) | Go | File management |
| [memo](example/memo) | Go | Memos (PreAction injection + scheduled reminders) |
| [music](example/music) | Go | Music playback |
| [ocr](example/ocr) | Go | Optical character recognition |
| [rss](example/rss) | Go | RSS subscriptions |
| [sanitizer](example/sanitizer) | Go | Content sanitization / safety filtering |
## Building & Installing
### Build
```bash
plugindev 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).
### Install
Via the pluginmgr HTTP API (default port 9876, listening on 127.0.0.1 only, no auth):
```bash
# Local path
curl -X POST http://127.0.0.1:9876/plugins \
-H "Content-Type: application/json" \
-d '{"path": "/path/to/my-plugin.hmap"}'
# Upload binary directly
curl -X POST http://127.0.0.1:9876/plugins \
--data-binary @dist/my-plugin.hmap
```
Or upload via the WebUI plugin management page, or manually place the `.hmap` in the plugin directory and restart the platform.