DeepSeek Harness: 插件配置:Config 与 Schemastery
最后更新:2026-08-31
配置是插件的"调节旋钮"——API Key、超时时间、功能开关,这些因环境而异的参数不应硬编码在插件里,而应通过配置系统外置。Schemastery 是 Cordis 的声明式配置框架,一次定义,自动获得类型安全、UI 表单、校验和文档。
📋 前置知识:已完成 15-define-tool.md,能编写基本工具
1. 你将学到
- Schemastery 声明式配置系统
- Schema.string/number/boolean/object/array
- .required()/.default()/.description()
- 嵌套配置 Schema.object
- 配置在 Web UI 设置页的展示
- 配置验证与错误提示
- 动态配置更新
2. Schemastery 声明式配置
(1) 基本概念
Schemastery 是 Cordis 内置的 Schema 定义库,灵感来自 Zod 和 JSON Schema,但专为交互式配置设计。
import { Schema } from '@deepseek-ai/cordis'
export const Config = Schema.object({
apiKey: Schema.string().required().description('API key for the service'),
maxRetries: Schema.number().default(3).description('Maximum retry attempts'),
debug: Schema.boolean().default(false).description('Enable debug logging')
})
(2) 与 JSON Schema 的对比
| 维度 | Schemastery | JSON Schema |
|---|---|---|
| 语法 | 链式 API | JSON 对象 |
| 类型推断 | ✅ 自动 | ❌ 需手动 |
| UI 表单 | ✅ 自动生成 | ❌ 需额外工具 |
| 默认值 | .default() |
default 字段 |
| 描述 | .description() |
description 字段 |
| 校验 | 链式校验器 | pattern/min/max 等 |
(3) ▶ 示例 3
export const Config = Schema.object({
apiKey: Schema.string().required(),
maxRetries: Schema.number().default(3)
})
export const name = 'my-plugin'
export function apply(ctx: Context) {
// ctx.config 类型自动推断
ctx.logger.info(`API key: ${ctx.config.apiKey}`)
ctx.logger.info(`Max retries: ${ctx.config.maxRetries}`)
}
框架会将用户提供的配置值校验后注入 ctx.config。
3. Schema 类型
(1) ▶ 示例 1
Schema.string() // 任意字符串
Schema.string().required() // 必填
Schema.string().default('hello') // 默认值
Schema.string().description('Your name') // 描述
Schema.string().pattern(/^[a-z]+$/) // 正则校验
Schema.string().min(1).max(100) // 长度限制
(2) ▶ 示例 2
Schema.number() // 任意数字
Schema.number().default(0) // 默认值
Schema.number().min(0).max(100) // 范围限制
Schema.number().step(1) // 步长(用于 UI 滑块)
Schema.integer() // 整数
(3) Schema.boolean
Schema.boolean() // 布尔值
Schema.boolean().default(false) // 默认 false
(4) Schema.object
Schema.object({
host: Schema.string().default('localhost'),
port: Schema.number().default(5432),
ssl: Schema.boolean().default(false)
})
(5) Schema.array
Schema.array(Schema.string()) // 字符串数组
Schema.array(Schema.string()).default([]) // 默认空数组
Schema.array(Schema.object({ // 对象数组
name: Schema.string().required(),
url: Schema.string().required()
}))
(6) Schema.union / Schema.const
// 枚举值
Schema.union(['read', 'write', 'execute'])
// 常量
Schema.const('fixed-value')
// 带描述的枚举
Schema.union([
Schema.const('read').description('Read-only access'),
Schema.const('write').description('Read and write access'),
Schema.const('execute').description('Full access')
])
(7) Schema.dict
// 字典类型
Schema.dict(
Schema.string(), // 值类型
Schema.string() // 键类型(可选)
)
4. 链式修饰符
(1) .required()
标记为必填。用户未提供时,框架报错并阻止加载。
apiKey: Schema.string().required()
(2) .default(value)
设置默认值。用户未提供时使用默认值,不报错。
maxRetries: Schema.number().default(3)
timeout: Schema.number().default(30000)
(3) .description(text)
为配置项添加描述,显示在 Web UI 中作为表单标签的提示文本。
apiKey: Schema.string().required()
.description('API key obtained from the service dashboard')
(4) .min() / .max()
数值范围或字符串长度限制:
port: Schema.number().min(1).max(65535).default(8080)
name: Schema.string().min(1).max(50)
(5) .pattern()
正则校验:
email: Schema.string().pattern(/^[^@]+@[^@]+\.[^@]+$/)
.description('Valid email address')
(6) .step()
数值步长,影响 UI 滑块的精度:
timeout: Schema.number().min(1000).max(300000).step(1000).default(30000)
(7) 组合使用
const Config = Schema.object({
apiKey: Schema.string()
.required()
.pattern(/^sk-[a-zA-Z0-9]+$/)
.description('DeepSeek API key (starts with sk-)'),
maxTokens: Schema.number()
.min(1).max(32768)
.default(4096)
.description('Maximum tokens per request'),
model: Schema.union(['deepseek-chat', 'deepseek-reasoner'])
.default('deepseek-chat')
.description('Model to use'),
temperature: Schema.number()
.min(0).max(2).step(0.1)
.default(0.7)
.description('Sampling temperature')
})
5. 嵌套配置
(1) 嵌套对象
const Config = Schema.object({
database: Schema.object({
host: Schema.string().default('localhost'),
port: Schema.number().default(5432),
name: Schema.string().required(),
ssl: Schema.boolean().default(false)
}).default({ host: 'localhost', port: 5432, ssl: false }),
cache: Schema.object({
enabled: Schema.boolean().default(true),
ttl: Schema.number().default(3600).description('Cache TTL in seconds')
}).default({ enabled: true, ttl: 3600 })
})
(2) 深层嵌套
const Config = Schema.object({
llm: Schema.object({
provider: Schema.union(['deepseek', 'openai']).default('deepseek'),
deepseek: Schema.object({
apiKey: Schema.string().required(),
model: Schema.string().default('deepseek-chat')
}),
openai: Schema.object({
apiKey: Schema.string(),
endpoint: Schema.string().default('https://api.openai.com/v1')
})
})
})
(3) 可复用 Schema
const ConnectionSchema = Schema.object({
host: Schema.string().default('localhost'),
port: Schema.number().default(5432),
timeout: Schema.number().default(5000)
})
const Config = Schema.object({
primary: ConnectionSchema.description('Primary connection'),
replica: ConnectionSchema.description('Replica connection')
})
6. 配置在 Web UI 设置页的展示
(1) 自动表单生成
Schemastery 定义的 Config 会自动在 Web UI 的设置页生成表单:
| Schema 类型 | UI 控件 |
|---|---|
Schema.string() |
文本输入框 |
Schema.number() |
数字输入框 / 滑块 |
Schema.boolean() |
开关 |
Schema.union() |
下拉选择 |
Schema.array() |
列表编辑器 |
Schema.object() |
分组面板 |
Schema.dict() |
键值对编辑器 |
(2) description 的展示
每个字段的 .description() 显示为输入框下方的提示文字:
┌─────────────────────────────────────────┐
│ API Key │
│ [sk-xxxxxxxxxxxxxxx ] │
│ DeepSeek API key (starts with sk-) │
├─────────────────────────────────────────┤
│ Max Tokens │
│ [4096 ] │
│ Maximum tokens per request │
└─────────────────────────────────────────┘
(3) 校验反馈
用户输入不符合 Schema 时,UI 即时提示:
┌─────────────────────────────────────────┐
│ API Key │
│ [invalid-key ] │
│ ❌ Must match pattern: /^sk-[a-zA-Z0-9]+$/ │
└─────────────────────────────────────────┘
7. 配置验证与错误提示
(1) 启动时校验
插件加载时,框架自动校验配置:
const Config = Schema.object({
port: Schema.number().min(1).max(65535)
})
// 用户配置 port: -1
// → Error: Invalid config for plugin my-plugin:
// port: must be >= 1
校验失败时,插件不会被加载,错误信息输出到终端。
(2) 类型安全
TypeScript 根据 Config 定义自动推断 ctx.config 的类型:
const Config = Schema.object({
apiKey: Schema.string().required(),
maxRetries: Schema.number().default(3)
})
export function apply(ctx: Context) {
ctx.config.apiKey // string ✅
ctx.config.maxRetries // number ✅
ctx.config.unknown // 类型错误 ❌
}
(3) 自定义校验
const Config = Schema.object({
startDate: Schema.string().required(),
endDate: Schema.string().required()
}).validate((value) => {
if (new Date(value.startDate) > new Date(value.endDate)) {
throw new Error('startDate must be before endDate')
}
return value
})
8. 动态配置更新
(1) 配置变更监听
export function apply(ctx: Context) {
ctx.on('config/updated', (newConfig) => {
ctx.logger.info('config updated:', newConfig)
// 根据新配置调整行为
})
}
(2) 热更新流程
graph LR
UI[用户修改配置] --> VALID[Schema 校验]
VALID --> APPLY[应用新配置]
APPLY --> EMIT[触发 config/updated]
EMIT --> RELOAD[插件响应更新]
(3) 需要重启的配置
某些配置(如端口号、依赖注入)变更后需要重启:
export function apply(ctx: Context) {
ctx.on('config/updated', (config) => {
if (config.port !== ctx.config.port) {
ctx.logger.warn('port change requires restart')
}
})
}
❓ 常见问题
Config 这个名字吗?export const Config。其他名称不会被识别。.hidden() 修饰符,UI 中用密码框显示: typescript apiKey: Schema.string().required().hidden() plugins.plugin-name.config,互不干扰。 ---📖 小节
- Schemastery 是 Cordis 的声明式配置框架:一次定义,自动获得类型安全、UI 表单和校验
- 支持 Schema.string/number/boolean/object/array/union/dict
- 链式修饰符:.required()/.default()/.description()/.min()/.max()/.pattern()
- 嵌套 Schema.object 组织复杂配置,可复用 Schema 定义
- Web UI 自动生成表单,description 显示为提示,校验失败即时反馈
- 配置变更通过 config/updated 事件监听,部分变更需要重启
📝 作业
1. ⭐ 基础题:为 file_count 工具添加 Config,包含 defaultPath(字符串,默认当前目录)和 maxDepth(数字,默认 10)两个配置项。在 Web UI 设置页验证表单生成。
2. ⭐⭐ 进阶题:编写一个多连接配置的插件,Config 包含 connections(对象数组,每项有 host/port/username/password),用嵌套 Schema.object 定义。验证:缺少必填项时报错,默认值正确填充。
3. ⭐⭐⭐ 挑战题:创建一个带自定义校验的配置:startDate 和 endDate 必须满足 startDate < endDate;maxRetries 必须是正整数。测试:输入非法值,确认校验错误信息准确显示在 Web UI 中。