Plugin configuration

Accept configuration supplied through cordis.yml.

Define the Config type

Export a Config type and a same-named Schemastery schema. Put defaults directly on the schema fields:

import type { Context } from '@deepseek-ai/cordis'
import Schema from '@deepseek-ai/schemastery'

export const name = 'my-plugin'

export interface Config {
  greeting: string
  maxRetries: number
  verbose?: boolean
}

export const Config: Schema<Config> = Schema.object({
  greeting: Schema.string().default('Hello'),
  maxRetries: Schema.number().default(3),
  verbose: Schema.boolean().default(false),
})

export function apply(ctx: Context, config: Config) {
  console.log(config.greeting)  // User value or schema default.
}

Add the configuration to the inserted local plugin row in scratch-plugin/cordis.yml:

- insert:
    - id: hello
      name: './src/my-plugin.ts'
      config:
        greeting: 'Hi there'
        maxRetries: 5

When loading the plugin, Cordis uses the exported schema to validate configuration and fill defaults. Do not export a plain object as Config; it does not implement the Standard Schema interface required by Cordis.

Schema validation

Use Schemastery to express stricter validation:

import type { Context } from '@deepseek-ai/cordis'
import Schema from '@deepseek-ai/schemastery'

export const name = 'validated-plugin'

export interface Config {
  apiKey: string
  timeout: number
  mode: 'fast' | 'accurate'
}

export const Config = Schema.object({
  apiKey: Schema.string().required(),
  timeout: Schema.number().default(30000),
  mode: Schema.union(['fast', 'accurate']).default('fast'),
})

export function apply(ctx: Context, config: Config) {
  // config is validated and type-safe.
}

The schema runs while the plugin loads. Invalid configuration fails the load with an actionable error.

Design principles

Do not hardcode tunable values

Harness requires anything that two deployments may want to set differently to be a configuration field.

// Wrong: hardcoded timeout.
const TIMEOUT = 30000

// Correct: configurable.
export interface Config {
  timeoutMs: number  // Defaults to 30000.
}

The test is whether cordis.yml can change the value without a code edit.

Fail loudly on invalid configuration

Express self-contained constraints in the schema so invalid configuration fails while the plugin loads. References to services or registered resources require dependency injection; the services tutorial introduces that contract.

Work with HMR

A configuration edit hot-replaces the plugin: the framework unloads the old instance and loads a new one. Because registrations are effects and clean themselves up, replacement does not retain the old instance's registrations.

Next steps

插件配置

让你的插件接受用户在 cordis.yml 中传入的配置。

定义 Config 类型

在插件中导出一个 Config 类型和同名的 Schemastery schema;默认值直接写在 schema 中:

import type { Context } from '@deepseek-ai/cordis'
import Schema from '@deepseek-ai/schemastery'

export const name = 'my-plugin'

export interface Config {
  greeting: string
  maxRetries: number
  verbose?: boolean
}

export const Config: Schema<Config> = Schema.object({
  greeting: Schema.string().default('Hello'),
  maxRetries: Schema.number().default(3),
  verbose: Schema.boolean().default(false),
})

export function apply(ctx: Context, config: Config) {
  console.log(config.greeting)  // User value or schema default.
}

scratch-plugin/cordis.yml 新插入的本地插件行中添加配置:

- insert:
    - id: hello
      name: './src/my-plugin.ts'
      config:
        greeting: 'Hi there'
        maxRetries: 5

插件加载时,Cordis 会通过导出的 schema 校验配置,并填充未提供字段的默认值。不要导出普通对象作为 Config,因为它不满足 Cordis 要求的 Standard Schema 接口。

Schema 校验

对于需要严格校验的场景,使用 Schemastery 定义 schema:

import type { Context } from '@deepseek-ai/cordis'
import Schema from '@deepseek-ai/schemastery'

export const name = 'validated-plugin'

export interface Config {
  apiKey: string
  timeout: number
  mode: 'fast' | 'accurate'
}

export const Config = Schema.object({
  apiKey: Schema.string().required(),
  timeout: Schema.number().default(30000),
  mode: Schema.union(['fast', 'accurate']).default('fast'),
})

export function apply(ctx: Context, config: Config) {
  // config is validated and type-safe.
}

Schema 在插件加载时执行校验。如果配置不合法,插件会加载失败并给出明确错误信息。

设计原则

无硬编码可调参数

Harness 的约定:凡是不同部署可能需要采用不同值的参数,都必须定义为配置字段

// Wrong: hardcoded timeout.
const TIMEOUT = 30000

// Correct: configurable.
export interface Config {
  timeoutMs: number  // Defaults to 30000.
}

检验标准:能否在 cordis.yml 中改变这个值,而不需要修改代码?

配置错误要响亮

在 schema 中表达自身完备的约束,使无效配置在插件加载时失败。对服务或已注册资源的引用需要依赖注入;服务教程 会介绍这项约定。

配合 HMR

配置变更会触发插件热替换:修改 cordis.yml 中某个插件的 config 后,框架会卸载旧实例并加载新实例。由于注册都属于 effect 并会自动清理,替换后不会保留旧实例的注册。

下一步