mirror of
https://gitcode.com/JianFeeeee/homeagent-sdk.git
synced 2026-10-03 15:44:11 +00:00
feat(sdk): 通用反代声明项(DeclareProxy)+ ToolDef.Serial 串行标记 + 场面策略文档
本次一并提交工作区此前累积的改动(均已验证),并接入工具并发调度所需的 声明项。 把「谁来反代谁」从内核硬编码变成插件可声明。设备网关(remotedevice) 这类**编译进内核、没有独立插件目录与 plugin.json** 的服务,静态扫描扫不到, 此前只能靠约定。新增 DeclareProxy 让它们能自己声明反代路由。 ParallelSafe 的**反向**声明项。判据优先级:Serial 胜出,显式声明不允许被 ParallelSafe 或任何默认值覆盖。 为什么需要它:ParallelSafe 零值 false 已表达「安全/串行」,插件无法区分 「我没想过」和「我确认过必须串行」。没有这个区分,工具作者只能靠命名约定 传递意图,那不是契约。 ParallelSafe 本身也补齐了注释,明确其零值语义(默认串行、保守)与理由 (新语义下并发会改变工具的行为前提,让存量插件意外并发比慢一点危险得多)。 配套 ScenePolicy 声明项的使用说明。 remotedevice/ 整目录(C 实现的设备网关,已由 Go 侧 DeclareProxy 路径取代)。 - sdk/knowledge.go:随场面策略配套调整 - docs/api/*、docs/assets/api-index.json、docs/llms.txt、mkdocs.yml: 由 tools/apidoc/build.sh 从源码重新生成(行号随 plugin.go 变动漂移)
This commit is contained in:
@ -12,7 +12,7 @@ type APIRegistrar func(name string) error
|
||||
|
||||
APIRegistrar registers a plugin API for external access.
|
||||
|
||||
<small>`plugin.go:311`</small>
|
||||
<small>`plugin.go:410`</small>
|
||||
|
||||
### `InputChannelRegistrar`
|
||||
|
||||
@ -22,7 +22,7 @@ type InputChannelRegistrar func(name string, def ChannelDef) error
|
||||
|
||||
InputChannelRegistrar registers an input channel with its memory behavior.
|
||||
|
||||
<small>`plugin.go:314`</small>
|
||||
<small>`plugin.go:413`</small>
|
||||
|
||||
### `OutputChannelRegistrar`
|
||||
|
||||
@ -32,7 +32,7 @@ type OutputChannelRegistrar func(name string, caps int, desc string, def Channel
|
||||
|
||||
OutputChannelRegistrar registers an output channel that the output_send tool can use.
|
||||
|
||||
<small>`plugin.go:317`</small>
|
||||
<small>`plugin.go:416`</small>
|
||||
|
||||
### `OutputChannelUnregistrar`
|
||||
|
||||
@ -46,7 +46,7 @@ OutputChannelUnregistrar 注销一个输出通道。
|
||||
动态通道 —— 典型是远程设备:`device/<id>` 只在设备在线期间存在,设备掉线后
|
||||
必须注销,否则 output_list_channels 会一直列着它、模型会往一个死通道发消息。
|
||||
|
||||
<small>`plugin.go:324`</small>
|
||||
<small>`plugin.go:423`</small>
|
||||
|
||||
### `PluginSDK.SetDocMemoryAPI`
|
||||
|
||||
@ -57,7 +57,7 @@ OutputChannelUnregistrar 注销一个输出通道。
|
||||
func (s *PluginSDK) SetDocMemoryAPI(dm DocMemoryAPI)
|
||||
```
|
||||
|
||||
<small>`plugin.go:619`</small>
|
||||
<small>`plugin.go:718`</small>
|
||||
|
||||
### `PluginSDK.SetEventSubscriber`
|
||||
|
||||
@ -68,7 +68,7 @@ func (s *PluginSDK) SetDocMemoryAPI(dm DocMemoryAPI)
|
||||
func (s *PluginSDK) SetEventSubscriber(es EventSubscriber)
|
||||
```
|
||||
|
||||
<small>`plugin.go:643`</small>
|
||||
<small>`plugin.go:742`</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:600`</small>
|
||||
<small>`plugin.go:699`</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:593`</small>
|
||||
<small>`plugin.go:692`</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:625`</small>
|
||||
<small>`plugin.go:724`</small>
|
||||
|
||||
### `PluginSDK.SetLLMAPI`
|
||||
|
||||
@ -116,7 +116,7 @@ func (s *PluginSDK) SetKnowledgeAPI(kn KnowledgeAPI)
|
||||
func (s *PluginSDK) SetLLMAPI(llm LLMAPI)
|
||||
```
|
||||
|
||||
<small>`plugin.go:631`</small>
|
||||
<small>`plugin.go:730`</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:607`</small>
|
||||
<small>`plugin.go:706`</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:579`</small>
|
||||
<small>`plugin.go:678`</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:586`</small>
|
||||
<small>`plugin.go:685`</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:650`</small>
|
||||
<small>`plugin.go:749`</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:637`</small>
|
||||
<small>`plugin.go:736`</small>
|
||||
|
||||
### `PluginSDK.SetTextMemoryAPI`
|
||||
|
||||
@ -190,7 +190,7 @@ func (s *PluginSDK) SetSocialAPI(social SocialAPI)
|
||||
func (s *PluginSDK) SetTextMemoryAPI(tm TextMemoryAPI)
|
||||
```
|
||||
|
||||
<small>`plugin.go:613`</small>
|
||||
<small>`plugin.go:712`</small>
|
||||
|
||||
### `ToolRegistrar`
|
||||
|
||||
@ -200,5 +200,5 @@ type ToolRegistrar func(name string, def ToolDef, handler ToolHandler) error
|
||||
|
||||
ToolRegistrar registers a tool dynamically.
|
||||
|
||||
<small>`plugin.go:305`</small>
|
||||
<small>`plugin.go:404`</small>
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ const PriorityL4
|
||||
|
||||
PriorityL4 仅内核级(内置)插件可用;外部插件声明会被夹到 L3。
|
||||
|
||||
<small>`plugin.go:127`</small>
|
||||
<small>`plugin.go:165`</small>
|
||||
|
||||
### `PluginSDK.Events`
|
||||
|
||||
@ -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:451`</small>
|
||||
<small>`plugin.go:550`</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:643`</small>
|
||||
<small>`plugin.go:742`</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:586`</small>
|
||||
<small>`plugin.go:685`</small>
|
||||
|
||||
### `PluginSDK.UnregisterOutputChannel`
|
||||
|
||||
@ -67,7 +67,7 @@ func (s *PluginSDK) UnregisterOutputChannel(name string) error
|
||||
|
||||
UnregisterOutputChannel 注销一个输出通道(动态通道随资源生灭时必须调用)。
|
||||
|
||||
<small>`plugin.go:544`</small>
|
||||
<small>`plugin.go:643`</small>
|
||||
|
||||
### `EventSubscriber.Subscribe`
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@ for routing the agent's response.
|
||||
InjectInputMedia(source, channel, text string, blocks []ContentBlock)
|
||||
```
|
||||
|
||||
<small>`plugin.go:230`</small>
|
||||
<small>`plugin.go:329`</small>
|
||||
|
||||
### `IOInjector.InjectInputMediaOpts`
|
||||
|
||||
@ -41,7 +41,7 @@ InjectInputMedia(source, channel, text string, blocks []ContentBlock)
|
||||
InjectInputMediaOpts(source, channel, text string, blocks []ContentBlock, opts InjectOptions)
|
||||
```
|
||||
|
||||
<small>`plugin.go:241`</small>
|
||||
<small>`plugin.go:340`</small>
|
||||
|
||||
### `IOInjector.InjectInputMediaSync`
|
||||
|
||||
@ -49,7 +49,7 @@ InjectInputMediaOpts(source, channel, text string, blocks []ContentBlock, opts I
|
||||
InjectInputMediaSync(source, channel, text string, blocks []ContentBlock) string
|
||||
```
|
||||
|
||||
<small>`plugin.go:231`</small>
|
||||
<small>`plugin.go:330`</small>
|
||||
|
||||
### `IOInjector.InjectInputMediaSyncOpts`
|
||||
|
||||
@ -57,7 +57,7 @@ InjectInputMediaSync(source, channel, text string, blocks []ContentBlock) string
|
||||
InjectInputMediaSyncOpts(source, channel, text string, blocks []ContentBlock, opts InjectOptions) string
|
||||
```
|
||||
|
||||
<small>`plugin.go:242`</small>
|
||||
<small>`plugin.go:341`</small>
|
||||
|
||||
### `IOInjector.InjectInputSync`
|
||||
|
||||
@ -75,7 +75,7 @@ InjectInputSync 注入输入事件并同步等待 agent 回复,返回回复文
|
||||
| [`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:226`</small>
|
||||
<small>`plugin.go:325`</small>
|
||||
|
||||
### `IOInjector.InjectInputSyncOpts`
|
||||
|
||||
@ -83,7 +83,7 @@ InjectInputSync 注入输入事件并同步等待 agent 回复,返回回复文
|
||||
InjectInputSyncOpts(source, channel, text string, opts InjectOptions) string
|
||||
```
|
||||
|
||||
<small>`plugin.go:240`</small>
|
||||
<small>`plugin.go:339`</small>
|
||||
|
||||
### `IOInjector.InjectInterruptMedia`
|
||||
|
||||
@ -91,7 +91,7 @@ InjectInputSyncOpts(source, channel, text string, opts InjectOptions) string
|
||||
InjectInterruptMedia(source, channel, text string, blocks []ContentBlock)
|
||||
```
|
||||
|
||||
<small>`plugin.go:232`</small>
|
||||
<small>`plugin.go:331`</small>
|
||||
|
||||
### `IOInjector.InjectInterruptMediaOpts`
|
||||
|
||||
@ -99,7 +99,7 @@ InjectInterruptMedia(source, channel, text string, blocks []ContentBlock)
|
||||
InjectInterruptMediaOpts(source, channel, text string, blocks []ContentBlock, opts InjectOptions)
|
||||
```
|
||||
|
||||
<small>`plugin.go:243`</small>
|
||||
<small>`plugin.go:342`</small>
|
||||
|
||||
### `IOInjector.InjectInterruptText`
|
||||
|
||||
@ -107,7 +107,7 @@ InjectInterruptMediaOpts(source, channel, text string, blocks []ContentBlock, op
|
||||
InjectInterruptText(source, channel, text string)
|
||||
```
|
||||
|
||||
<small>`plugin.go:221`</small>
|
||||
<small>`plugin.go:320`</small>
|
||||
|
||||
### `IOInjector.InjectInterruptTextOpts`
|
||||
|
||||
@ -124,7 +124,7 @@ InjectInterruptTextOpts(source, channel, text string, opts InjectOptions)
|
||||
| [`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:239`</small>
|
||||
<small>`plugin.go:338`</small>
|
||||
|
||||
### `IOInjector.InjectText`
|
||||
|
||||
@ -132,7 +132,7 @@ InjectInterruptTextOpts(source, channel, text string, opts InjectOptions)
|
||||
InjectText(source, channel, text string)
|
||||
```
|
||||
|
||||
<small>`plugin.go:222`</small>
|
||||
<small>`plugin.go:321`</small>
|
||||
|
||||
### `IOInjector.InjectTextNoMemory`
|
||||
|
||||
@ -146,7 +146,7 @@ InjectTextNoMemory(source, channel, text string)
|
||||
|---|---|---|
|
||||
| [`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:223`</small>
|
||||
<small>`plugin.go:322`</small>
|
||||
|
||||
### `IOInjector.InjectTextOpts`
|
||||
|
||||
@ -159,7 +159,7 @@ InjectTextOpts(source, channel, text string, opts InjectOptions)
|
||||
上面那些不带 opts 的方法等价于传零值 InjectOptions(记入记忆 + 不裁剪),
|
||||
保留它们是为了不破坏已有插件;新代码应当用 Opts 变体把意图写清楚。
|
||||
|
||||
<small>`plugin.go:238`</small>
|
||||
<small>`plugin.go:337`</small>
|
||||
|
||||
### `IOInjector.SetToolBlocks`
|
||||
|
||||
@ -170,7 +170,7 @@ SetToolBlocks(blocks []ContentBlock)
|
||||
SetToolBlocks 插件工具注入多模态内容块(image_url/audio_url),内核在下一条
|
||||
tool message 的 content 数组里带上这些块,让模型在后续轮次看到图/听到音频。
|
||||
|
||||
<small>`plugin.go:229`</small>
|
||||
<small>`plugin.go:328`</small>
|
||||
|
||||
### `CapAudio`
|
||||
|
||||
@ -180,7 +180,7 @@ const CapAudio
|
||||
|
||||
Output capability flags
|
||||
|
||||
<small>`plugin.go:331`</small>
|
||||
<small>`plugin.go:430`</small>
|
||||
|
||||
### `CapFile`
|
||||
|
||||
@ -190,7 +190,7 @@ const CapFile
|
||||
|
||||
Output capability flags
|
||||
|
||||
<small>`plugin.go:329`</small>
|
||||
<small>`plugin.go:428`</small>
|
||||
|
||||
### `CapImage`
|
||||
|
||||
@ -200,7 +200,7 @@ const CapImage
|
||||
|
||||
Output capability flags
|
||||
|
||||
<small>`plugin.go:330`</small>
|
||||
<small>`plugin.go:429`</small>
|
||||
|
||||
### `CapStructured`
|
||||
|
||||
@ -210,7 +210,7 @@ const CapStructured
|
||||
|
||||
Output capability flags
|
||||
|
||||
<small>`plugin.go:332`</small>
|
||||
<small>`plugin.go:431`</small>
|
||||
|
||||
### `CapText`
|
||||
|
||||
@ -220,7 +220,7 @@ const CapText
|
||||
|
||||
Output capability flags
|
||||
|
||||
<small>`plugin.go:328`</small>
|
||||
<small>`plugin.go:427`</small>
|
||||
|
||||
### `ChannelDef`
|
||||
|
||||
@ -233,12 +233,13 @@ NoMemory: 此通道输入/输出不参与记忆计算(向量化/关键词提
|
||||
Cleaner: 计算层过滤函数,不改原文;仅在向量化/jieba/蒸馏/存档提取关键词时调用
|
||||
ContextPolicy: 此通道的输入到达后是否据此裁剪上下文,默认 none(不裁剪)
|
||||
RecallPolicy: 此通道的输入到达后是否据此召回相关记忆,默认 auto(召回)
|
||||
ScenePolicy: 此通道的输入到达后是否参与场面识别(场景式记忆),默认 auto(参与)
|
||||
|
||||
JSON tag 是必需的:通道定义要跨进程传给内核,而 Cleaner 是函数(必须忽略)。
|
||||
没有 tag 时既无法整体 marshal(func 不支持),又会诱使调用方手写字段白名单——
|
||||
那样新增字段会被静默丢掉。
|
||||
|
||||
<small>`plugin.go:139`</small>
|
||||
<small>`plugin.go:178`</small>
|
||||
|
||||
### `ContextPolicyNone`
|
||||
|
||||
@ -280,7 +281,7 @@ blocks 会落进媒体存储被记忆引用捕获,同时作为当前轮 conten
|
||||
的「下一轮 tool message」语义。
|
||||
等价于 InjectInputMediaOpts(..., InjectOptions{})。
|
||||
|
||||
<small>`plugin.go:706`</small>
|
||||
<small>`plugin.go:805`</small>
|
||||
|
||||
### `PluginSDK.InjectInputMediaOpts`
|
||||
|
||||
@ -290,7 +291,7 @@ func (s *PluginSDK) InjectInputMediaOpts(source, channel, text string, blocks []
|
||||
|
||||
InjectInputMediaOpts 注入带媒体块的输入,并声明记忆/裁剪行为。
|
||||
|
||||
<small>`plugin.go:745`</small>
|
||||
<small>`plugin.go:844`</small>
|
||||
|
||||
### `PluginSDK.InjectInputMediaSync`
|
||||
|
||||
@ -301,7 +302,7 @@ func (s *PluginSDK) InjectInputMediaSync(source, channel, text string, blocks []
|
||||
InjectInputMediaSync 注入带媒体内容块的输入并同步等待 agent 回复。
|
||||
等价于 InjectInputMediaSyncOpts(..., InjectOptions{})。
|
||||
|
||||
<small>`plugin.go:712`</small>
|
||||
<small>`plugin.go:811`</small>
|
||||
|
||||
### `PluginSDK.InjectInputMediaSyncOpts`
|
||||
|
||||
@ -311,7 +312,7 @@ func (s *PluginSDK) InjectInputMediaSyncOpts(source, channel, text string, block
|
||||
|
||||
InjectInputMediaSyncOpts 注入带媒体块的输入并同步等待回复,同时声明记忆/裁剪行为。
|
||||
|
||||
<small>`plugin.go:752`</small>
|
||||
<small>`plugin.go:851`</small>
|
||||
|
||||
### `PluginSDK.InjectInputSync`
|
||||
|
||||
@ -330,7 +331,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:697`</small>
|
||||
<small>`plugin.go:796`</small>
|
||||
|
||||
### `PluginSDK.InjectInputSyncOpts`
|
||||
|
||||
@ -340,7 +341,7 @@ func (s *PluginSDK) InjectInputSyncOpts(source, channel, text string, opts Injec
|
||||
|
||||
InjectInputSyncOpts 注入输入并同步等待回复,同时在这次注入上声明记忆/裁剪行为。
|
||||
|
||||
<small>`plugin.go:736`</small>
|
||||
<small>`plugin.go:835`</small>
|
||||
|
||||
### `PluginSDK.InjectInterruptMedia`
|
||||
|
||||
@ -351,7 +352,7 @@ func (s *PluginSDK) InjectInterruptMedia(source, channel, text string, blocks []
|
||||
InjectInterruptMedia 注入带媒体内容块的中断,可抢占当前 LLM 处理。
|
||||
blocks 随中断消息一起发给模型。
|
||||
|
||||
<small>`plugin.go:769`</small>
|
||||
<small>`plugin.go:868`</small>
|
||||
|
||||
### `PluginSDK.InjectInterruptMediaOpts`
|
||||
|
||||
@ -361,7 +362,7 @@ func (s *PluginSDK) InjectInterruptMediaOpts(source, channel, text string, block
|
||||
|
||||
InjectInterruptMediaOpts 注入带媒体块的中断,并声明记忆/裁剪行为。
|
||||
|
||||
<small>`plugin.go:761`</small>
|
||||
<small>`plugin.go:860`</small>
|
||||
|
||||
### `PluginSDK.InjectInterruptText`
|
||||
|
||||
@ -372,7 +373,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:678`</small>
|
||||
<small>`plugin.go:777`</small>
|
||||
|
||||
### `PluginSDK.InjectInterruptTextOpts`
|
||||
|
||||
@ -394,7 +395,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:729`</small>
|
||||
<small>`plugin.go:828`</small>
|
||||
|
||||
### `InjectOptions`
|
||||
|
||||
@ -424,7 +425,7 @@ CleanerName: 此次注入的内容用哪个**已注册的通道 cleaner** 清
|
||||
而注入内容往往带 ANSI/JSON 包装,需要清洗后才是有效内容;
|
||||
不指定就只能退到「按 source 查不到就不清洗」。
|
||||
|
||||
<small>`plugin.go:98`</small>
|
||||
<small>`plugin.go:132`</small>
|
||||
|
||||
### `PluginSDK.InjectText`
|
||||
|
||||
@ -435,7 +436,7 @@ func (s *PluginSDK) InjectText(source, channel, text string)
|
||||
InjectText injects a text message into the agent pipeline.
|
||||
等价于 InjectTextOpts(..., InjectOptions{}):记入记忆、不裁剪。
|
||||
|
||||
<small>`plugin.go:684`</small>
|
||||
<small>`plugin.go:783`</small>
|
||||
|
||||
### `PluginSDK.InjectTextNoMemory`
|
||||
|
||||
@ -452,7 +453,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:690`</small>
|
||||
<small>`plugin.go:789`</small>
|
||||
|
||||
### `PluginSDK.InjectTextOpts`
|
||||
|
||||
@ -462,7 +463,7 @@ func (s *PluginSDK) InjectTextOpts(source, channel, text string, opts InjectOpti
|
||||
|
||||
InjectTextOpts 注入文本到 agent,并在这一次注入上声明记忆与裁剪行为。
|
||||
|
||||
<small>`plugin.go:719`</small>
|
||||
<small>`plugin.go:818`</small>
|
||||
|
||||
### `PriorityL1`
|
||||
|
||||
@ -476,7 +477,7 @@ L1..L3 任何插件都可声明;**L4 只有内核级插件**(编译期内置
|
||||
如 cli/webui/timer)才能声明——它用于实现真正的“立即打断”能力,
|
||||
例如 WebUI 的终止按钮。外部插件(走 proc 桥)声明 L4 会被内核夹到 L3。
|
||||
|
||||
<small>`plugin.go:123`</small>
|
||||
<small>`plugin.go:161`</small>
|
||||
|
||||
### `PriorityL2`
|
||||
|
||||
@ -490,7 +491,7 @@ L1..L3 任何插件都可声明;**L4 只有内核级插件**(编译期内置
|
||||
如 cli/webui/timer)才能声明——它用于实现真正的“立即打断”能力,
|
||||
例如 WebUI 的终止按钮。外部插件(走 proc 桥)声明 L4 会被内核夹到 L3。
|
||||
|
||||
<small>`plugin.go:124`</small>
|
||||
<small>`plugin.go:162`</small>
|
||||
|
||||
### `PriorityL3`
|
||||
|
||||
@ -504,7 +505,7 @@ L1..L3 任何插件都可声明;**L4 只有内核级插件**(编译期内置
|
||||
如 cli/webui/timer)才能声明——它用于实现真正的“立即打断”能力,
|
||||
例如 WebUI 的终止按钮。外部插件(走 proc 桥)声明 L4 会被内核夹到 L3。
|
||||
|
||||
<small>`plugin.go:125`</small>
|
||||
<small>`plugin.go:163`</small>
|
||||
|
||||
### `PriorityL4`
|
||||
|
||||
@ -517,7 +518,7 @@ const PriorityL4
|
||||
|
||||
PriorityL4 仅内核级(内置)插件可用;外部插件声明会被夹到 L3。
|
||||
|
||||
<small>`plugin.go:127`</small>
|
||||
<small>`plugin.go:165`</small>
|
||||
|
||||
### `RecallPolicyAuto`
|
||||
|
||||
@ -577,7 +578,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:566`</small>
|
||||
<small>`plugin.go:665`</small>
|
||||
|
||||
### `PluginSDK.RegisterOutputChannel`
|
||||
|
||||
@ -614,7 +615,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:533`</small>
|
||||
<small>`plugin.go:632`</small>
|
||||
|
||||
### `PluginSDK.SetToolBlocks`
|
||||
|
||||
@ -625,7 +626,7 @@ func (s *PluginSDK) SetToolBlocks(blocks []ContentBlock)
|
||||
SetToolBlocks 在工具处理函数内注入多模态内容块,内核在下一条 tool message
|
||||
的 content 数组里带上它们。需要「本轮就让模型看到」时用 InjectInputMedia。
|
||||
|
||||
<small>`plugin.go:777`</small>
|
||||
<small>`plugin.go:876`</small>
|
||||
|
||||
### `ValidContextPolicy`
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ controls which events are delivered.
|
||||
Subscribe(eventType EventType, handler EventHandler) func()
|
||||
```
|
||||
|
||||
<small>`plugin.go:279`</small>
|
||||
<small>`plugin.go:378`</small>
|
||||
|
||||
### `Event`
|
||||
|
||||
@ -32,7 +32,7 @@ type Event struct { Type EventType `json:"type"` Source string `json:"source"` P
|
||||
|
||||
Event represents a system event published by the kernel.
|
||||
|
||||
<small>`plugin.go:265`</small>
|
||||
<small>`plugin.go:364`</small>
|
||||
|
||||
### `EventHandler`
|
||||
|
||||
@ -42,7 +42,7 @@ type EventHandler func(evt *Event)
|
||||
|
||||
EventHandler processes a system event.
|
||||
|
||||
<small>`plugin.go:273`</small>
|
||||
<small>`plugin.go:372`</small>
|
||||
|
||||
### `EventType`
|
||||
|
||||
@ -52,7 +52,7 @@ type EventType string
|
||||
|
||||
EventType identifies the kind of system event.
|
||||
|
||||
<small>`plugin.go:247`</small>
|
||||
<small>`plugin.go:346`</small>
|
||||
|
||||
### `PluginSDK.Events`
|
||||
|
||||
@ -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:451`</small>
|
||||
<small>`plugin.go:550`</small>
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ IsPluginDisabled(name string) bool
|
||||
|
||||
IsPluginDisabled 查询插件是否被禁用。
|
||||
|
||||
<small>`plugin.go:290`</small>
|
||||
<small>`plugin.go:389`</small>
|
||||
|
||||
### `PluginMgrAPI.ListLoadedPlugins`
|
||||
|
||||
@ -67,7 +67,7 @@ ListLoadedPlugins() []string
|
||||
|
||||
ListLoadedPlugins 列出已加载插件。
|
||||
|
||||
<small>`plugin.go:288`</small>
|
||||
<small>`plugin.go:387`</small>
|
||||
|
||||
### `PluginMgrAPI.ReloadOne`
|
||||
|
||||
@ -77,7 +77,7 @@ ReloadOne(name string) error
|
||||
|
||||
ReloadOne 重载单个插件(停止后重新加载)。
|
||||
|
||||
<small>`plugin.go:286`</small>
|
||||
<small>`plugin.go:385`</small>
|
||||
|
||||
### `PluginSDK.AutoRestart`
|
||||
|
||||
@ -87,7 +87,7 @@ func (s *PluginSDK) AutoRestart() bool
|
||||
|
||||
AutoRestart 返回插件是否允许自动重启。
|
||||
|
||||
<small>`plugin.go:796`</small>
|
||||
<small>`plugin.go:895`</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:658`</small>
|
||||
<small>`plugin.go:757`</small>
|
||||
|
||||
### `PluginSDK.PluginName`
|
||||
|
||||
@ -108,7 +108,7 @@ func (s *PluginSDK) PluginName() string
|
||||
|
||||
PluginName returns the name of the plugin.
|
||||
|
||||
<small>`plugin.go:402`</small>
|
||||
<small>`plugin.go:501`</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:831`</small>
|
||||
<small>`plugin.go:930`</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:507`</small>
|
||||
<small>`plugin.go:606`</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:806`</small>
|
||||
<small>`plugin.go:905`</small>
|
||||
|
||||
### `PluginSDK.RunOnRemoveHandlers`
|
||||
|
||||
@ -170,7 +170,7 @@ func (s *PluginSDK) RunOnRemoveHandlers()
|
||||
RunOnRemoveHandlers 执行全部已注册的 onRemove handler(后注册先执行,执行后清空,幂等)。
|
||||
由内核在卸载插件(registry.RemovePlugin)时、插件 Stop() 之后执行。
|
||||
|
||||
<small>`plugin.go:842`</small>
|
||||
<small>`plugin.go:941`</small>
|
||||
|
||||
### `PluginSDK.RunStopHandlers`
|
||||
|
||||
@ -181,7 +181,7 @@ func (s *PluginSDK) RunStopHandlers()
|
||||
RunStopHandlers 执行全部已注册的 stop handler(后注册先执行,执行后清空,幂等)。
|
||||
由内核(内置插件)或插件桥接层(外部插件 z_bridge 的 StopPlugin)在调用插件 Stop() 前执行。
|
||||
|
||||
<small>`plugin.go:817`</small>
|
||||
<small>`plugin.go:916`</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:789`</small>
|
||||
<small>`plugin.go:888`</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:437`</small>
|
||||
<small>`plugin.go:536`</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:423`</small>
|
||||
<small>`plugin.go:522`</small>
|
||||
|
||||
### `Entity`
|
||||
|
||||
@ -251,7 +251,7 @@ Entity represents a named entity in the knowledge graph.
|
||||
### `Knowledge`
|
||||
|
||||
```go
|
||||
type Knowledge struct { Name string `json:"name"` Content string `json:"content"` }
|
||||
type Knowledge struct { Name string `json:"name"` // Category 是该条目的父分类路径(如 "tech/go"),根下条目为空。 // // 为何加这个字段:对<EFBC9A><E5AFB9> …
|
||||
```
|
||||
|
||||
Knowledge represents a knowledge entry.
|
||||
@ -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:430`</small>
|
||||
<small>`plugin.go:529`</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:409`</small>
|
||||
<small>`plugin.go:508`</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:444`</small>
|
||||
<small>`plugin.go:543`</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:416`</small>
|
||||
<small>`plugin.go:515`</small>
|
||||
|
||||
### `Triple`
|
||||
|
||||
|
||||
151
docs/api/misc.md
151
docs/api/misc.md
@ -79,7 +79,7 @@ controls which events are delivered.
|
||||
Subscribe(eventType EventType, handler EventHandler) func()
|
||||
```
|
||||
|
||||
<small>`plugin.go:279`</small>
|
||||
<small>`plugin.go:378`</small>
|
||||
|
||||
## `IOInjector`
|
||||
|
||||
@ -110,7 +110,7 @@ for routing the agent's response.
|
||||
InjectInputMedia(source, channel, text string, blocks []ContentBlock)
|
||||
```
|
||||
|
||||
<small>`plugin.go:230`</small>
|
||||
<small>`plugin.go:329`</small>
|
||||
|
||||
### `IOInjector.InjectInputMediaOpts`
|
||||
|
||||
@ -118,7 +118,7 @@ InjectInputMedia(source, channel, text string, blocks []ContentBlock)
|
||||
InjectInputMediaOpts(source, channel, text string, blocks []ContentBlock, opts InjectOptions)
|
||||
```
|
||||
|
||||
<small>`plugin.go:241`</small>
|
||||
<small>`plugin.go:340`</small>
|
||||
|
||||
### `IOInjector.InjectInputMediaSync`
|
||||
|
||||
@ -126,7 +126,7 @@ InjectInputMediaOpts(source, channel, text string, blocks []ContentBlock, opts I
|
||||
InjectInputMediaSync(source, channel, text string, blocks []ContentBlock) string
|
||||
```
|
||||
|
||||
<small>`plugin.go:231`</small>
|
||||
<small>`plugin.go:330`</small>
|
||||
|
||||
### `IOInjector.InjectInputMediaSyncOpts`
|
||||
|
||||
@ -134,7 +134,7 @@ InjectInputMediaSync(source, channel, text string, blocks []ContentBlock) string
|
||||
InjectInputMediaSyncOpts(source, channel, text string, blocks []ContentBlock, opts InjectOptions) string
|
||||
```
|
||||
|
||||
<small>`plugin.go:242`</small>
|
||||
<small>`plugin.go:341`</small>
|
||||
|
||||
### `IOInjector.InjectInputSync`
|
||||
|
||||
@ -152,7 +152,7 @@ InjectInputSync 注入输入事件并同步等待 agent 回复,返回回复文
|
||||
| [`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:226`</small>
|
||||
<small>`plugin.go:325`</small>
|
||||
|
||||
### `IOInjector.InjectInputSyncOpts`
|
||||
|
||||
@ -160,7 +160,7 @@ InjectInputSync 注入输入事件并同步等待 agent 回复,返回回复文
|
||||
InjectInputSyncOpts(source, channel, text string, opts InjectOptions) string
|
||||
```
|
||||
|
||||
<small>`plugin.go:240`</small>
|
||||
<small>`plugin.go:339`</small>
|
||||
|
||||
### `IOInjector.InjectInterruptMedia`
|
||||
|
||||
@ -168,7 +168,7 @@ InjectInputSyncOpts(source, channel, text string, opts InjectOptions) string
|
||||
InjectInterruptMedia(source, channel, text string, blocks []ContentBlock)
|
||||
```
|
||||
|
||||
<small>`plugin.go:232`</small>
|
||||
<small>`plugin.go:331`</small>
|
||||
|
||||
### `IOInjector.InjectInterruptMediaOpts`
|
||||
|
||||
@ -176,7 +176,7 @@ InjectInterruptMedia(source, channel, text string, blocks []ContentBlock)
|
||||
InjectInterruptMediaOpts(source, channel, text string, blocks []ContentBlock, opts InjectOptions)
|
||||
```
|
||||
|
||||
<small>`plugin.go:243`</small>
|
||||
<small>`plugin.go:342`</small>
|
||||
|
||||
### `IOInjector.InjectInterruptText`
|
||||
|
||||
@ -184,7 +184,7 @@ InjectInterruptMediaOpts(source, channel, text string, blocks []ContentBlock, op
|
||||
InjectInterruptText(source, channel, text string)
|
||||
```
|
||||
|
||||
<small>`plugin.go:221`</small>
|
||||
<small>`plugin.go:320`</small>
|
||||
|
||||
### `IOInjector.InjectInterruptTextOpts`
|
||||
|
||||
@ -201,7 +201,7 @@ InjectInterruptTextOpts(source, channel, text string, opts InjectOptions)
|
||||
| [`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:239`</small>
|
||||
<small>`plugin.go:338`</small>
|
||||
|
||||
### `IOInjector.InjectText`
|
||||
|
||||
@ -209,7 +209,7 @@ InjectInterruptTextOpts(source, channel, text string, opts InjectOptions)
|
||||
InjectText(source, channel, text string)
|
||||
```
|
||||
|
||||
<small>`plugin.go:222`</small>
|
||||
<small>`plugin.go:321`</small>
|
||||
|
||||
### `IOInjector.InjectTextNoMemory`
|
||||
|
||||
@ -223,7 +223,7 @@ InjectTextNoMemory(source, channel, text string)
|
||||
|---|---|---|
|
||||
| [`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:223`</small>
|
||||
<small>`plugin.go:322`</small>
|
||||
|
||||
### `IOInjector.InjectTextOpts`
|
||||
|
||||
@ -236,7 +236,7 @@ InjectTextOpts(source, channel, text string, opts InjectOptions)
|
||||
上面那些不带 opts 的方法等价于传零值 InjectOptions(记入记忆 + 不裁剪),
|
||||
保留它们是为了不破坏已有插件;新代码应当用 Opts 变体把意图写清楚。
|
||||
|
||||
<small>`plugin.go:238`</small>
|
||||
<small>`plugin.go:337`</small>
|
||||
|
||||
### `IOInjector.SetToolBlocks`
|
||||
|
||||
@ -247,7 +247,7 @@ SetToolBlocks(blocks []ContentBlock)
|
||||
SetToolBlocks 插件工具注入多模态内容块(image_url/audio_url),内核在下一条
|
||||
tool message 的 content 数组里带上这些块,让模型在后续轮次看到图/听到音频。
|
||||
|
||||
<small>`plugin.go:229`</small>
|
||||
<small>`plugin.go:328`</small>
|
||||
|
||||
## `KnowledgeAPI`
|
||||
|
||||
@ -422,7 +422,7 @@ IsPluginDisabled(name string) bool
|
||||
|
||||
IsPluginDisabled 查询插件是否被禁用。
|
||||
|
||||
<small>`plugin.go:290`</small>
|
||||
<small>`plugin.go:389`</small>
|
||||
|
||||
### `PluginMgrAPI.ListLoadedPlugins`
|
||||
|
||||
@ -432,7 +432,7 @@ ListLoadedPlugins() []string
|
||||
|
||||
ListLoadedPlugins 列出已加载插件。
|
||||
|
||||
<small>`plugin.go:288`</small>
|
||||
<small>`plugin.go:387`</small>
|
||||
|
||||
### `PluginMgrAPI.ReloadOne`
|
||||
|
||||
@ -442,7 +442,7 @@ ReloadOne(name string) error
|
||||
|
||||
ReloadOne 重载单个插件(停止后重新加载)。
|
||||
|
||||
<small>`plugin.go:286`</small>
|
||||
<small>`plugin.go:385`</small>
|
||||
|
||||
## `SettingsAPI`
|
||||
|
||||
@ -680,7 +680,7 @@ Append(evt TextEvent) error
|
||||
type AudioURL struct { URL string `json:"url"` }
|
||||
```
|
||||
|
||||
<small>`plugin.go:867`</small>
|
||||
<small>`plugin.go:966`</small>
|
||||
|
||||
### `EffectiveProxyAuth`
|
||||
|
||||
@ -692,13 +692,32 @@ EffectiveProxyAuth 返回生效的鉴权模式(空串归一化为 ProxyAuthHom
|
||||
|
||||
<small>`proxy.go:169`</small>
|
||||
|
||||
### `ToolError.Error`
|
||||
|
||||
```go
|
||||
func (e *ToolError) Error() string
|
||||
```
|
||||
|
||||
Error 实现 error,便于工具同时走 (ToolError, error) 通道。
|
||||
|
||||
**示例插件里的真实用法**
|
||||
|
||||
| 插件 | 位置 | 代码 |
|
||||
|---|---|---|
|
||||
| [`a2a`](../examples/index.md#a2a) | `example/a2a/plugin.go:317` | `http.Error(w, "query/message.text required", http.StatusBadRequest)` |
|
||||
| [`acp`](../examples/index.md#acp) | `example/acp/plugin.go:175` | `http.Error(w, "", http.StatusMethodNotAllowed)` |
|
||||
| [`ai_image`](../examples/index.md#ai_image) | `example/ai_image/plugin.go:259` | `return map[string]interface{}{"isError": true, "content": "Request failed: " + err.Error()}, nil` |
|
||||
| [`browser`](../examples/index.md#browser) | `example/browser/plugin_test.go:15` | `if err == nil \|\| !strings.Contains(err.Error(), "timeout is required") {` |
|
||||
|
||||
<small>`plugin.go:264`</small>
|
||||
|
||||
### `ImageURL`
|
||||
|
||||
```go
|
||||
type ImageURL struct { URL string `json:"url"` Detail string `json:"detail,omitempty"` }
|
||||
```
|
||||
|
||||
<small>`plugin.go:862`</small>
|
||||
<small>`plugin.go:961`</small>
|
||||
|
||||
### `MemItem`
|
||||
|
||||
@ -708,7 +727,7 @@ type MemItem struct { Role string `json:"role"` Content string `json:"content"`
|
||||
|
||||
MemItem represents a memory item in stage context.
|
||||
|
||||
<small>`plugin.go:179`</small>
|
||||
<small>`plugin.go:220`</small>
|
||||
|
||||
### `NormalizeProxyHost`
|
||||
|
||||
@ -732,7 +751,7 @@ type PluginSDK struct { name string regTool ToolRegistrar regStage StageRegistra
|
||||
PluginSDK is the main API surface provided to plugins at runtime.
|
||||
It wraps tool registration, settings, memory, knowledge, LLM, and IO injection.
|
||||
|
||||
<small>`plugin.go:337`</small>
|
||||
<small>`plugin.go:436`</small>
|
||||
|
||||
### `ProxyAuthHomeAgent`
|
||||
|
||||
@ -877,6 +896,64 @@ SDKVersion 是对外暴露的 SDK 版本号。
|
||||
|
||||
<small>`plugin.go:10`</small>
|
||||
|
||||
### `ScenePolicyAuto`
|
||||
|
||||
```go
|
||||
const ScenePolicyAuto
|
||||
```
|
||||
|
||||
场面策略:决定一次输入是否参与**场面识别**(场景式记忆)。
|
||||
|
||||
与前两项再正交一轴:NoMemory 管「进不进记忆计算」、ContextPolicy 管
|
||||
「裁不裁上下文」、RecallPolicy 管「召不召回记忆」,本项管的是
|
||||
「这条输入算不算一场戏的一部分」——它决定输入会不会产出现场指纹
|
||||
(通道/对话对象/工具/话题/时段),进而决定会不会长出、命中、写入场景。
|
||||
|
||||
默认(空串或 ScenePolicyAuto)**参与**,保持既有行为:场景式记忆自
|
||||
v1.3 落地起就对所有通道无条件生效,没有开关。不默认关有两个原因:
|
||||
1. 场景只**附加**现有记忆的检索路,不改记忆本体,默认关会让存量
|
||||
通道突然失去场景召回;
|
||||
2. 「关」是少数意图(内部信噪通道),少数意图不该是默认——
|
||||
与 ContextPolicy 刻意相反(同为破坏性操作,那里是默认关)。
|
||||
|
||||
该关的典型是纯内部通道:system(内核自循环)、kernel、timer、healthcheck。
|
||||
但**现网不标任何一个**(2026-09-26 裁定):实测这些 0-refs 通道合计 70
|
||||
strength、0 条记忆,场景召回返回空;而 declared 场景不进相似度空间
|
||||
(loadEmergentScenesLocked 只取 origin='emergent'),多写对聚类零影响。
|
||||
「多写无影响、少写会缺场景」——默认 auto 保持开,声明项只作为插件
|
||||
将来确实需要时的闸门。
|
||||
|
||||
<small>`plugin.go:98`</small>
|
||||
|
||||
### `ScenePolicyNone`
|
||||
|
||||
```go
|
||||
const ScenePolicyNone
|
||||
```
|
||||
|
||||
场面策略:决定一次输入是否参与**场面识别**(场景式记忆)。
|
||||
|
||||
与前两项再正交一轴:NoMemory 管「进不进记忆计算」、ContextPolicy 管
|
||||
「裁不裁上下文」、RecallPolicy 管「召不召回记忆」,本项管的是
|
||||
「这条输入算不算一场戏的一部分」——它决定输入会不会产出现场指纹
|
||||
(通道/对话对象/工具/话题/时段),进而决定会不会长出、命中、写入场景。
|
||||
|
||||
默认(空串或 ScenePolicyAuto)**参与**,保持既有行为:场景式记忆自
|
||||
v1.3 落地起就对所有通道无条件生效,没有开关。不默认关有两个原因:
|
||||
1. 场景只**附加**现有记忆的检索路,不改记忆本体,默认关会让存量
|
||||
通道突然失去场景召回;
|
||||
2. 「关」是少数意图(内部信噪通道),少数意图不该是默认——
|
||||
与 ContextPolicy 刻意相反(同为破坏性操作,那里是默认关)。
|
||||
|
||||
该关的典型是纯内部通道:system(内核自循环)、kernel、timer、healthcheck。
|
||||
但**现网不标任何一个**(2026-09-26 裁定):实测这些 0-refs 通道合计 70
|
||||
strength、0 条记忆,场景召回返回空;而 declared 场景不进相似度空间
|
||||
(loadEmergentScenesLocked 只取 origin='emergent'),多写对聚类零影响。
|
||||
「多写无影响、少写会缺场景」——默认 auto 保持开,声明项只作为插件
|
||||
将来确实需要时的闸门。
|
||||
|
||||
<small>`plugin.go:99`</small>
|
||||
|
||||
### `PluginSDK.SetProxyRegistrar`
|
||||
|
||||
```go
|
||||
@ -887,6 +964,24 @@ SetProxyRegistrar 由内核注入。插件不直接调它(与 SetInputChannelR
|
||||
|
||||
<small>`proxy.go:309`</small>
|
||||
|
||||
### `ToolError`
|
||||
|
||||
```go
|
||||
type ToolError struct { // Field 是出错的参数字段名(参数校验失败时填)。 Field string `json:"field,omitempty"` // Reason 是机器可读的原因码: …
|
||||
```
|
||||
|
||||
ToolError 描述一次工具调用的失败原因。
|
||||
|
||||
存在的理由:失败若只表达为文本,模型无法定位到字段,只能原样重试
|
||||
(实测 cmd_run 失败率 34%~48%,全部源于同一个成因:参数被截断或
|
||||
JSON 写坏,工具却只回报 "command is required" 这类与真因无关的错)。
|
||||
|
||||
⚠️ 零值语义:插件**不必**改用本类型。内核的失败识别同时兼容既有三种约定
|
||||
({"error":…}、{"isError":true,…}、显式 error 返回),见 core.isToolError。
|
||||
本类型是给**新写**的工具用的可选项,不是迁移要求。
|
||||
|
||||
<small>`plugin.go:252`</small>
|
||||
|
||||
### `PluginSDK.UnregisterOutputChannel`
|
||||
|
||||
!!! warning "仅内核内置插件可用"
|
||||
@ -898,7 +993,7 @@ func (s *PluginSDK) UnregisterOutputChannel(name string) error
|
||||
|
||||
UnregisterOutputChannel 注销一个输出通道(动态通道随资源生灭时必须调用)。
|
||||
|
||||
<small>`plugin.go:544`</small>
|
||||
<small>`plugin.go:643`</small>
|
||||
|
||||
### `ValidProxyAuth`
|
||||
|
||||
@ -923,6 +1018,16 @@ ValidProxyHostLabel 校验子域名标签是否合法(DNS label 规则)。
|
||||
|
||||
<small>`proxy.go:180`</small>
|
||||
|
||||
### `ValidScenePolicy`
|
||||
|
||||
```go
|
||||
func ValidScenePolicy(policy string) bool
|
||||
```
|
||||
|
||||
ValidScenePolicy 校验场面策略取值;空串等价于 ScenePolicyAuto。
|
||||
|
||||
<small>`plugin.go:103`</small>
|
||||
|
||||
### `ValidateProxyDef`
|
||||
|
||||
```go
|
||||
|
||||
@ -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:406`</small>
|
||||
<small>`plugin.go:505`</small>
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
func (c *StageContext) IsResponded() bool
|
||||
```
|
||||
|
||||
<small>`plugin.go:172`</small>
|
||||
<small>`plugin.go:213`</small>
|
||||
|
||||
### `StageContext.Lock`
|
||||
|
||||
@ -27,7 +27,7 @@ func (c *StageContext) Lock()
|
||||
| [`browser`](../examples/index.md#browser) | `example/browser/plugin.go:427` | `p.mu.Lock()` |
|
||||
| [`calendar`](../examples/index.md#calendar) | `example/calendar/plugin.go:433` | `p.mu.Lock()` |
|
||||
|
||||
<small>`plugin.go:170`</small>
|
||||
<small>`plugin.go:211`</small>
|
||||
|
||||
### `StageContext.RLock`
|
||||
|
||||
@ -44,7 +44,7 @@ func (c *StageContext) RLock()
|
||||
| [`memo`](../examples/index.md#memo) | `example/memo/plugin.go:224` | `p.mu.RLock()` |
|
||||
| [`qq`](../examples/index.md#qq) | `example/qq/plugin.go:1152` | `ctx.RLock()` |
|
||||
|
||||
<small>`plugin.go:168`</small>
|
||||
<small>`plugin.go:209`</small>
|
||||
|
||||
### `StageContext.RUnlock`
|
||||
|
||||
@ -61,7 +61,7 @@ func (c *StageContext) RUnlock()
|
||||
| [`memo`](../examples/index.md#memo) | `example/memo/plugin.go:229` | `p.mu.RUnlock()` |
|
||||
| [`qq`](../examples/index.md#qq) | `example/qq/plugin.go:1155` | `ctx.RUnlock()` |
|
||||
|
||||
<small>`plugin.go:169`</small>
|
||||
<small>`plugin.go:210`</small>
|
||||
|
||||
### `PluginSDK.RegisterStage`
|
||||
|
||||
@ -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:472`</small>
|
||||
<small>`plugin.go:571`</small>
|
||||
|
||||
### `Stage`
|
||||
|
||||
@ -103,7 +103,7 @@ type StageContext struct { mu sync.RWMutex RawMessage string UserID string Group
|
||||
|
||||
StageContext provides context for stage handlers.
|
||||
|
||||
<small>`plugin.go:148`</small>
|
||||
<small>`plugin.go:189`</small>
|
||||
|
||||
### `StageHandler`
|
||||
|
||||
@ -123,7 +123,7 @@ type StageRegistrar func(stage Stage, handler StageHandler)
|
||||
|
||||
StageRegistrar registers a stage handler.
|
||||
|
||||
<small>`plugin.go:308`</small>
|
||||
<small>`plugin.go:407`</small>
|
||||
|
||||
### `StageScope`
|
||||
|
||||
@ -133,7 +133,7 @@ type StageScope int
|
||||
|
||||
StageScope controls which events a stage handler receives.
|
||||
|
||||
<small>`plugin.go:294`</small>
|
||||
<small>`plugin.go:393`</small>
|
||||
|
||||
### `StageContext.Unlock`
|
||||
|
||||
@ -150,5 +150,5 @@ func (c *StageContext) Unlock()
|
||||
| [`browser`](../examples/index.md#browser) | `example/browser/plugin.go:432` | `p.mu.Unlock()` |
|
||||
| [`calendar`](../examples/index.md#calendar) | `example/calendar/plugin.go:523` | `p.mu.Unlock()` |
|
||||
|
||||
<small>`plugin.go:171`</small>
|
||||
<small>`plugin.go:212`</small>
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ ContentBlock 是多模态内容块(OpenAI 格式:text/image_url/audio_url)
|
||||
插件工具返回结果时可用 PluginSDK.SetToolBlocks 注入,让下一轮 LLM
|
||||
请求在 tool message 的 content 数组里带上图片/音频,实现"模型看图/听音频"。
|
||||
|
||||
<small>`plugin.go:855`</small>
|
||||
<small>`plugin.go:954`</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:458`</small>
|
||||
<small>`plugin.go:557`</small>
|
||||
|
||||
### `ToolCall`
|
||||
|
||||
@ -43,7 +43,7 @@ type ToolCall struct { ID string `json:"id"` Name string `json:"name"` Plugin st
|
||||
|
||||
ToolCall represents a model's request to call a tool.
|
||||
|
||||
<small>`plugin.go:186`</small>
|
||||
<small>`plugin.go:227`</small>
|
||||
|
||||
### `ToolDef`
|
||||
|
||||
@ -53,7 +53,7 @@ type ToolDef struct { Name string `json:"name"` Plugin string `json:"plugin,omit
|
||||
|
||||
ToolDef describes a tool that the plugin exposes.
|
||||
|
||||
<small>`plugin.go:203`</small>
|
||||
<small>`plugin.go:279`</small>
|
||||
|
||||
### `ToolHandler`
|
||||
|
||||
@ -73,5 +73,5 @@ type ToolResult struct { CallID string `json:"call_id"` Name string `json:"name"
|
||||
|
||||
ToolResult represents the result of a tool call.
|
||||
|
||||
<small>`plugin.go:194`</small>
|
||||
<small>`plugin.go:235`</small>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -8,15 +8,15 @@ SDK 仓 `example/` 下有多个**真实可编译**的示例插件,覆盖工具
|
||||
|
||||
## `a2a`
|
||||
|
||||
用到的 API:`InjectInputSync` · `Lock` · `RegisterInputChannel` · `RegisterOutputChannel` · `RegisterTool` · `SetAutoRestart` · `Settings` · `Unlock`
|
||||
用到的 API:`Error` · `InjectInputSync` · `Lock` · `RegisterInputChannel` · `RegisterOutputChannel` · `RegisterTool` · `SetAutoRestart` · `Settings` · `Unlock`
|
||||
|
||||
## `acp`
|
||||
|
||||
用到的 API:`InjectInputSync` · `Lock` · `RLock` · `RUnlock` · `RegisterInputChannel` · `RegisterOutputChannel` · `RegisterTool` · `SetAutoRestart` · `Settings` · `Unlock`
|
||||
用到的 API:`Error` · `InjectInputSync` · `Lock` · `RLock` · `RUnlock` · `RegisterInputChannel` · `RegisterOutputChannel` · `RegisterTool` · `SetAutoRestart` · `Settings` · `Unlock`
|
||||
|
||||
## `ai_image`
|
||||
|
||||
用到的 API:`RegisterTool` · `SetAutoRestart` · `Settings`
|
||||
用到的 API:`Error` · `RegisterTool` · `SetAutoRestart` · `Settings`
|
||||
|
||||
## `bili`
|
||||
|
||||
@ -24,7 +24,7 @@ SDK 仓 `example/` 下有多个**真实可编译**的示例插件,覆盖工具
|
||||
|
||||
## `browser`
|
||||
|
||||
用到的 API:`InjectInterruptTextOpts` · `InjectTextNoMemory` · `Lock` · `RegisterInputChannel` · `Unlock`
|
||||
用到的 API:`Error` · `InjectInterruptTextOpts` · `InjectTextNoMemory` · `Lock` · `RegisterInputChannel` · `Unlock`
|
||||
|
||||
## `calendar`
|
||||
|
||||
|
||||
113
docs/guide/scene-memory.md
Normal file
113
docs/guide/scene-memory.md
Normal file
@ -0,0 +1,113 @@
|
||||
# 场景记忆(Scene Memory)
|
||||
|
||||
> 场景式记忆是内核 v1.3 起的能力。它不新增 API 面,只影响**你的输入被怎样记住与取回**。
|
||||
> 与 `NoMemory` / `ContextPolicy` / `RecallPolicy` 并列为第四项声明:`ScenePolicy`。
|
||||
|
||||
## 它解决什么问题
|
||||
|
||||
三层记忆按**字面相关性**召回:你得说出相近的词,记忆才会被取回来。
|
||||
场景记忆补上另一半:按**场合**召回。
|
||||
|
||||
同一场合再次出现时,当时挂在这个场合上的约定、偏好、人物关系会自动回来——
|
||||
与这次说了什么措辞无关。
|
||||
|
||||
```
|
||||
你:以后在群里回消息简短点
|
||||
└─ 这条记忆挂到场面「chan:qq + peer:group_xxx」上
|
||||
|
||||
一周后,同一个群里有人问「上次说的格式是什么」
|
||||
└─ 场面重现(还没等你提到「格式」),那条约定已经被取回
|
||||
```
|
||||
|
||||
## 场面是自己长出来的
|
||||
|
||||
场景**不需要声明**。每轮交互,内核采集一组可观察信号当这轮<E8BF99><E8BDAE><EFBFBD>「场面指纹」:
|
||||
|
||||
| 特征 | 来源 | 权重 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `chan` | 输入通道名 | 1.0 | 最强的同一性信号 |
|
||||
| `peer` / `peer_group` | 注入点给的 `payload` 里的 `group_id`/`user_id`/`chat_id` 等 | 1.0 | 群与私聊分开,避免互相命中 |
|
||||
| `tool` | 触发这一步的工具名 | 0.8 | 行为信号 |
|
||||
| `topic` | 清洗后输入的内容词 | 0.4 | 软信号,同场面的不同话题不该被拆开 |
|
||||
| `part` | 时段(夜间/上午/下午/晚间) | 0.2 | 最弱,只做辅助 |
|
||||
|
||||
指纹反复重合时,一场场面就成形了。相似度按**加权 Jaccard** 算
|
||||
(共享特征的权重和 ÷ 并集的权重和)——不加权的话,一次偶然的话题重合
|
||||
会把两个不同场面并成一个。
|
||||
|
||||
**同类场面出现第二次才被认定。** 一次性的交互不建场面:
|
||||
那不是「场面」,建了只会让图库被一次性事件撑满。
|
||||
|
||||
## 声明你的参与姿态
|
||||
|
||||
```go
|
||||
sdk.ChannelDef{
|
||||
ScenePolicy: sdk.ScenePolicyNone, // 这条通道不参与场面识别
|
||||
}
|
||||
```
|
||||
|
||||
或单次注入覆盖:
|
||||
|
||||
```go
|
||||
sdk.InjectOptions{
|
||||
ScenePolicy: sdk.ScenePolicyNone,
|
||||
}
|
||||
```
|
||||
|
||||
| 取值 | 含义 |
|
||||
|---|---|
|
||||
| `""`(空)/ `ScenePolicyAuto` | **参与**(默认,保持既有行为) |
|
||||
| `ScenePolicyNone` | **不参与**:不产任何场面指纹,也不派生场景键 |
|
||||
|
||||
**默认是参与而不是不参与**,与 `ContextPolicy` 刻意相反。原因是场景只
|
||||
**附加**检索路径、不改记忆本体,默认关会让存量通道突然失去场景召回;
|
||||
而「关」是少数意图(纯内部信号)。
|
||||
|
||||
声明 `none` 之后连时段特征都不产——一个不参与的门面不该在场面索引里
|
||||
留下任何足迹。
|
||||
|
||||
### 谁该考虑关掉
|
||||
|
||||
内核自循环(`system`)、心跳(`timer`)、内部状态汇报(`kernel`)这类
|
||||
纯内部信号。它们每次触发都在撑一个场面,会把不相干的交互聚到一起。
|
||||
|
||||
反过来说,**多标一个通道通常没有代价**:一个没人往上面写记忆的场面,
|
||||
召回时返回空。关不关都不影响正确性——所以拿不准时,默认参与就好。
|
||||
|
||||
## 怎么给场面命名
|
||||
|
||||
场景键有两种来源:
|
||||
|
||||
**通道派生(默认)**——`evt.Source` 派生出 `chan:qq` 这类键。你不用管。
|
||||
|
||||
**显式声明(进阶)**——在注入时给出更有语义的键:
|
||||
|
||||
```go
|
||||
p.sdk.InjectInterruptTextOpts("qq", "qq", text, sdk.InjectOptions{
|
||||
ScenePolicy: sdk.ScenePolicyAuto,
|
||||
})
|
||||
```
|
||||
|
||||
也可以通过 `payload["scene"]` 传层级键(支持 `string` / `[]string` /
|
||||
`[]interface{}` 三种形态):
|
||||
|
||||
```go
|
||||
"chan:qq/peer:group_1027"
|
||||
```
|
||||
|
||||
召回走**前缀匹配**(`chan:qq` 能覆盖 `chan:qq/peer:xxx`),用 `/` 兜底
|
||||
以免 `chan:qq` 误吞 `chan:qq2` 这种同前缀但不同层的场景。
|
||||
|
||||
## 场面记忆不改变什么
|
||||
|
||||
- **不改记忆本体**:场景是记忆的**附加索引**,删掉场景不删记忆。
|
||||
- **不让模型负责**:`memory_commit` 的 `scene` 留空即可,内核会挂到本轮
|
||||
解析出的场面上。留空是安全的一侧——猜错的场面会把无关记忆钉死。
|
||||
- **不影响同步通道**:`webui` / `cli` / 终端走 `ResponseCh`,不经
|
||||
`output_send__*`,与场面无关。
|
||||
|
||||
## 相关 API
|
||||
|
||||
- `ChannelDef.ScenePolicy` —— 通道级声明(见 [输入/输出通道](../api/channels.md))
|
||||
- `InjectOptions.ScenePolicy` —— 单次注入覆盖(见 [其他类型](../api/misc.md))
|
||||
- `ScenePolicyAuto` / `ScenePolicyNone` / `ValidScenePolicy` —— 常量与校验
|
||||
@ -29,5 +29,6 @@
|
||||
- [环境与工具链](https://sdk.homeagent.jianfgit.xyz/guide/getting-started.md): hmapdev 是 SDK 仓提供的统一插件开发工具链,Go 与 Lua 两种插件都用它,
|
||||
- [多平台构建](https://sdk.homeagent.jianfgit.xyz/guide/multi-platform.md): hmapdev build 默认 bundle 模式,一次产出含三个平台的单个
|
||||
- [打包与发布](https://sdk.homeagent.jianfgit.xyz/guide/packaging.md): hmapdev build 一次完成编译与打包,产出
|
||||
- [场景记忆(Scene Memory)](https://sdk.homeagent.jianfgit.xyz/guide/scene-memory.md): > 场景式记忆是内核 v1
|
||||
- [受限 SDK 与安全](https://sdk.homeagent.jianfgit.xyz/guide/security.md): 外部插件与内置插件的区别不只是「能不能调某个函数」,还包含一层安全边界:
|
||||
- [版本与兼容](https://sdk.homeagent.jianfgit.xyz/versions.md): SDK 版本跟随内核的中版本,patch 位恒为
|
||||
|
||||
Reference in New Issue
Block a user