Skip to content

Commit a4043d6

Browse files
authored
docs(model-tool): 补充工具元数据与 reply 字段说明 (#25)
1 parent c5f52c2 commit a4043d6

1 file changed

Lines changed: 154 additions & 0 deletions

File tree

docs/development/connect-to-core-services/model-tool.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,157 @@ export function apply(ctx: Context, config: Config) {
165165
- `session` - 当前会话对象
166166
- 返回:`Tool` 实例
167167
- 用途:创建并返回工具的实例
168+
- `meta`: 工具元数据(推荐填写)
169+
- `source`: 工具来源
170+
- 常见值:`core``extension``mcp``action`
171+
- `group`: 工具所属分组
172+
- 如:`search``plugin-common`
173+
- `tags`: 工具标签列表
174+
- 用于分类、筛选和展示
175+
- `defaultAvailability`: 工具的默认可用性配置
176+
- `enabled`: 是否默认启用
177+
- `main`: 是否在主聊天模式中默认可用
178+
- `chatluna`: 是否在 ChatLuna 主能力中默认可用
179+
- `characterScope`: 是否在伪装插件中默认可用
180+
- `all`: 群聊和私聊都默认可用
181+
- `group`: 仅群聊默认可用
182+
- `private`: 仅私聊默认可用
183+
- `none`: 默认不在伪装插件中启用
184+
185+
### 工具元数据
186+
187+
当前 ChatLuna 的工具注册,通常都会补充 `meta` 字段。虽然它不是强制项,但推荐在开发插件时始终填写,便于工具系统、配置界面和其他上层功能正确识别工具来源、分组与默认启用范围。
188+
189+
示例:
190+
191+
```ts
192+
plugin.registerTool('web_search', {
193+
description: SEARCH_TOOL_DESCRIPTION,
194+
selector() {
195+
return true
196+
},
197+
createTool(params) {
198+
return new SearchTool(...)
199+
},
200+
meta: {
201+
source: 'extension',
202+
group: 'search',
203+
tags: ['search', 'web'],
204+
defaultAvailability: {
205+
enabled: true,
206+
main: true,
207+
chatluna: true,
208+
characterScope: 'all'
209+
}
210+
}
211+
})
212+
```
213+
214+
如果你的工具是为伪装插件的回复流程服务的,建议你明确设置 `characterScope`,避免工具默认暴露到不合适的会话范围。
215+
216+
## 为伪装插件的回复工具挂载自定义字段
217+
218+
[chatluna-character](../../ecosystem/other/character.md) 伪装插件支持一种实验性的「工具调用回复」模式。在该模式下,模型不再通过 XML 块输出回复内容,而是通过调用一个名为 `character_reply` 的工具来完成状态更新、消息发送、触发条件设置等操作。
219+
220+
外部插件可以通过 `ctx.chatluna_character.registerReplyToolField()` 方法,向 `character_reply` 工具注册额外的自定义参数字段。
221+
222+
> [!TIP] 最佳实践
223+
> 建议只在此处注册与消息交互有关的能力,如:戳一戳、撤回消息等,因为它们几乎不需要模型查看工具返回的结果,并且更适合在模型完成消息回复时一起操作。
224+
225+
当模型调用 `character_reply` 时,伪装插件会自动将这些自定义字段连同内置字段一起传递给模型,并在工具被调用时执行对应的回调。
226+
227+
### CharacterReplyToolField 接口
228+
229+
注册的字段需要符合 `CharacterReplyToolField` 接口:
230+
231+
```ts
232+
interface CharacterReplyToolField {
233+
/** 字段名称,将作为 character_reply 工具的参数名 */
234+
name: string
235+
236+
/** JSON Schema,描述该字段的类型与结构 */
237+
schema: Record<string, unknown>
238+
239+
/**
240+
* 可用性检查(可选)。
241+
* 返回 false 时,该字段不会出现在工具参数中,也不会被调用。
242+
*/
243+
isAvailable?: (
244+
ctx: Context,
245+
session: Session,
246+
config: Config | GuildConfig | PrivateConfig
247+
) => boolean
248+
249+
/**
250+
* 工具被调用时的回调。
251+
* 当模型在调用 character_reply 时传入了该字段的值,此回调会被执行。
252+
*/
253+
invoke?: (
254+
ctx: Context,
255+
session: Session,
256+
value: unknown,
257+
config: Config | GuildConfig | PrivateConfig
258+
) => Promise<void> | void
259+
260+
/**
261+
* 渲染回调。
262+
* 将工具调用的结果转换为 XML 字符串,插入到 <action> 块中。
263+
* 用于将工具调用的输出回写到对话历史中,以便模型在后续轮次中看到之前的操作。
264+
*/
265+
render?: (
266+
ctx: Context,
267+
session: Session,
268+
value: unknown,
269+
config: Config | GuildConfig | PrivateConfig
270+
) => string | string[] | undefined
271+
}
272+
```
273+
274+
### 注册字段
275+
276+
调用 `ctx.chatluna_character.registerReplyToolField()` 注册字段。该方法返回一个注销函数,调用后可移除已注册的字段。
277+
278+
```ts
279+
import { Context } from 'koishi'
280+
import type {} from 'koishi-plugin-chatluna-character'
281+
282+
export function apply(ctx: Context) {
283+
// 注册一个自定义字段
284+
const dispose = ctx.chatluna_character.registerReplyToolField({
285+
name: 'poke',
286+
287+
schema: {
288+
type: 'string',
289+
description: 'Platform user ID to poke.'
290+
},
291+
292+
// 仅在非私聊的 OneBot 平台上可用
293+
isAvailable(ctx, session) {
294+
return !session.isDirect && session.platform === 'onebot'
295+
},
296+
297+
// 模型调用 character_reply 并传入 poke 字段时执行
298+
async invoke(ctx, session, value) {
299+
if (typeof value !== 'string') return
300+
// 执行戳一戳操作……
301+
},
302+
303+
// 将工具调用结果渲染为 XML,写入对话历史
304+
render(ctx, session, value) {
305+
if (typeof value !== 'string') return undefined
306+
return `<poke user_id="${value}" />`
307+
}
308+
})
309+
310+
// 插件卸载时自动注销
311+
ctx.on('dispose', dispose)
312+
}
313+
```
314+
315+
### 工作流程
316+
317+
注册的字段会参与以下流程:
318+
319+
1. **构建工具参数**:伪装插件在创建 `character_reply` 工具时,遍历所有已注册字段,对通过 `isAvailable` 检查的字段,将其 `schema` 添加到工具的参数定义中。
320+
2. **执行回调**:当模型调用 `character_reply` 并传入了某个自定义字段的值时,伪装插件会调用该字段的 `invoke` 回调。
321+
3. **渲染到历史**:在将工具调用结果写入对话历史时,伪装插件会调用每个字段的 `render` 回调,将返回的 XML 字符串插入到 `<action>` 块中,使模型在后续轮次中可以看到之前的操作记录。

0 commit comments

Comments
 (0)