开发者文档/开发指南

服务与 Contract

发布可复用的能力,让其他 Curio 通过带版本的契约调用它。

核对日期:2026 年 9 月 11 日

本页目录

声明服务提供方#

公共服务由 Curio Backend 实现,是带版本的可复用能力。示例使用提供方 ID dev.example.text-tools 和服务 ID dev.example.text-tools.transformer。这些名称用于演示,不代表系统已安装该服务。

在提供方 Manifest 的真实 Backend 配置旁合并以下片段:

json
{
  "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

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 中加入:

json
{
  "services": {
    "requires": [{
      "id": "dev.example.text-tools.transformer",
      "version": "^1.0.0",
      "optional": false
    }]
  }
}

安装或运行兼容的提供方后,从调用方执行:

ts
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#

sh
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/:

ts
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 的返回值。详见测试指南