mirror of
https://gitcode.com/JianFeeeee/homeagent-sdk.git
synced 2026-10-02 15:14:37 +00:00
feat(sdk): 反代声明(ProxyDef / RegisterProxy)—— 插件声明服务,HomeAgent 反代出去
配套核心仓「webui 通用反向代理」。SDK 1.4.0 尚未发布,接口未冻结,
本次按开发期自由变更处理(正式发版时并入版本号推进)。
## 声明契约
plugin.json 的 proxies 字段(声明式,静态可发现)或 RegisterProxy
(运行期,供没有 plugin.json 的内置插件用):
{"name":"ui","host":"myapp","path":"/p/myapp","strip_path":true,
"target":"127.0.0.1:12100","auth":"homeagent"}
命名与既有能力对齐(ToolDef / ChannelDef / ConfigDef / RegisterTool /
ToolRegistrar)——第一版写成 ProxyDecl / DeclareProxy / ProxyDeclarer
被评审指出「跟 SDK 其他接口不是一个风格」,已全面改名。
## strip_path:Path 的两种语义
Path 不能一刀切成「原样保留」,真实需求有两种且**不能自动判定**
(同一个 path 在两种语义下都说得通,猜错即全部 404 且像上游故障):
strip_path 缺省/false(别名模式)—— path 是上游真实路径的一部分
/api/v1/device/ws + path=/api/v1/device → 上游收到原样
适用:客户端**已硬编码**路径的机器接口(设备网关即如此)
strip_path=true(前缀模式)—— path 只是门户上的挂载点
/p/myapp/api/status + path=/p/myapp → 上游收到 /api/status
适用:自带 UI 的服务(前端用相对路径)
非法组合(strip_path 而无 path)被 ValidateProxyDef 挡住。
## 单一入口原则(契约级要求)
一个声明 = 一个入口。两种挂载形态对「根路径」处理截然不同:
Host 形态下根路径是插件的根(fetch('/api/x') 天然正确);
Path 形态下根路径**属于门户**,同样代码会打到门户自己身上
(静默错路由:页面能开、功能全坏)。
故被反代的插件必须**一律使用相对路径**,绝不硬编码以 / 开头的绝对路径。
这样同一份前端在两种形态下都正确,插件不必知道自己被挂在哪,
反代层也能按外部条件(子域是否有证书/放行)自由选择形态。
## 判据
sdk/proxy_test.go:两种语义的映射、非法组合、单一入口原则的契约存在性。
hmapdev proxy_config_test.go:schema 漂移保护(新增字段忘了同步就判红)、
非法声明在**打包时**就被拒(不必装到 HomeAgent 才看到)。
两模块 go test 全绿;文档站已重新生成(ProxyDef 与单一入口原则进入
docs/api/misc.md 与 llms-full.txt)。
## 顺带修回的一处(此前随工作树丢失)
writePluginJSON 漏写 proxies 键 —— 漏写的话插件装得上、启动正常、
就是不出现,没有任何报错。该 bug 曾在核心仓侧出现过(判据抓到过),
这次移植时由 TestWritePluginJSONPreservesProxies 再次判红并修复。
This commit is contained in:
@ -57,7 +57,7 @@ OutputChannelUnregistrar 注销一个输出通道。
|
||||
func (s *PluginSDK) SetDocMemoryAPI(dm DocMemoryAPI)
|
||||
```
|
||||
|
||||
<small>`plugin.go:614`</small>
|
||||
<small>`plugin.go:619`</small>
|
||||
|
||||
### `PluginSDK.SetEventSubscriber`
|
||||
|
||||
@ -68,7 +68,7 @@ func (s *PluginSDK) SetDocMemoryAPI(dm DocMemoryAPI)
|
||||
func (s *PluginSDK) SetEventSubscriber(es EventSubscriber)
|
||||
```
|
||||
|
||||
<small>`plugin.go:638`</small>
|
||||
<small>`plugin.go:643`</small>
|
||||
|
||||
### `PluginSDK.SetIOInjector`
|
||||
|
||||
@ -81,7 +81,7 @@ func (s *PluginSDK) SetIOInjector(io IOInjector)
|
||||
|
||||
SetIOInjector sets the IO injector (called by the core at startup).
|
||||
|
||||
<small>`plugin.go:595`</small>
|
||||
<small>`plugin.go:600`</small>
|
||||
|
||||
### `PluginSDK.SetInputChannelRegistrar`
|
||||
|
||||
@ -94,7 +94,7 @@ func (s *PluginSDK) SetInputChannelRegistrar(r InputChannelRegistrar)
|
||||
|
||||
SetInputChannelRegistrar sets the input channel registrar (called by the core at startup).
|
||||
|
||||
<small>`plugin.go:588`</small>
|
||||
<small>`plugin.go:593`</small>
|
||||
|
||||
### `PluginSDK.SetKnowledgeAPI`
|
||||
|
||||
@ -105,7 +105,7 @@ SetInputChannelRegistrar sets the input channel registrar (called by the core at
|
||||
func (s *PluginSDK) SetKnowledgeAPI(kn KnowledgeAPI)
|
||||
```
|
||||
|
||||
<small>`plugin.go:620`</small>
|
||||
<small>`plugin.go:625`</small>
|
||||
|
||||
### `PluginSDK.SetLLMAPI`
|
||||
|
||||
@ -116,7 +116,7 @@ func (s *PluginSDK) SetKnowledgeAPI(kn KnowledgeAPI)
|
||||
func (s *PluginSDK) SetLLMAPI(llm LLMAPI)
|
||||
```
|
||||
|
||||
<small>`plugin.go:626`</small>
|
||||
<small>`plugin.go:631`</small>
|
||||
|
||||
### `PluginSDK.SetMemoryAPI`
|
||||
|
||||
@ -129,7 +129,7 @@ func (s *PluginSDK) SetMemoryAPI(mem MemoryAPI)
|
||||
|
||||
SetMemoryAPI sets the memory API (called by the core at startup).
|
||||
|
||||
<small>`plugin.go:602`</small>
|
||||
<small>`plugin.go:607`</small>
|
||||
|
||||
### `PluginSDK.SetOutputChannelRegistrar`
|
||||
|
||||
@ -142,7 +142,7 @@ func (s *PluginSDK) SetOutputChannelRegistrar(r OutputChannelRegistrar)
|
||||
|
||||
SetOutputChannelRegistrar sets the output channel registrar (called by the core at startup).
|
||||
|
||||
<small>`plugin.go:574`</small>
|
||||
<small>`plugin.go:579`</small>
|
||||
|
||||
### `PluginSDK.SetOutputChannelUnregistrar`
|
||||
|
||||
@ -155,7 +155,7 @@ func (s *PluginSDK) SetOutputChannelUnregistrar(r OutputChannelUnregistrar)
|
||||
|
||||
SetOutputChannelUnregistrar sets the output channel unregistrar (called by the core at startup).
|
||||
|
||||
<small>`plugin.go:581`</small>
|
||||
<small>`plugin.go:586`</small>
|
||||
|
||||
### `PluginSDK.SetPluginMgrAPI`
|
||||
|
||||
@ -168,7 +168,7 @@ func (s *PluginSDK) SetPluginMgrAPI(pm PluginMgrAPI)
|
||||
|
||||
SetPluginMgrAPI sets the plugin manager API (called by the bridge at startup).
|
||||
|
||||
<small>`plugin.go:645`</small>
|
||||
<small>`plugin.go:650`</small>
|
||||
|
||||
### `PluginSDK.SetSocialAPI`
|
||||
|
||||
@ -179,7 +179,7 @@ SetPluginMgrAPI sets the plugin manager API (called by the bridge at startup).
|
||||
func (s *PluginSDK) SetSocialAPI(social SocialAPI)
|
||||
```
|
||||
|
||||
<small>`plugin.go:632`</small>
|
||||
<small>`plugin.go:637`</small>
|
||||
|
||||
### `PluginSDK.SetTextMemoryAPI`
|
||||
|
||||
@ -190,7 +190,7 @@ func (s *PluginSDK) SetSocialAPI(social SocialAPI)
|
||||
func (s *PluginSDK) SetTextMemoryAPI(tm TextMemoryAPI)
|
||||
```
|
||||
|
||||
<small>`plugin.go:608`</small>
|
||||
<small>`plugin.go:613`</small>
|
||||
|
||||
### `ToolRegistrar`
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ func (s *PluginSDK) Events() EventSubscriber
|
||||
|
||||
Events returns the event subscriber for listening to kernel events (may be nil if not available).
|
||||
|
||||
<small>`plugin.go:446`</small>
|
||||
<small>`plugin.go:451`</small>
|
||||
|
||||
### `PluginSDK.SetEventSubscriber`
|
||||
|
||||
@ -41,7 +41,7 @@ Events returns the event subscriber for listening to kernel events (may be nil i
|
||||
func (s *PluginSDK) SetEventSubscriber(es EventSubscriber)
|
||||
```
|
||||
|
||||
<small>`plugin.go:638`</small>
|
||||
<small>`plugin.go:643`</small>
|
||||
|
||||
### `PluginSDK.SetOutputChannelUnregistrar`
|
||||
|
||||
@ -54,7 +54,7 @@ func (s *PluginSDK) SetOutputChannelUnregistrar(r OutputChannelUnregistrar)
|
||||
|
||||
SetOutputChannelUnregistrar sets the output channel unregistrar (called by the core at startup).
|
||||
|
||||
<small>`plugin.go:581`</small>
|
||||
<small>`plugin.go:586`</small>
|
||||
|
||||
### `PluginSDK.UnregisterOutputChannel`
|
||||
|
||||
@ -67,7 +67,7 @@ func (s *PluginSDK) UnregisterOutputChannel(name string) error
|
||||
|
||||
UnregisterOutputChannel 注销一个输出通道(动态通道随资源生灭时必须调用)。
|
||||
|
||||
<small>`plugin.go:539`</small>
|
||||
<small>`plugin.go:544`</small>
|
||||
|
||||
### `EventSubscriber.Subscribe`
|
||||
|
||||
|
||||
@ -280,7 +280,7 @@ blocks 会落进媒体存储被记忆引用捕获,同时作为当前轮 conten
|
||||
的「下一轮 tool message」语义。
|
||||
等价于 InjectInputMediaOpts(..., InjectOptions{})。
|
||||
|
||||
<small>`plugin.go:701`</small>
|
||||
<small>`plugin.go:706`</small>
|
||||
|
||||
### `PluginSDK.InjectInputMediaOpts`
|
||||
|
||||
@ -290,7 +290,7 @@ func (s *PluginSDK) InjectInputMediaOpts(source, channel, text string, blocks []
|
||||
|
||||
InjectInputMediaOpts 注入带媒体块的输入,并声明记忆/裁剪行为。
|
||||
|
||||
<small>`plugin.go:740`</small>
|
||||
<small>`plugin.go:745`</small>
|
||||
|
||||
### `PluginSDK.InjectInputMediaSync`
|
||||
|
||||
@ -301,7 +301,7 @@ func (s *PluginSDK) InjectInputMediaSync(source, channel, text string, blocks []
|
||||
InjectInputMediaSync 注入带媒体内容块的输入并同步等待 agent 回复。
|
||||
等价于 InjectInputMediaSyncOpts(..., InjectOptions{})。
|
||||
|
||||
<small>`plugin.go:707`</small>
|
||||
<small>`plugin.go:712`</small>
|
||||
|
||||
### `PluginSDK.InjectInputMediaSyncOpts`
|
||||
|
||||
@ -311,7 +311,7 @@ func (s *PluginSDK) InjectInputMediaSyncOpts(source, channel, text string, block
|
||||
|
||||
InjectInputMediaSyncOpts 注入带媒体块的输入并同步等待回复,同时声明记忆/裁剪行为。
|
||||
|
||||
<small>`plugin.go:747`</small>
|
||||
<small>`plugin.go:752`</small>
|
||||
|
||||
### `PluginSDK.InjectInputSync`
|
||||
|
||||
@ -330,7 +330,7 @@ to the source channel by the caller.
|
||||
| [`a2a`](../examples/index.md#a2a) | `example/a2a/plugin.go:345` | `reply := p.sdk.InjectInputSync(p.name, p.name,` |
|
||||
| [`acp`](../examples/index.md#acp) | `example/acp/plugin.go:237` | `reply = p.sdk.InjectInputSync(p.name, p.name,` |
|
||||
|
||||
<small>`plugin.go:692`</small>
|
||||
<small>`plugin.go:697`</small>
|
||||
|
||||
### `PluginSDK.InjectInputSyncOpts`
|
||||
|
||||
@ -340,7 +340,7 @@ func (s *PluginSDK) InjectInputSyncOpts(source, channel, text string, opts Injec
|
||||
|
||||
InjectInputSyncOpts 注入输入并同步等待回复,同时在这次注入上声明记忆/裁剪行为。
|
||||
|
||||
<small>`plugin.go:731`</small>
|
||||
<small>`plugin.go:736`</small>
|
||||
|
||||
### `PluginSDK.InjectInterruptMedia`
|
||||
|
||||
@ -351,7 +351,7 @@ func (s *PluginSDK) InjectInterruptMedia(source, channel, text string, blocks []
|
||||
InjectInterruptMedia 注入带媒体内容块的中断,可抢占当前 LLM 处理。
|
||||
blocks 随中断消息一起发给模型。
|
||||
|
||||
<small>`plugin.go:764`</small>
|
||||
<small>`plugin.go:769`</small>
|
||||
|
||||
### `PluginSDK.InjectInterruptMediaOpts`
|
||||
|
||||
@ -361,7 +361,7 @@ func (s *PluginSDK) InjectInterruptMediaOpts(source, channel, text string, block
|
||||
|
||||
InjectInterruptMediaOpts 注入带媒体块的中断,并声明记忆/裁剪行为。
|
||||
|
||||
<small>`plugin.go:756`</small>
|
||||
<small>`plugin.go:761`</small>
|
||||
|
||||
### `PluginSDK.InjectInterruptText`
|
||||
|
||||
@ -372,7 +372,7 @@ func (s *PluginSDK) InjectInterruptText(source, channel, text string)
|
||||
InjectInterruptText injects a text interrupt that can preempt current LLM processing.
|
||||
等价于 InjectInterruptTextOpts(..., InjectOptions{}):记入记忆、不裁剪。
|
||||
|
||||
<small>`plugin.go:673`</small>
|
||||
<small>`plugin.go:678`</small>
|
||||
|
||||
### `PluginSDK.InjectInterruptTextOpts`
|
||||
|
||||
@ -394,7 +394,7 @@ InjectInterruptTextOpts 注入可抢占当前处理的中断文本。
|
||||
| [`memo`](../examples/index.md#memo) | `example/memo/plugin.go:299` | `p.sdk.InjectInterruptTextOpts(p.name, p.name,` |
|
||||
| [`qq`](../examples/index.md#qq) | `example/qq/plugin.go:1493` | `p.sdk.InjectInterruptTextOpts(p.name, p.name, text, sdk.InjectOptions{` |
|
||||
|
||||
<small>`plugin.go:724`</small>
|
||||
<small>`plugin.go:729`</small>
|
||||
|
||||
### `InjectOptions`
|
||||
|
||||
@ -435,7 +435,7 @@ func (s *PluginSDK) InjectText(source, channel, text string)
|
||||
InjectText injects a text message into the agent pipeline.
|
||||
等价于 InjectTextOpts(..., InjectOptions{}):记入记忆、不裁剪。
|
||||
|
||||
<small>`plugin.go:679`</small>
|
||||
<small>`plugin.go:684`</small>
|
||||
|
||||
### `PluginSDK.InjectTextNoMemory`
|
||||
|
||||
@ -452,7 +452,7 @@ InjectTextNoMemory injects a text message without generating memory.
|
||||
|---|---|---|
|
||||
| [`browser`](../examples/index.md#browser) | `example/browser/plugin.go:1114` | `p.sdk.InjectTextNoMemory(p.name, p.name, fmt.Sprintf("[浏览器 %s 已导航到 %s]", id, rawURL))` |
|
||||
|
||||
<small>`plugin.go:685`</small>
|
||||
<small>`plugin.go:690`</small>
|
||||
|
||||
### `PluginSDK.InjectTextOpts`
|
||||
|
||||
@ -462,7 +462,7 @@ func (s *PluginSDK) InjectTextOpts(source, channel, text string, opts InjectOpti
|
||||
|
||||
InjectTextOpts 注入文本到 agent,并在这一次注入上声明记忆与裁剪行为。
|
||||
|
||||
<small>`plugin.go:714`</small>
|
||||
<small>`plugin.go:719`</small>
|
||||
|
||||
### `PriorityL1`
|
||||
|
||||
@ -577,7 +577,7 @@ def.Cleaner: 计算层对输入文本清洗后(不改原文)再向量化/
|
||||
| [`browser`](../examples/index.md#browser) | `example/browser/plugin.go:209` | `_ = s.RegisterInputChannel(p.name, sdk.ChannelDef{})` |
|
||||
| [`calendar`](../examples/index.md#calendar) | `example/calendar/plugin.go:281` | `_ = s.RegisterInputChannel("calendar", sdk.ChannelDef{NoMemory: true})` |
|
||||
|
||||
<small>`plugin.go:561`</small>
|
||||
<small>`plugin.go:566`</small>
|
||||
|
||||
### `PluginSDK.RegisterOutputChannel`
|
||||
|
||||
@ -614,7 +614,7 @@ handler: receives args map with keys: payload (string), type (string), meta (str
|
||||
| [`qq`](../examples/index.md#qq) | `example/qq/plugin.go:411` | `s.RegisterOutputChannel("qq", sdk.CapText\|sdk.CapFile\|sdk.CapImage\|sdk.CapAudio,` |
|
||||
| [`weather`](../examples/index.md#weather) | `example/weather/plugin.go:104` | `if err := s.RegisterOutputChannel(tp+"weather_out", 0, "push weather to user", sdk.ChannelDef{` |
|
||||
|
||||
<small>`plugin.go:528`</small>
|
||||
<small>`plugin.go:533`</small>
|
||||
|
||||
### `PluginSDK.SetToolBlocks`
|
||||
|
||||
@ -625,7 +625,7 @@ func (s *PluginSDK) SetToolBlocks(blocks []ContentBlock)
|
||||
SetToolBlocks 在工具处理函数内注入多模态内容块,内核在下一条 tool message
|
||||
的 content 数组里带上它们。需要「本轮就让模型看到」时用 InjectInputMedia。
|
||||
|
||||
<small>`plugin.go:772`</small>
|
||||
<small>`plugin.go:777`</small>
|
||||
|
||||
### `ValidContextPolicy`
|
||||
|
||||
|
||||
@ -70,3 +70,10 @@ SDK 里的取值枚举。其中带「仅内置」标注的取值在内核侧会
|
||||
| `CapAudio` | |
|
||||
| `CapStructured` | |
|
||||
|
||||
## ProxyAuthHomeAgent 等
|
||||
|
||||
| 名称 | 说明 |
|
||||
|---|---|
|
||||
| `ProxyAuthHomeAgent` | ProxyAuthHomeAgent 表示由 HomeAgent 统一保护:浏览器走门户会话 |
|
||||
| `ProxyAuthNone` | ProxyAuthNone 表示不经 HomeAgent 鉴权,直接把请求转发给上游。 |
|
||||
|
||||
|
||||
@ -65,5 +65,5 @@ func (s *PluginSDK) Events() EventSubscriber
|
||||
|
||||
Events returns the event subscriber for listening to kernel events (may be nil if not available).
|
||||
|
||||
<small>`plugin.go:446`</small>
|
||||
<small>`plugin.go:451`</small>
|
||||
|
||||
|
||||
@ -87,7 +87,7 @@ func (s *PluginSDK) AutoRestart() bool
|
||||
|
||||
AutoRestart 返回插件是否允许自动重启。
|
||||
|
||||
<small>`plugin.go:791`</small>
|
||||
<small>`plugin.go:796`</small>
|
||||
|
||||
### `PluginSDK.PluginMgr`
|
||||
|
||||
@ -98,7 +98,7 @@ func (s *PluginSDK) PluginMgr() PluginMgrAPI
|
||||
PluginMgr returns the plugin manager API (ReloadOne / ReloadPlugins / list).
|
||||
May be nil if the host did not wire it.
|
||||
|
||||
<small>`plugin.go:653`</small>
|
||||
<small>`plugin.go:658`</small>
|
||||
|
||||
### `PluginSDK.PluginName`
|
||||
|
||||
@ -108,7 +108,7 @@ func (s *PluginSDK) PluginName() string
|
||||
|
||||
PluginName returns the name of the plugin.
|
||||
|
||||
<small>`plugin.go:397`</small>
|
||||
<small>`plugin.go:402`</small>
|
||||
|
||||
### `PluginSDK.RegisterOnRemoveHandler`
|
||||
|
||||
@ -129,7 +129,7 @@ RegisterOnRemoveHandler 注册插件被删除(卸载)时的清理回调。
|
||||
| [`memo`](../examples/index.md#memo) | `example/memo/plugin.go:69` | `s.RegisterOnRemoveHandler(p.cleanupData)` |
|
||||
| [`rss`](../examples/index.md#rss) | `example/rss/plugin.go:127` | `s.RegisterOnRemoveHandler(p.cleanupData)` |
|
||||
|
||||
<small>`plugin.go:826`</small>
|
||||
<small>`plugin.go:831`</small>
|
||||
|
||||
### `PluginSDK.RegisterPluginAPI`
|
||||
|
||||
@ -139,7 +139,7 @@ func (s *PluginSDK) RegisterPluginAPI(name string) error
|
||||
|
||||
RegisterPluginAPI registers this plugin's API for access by other plugins.
|
||||
|
||||
<small>`plugin.go:502`</small>
|
||||
<small>`plugin.go:507`</small>
|
||||
|
||||
### `PluginSDK.RegisterStopHandler`
|
||||
|
||||
@ -159,7 +159,7 @@ RegisterStopHandler 注册插件停止阶段的清理回调。
|
||||
| [`calendar`](../examples/index.md#calendar) | `example/calendar/plugin.go:294` | `s.RegisterStopHandler(p.saveEvents)` |
|
||||
| [`deepsearch`](../examples/index.md#deepsearch) | `example/deepsearch/plugin.go:695` | `s.RegisterStopHandler(func() { p.shutdownSearxng() })` |
|
||||
|
||||
<small>`plugin.go:801`</small>
|
||||
<small>`plugin.go:806`</small>
|
||||
|
||||
### `PluginSDK.RunOnRemoveHandlers`
|
||||
|
||||
@ -170,7 +170,7 @@ func (s *PluginSDK) RunOnRemoveHandlers()
|
||||
RunOnRemoveHandlers 执行全部已注册的 onRemove handler(后注册先执行,执行后清空,幂等)。
|
||||
由内核在卸载插件(registry.RemovePlugin)时、插件 Stop() 之后执行。
|
||||
|
||||
<small>`plugin.go:837`</small>
|
||||
<small>`plugin.go:842`</small>
|
||||
|
||||
### `PluginSDK.RunStopHandlers`
|
||||
|
||||
@ -181,7 +181,7 @@ func (s *PluginSDK) RunStopHandlers()
|
||||
RunStopHandlers 执行全部已注册的 stop handler(后注册先执行,执行后清空,幂等)。
|
||||
由内核(内置插件)或插件桥接层(外部插件 z_bridge 的 StopPlugin)在调用插件 Stop() 前执行。
|
||||
|
||||
<small>`plugin.go:812`</small>
|
||||
<small>`plugin.go:817`</small>
|
||||
|
||||
### `PluginSDK.SetAutoRestart`
|
||||
|
||||
@ -205,5 +205,5 @@ SetAutoRestart 设置插件崩溃后内核是否自动重启它。
|
||||
| [`ai_image`](../examples/index.md#ai_image) | `example/ai_image/plugin.go:110` | `s.SetAutoRestart(true)` |
|
||||
| [`bili`](../examples/index.md#bili) | `example/bili/plugin.go:25` | `s.SetAutoRestart(true)` |
|
||||
|
||||
<small>`plugin.go:784`</small>
|
||||
<small>`plugin.go:789`</small>
|
||||
|
||||
|
||||
@ -46,5 +46,5 @@ func (s *PluginSDK) LLM() LLMAPI
|
||||
|
||||
LLM returns the LLM provider API (may be nil if not available).
|
||||
|
||||
<small>`plugin.go:432`</small>
|
||||
<small>`plugin.go:437`</small>
|
||||
|
||||
|
||||
@ -236,7 +236,7 @@ func (s *PluginSDK) DocMemory() DocMemoryAPI
|
||||
|
||||
DocMemory returns the document memory API (may be nil if not available).
|
||||
|
||||
<small>`plugin.go:418`</small>
|
||||
<small>`plugin.go:423`</small>
|
||||
|
||||
### `Entity`
|
||||
|
||||
@ -278,7 +278,7 @@ Knowledge returns the knowledge store API (may be nil if not available).
|
||||
|---|---|---|
|
||||
| [`recoverydiag`](../examples/index.md#recoverydiag) | `example/recoverydiag/plugin.go:978` | `if p.sdk != nil && p.sdk.Knowledge() != nil {` |
|
||||
|
||||
<small>`plugin.go:425`</small>
|
||||
<small>`plugin.go:430`</small>
|
||||
|
||||
### `MediaAttachment`
|
||||
|
||||
@ -308,7 +308,7 @@ func (s *PluginSDK) Memory() MemoryAPI
|
||||
|
||||
Memory returns the graph memory API (may be nil if not available).
|
||||
|
||||
<small>`plugin.go:404`</small>
|
||||
<small>`plugin.go:409`</small>
|
||||
|
||||
### `PersonProfile`
|
||||
|
||||
@ -338,7 +338,7 @@ func (s *PluginSDK) Social() SocialAPI
|
||||
|
||||
Social returns the social graph API (may be nil if not available).
|
||||
|
||||
<small>`plugin.go:439`</small>
|
||||
<small>`plugin.go:444`</small>
|
||||
|
||||
### `SocialRelation`
|
||||
|
||||
@ -366,7 +366,7 @@ func (s *PluginSDK) TextMemory() TextMemoryAPI
|
||||
|
||||
TextMemory returns the text memory API (may be nil if not available).
|
||||
|
||||
<small>`plugin.go:411`</small>
|
||||
<small>`plugin.go:416`</small>
|
||||
|
||||
### `Triple`
|
||||
|
||||
|
||||
209
docs/api/misc.md
209
docs/api/misc.md
@ -680,7 +680,17 @@ Append(evt TextEvent) error
|
||||
type AudioURL struct { URL string `json:"url"` }
|
||||
```
|
||||
|
||||
<small>`plugin.go:862`</small>
|
||||
<small>`plugin.go:867`</small>
|
||||
|
||||
### `EffectiveProxyAuth`
|
||||
|
||||
```go
|
||||
func EffectiveProxyAuth(auth string) string
|
||||
```
|
||||
|
||||
EffectiveProxyAuth 返回生效的鉴权模式(空串归一化为 ProxyAuthHomeAgent)。
|
||||
|
||||
<small>`proxy.go:169`</small>
|
||||
|
||||
### `ImageURL`
|
||||
|
||||
@ -688,7 +698,7 @@ type AudioURL struct { URL string `json:"url"` }
|
||||
type ImageURL struct { URL string `json:"url"` Detail string `json:"detail,omitempty"` }
|
||||
```
|
||||
|
||||
<small>`plugin.go:857`</small>
|
||||
<small>`plugin.go:862`</small>
|
||||
|
||||
### `MemItem`
|
||||
|
||||
@ -700,6 +710,19 @@ MemItem represents a memory item in stage context.
|
||||
|
||||
<small>`plugin.go:179`</small>
|
||||
|
||||
### `NormalizeProxyHost`
|
||||
|
||||
```go
|
||||
func NormalizeProxyHost(pluginName string) string
|
||||
```
|
||||
|
||||
NormalizeProxyHost 由插件名派生默认 Host 标签。
|
||||
|
||||
下划线转连字符:插件名允许下划线(huawei_smarthome),但 DNS label 不允许,
|
||||
直接用会导致该子域名无法解析——这里统一转换,避免每个插件各自碰运气。
|
||||
|
||||
<small>`proxy.go:202`</small>
|
||||
|
||||
### `PluginSDK`
|
||||
|
||||
```go
|
||||
@ -711,6 +734,139 @@ It wraps tool registration, settings, memory, knowledge, LLM, and IO injection.
|
||||
|
||||
<small>`plugin.go:337`</small>
|
||||
|
||||
### `ProxyAuthHomeAgent`
|
||||
|
||||
```go
|
||||
const ProxyAuthHomeAgent
|
||||
```
|
||||
|
||||
ProxyAuthHomeAgent 表示由 HomeAgent 统一保护:浏览器走门户会话
|
||||
(homeagent_session cookie),非浏览器客户端走 X-API-Key。
|
||||
两者都没有时返回 401,而不是把请求透传给上游。
|
||||
|
||||
<small>`proxy.go:149`</small>
|
||||
|
||||
### `ProxyAuthNone`
|
||||
|
||||
```go
|
||||
const ProxyAuthNone
|
||||
```
|
||||
|
||||
ProxyAuthNone 表示不经 HomeAgent 鉴权,直接把请求转发给上游。
|
||||
|
||||
适用场景:上游自己有鉴权且调用方不是浏览器(设备/嵌入式客户端),
|
||||
或上游是刻意公开的服务。选用它意味着**信任上游自身的鉴权**,
|
||||
且该服务在网络层可达范围内对所有人开放。
|
||||
|
||||
<small>`proxy.go:156`</small>
|
||||
|
||||
### `ProxyDef`
|
||||
|
||||
```go
|
||||
type ProxyDef struct { // Name 是同一插件内多条声明的唯一标识(如 "ui"、"api")。 // 运行期由 RegisterProxy 的第一个参数填入;声明式由 …
|
||||
```
|
||||
|
||||
反向代理声明:插件告诉 HomeAgent「我起了个 HTTP 服务,请把它反代出去」。
|
||||
|
||||
为什么需要:插件自带 Web UI / HTTP API 时,监听地址在插件自己的配置里
|
||||
(如 127.0.0.1:12100),外部无从得知;而 webui 的对外端口通常只有一个
|
||||
(默认 :8080,且常经 frp 单端口隧道穿透)。没有声明机制时,用户只能
|
||||
「知道端口 + 自己配转发」,插件换端口就失效。
|
||||
|
||||
设计取舍——**声明式而非注册式**:声明写在 plugin.json 里,由 HomeAgent
|
||||
在加载插件时读取聚合,而不是让插件在运行期调 API 注册。理由:
|
||||
1. 静态可发现:未启动/已崩溃的插件,其服务声明依然可见(可给出准确报错
|
||||
「插件 X 声明了 ui 但目标 127.0.0.1:12100 不可达」,而不是静默 404);
|
||||
2. 可版本化:声明随插件包一起分发、可 diff、可审计;
|
||||
3. 旧内核无害:manifest 解析忽略未知字段,未支持该能力的 HomeAgent 读旧
|
||||
插件、或旧 HomeAgent 读新插件都不会报错。
|
||||
|
||||
与 ToolDef / ChannelDef / ConfigDef 同族:SDK 定义声明契约,内核实现行为。
|
||||
声明方式与其它能力一致 —— 在 Start() 里调 RegisterProxy(name, def),
|
||||
或写进 plugin.json 的 proxies 字段(外部插件两种都支持)。
|
||||
|
||||
安全性:**不声明 = 不被反代**。声明本身就是能力声明,因此不需要在
|
||||
capabilities 里另外开一个开关——最小权限默认生效。
|
||||
|
||||
# 单一入口原则(强制要求)
|
||||
|
||||
**一个声明 = 一个入口**。被反代的插件必须让它的全部资源与接口都能从
|
||||
该入口的一个基准路径出发访问到,不得依赖「入口之外的根路径」。
|
||||
|
||||
为什么强制:反代有两种挂载形态,而它们对「根路径」的处理截然不同——
|
||||
|
||||
Host 形态(host):插件独占 <标签>.<基域名>,根路径就是插件的根。
|
||||
根绝对路径(fetch('/api/x'))**天然正确**。
|
||||
Path 形态(path):插件挂在门户自身 host 的某个前缀下,根路径属于**门户**。
|
||||
此时插件里的 fetch('/api/x') 会打到门户自己的 /api/x
|
||||
—— 静默错路由,页面能开但功能全坏。
|
||||
|
||||
于是「同一个插件必须同时支持两种形态」这条要求,等价于:
|
||||
|
||||
**插件内部一律使用相对路径**(或基于 <base>/location 推导的路径),
|
||||
绝不硬编码以 / 开头的绝对路径。
|
||||
|
||||
这样同一份前端在两种形态下都正确,插件作者也不必知道自己被挂在哪。
|
||||
反代层据此可以:外部子域可用时给 Host 形态,子域不可用(证书/放行限制)
|
||||
时给 Path 形态,**无需插件配合改动**。
|
||||
|
||||
自检(插件作者在本地就该做):把页面挂到 <门户>/<任意前缀>/ 下访问,
|
||||
所有请求都必须仍然打到插件自己。
|
||||
|
||||
本项目实测案例:某插件前端写死 fetch('/api/status'),配在
|
||||
/p/huawei/ 下会打到门户的 /api/status(404 或返回门户数据);
|
||||
改成相对路径后两种形态同时可用。
|
||||
ProxyDef 是一个服务的**反代声明体**。
|
||||
|
||||
与 ToolDef 同构:Name 同时出现在字段与 RegisterProxy 的第一个参数里
|
||||
(ToolDef 也是这么做的 —— 字段供 plugin.json 序列化,参数供运行期调用)。
|
||||
Name 只用于展示、日志与冲突提示,**不参与路由**(路由键是 Host 与 Path)。
|
||||
|
||||
<small>`proxy.go:64`</small>
|
||||
|
||||
### `ProxyRegistrar`
|
||||
|
||||
```go
|
||||
type ProxyRegistrar func(name string, def ProxyDef)
|
||||
```
|
||||
|
||||
ProxyRegistrar 由内核注入(与 ToolRegistrar / InputChannelRegistrar 同族)。
|
||||
插件不直接调它,用 RegisterProxy。
|
||||
|
||||
为什么需要运行期注册(明明有 plugin.json 自动发现):**内置插件**
|
||||
(编译进内核、没有独立插件目录与 plugin.json,如 remotedevice)扫不到;
|
||||
而它们恰恰最需要被反代出去(设备网关就是内置的)。两种来源互补:
|
||||
- 外部插件 → plugin.json 的 proxies(静态,未启动也可见)
|
||||
- 内置插件 → RegisterProxy(运行期,随 Start 注册)
|
||||
|
||||
<small>`proxy.go:306`</small>
|
||||
|
||||
### `PluginSDK.RegisterProxy`
|
||||
|
||||
```go
|
||||
func (s *PluginSDK) RegisterProxy(name string, def ProxyDef)
|
||||
```
|
||||
|
||||
RegisterProxy 声明一个需要 HomeAgent 反代出去的服务。
|
||||
|
||||
与 RegisterTool / RegisterInputChannel / RegisterOutputChannel 同一风格:
|
||||
显式给名字 + 声明体。名字用于展示、日志与冲突提示(不参与路由 —— 路由键是
|
||||
def.Host / def.Path)。
|
||||
|
||||
用法(通常在 Start 里调用):
|
||||
|
||||
s.RegisterProxy("ui", sdk.ProxyDef{
|
||||
Host: "myapp", Target: "127.0.0.1:12100",
|
||||
})
|
||||
|
||||
声明立即生效(反代表在下一次请求时重建)。**不做去重**:同一 Host/Path
|
||||
被两条声明占用时由反代层判定冲突并明确报错,而不是在这里静默吞掉 ——
|
||||
插件作者需要看见冲突。
|
||||
|
||||
与 plugin.json 的 proxies 字段等价:写哪个都行,两者会合并(同名以本调用为准)。
|
||||
|
||||
<small>`proxy.go:335`</small>
|
||||
|
||||
### `SDKVersion`
|
||||
|
||||
```go
|
||||
@ -721,6 +877,16 @@ SDKVersion 是对外暴露的 SDK 版本号。
|
||||
|
||||
<small>`plugin.go:10`</small>
|
||||
|
||||
### `PluginSDK.SetProxyRegistrar`
|
||||
|
||||
```go
|
||||
func (s *PluginSDK) SetProxyRegistrar(r ProxyRegistrar)
|
||||
```
|
||||
|
||||
SetProxyRegistrar 由内核注入。插件不直接调它(与 SetInputChannelRegistrar 同族)。
|
||||
|
||||
<small>`proxy.go:309`</small>
|
||||
|
||||
### `PluginSDK.UnregisterOutputChannel`
|
||||
|
||||
!!! warning "仅内核内置插件可用"
|
||||
@ -732,5 +898,42 @@ func (s *PluginSDK) UnregisterOutputChannel(name string) error
|
||||
|
||||
UnregisterOutputChannel 注销一个输出通道(动态通道随资源生灭时必须调用)。
|
||||
|
||||
<small>`plugin.go:539`</small>
|
||||
<small>`plugin.go:544`</small>
|
||||
|
||||
### `ValidProxyAuth`
|
||||
|
||||
```go
|
||||
func ValidProxyAuth(auth string) bool
|
||||
```
|
||||
|
||||
ValidProxyAuth 校验 Auth 取值;空串合法(等价 ProxyAuthHomeAgent)。
|
||||
|
||||
<small>`proxy.go:160`</small>
|
||||
|
||||
### `ValidProxyHostLabel`
|
||||
|
||||
```go
|
||||
func ValidProxyHostLabel(label string) bool
|
||||
```
|
||||
|
||||
ValidProxyHostLabel 校验子域名标签是否合法(DNS label 规则)。
|
||||
|
||||
独立成导出函数:插件作者在写声明时、HomeAgent 在加载时、工具链在打包时
|
||||
都要用同一套规则判定,避免三处各写一份而互相不一致。
|
||||
|
||||
<small>`proxy.go:180`</small>
|
||||
|
||||
### `ValidateProxyDef`
|
||||
|
||||
```go
|
||||
func ValidateProxyDef(d ProxyDef) string
|
||||
```
|
||||
|
||||
ValidateProxyDef 校验一条反代声明,返回人类可读的错误说明(合法时为空)。
|
||||
|
||||
为什么要在 SDK 里做校验:HomeAgent 加载插件时必须能明确拒绝坏声明并说明
|
||||
原因(而不是静默忽略导致用户以为配好了);插件作者也需要在本地就能查出
|
||||
拼错的 Target/Host。同一套规则两端共用。
|
||||
|
||||
<small>`proxy.go:229`</small>
|
||||
|
||||
|
||||
@ -193,5 +193,5 @@ sett 在 New 时一次性写入且无 setter,故不需要加锁。
|
||||
| [`ai_image`](../examples/index.md#ai_image) | `example/ai_image/plugin.go:114` | `s.Settings().RegisterDef(sdk.ConfigDef{` |
|
||||
| [`bili`](../examples/index.md#bili) | `example/bili/plugin.go:29` | `s.Settings().RegisterDef(sdk.ConfigDef{` |
|
||||
|
||||
<small>`plugin.go:401`</small>
|
||||
<small>`plugin.go:406`</small>
|
||||
|
||||
|
||||
@ -83,7 +83,7 @@ RegisterStage registers a handler for a pipeline stage.
|
||||
| [`sanitizer`](../examples/index.md#sanitizer) | `example/sanitizer/plugin.go:52` | `s.RegisterStage(sdk.StageOnInput, func(ctx *sdk.StageContext) error {` |
|
||||
| [`weather`](../examples/index.md#weather) | `example/weather/plugin.go:94` | `s.RegisterStage(sdk.StageAfterToolcall, func(ctx *sdk.StageContext) error {` |
|
||||
|
||||
<small>`plugin.go:467`</small>
|
||||
<small>`plugin.go:472`</small>
|
||||
|
||||
### `Stage`
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ ContentBlock 是多模态内容块(OpenAI 格式:text/image_url/audio_url)
|
||||
插件工具返回结果时可用 PluginSDK.SetToolBlocks 注入,让下一轮 LLM
|
||||
请求在 tool message 的 content 数组里带上图片/音频,实现"模型看图/听音频"。
|
||||
|
||||
<small>`plugin.go:850`</small>
|
||||
<small>`plugin.go:855`</small>
|
||||
|
||||
### `PluginSDK.RegisterTool`
|
||||
|
||||
@ -33,7 +33,7 @@ RegisterTool registers a tool that the LLM can call.
|
||||
| [`ai_image`](../examples/index.md#ai_image) | `example/ai_image/plugin.go:159` | `s.RegisterTool(tp+"generate", sdk.ToolDef{` |
|
||||
| [`bili`](../examples/index.md#bili) | `example/bili/plugin.go:47` | `s.RegisterTool(tp+"video", sdk.ToolDef{` |
|
||||
|
||||
<small>`plugin.go:453`</small>
|
||||
<small>`plugin.go:458`</small>
|
||||
|
||||
### `ToolCall`
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 862
|
||||
"l": 867
|
||||
},
|
||||
{
|
||||
"n": "AutoRestart",
|
||||
@ -58,7 +58,7 @@
|
||||
"p": "lifecycle",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 791,
|
||||
"l": 796,
|
||||
"g": [
|
||||
"自动重启",
|
||||
"崩溃自愈",
|
||||
@ -190,7 +190,7 @@
|
||||
"p": "tools",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 850,
|
||||
"l": 855,
|
||||
"g": [
|
||||
"多模态内容块",
|
||||
"图片块",
|
||||
@ -295,7 +295,7 @@
|
||||
"p": "memory",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 418,
|
||||
"l": 423,
|
||||
"g": [
|
||||
"记忆",
|
||||
"内存",
|
||||
@ -327,6 +327,17 @@
|
||||
"导出配置"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "EffectiveProxyAuth",
|
||||
"s": "func EffectiveProxyAuth(auth string) string",
|
||||
"d": "EffectiveProxyAuth 返回生效的鉴权模式(空串归一化为 ProxyAuthHomeAgent)。",
|
||||
"k": "func",
|
||||
"r": "",
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "proxy.go",
|
||||
"l": 169
|
||||
},
|
||||
{
|
||||
"n": "Entity",
|
||||
"s": "type Entity struct { Name string `json:\"name\"` Type string `json:\"type\"` MentionCount int `json:\"mention_count\"` }",
|
||||
@ -545,7 +556,7 @@
|
||||
"p": "events",
|
||||
"b": true,
|
||||
"f": "plugin.go",
|
||||
"l": 446,
|
||||
"l": 451,
|
||||
"g": [
|
||||
"事件",
|
||||
"订阅",
|
||||
@ -671,7 +682,7 @@
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 857
|
||||
"l": 862
|
||||
},
|
||||
{
|
||||
"n": "InjectInputMedia",
|
||||
@ -682,7 +693,7 @@
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 701,
|
||||
"l": 706,
|
||||
"g": [
|
||||
"注入输入",
|
||||
"投喂输入",
|
||||
@ -713,14 +724,14 @@
|
||||
},
|
||||
{
|
||||
"n": "InjectInputMediaOpts",
|
||||
"s": "func (s *PluginSDK) InjectInputMediaOpts(source, channel, text string, blocks []ContentBlock, opts InjectOptions)",
|
||||
"d": "InjectInputMediaOpts 注入带媒体块的输入,并声明记忆/裁剪行为。",
|
||||
"s": "InjectInputMediaOpts(source, channel, text string, blocks []ContentBlock, opts InjectOptions)",
|
||||
"d": "",
|
||||
"k": "method",
|
||||
"r": "PluginSDK",
|
||||
"r": "IOInjector",
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 740,
|
||||
"l": 241,
|
||||
"g": [
|
||||
"注入输入",
|
||||
"投喂输入",
|
||||
@ -732,14 +743,14 @@
|
||||
},
|
||||
{
|
||||
"n": "InjectInputMediaOpts",
|
||||
"s": "InjectInputMediaOpts(source, channel, text string, blocks []ContentBlock, opts InjectOptions)",
|
||||
"d": "",
|
||||
"s": "func (s *PluginSDK) InjectInputMediaOpts(source, channel, text string, blocks []ContentBlock, opts InjectOptions)",
|
||||
"d": "InjectInputMediaOpts 注入带媒体块的输入,并声明记忆/裁剪行为。",
|
||||
"k": "method",
|
||||
"r": "IOInjector",
|
||||
"r": "PluginSDK",
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 241,
|
||||
"l": 745,
|
||||
"g": [
|
||||
"注入输入",
|
||||
"投喂输入",
|
||||
@ -777,7 +788,7 @@
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 707,
|
||||
"l": 712,
|
||||
"g": [
|
||||
"注入输入",
|
||||
"投喂输入",
|
||||
@ -796,7 +807,7 @@
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 747,
|
||||
"l": 752,
|
||||
"g": [
|
||||
"注入输入",
|
||||
"投喂输入",
|
||||
@ -850,7 +861,7 @@
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 692,
|
||||
"l": 697,
|
||||
"g": [
|
||||
"注入输入",
|
||||
"投喂输入",
|
||||
@ -882,7 +893,7 @@
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 731,
|
||||
"l": 736,
|
||||
"g": [
|
||||
"注入输入",
|
||||
"投喂输入",
|
||||
@ -918,27 +929,7 @@
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 764,
|
||||
"g": [
|
||||
"中断注入",
|
||||
"插话",
|
||||
"打断",
|
||||
"抢占",
|
||||
"媒体",
|
||||
"图片",
|
||||
"音频"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "InjectInterruptMediaOpts",
|
||||
"s": "func (s *PluginSDK) InjectInterruptMediaOpts(source, channel, text string, blocks []ContentBlock, opts InjectOptions)",
|
||||
"d": "InjectInterruptMediaOpts 注入带媒体块的中断,并声明记忆/裁剪行为。",
|
||||
"k": "method",
|
||||
"r": "PluginSDK",
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 756,
|
||||
"l": 769,
|
||||
"g": [
|
||||
"中断注入",
|
||||
"插话",
|
||||
@ -970,20 +961,23 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "InjectInterruptText",
|
||||
"s": "func (s *PluginSDK) InjectInterruptText(source, channel, text string)",
|
||||
"d": "InjectInterruptText injects a text interrupt that can preempt current LLM processing.",
|
||||
"n": "InjectInterruptMediaOpts",
|
||||
"s": "func (s *PluginSDK) InjectInterruptMediaOpts(source, channel, text string, blocks []ContentBlock, opts InjectOptions)",
|
||||
"d": "InjectInterruptMediaOpts 注入带媒体块的中断,并声明记忆/裁剪行为。",
|
||||
"k": "method",
|
||||
"r": "PluginSDK",
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 673,
|
||||
"l": 761,
|
||||
"g": [
|
||||
"中断注入",
|
||||
"插话",
|
||||
"打断",
|
||||
"抢占"
|
||||
"抢占",
|
||||
"媒体",
|
||||
"图片",
|
||||
"音频"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1003,6 +997,23 @@
|
||||
"抢占"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "InjectInterruptText",
|
||||
"s": "func (s *PluginSDK) InjectInterruptText(source, channel, text string)",
|
||||
"d": "InjectInterruptText injects a text interrupt that can preempt current LLM processing.",
|
||||
"k": "method",
|
||||
"r": "PluginSDK",
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 678,
|
||||
"g": [
|
||||
"中断注入",
|
||||
"插话",
|
||||
"打断",
|
||||
"抢占"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "InjectInterruptTextOpts",
|
||||
"s": "InjectInterruptTextOpts(source, channel, text string, opts InjectOptions)",
|
||||
@ -1029,7 +1040,7 @@
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 724,
|
||||
"l": 729,
|
||||
"g": [
|
||||
"中断注入",
|
||||
"插话",
|
||||
@ -1079,7 +1090,7 @@
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 679,
|
||||
"l": 684,
|
||||
"g": [
|
||||
"注入文本",
|
||||
"注入消息",
|
||||
@ -1115,7 +1126,7 @@
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 685,
|
||||
"l": 690,
|
||||
"g": [
|
||||
"注入文本",
|
||||
"注入消息",
|
||||
@ -1125,6 +1136,23 @@
|
||||
"内存"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "InjectTextOpts",
|
||||
"s": "func (s *PluginSDK) InjectTextOpts(source, channel, text string, opts InjectOptions)",
|
||||
"d": "InjectTextOpts 注入文本到 agent,并在这一次注入上声明记忆与裁剪行为。",
|
||||
"k": "method",
|
||||
"r": "PluginSDK",
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 719,
|
||||
"g": [
|
||||
"注入文本",
|
||||
"注入消息",
|
||||
"投喂输入",
|
||||
"灌入内容"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "InjectTextOpts",
|
||||
"s": "InjectTextOpts(source, channel, text string, opts InjectOptions)",
|
||||
@ -1142,23 +1170,6 @@
|
||||
"灌入内容"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "InjectTextOpts",
|
||||
"s": "func (s *PluginSDK) InjectTextOpts(source, channel, text string, opts InjectOptions)",
|
||||
"d": "InjectTextOpts 注入文本到 agent,并在这一次注入上声明记忆与裁剪行为。",
|
||||
"k": "method",
|
||||
"r": "PluginSDK",
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 714,
|
||||
"g": [
|
||||
"注入文本",
|
||||
"注入消息",
|
||||
"投喂输入",
|
||||
"灌入内容"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "InputChannelRegistrar",
|
||||
"s": "type InputChannelRegistrar func(name string, def ChannelDef) error",
|
||||
@ -1245,6 +1256,21 @@
|
||||
"f": "plugin.go",
|
||||
"l": 172
|
||||
},
|
||||
{
|
||||
"n": "Knowledge",
|
||||
"s": "func (s *PluginSDK) Knowledge() KnowledgeAPI",
|
||||
"d": "Knowledge returns the knowledge store API (may be nil if not available).",
|
||||
"k": "method",
|
||||
"r": "PluginSDK",
|
||||
"p": "memory",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 430,
|
||||
"g": [
|
||||
"知识库",
|
||||
"知识"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "Knowledge",
|
||||
"s": "type Knowledge struct { Name string `json:\"name\"` Content string `json:\"content\"` }",
|
||||
@ -1260,21 +1286,6 @@
|
||||
"知识"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "Knowledge",
|
||||
"s": "func (s *PluginSDK) Knowledge() KnowledgeAPI",
|
||||
"d": "Knowledge returns the knowledge store API (may be nil if not available).",
|
||||
"k": "method",
|
||||
"r": "PluginSDK",
|
||||
"p": "memory",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 425,
|
||||
"g": [
|
||||
"知识库",
|
||||
"知识"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "KnowledgeAPI",
|
||||
"s": "type KnowledgeAPI interface",
|
||||
@ -1295,7 +1306,7 @@
|
||||
"p": "llm",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 432
|
||||
"l": 437
|
||||
},
|
||||
{
|
||||
"n": "LLMAPI",
|
||||
@ -1308,20 +1319,6 @@
|
||||
"f": "",
|
||||
"l": 0
|
||||
},
|
||||
{
|
||||
"n": "List",
|
||||
"s": "List() ([]string, error)",
|
||||
"d": "",
|
||||
"k": "method",
|
||||
"r": "KnowledgeAPI",
|
||||
"p": "memory",
|
||||
"b": false,
|
||||
"f": "knowledge.go",
|
||||
"l": 7,
|
||||
"g": [
|
||||
"列出"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "List",
|
||||
"s": "List(prefix string) ([]string, error)",
|
||||
@ -1336,6 +1333,20 @@
|
||||
"列出"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "List",
|
||||
"s": "List() ([]string, error)",
|
||||
"d": "",
|
||||
"k": "method",
|
||||
"r": "KnowledgeAPI",
|
||||
"p": "memory",
|
||||
"b": false,
|
||||
"f": "knowledge.go",
|
||||
"l": 7,
|
||||
"g": [
|
||||
"列出"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "ListCore",
|
||||
"s": "ListCore(prefix string) ([]string, error)",
|
||||
@ -1454,7 +1465,7 @@
|
||||
"p": "memory",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 404,
|
||||
"l": 409,
|
||||
"g": [
|
||||
"记忆",
|
||||
"内存"
|
||||
@ -1499,6 +1510,17 @@
|
||||
"名称"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "NormalizeProxyHost",
|
||||
"s": "func NormalizeProxyHost(pluginName string) string",
|
||||
"d": "NormalizeProxyHost 由插件名派生默认 Host 标签。",
|
||||
"k": "func",
|
||||
"r": "",
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "proxy.go",
|
||||
"l": 202
|
||||
},
|
||||
{
|
||||
"n": "OutputChannelRegistrar",
|
||||
"s": "type OutputChannelRegistrar func(name string, caps int, desc string, def ChannelDef, handler ToolHandler) error",
|
||||
@ -1563,7 +1585,7 @@
|
||||
"p": "lifecycle",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 653,
|
||||
"l": 658,
|
||||
"g": [
|
||||
"插件管理",
|
||||
"重载插件",
|
||||
@ -1591,7 +1613,7 @@
|
||||
"p": "lifecycle",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 397,
|
||||
"l": 402,
|
||||
"g": [
|
||||
"插件名"
|
||||
]
|
||||
@ -1681,6 +1703,50 @@
|
||||
"中断级别"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "ProxyAuthHomeAgent",
|
||||
"s": "const ProxyAuthHomeAgent",
|
||||
"d": "ProxyAuthHomeAgent 表示由 HomeAgent 统一保护:浏览器走门户会话",
|
||||
"k": "const",
|
||||
"r": "",
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "proxy.go",
|
||||
"l": 149
|
||||
},
|
||||
{
|
||||
"n": "ProxyAuthNone",
|
||||
"s": "const ProxyAuthNone",
|
||||
"d": "ProxyAuthNone 表示不经 HomeAgent 鉴权,直接把请求转发给上游。",
|
||||
"k": "const",
|
||||
"r": "",
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "proxy.go",
|
||||
"l": 156
|
||||
},
|
||||
{
|
||||
"n": "ProxyDef",
|
||||
"s": "type ProxyDef struct { // Name 是同一插件内多条声明的唯一标识(如 \"ui\"、\"api\")。 // 运行期由 RegisterProxy 的第一个参数填入;声明式由 …",
|
||||
"d": "反向代理声明:插件告诉 HomeAgent「我起了个 HTTP 服务,请把它反代出去」。",
|
||||
"k": "type",
|
||||
"r": "",
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "proxy.go",
|
||||
"l": 64
|
||||
},
|
||||
{
|
||||
"n": "ProxyRegistrar",
|
||||
"s": "type ProxyRegistrar func(name string, def ProxyDef)",
|
||||
"d": "ProxyRegistrar 由内核注入(与 ToolRegistrar / InputChannelRegistrar 同族)。",
|
||||
"k": "type",
|
||||
"r": "",
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "proxy.go",
|
||||
"l": 306
|
||||
},
|
||||
{
|
||||
"n": "Purge",
|
||||
"s": "Purge(criteria map[string]string, mode string) (int, error)",
|
||||
@ -1811,7 +1877,7 @@
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 561,
|
||||
"l": 566,
|
||||
"g": [
|
||||
"注册输入通道",
|
||||
"收消息",
|
||||
@ -1830,7 +1896,7 @@
|
||||
"p": "lifecycle",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 826,
|
||||
"l": 831,
|
||||
"g": [
|
||||
"卸载回调",
|
||||
"删除清理",
|
||||
@ -1847,7 +1913,7 @@
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 528,
|
||||
"l": 533,
|
||||
"g": [
|
||||
"注册输出通道",
|
||||
"发消息",
|
||||
@ -1866,12 +1932,23 @@
|
||||
"p": "lifecycle",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 502,
|
||||
"l": 507,
|
||||
"g": [
|
||||
"注册插件接口",
|
||||
"暴露接口"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "RegisterProxy",
|
||||
"s": "func (s *PluginSDK) RegisterProxy(name string, def ProxyDef)",
|
||||
"d": "RegisterProxy 声明一个需要 HomeAgent 反代出去的服务。",
|
||||
"k": "method",
|
||||
"r": "PluginSDK",
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "proxy.go",
|
||||
"l": 335
|
||||
},
|
||||
{
|
||||
"n": "RegisterStage",
|
||||
"s": "func (s *PluginSDK) RegisterStage(stage Stage, handler StageHandler, scope ...StageScope)",
|
||||
@ -1881,7 +1958,7 @@
|
||||
"p": "stages",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 467,
|
||||
"l": 472,
|
||||
"g": [
|
||||
"注册阶段",
|
||||
"阶段钩子",
|
||||
@ -1901,7 +1978,7 @@
|
||||
"p": "lifecycle",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 801,
|
||||
"l": 806,
|
||||
"g": [
|
||||
"停止回调",
|
||||
"关闭清理",
|
||||
@ -1917,7 +1994,7 @@
|
||||
"p": "tools",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 453,
|
||||
"l": 458,
|
||||
"g": [
|
||||
"注册工具",
|
||||
"添加工具",
|
||||
@ -1982,7 +2059,7 @@
|
||||
"p": "lifecycle",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 837
|
||||
"l": 842
|
||||
},
|
||||
{
|
||||
"n": "RunStopHandlers",
|
||||
@ -1993,7 +2070,7 @@
|
||||
"p": "lifecycle",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 812
|
||||
"l": 817
|
||||
},
|
||||
{
|
||||
"n": "SDKVersion",
|
||||
@ -2048,7 +2125,7 @@
|
||||
"p": "lifecycle",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 784,
|
||||
"l": 789,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
@ -2084,7 +2161,7 @@
|
||||
"p": "bridge",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 614,
|
||||
"l": 619,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
@ -2102,7 +2179,7 @@
|
||||
"p": "bridge",
|
||||
"b": true,
|
||||
"f": "plugin.go",
|
||||
"l": 638,
|
||||
"l": 643,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
@ -2119,7 +2196,7 @@
|
||||
"p": "bridge",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 595,
|
||||
"l": 600,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配"
|
||||
@ -2134,7 +2211,7 @@
|
||||
"p": "bridge",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 588,
|
||||
"l": 593,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
@ -2151,7 +2228,7 @@
|
||||
"p": "bridge",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 620,
|
||||
"l": 625,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
@ -2168,7 +2245,7 @@
|
||||
"p": "bridge",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 626,
|
||||
"l": 631,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配"
|
||||
@ -2183,7 +2260,7 @@
|
||||
"p": "bridge",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 602,
|
||||
"l": 607,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
@ -2200,7 +2277,7 @@
|
||||
"p": "bridge",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 574,
|
||||
"l": 579,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
@ -2217,7 +2294,7 @@
|
||||
"p": "bridge",
|
||||
"b": true,
|
||||
"f": "plugin.go",
|
||||
"l": 581,
|
||||
"l": 586,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
@ -2250,7 +2327,7 @@
|
||||
"p": "bridge",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 645,
|
||||
"l": 650,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
@ -2259,6 +2336,21 @@
|
||||
"禁用插件"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "SetProxyRegistrar",
|
||||
"s": "func (s *PluginSDK) SetProxyRegistrar(r ProxyRegistrar)",
|
||||
"d": "SetProxyRegistrar 由内核注入。插件不直接调它(与 SetInputChannelRegistrar 同族)。",
|
||||
"k": "method",
|
||||
"r": "PluginSDK",
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "proxy.go",
|
||||
"l": 309,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "SetSocialAPI",
|
||||
"s": "func (s *PluginSDK) SetSocialAPI(social SocialAPI)",
|
||||
@ -2268,7 +2360,7 @@
|
||||
"p": "bridge",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 632,
|
||||
"l": 637,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
@ -2302,7 +2394,7 @@
|
||||
"p": "bridge",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 608,
|
||||
"l": 613,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
@ -2310,25 +2402,6 @@
|
||||
"内存"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "SetToolBlocks",
|
||||
"s": "func (s *PluginSDK) SetToolBlocks(blocks []ContentBlock)",
|
||||
"d": "SetToolBlocks 在工具处理函数内注入多模态内容块,内核在下一条 tool message",
|
||||
"k": "method",
|
||||
"r": "PluginSDK",
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 772,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
"工具",
|
||||
"工具返回图片",
|
||||
"多模态返回",
|
||||
"让模型看图"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "SetToolBlocks",
|
||||
"s": "SetToolBlocks(blocks []ContentBlock)",
|
||||
@ -2348,6 +2421,25 @@
|
||||
"让模型看图"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "SetToolBlocks",
|
||||
"s": "func (s *PluginSDK) SetToolBlocks(blocks []ContentBlock)",
|
||||
"d": "SetToolBlocks 在工具处理函数内注入多模态内容块,内核在下一条 tool message",
|
||||
"k": "method",
|
||||
"r": "PluginSDK",
|
||||
"p": "channels",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 777,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配",
|
||||
"工具",
|
||||
"工具返回图片",
|
||||
"多模态返回",
|
||||
"让模型看图"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "Settings",
|
||||
"s": "func (s *PluginSDK) Settings() SettingsAPI",
|
||||
@ -2357,7 +2449,7 @@
|
||||
"p": "settings",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 401,
|
||||
"l": 406,
|
||||
"g": [
|
||||
"设置",
|
||||
"装配"
|
||||
@ -2383,7 +2475,7 @@
|
||||
"p": "memory",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 439,
|
||||
"l": 444,
|
||||
"g": [
|
||||
"社交",
|
||||
"关系",
|
||||
@ -2716,7 +2808,7 @@
|
||||
"p": "memory",
|
||||
"b": false,
|
||||
"f": "plugin.go",
|
||||
"l": 411,
|
||||
"l": 416,
|
||||
"g": [
|
||||
"记忆",
|
||||
"内存"
|
||||
@ -2845,7 +2937,7 @@
|
||||
"p": "misc",
|
||||
"b": true,
|
||||
"f": "plugin.go",
|
||||
"l": 539,
|
||||
"l": 544,
|
||||
"g": [
|
||||
"通道",
|
||||
"频道",
|
||||
@ -2868,6 +2960,28 @@
|
||||
"校验裁剪策略"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "ValidProxyAuth",
|
||||
"s": "func ValidProxyAuth(auth string) bool",
|
||||
"d": "ValidProxyAuth 校验 Auth 取值;空串合法(等价 ProxyAuthHomeAgent)。",
|
||||
"k": "func",
|
||||
"r": "",
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "proxy.go",
|
||||
"l": 160
|
||||
},
|
||||
{
|
||||
"n": "ValidProxyHostLabel",
|
||||
"s": "func ValidProxyHostLabel(label string) bool",
|
||||
"d": "ValidProxyHostLabel 校验子域名标签是否合法(DNS label 规则)。",
|
||||
"k": "func",
|
||||
"r": "",
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "proxy.go",
|
||||
"l": 180
|
||||
},
|
||||
{
|
||||
"n": "ValidRecallPolicy",
|
||||
"s": "func ValidRecallPolicy(policy string) bool",
|
||||
@ -2884,5 +2998,16 @@
|
||||
"检索记忆",
|
||||
"校验召回策略"
|
||||
]
|
||||
},
|
||||
{
|
||||
"n": "ValidateProxyDef",
|
||||
"s": "func ValidateProxyDef(d ProxyDef) string",
|
||||
"d": "ValidateProxyDef 校验一条反代声明,返回人类可读的错误说明(合法时为空)。",
|
||||
"k": "func",
|
||||
"r": "",
|
||||
"p": "misc",
|
||||
"b": false,
|
||||
"f": "proxy.go",
|
||||
"l": 229
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user