DeepSeek Harness: إعدادات الإضافة: Config و Schemastery
آخر تحديث: 2026-08-31
الإعدادات هي "مقبول التحكم" للإضافة — مفاتيح API، مهلات الانتظار، مفاتيح الميزات، هذه المُعاملات الخاصة بالبيئة لا يجب أن تكون مُرمّزة بثبات بل تُخرج عبر نظام إعدادات. Schemastery هو إطار الإعدادات التصريحي في Cordis: عرّف مرة، واحصل تلقائياً على أمان الأنواع ونماذج واجهة المستخدم والتحقق والتوثيق.
📋 المتطلبات المسبقة: أكمل 15-define-tool.md، قادر على كتابة أدوات أساسية
1. ما ستتعلمه
- نظام الإعدادات التصريحي Schemastery
- Schema.string/number/boolean/object/array
- .required()/.default()/.description()
- الإعدادات المتداخلة بـ Schema.object
- عرض الإعدادات في صفحة إعدادات واجهة الويب
- تحقق الإعدادات ورسائل الخطأ
- تحديثات الإعدادات الديناميكية
2. نظام الإعدادات التصريحي Schemastery
(1) المفهوم الأساسي
Schemastery هي مكتبة تعريف Schema المدمجة في Cordis، مُستلهمة من 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 |
| استنتاج الأنواع | ✅ تلقائي | ❌ يدوي |
| نماذج واجهة المستخدم | ✅ مُولّدة تلقائياً | ❌ تحتاج أدوات إضافية |
| القيم الافتراضية | .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) // خطوة (لشرائح واجهة المستخدم)
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)
يُضيف وصفاً لعنصر إعدادات، يُعرض في واجهة الويب كنص تلميح لتسميات النموذج.
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()
خطوة عددية، تؤثر على دقة شريحة واجهة المستخدم:
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. عرض الإعدادات في صفحة إعدادات واجهة الويب
(1) توليد النماذج تلقائياً
Config المُعرّف بـ Schemastery يُولّد تلقائياً نماذج في صفحة إعدادات واجهة الويب:
| نوع Schema | عنصر واجهة المستخدم |
|---|---|
Schema.string() |
حقل إدخال نصي |
Schema.number() |
حقل إدخال رقمي / شريحة |
Schema.boolean() |
مفتاح تبديل |
Schema.union() |
قائمة منسدلة |
Schema.array() |
مُحرّر قوائم |
Schema.object() |
لوحة مُجمّعة |
Schema.dict() |
مُحرّر مفتاح-قيمة |
(2) عرض الوصف
وصف .description() لكل حقل يظهر كنص تلميح أسفل الإدخال:
┌─────────────────────────────────────────┐
│ API Key │
│ [sk-xxxxxxxxxxxxxxx ] │
│ DeepSeek API key (starts with sk-) │
├─────────────────────────────────────────┤
│ Max Tokens │
│ [4096 ] │
│ Maximum tokens per request │
└─────────────────────────────────────────┘
(3) ملاحظات التحقق
عندما لا يتطابق إدخال المستخدم مع Schema، تعرض واجهة المستخدم ملاحظات فورية:
┌─────────────────────────────────────────┐
│ 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 يستنتج نوع ctx.config تلقائياً من تعريف 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()، الذي يعرض حقل كلمة مرور في واجهة المستخدم: typescript apiKey: Schema.string().required().hidden() plugins.plugin-name.config، معزول عن بعضها.📖 ملخص
- Schemastery هو إطار الإعدادات التصريحي في Cordis: عرّف مرة واحصل تلقائياً على أمان الأنواع ونماذج واجهة المستخدم والتحقق
- يدعم Schema.string/number/boolean/object/array/union/dict
- المُعدّلات القابلة للسلسلة: .required()/.default()/.description()/.min()/.max()/.pattern()
- Schema.object المتداخل يُنظّم الإعدادات المعقدة؛ تعريفات Schema قابلة لإعادة الاستخدام
- واجهة الويب تولّد النماذج تلقائياً؛ الوصف يُعرض كتلميحات؛ فشل التحقق يُعطي ملاحظات فورية
- تغييرات الإعدادات تُراقب عبر أحداث config/updated؛ بعض التغييرات تتطلب إعادة التشغيل
📝 تمارين
1. ⭐ أساسي: أضف Config لأداة file_count مع defaultPath (سلسلة، الدليل الحالي افتراضياً) و maxDepth (عدد، 10 افتراضياً). تحقق من توليد النموذج في صفحة إعدادات واجهة الويب.
2. ⭐⭐ متوسط: اكتب إضافة إعدادات اتصالات متعددة. Config يحتوي connections (مصفوفة كائنات، كل منها host/port/username/password)، مُعرّفة بـ Schema.object متداخل. تحقق: أخطاء عند فقدان حقول مطلوبة، القيم الافتراضية تملأ بشكل صحيح.
3. ⭐⭐⭐ تحدٍ: أنشئ إعدادات بتحقق مخصص: startDate و endDate يجب أن يحققا startDate < endDate؛ maxRetries يجب أن يكون عدداً صحيحاً موجباً. الاختبار: أدخل قيماً غير صالحة وتأكد أن رسائل خطأ التحقق تُعرض بشكل صحيح في واجهة الويب.