Introduction¶
The DeepSeek Harness ecosystem is plugin-centric. When developing plugins, developers often need to handle settings page form rendering, storage logic, route registration, and security validation themselves. Reinventing the wheel is not only time-consuming but can also introduce security vulnerabilities. dsh-config-form provides a unified settings page container; plugins only need to declare fields to obtain a rendered form and routes.
Plugin Overview¶
This is a router and renderer, not a framework. It provides a unified settings entry point for all DeepSeek Harness plugins that actively integrate with it. The maintainer is begonia599. Through declarative configuration, plugins can quickly obtain a complete settings form while sharing routing and security check mechanisms.
Core Features¶
- Declarative field routing and rendering: Plugins define the form structure through declarations, and this plugin handles routing and rendering.
- Shared routing and security checks: Provides a unified HTTP route and entry point, centralizing security validation.
- Secret isolation: Sensitive information (such as tokens) is accessed via
ctx.credentialsand does not appear in the settings document. - Layered parsing and version fencing: Supports layered resolution of configuration values and prevents concurrent write conflicts with version fencing.
- HTTP API support: Provides HTTP interfaces for listing, details, writing, and secret management.
Installation and Setup¶
Use the official installation command to complete the installation:
dsh plugin --profile web add dsh-config-form
Typical Usage¶
Plugin developers need to introduce the configForm dependency and declare the field structure. The standard usage workflow is as follows:
- Declare fields: Call
ctx.configForm.declarein the plugin code to define configuration items. - Get configuration: Use
cfg.get()to retrieve the resolved configuration values. - Watch changes: Use
cfg.watchto listen for user save operations and execute follow-up logic. - Handle secrets: Use
await cfg.secret('token')to securely obtain sensitive credentials.
Code example:
export const inject = ['configForm']
export function apply(ctx: Context) {
const cfg = ctx.configForm.declare<Settings>(ctx, {
id: 'my-plugin',
title: { zh: '插件标题', en: 'Plugin Title' },
groups: [
{
title: { zh: '常规', en: 'General' },
fields: [
{ kind: 'text', key: 'settingKey', label: { zh: '设置项', en: 'Setting' }, default: 'value' }
]
}
]
})
// 读取配置
cfg.get().settingKey
// 监听变更
cfg.watch(next => {
// 配置已保存
})
// 安全获取密钥
await cfg.secret('token')
}
Applicable Scenarios and Notes¶
- Positioning: It is a router and renderer, not a framework.
- Storage: The plugin author chooses the storage logic. A
storeobject can be passed, or the settings seam can be relied on for automatic saving. - Security restrictions: Secrets do not appear in the settings document. Security checks rely on the loopback address, Host header, and Same-Origin Policy. Write operations can only modify declared value fields.
- Environment requirements: Before installation, confirm that the Node.js version satisfies
^22.19.0 || >=24.0.0.
Conclusion¶
With this plugin, developers can focus on business logic rather than repetitive UI and security code. For detailed information, refer to the plugin catalog or the source repository.