# Conflicts: # docs/user/develop/basic/config.zh.md # docs/user/develop/basic/index.zh.md # docs/user/develop/basic/tool.zh.md # docs/user/develop/framework/index.zh.md # docs/user/develop/framework/service.zh.md # docs/user/develop/practice/index.zh.md # docs/user/guide/index.zh.md # package.json # pnpm-lock.yaml # pnpm-workspace.yaml # website/.vitepress/config/index.ts # website/.vitepress/config/zh-CN.ts # website/package.json # website/zh-CN/api/cordis/context.md # website/zh-CN/api/cordis/events.md # website/zh-CN/api/cordis/fiber.md # website/zh-CN/api/cordis/registry.md # website/zh-CN/api/cordis/service.md # website/zh-CN/api/harness/bash.md # website/zh-CN/api/harness/fs.md # website/zh-CN/api/harness/llm.md # website/zh-CN/api/harness/tools.md # website/zh-CN/api/index.md # website/zh-CN/design/composability.md # website/zh-CN/design/context-model.md # website/zh-CN/design/reactive-coeffects.md # website/zh-CN/design/revertible-effects.md # website/zh-CN/develop/framework/events.md # website/zh-CN/develop/practice/llm-adapter.md # website/zh-CN/guide/config.md
119 lines
3.1 KiB
Markdown
119 lines
3.1 KiB
Markdown
# Plugin configuration
|
|
|
|
English | [中文](config.zh.md)
|
|
|
|
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:
|
|
|
|
```ts
|
|
import type { Context } from 'cordis'
|
|
import Schema from '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.
|
|
}
|
|
```
|
|
|
|
Configure it in `cordis.yml`:
|
|
|
|
```yaml
|
|
- 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:
|
|
|
|
```ts
|
|
import type { Context } from 'cordis'
|
|
import Schema from '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**.
|
|
|
|
```ts
|
|
// 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
|
|
|
|
If configuration refers to an unregistered LLM provider route or another nonexistent resource, fail early instead of silently skipping it:
|
|
|
|
```ts
|
|
import type { Context } from 'cordis'
|
|
import type {} from '@deepseek-ai/dsh-llm'
|
|
|
|
export interface ModelConfig {
|
|
provider: string
|
|
}
|
|
|
|
export function apply(ctx: Context, config: ModelConfig) {
|
|
if (!ctx.llm.listProviders().some(provider => provider.id === config.provider)) {
|
|
throw new Error(`LLM provider "${config.provider}" is not registered`)
|
|
}
|
|
}
|
|
```
|
|
|
|
## 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
|
|
|
|
- [Plugins and lifecycle](../framework/) — understand the full plugin lifecycle
|
|
- [Services and dependencies](../framework/service.md) — provide a service to other plugins
|