DeepSeek Harness: プラグイン設定:Config と Schemastery
最終更新:2026-08-31
設定はプラグインの「コントロールノブ」——API キー、タイムアウト、機能トグル、これらの環境依存パラメータはハードコードせず、設定システムを通じて外部化すべきです。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:
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:
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:
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
// Enum 値
Schema.union(['read', 'write', 'execute'])
// 定数
Schema.const('fixed-value')
// 説明付き Enum
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 キー')
(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('有効なメールアドレス')
(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:/^[a-z]+[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 を探します。他の名前は認識されません。ctx.on('config/updated') で設定変更に対応してください。.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(string、デフォルトはカレントディレクトリ)と maxDepth(number、デフォルト 10)。Web UI 設定ページでフォーム生成を確認すること。
2. ⭐⭐ 応用:マルチ接続設定プラグインを書いてください。Config に connections(オブジェクト配列、各オブジェクトに host/port/username/password)を含め、ネスト Schema.object で定義。確認:必須フィールド欠落時にエラー、デフォルト値が正しく埋まること。
3. ⭐⭐⭐ チャレンジ:カスタム検証付きの設定を作成してください:startDate と endDate は startDate < endDate を満たす必要あり;maxRetries は正の整数であること。テスト:無効な値を入力し、Web UI で検証エラーメッセージが正しく表示されることを確認。