插件是什么
插件给游戏增加行为:一种叙事方式、一套判定规则、一个任务日志、一块界面面板。世界决定内容,插件决定怎么玩。
插件是一个文件夹。最简单的插件只有一个写着配置和提示词的 Markdown 文件,不需要写代码。
一个插件里有什么
my-plugin/
├── PLUGIN.md 说明、它依赖的能力、它贡献的工具和界面;只有它是必需的
├── README.md
├── runtimes/ 可选:一个或多个运行单元
│ └── <名字>/
│ ├── RUNTIME.md 何时运行、读什么、输出什么;agent 的提示词写在正文里
│ └── handler.js 函数型运行单元的代码
└── locales/ 可选:名称和界面文字的译文PLUGIN.md 的开头是一段 YAML,声明这个包是什么;后面的正文是给模型的指令。
运行单元:agent 和函数
插件里真正被执行的东西叫 runtime(运行单元)。一个插件可以没有,可以有一个,也可以有好几个。它有两种:
| 类型 | 它是什么 | 适合做什么 | 花不花模型费用 |
|---|---|---|---|
| agent | 一段提示词。模型读它,再调用工具完成任务 | 写故事、从正文里提取事实、做判断 | 花 |
| function | 一个 JavaScript 函数 | 掷骰、计算、读写数据、调用外部接口 | 直接执行不花;主动调用模型时花 |
函数也可以通过 ctx.gateway 调用模型,或通过 ctx.agents.run 委托子 agent;这些调用仍会产生相应的模型用量。
经验法则:**能用确定的规则算出来的事交给函数,需要理解文字的事交给 agent。**骰子应该由函数来掷,这样结果不会被行文倒推改写。
什么时候运行
每个 runtime 声明自己在回合的哪个阶段运行:
| 阶段 | 时机 | 典型用途 |
|---|---|---|
setup | 开局,游戏开始之前 | 创建角色、初始化数据 |
pre-turn | 叙事之前 | 检索资料、预先掷骰 |
narrative | 叙事 | 写这一回合的故事 |
post-turn | 叙事之后 | 根据正文更新任务、行囊、关系 |
audit | 最后 | 检查和收尾 |
前一个阶段全部完成后,下一个阶段才开始。除了按阶段自动运行,runtime 也可以由玩家点按钮手动触发,或者由一个事件触发。
插件之间怎样配合
插件之间不直接点名对方。一个插件说自己提供什么能力,另一个说自己需要什么能力,Covel 负责把它们接起来。能力有一个带版本号的名字,例如 narrative-engine@2,意思是“写故事的能力,第 2 版”。
requires: [narrative-engine@2]这一行的意思是“我需要一个能写故事的插件”,而不是“我需要名叫 narrator 的那个插件”。所以叙事者可以被替换,依赖它的插件不用改。
插件怎样保存数据
插件不能直接改存档。它只能提出“我想改这个”,Covel 检查后才提交。runtime 失败时,它的写入不会保存;有故事的执行会隔离可选插件的提交失败,已经接受的故事仍可保留。具体边界见事务。
每个插件有一块自己的数据,别的插件读不到。角色、资料库这些大家共用的数据由 Covel 保管:插件可以读,想改也要先提出来。
选一条路
| 你的需求 | 形式 | 从哪里开始 |
|---|---|---|
| 让模型多做一件事,例如每回合补一段观察 | 只有提示词 | 只写提示词的插件 |
| 让模型使用我自己写的工具 | 提示词加代码 | 带代码的插件 |
| 确定的规则、多个步骤配合、预置数据 | 多个 runtime | 多个 runtime 与数据 |
| 加一块面板、一张表单或一段自定义界面 | 一份描述界面的文件 | 给插件加界面 |
不确定选哪个时,从第一个插件开始:它生成的示例同时包含一个 agent、一个函数和一块面板。
本章内容
| 页面 | 你会得到什么 |
|---|---|
| 第一个插件 | 生成一个插件,离线跑通,再装进游戏里看到它工作 |
| 只写提示词的插件 | 一个只有 PLUGIN.md 的插件 |
| 带代码的插件 | 自己的工具、按钮动作和函数 |
| 多个 runtime 与数据 | 几个 runtime 互相配合,接收世界预置的数据,申请权限 |
| 给插件加界面 | 侧栏面板、正文里的区块、表单和自定义页面 |
| 写插件要知道的规则 | 每个插件作者都会遇到的规则,按问题查 |
| 提示词写法 | 怎样把给模型的指令写清楚 |
| 深入测试 | 单元测试、整回合测试和离线用例的全部写法 |
查细节
| 你想查的内容 | 参考页 |
|---|---|
PLUGIN.md 和 RUNTIME.md 的字段 | 插件字段 |
| 内置工具和怎样写工具 | 工具 |
| 在回合的各个节点拦截或改写 | Hook |
| 插件之间怎样通信 | 插件扩展与通信 |
| 界面组件和面板 | 界面组件、面板 |