自定义插件
编写、发布并为 Agent 配置可安装的 Downcity Plugin
自定义插件
一个 CLI 入口可以导出多个 Plugin constructor。每个 Plugin 自己持有静态 Manifest 和可选 Resource Resolver;CLI 负责安装、校验并统一实例化。
制品结构
example-connectors/
├── downcity.plugin.json
└── dist/
└── index.js入口只需要导出数组:
export const plugins = [GithubPlugin, LinearPlugin];不需要 PluginProject 或每个 Plugin 的 Factory。
Plugin constructor
import type { JsonObject } from "@downcity/agent";
export class GithubPlugin {
static readonly manifest = {
name: "github",
version: "1.0.0",
title: "GitHub",
description: "GitHub 集成",
config: {
schema: GITHUB_CONFIG_JSON_SCHEMA,
defaults: {
api_url: "https://api.github.com",
},
},
resources: {
schema: GITHUB_RESOURCE_JSON_SCHEMA,
},
};
static async resolve_resource({ resource }: { resource: JsonObject }) {
const user = await get_github_user(String(resource.token));
return { name: user.name, login: user.login };
}
readonly name = "github";
readonly actions = {};
constructor({ config, resources }: {
config: JsonObject;
resources: JsonObject[];
}) {
// config 和 resources 已经由 CLI 校验并解析完成。
}
}CLI 最终统一执行:
new GithubPlugin({ config, resources });实例 name 必须与 static manifest.name 一致。
Config 与 Resource Schema
Schema 使用 JSON Schema 2020-12,并直接放在 Plugin 静态 Manifest 中。可以使用 Zod 作为源码定义:
import { z } from "zod";
const config_schema = z.object({
api_url: z.url(),
}).strict();
export const GITHUB_CONFIG_JSON_SCHEMA = z.toJSONSchema(config_schema, {
target: "draft-2020-12",
});Resource Schema 描述完整 Item,要求 id、type 和 name。id 由 City 写入;普通字段和 writeOnly 字段由用户填写;其他 readOnly 字段由 static resolve_resource 返回。
每个 Plugin 必须提供非空 description。City 会在普通 Plugin 列表、交互式列表和 JSON Catalog 中统一展示这段用途说明。
Resolver 只在 Resource 创建、编辑或刷新时调用。Agent 启动只读取已经保存的完整 Resource Item,不会隐式联网刷新。
静态安装清单
安装阶段不会执行第三方入口,因此构建过程必须从 Plugin 的静态 Manifest 生成并提交 downcity.plugin.json:
{
"manifest_version": 3,
"entry": "dist/index.js",
"plugins": [
{
"name": "github",
"version": "1.0.0",
"title": "GitHub",
"config": {
"schema": {
"type": "object",
"properties": {
"api_url": { "type": "string", "format": "uri" }
},
"additionalProperties": false
},
"defaults": {
"api_url": "https://api.github.com"
}
}
},
{
"name": "linear",
"version": "1.0.0",
"title": "Linear",
"description": "Linear 集成"
}
]
}运行时,CLI 会确认 plugins[] 中每个 constructor 的静态 Manifest 与该安装快照一致。
Action 不写入静态 Manifest。实际 Action 只由 Plugin 实例的 actions 定义,避免维护重复的 Action 名称列表。
安装与配置
city plugin install ./example-connectors
city plugin install github:acme/example-connectors#main
city plugin resource create github --interactive
city plugin config github my-agent --interactive
city plugin enable github my-agent
city plugin update github
city plugin uninstall github如果一个入口同时导出 github 和 linear,更新其中任意一个都会更新整个共享入口;卸载其中任意一个会卸载该入口的全部 Plugin。存在 Binding 或 Resource 时 CLI 会拒绝卸载。
安全边界
安装过程只读取静态 Manifest 和制品文件,不执行 npm install、构建脚本、生命周期脚本或 Plugin 入口。City 会记录 Git commit 和完整制品的 SHA-256 摘要。
Plugin 入口会在创建或刷新 Resource,以及 Agent 启动时执行,因此只应安装可信来源。
继续阅读: