服务与 Contract
发布可复用的能力,让其他 Curio 通过带版本的契约调用它。
核对日期:2026 年 9 月 11 日
本页目录
声明服务提供方#
公共服务由 Curio Backend 实现,是带版本的可复用能力。示例使用提供方 ID dev.example.text-tools 和服务 ID dev.example.text-tools.transformer。这些名称用于演示,不代表系统已安装该服务。
在提供方 Manifest 的真实 Backend 配置旁合并以下片段:
{
"services": {
"provides": [{
"id": "dev.example.text-tools.transformer",
"version": "1.0.0",
"contract": "contracts/transformer.json"
}]
}
}
服务 ID 必须位于提供方 Curio 命名空间中。把 Contract 和可执行文件放入 package.files,进程与协议配置见 Backend 接入。
编写 Contract#
创建 contracts/transformer.json:
{
"schemaVersion": 1,
"service": "dev.example.text-tools.transformer",
"version": "1.0.0",
"methods": {
"uppercase": {
"params": {
"type": "object",
"properties": { "text": { "type": "string" } },
"required": ["text"],
"additionalProperties": false
},
"result": {
"type": "object",
"properties": { "text": { "type": "string" } },
"required": ["text"],
"additionalProperties": false
},
"timeoutMs": 5000,
"idempotent": true
}
},
"events": {}
}
Host 会根据 Contract 校验公共方法的输入与输出。声明接口不等于实现方法:Backend 必须处理 uppercase、返回 text,并报告结构化错误。idempotent: true 表示方法语义,不会自动触发重试。
可下载 Service Contract Schema 接入工具。service 与 version 要与 Manifest 完全一致;改变公共接口时维护服务版本,它与 Curio 包版本相互独立。
声明调用方依赖#
在调用方的 Manifest 中加入:
{
"services": {
"requires": [{
"id": "dev.example.text-tools.transformer",
"version": "^1.0.0",
"optional": false
}]
}
}
安装或运行兼容的提供方后,从调用方执行:
import { trove } from "@trove/plugin-sdk";
await trove.ready();
const result = await trove.call<{ text: string }>(
"dev.example.text-tools.transformer",
"uppercase",
{ text: "hello" },
{ timeoutMs: 5_000 },
);
console.log(result.text); // HELLO
声明依赖不会下载提供方。optional 为 true 表示你的工具在缺少该能力时仍可工作,应只禁用依赖它的功能,并在 UI 中处理缺失。可调用 host.services.resolve,传入要求的版本范围,诊断服务可用性。
生成 TypeScript#
trove contract generate contracts/transformer.json --out src/generated/transformer.ts
省略输入文件时,CLI 从当前 Manifest 的 provides 中选择,并默认生成到 src/generated/。多个 Contract 需要选择,已有输出需要确认或 --overwrite。目前仅支持 TypeScript 生成。
生成器输出带 methods/events 的 ServiceContract,不是 service<TContract> 接受的方法函数接口。可以用生成的参数与返回类型调用 call;下面代码假定位于 src/:
import { trove } from "@trove/plugin-sdk";
import type { ServiceContract } from "./generated/transformer";
type Uppercase = ServiceContract["methods"]["uppercase"];
const result = await trove.call<Uppercase["result"], Uppercase["params"]>(
"dev.example.text-tools.transformer", "uppercase", { text: "hello" },
);
JSON Contract 是共享的接口来源,修改后重新生成类型。生成的类型不能替代 Host 校验与 Backend 测试。
有明确需求再加入事件#
事件 Contract 声明订阅参数 params、事件数据 payload,以及 coalesce(none 或 latest)。提供方实现 subscribe、unsubscribe、事件序号和清理后,才能对外提供主题。调用方使用 SDK 订阅,在任务结束时关闭。
测试提供方正常、缺失和版本不兼容的情况,也测试调用中断连、非法输入和违反 Contract 的返回值。详见测试指南。