الانتقال إلى المحتوى الرئيسي

إعداد الإضافة وConfig الخاص بها

مرجع لتغليف الإضافات (بيانات package.json الوصفية)، وmanifest (openclaw.plugin.json)، ومداخل الإعداد، ومخططات config.
هل تبحث عن شرح عملي؟ تغطي أدلة التنفيذ التغليف ضمن السياق: إضافات القنوات و إضافات المزوّدين.

بيانات الحزمة الوصفية

يحتاج package.json الخاص بك إلى حقل openclaw يخبر نظام الإضافات بما توفّره إضافتك: إضافة قناة:
{
  "name": "@myorg/openclaw-my-channel",
  "version": "1.0.0",
  "type": "module",
  "openclaw": {
    "extensions": ["./index.ts"],
    "setupEntry": "./setup-entry.ts",
    "channel": {
      "id": "my-channel",
      "label": "My Channel",
      "blurb": "وصف قصير للقناة."
    }
  }
}
إضافة مزوّد / خط أساس النشر على ClawHub:
openclaw-clawhub-package.json
{
  "name": "@myorg/openclaw-my-plugin",
  "version": "1.0.0",
  "type": "module",
  "openclaw": {
    "extensions": ["./index.ts"],
    "compat": {
      "pluginApi": ">=2026.3.24-beta.2",
      "minGatewayVersion": "2026.3.24-beta.2"
    },
    "build": {
      "openclawVersion": "2026.3.24-beta.2",
      "pluginSdkVersion": "2026.3.24-beta.2"
    }
  }
}
إذا كنت تنشر الإضافة خارجيًا على ClawHub، فإن حقلي compat وbuild مطلوبان. وتوجد مقتطفات النشر القانونية في docs/snippets/plugin-publish/.

حقول openclaw

الحقلالنوعالوصف
extensionsstring[]ملفات نقاط الإدخال (نسبةً إلى جذر الحزمة)
setupEntrystringإدخال خفيف مخصص للإعداد فقط (اختياري)
channelobjectبيانات وصفية لفهرس القنوات لأسطح الإعداد والمنتقي والبداية السريعة والحالة
providersstring[]معرّفات المزوّدين التي تسجلها هذه الإضافة
installobjectتلميحات التثبيت: npmSpec وlocalPath وdefaultChoice وminHostVersion وallowInvalidConfigRecovery
startupobjectرايات سلوك بدء التشغيل

openclaw.channel

يمثل openclaw.channel بيانات وصفية رخيصة على مستوى الحزمة لاكتشاف القنوات وأسطر الإعداد قبل تحميل وقت التشغيل.
الحقلالنوعما الذي يعنيه
idstringمعرّف القناة القانوني.
labelstringالتسمية الأساسية للقناة.
selectionLabelstringتسمية المنتقي/الإعداد عندما ينبغي أن تختلف عن label.
detailLabelstringتسمية تفاصيل ثانوية لفهارس القنوات الأغنى وأسطر الحالة.
docsPathstringمسار المستندات لروابط الإعداد والاختيار.
docsLabelstringتجاوز للتسمية المستخدمة لروابط المستندات عندما ينبغي أن تختلف عن معرّف القناة.
blurbstringوصف قصير للفهرس/التهيئة الأولية.
ordernumberترتيب الفرز في فهارس القنوات.
aliasesstring[]أسماء بديلة إضافية للبحث عن القناة عند الاختيار.
preferOverstring[]معرّفات إضافات/قنوات أقل أولوية ينبغي أن تتفوق عليها هذه القناة.
systemImagestringاسم icon/system-image اختياري لفهارس UI الخاصة بالقنوات.
selectionDocsPrefixstringنص بادئة قبل روابط المستندات في أسطح الاختيار.
selectionDocsOmitLabelbooleanعرض مسار المستندات مباشرة بدل رابط مستندات ذي تسمية في نص الاختيار.
selectionExtrasstring[]سلاسل قصيرة إضافية تُلحَق في نص الاختيار.
markdownCapablebooleanيضع علامة على أن القناة تدعم Markdown لقرارات التنسيق الصادر.
exposureobjectعناصر تحكم في ظهور القناة في أسطح الإعداد والقوائم المهيأة والمستندات.
quickstartAllowFrombooleanيدرج هذه القناة في تدفق إعداد allowFrom القياسي للبداية السريعة.
forceAccountBindingbooleanيطلب ربط حساب صريحًا حتى عند وجود حساب واحد فقط.
preferSessionLookupForAnnounceTargetbooleanيفضّل البحث في الجلسة عند حل أهداف الإعلان لهذه القناة.
مثال:
{
  "openclaw": {
    "channel": {
      "id": "my-channel",
      "label": "My Channel",
      "selectionLabel": "My Channel (self-hosted)",
      "detailLabel": "My Channel Bot",
      "docsPath": "/channels/my-channel",
      "docsLabel": "my-channel",
      "blurb": "تكامل دردشة مستضاف ذاتيًا قائم على webhook.",
      "order": 80,
      "aliases": ["mc"],
      "preferOver": ["my-channel-legacy"],
      "selectionDocsPrefix": "الدليل:",
      "selectionExtras": ["Markdown"],
      "markdownCapable": true,
      "exposure": {
        "configured": true,
        "setup": true,
        "docs": true
      },
      "quickstartAllowFrom": true
    }
  }
}
يدعم exposure ما يلي:
  • configured: تضمين القناة في أسطح القوائم من نمط configured/status
  • setup: تضمين القناة في منتقيات الإعداد/التهيئة التفاعلية
  • docs: وضع علامة على أن القناة موجهة للعامة في أسطح المستندات/التنقل
لا يزال showConfigured وshowInSetup مدعومين كأسماء بديلة قديمة. ويفضَّل استخدام exposure.

openclaw.install

يمثل openclaw.install بيانات وصفية على مستوى الحزمة، وليس بيانات manifest وصفية.
الحقلالنوعما الذي يعنيه
npmSpecstringمواصفة npm القانونية لتدفقات التثبيت/التحديث.
localPathstringمسار تثبيت محلي للتطوير أو للإضافات المجمعة.
defaultChoice"npm" | "local"مصدر التثبيت المفضل عند توفر الاثنين.
minHostVersionstringالحد الأدنى لإصدار OpenClaw المدعوم بصيغة >=x.y.z.
allowInvalidConfigRecoverybooleanيتيح لتدفقات إعادة تثبيت الإضافات المجمعة التعافي من إخفاقات config قديمة محددة.
إذا تم تعيين minHostVersion، فإن التثبيت وتحميل سجل manifest يفرضان هذا الحقل كليهما. وتتجاوز المضيفات الأقدم الإضافة؛ أما سلاسل الإصدارات غير الصالحة فتُرفض. إن allowInvalidConfigRecovery ليس تجاوزًا عامًا لإعدادات config المكسورة. بل هو للتعافي الضيق الخاص بالإضافات المجمعة فقط، حتى تتمكن إعادة التثبيت/الإعداد من إصلاح مخلّفات الترقيات المعروفة مثل مسار إضافة مجمعة مفقود أو إدخال channels.<id> قديم لتلك الإضافة نفسها. وإذا كان config مكسورًا لأسباب غير مرتبطة، فلا يزال التثبيت يفشل بشكل مغلق ويوجه المشغّل إلى تشغيل openclaw doctor --fix.

تأجيل التحميل الكامل

يمكن لإضافات القنوات الاشتراك في التحميل المؤجل باستخدام:
{
  "openclaw": {
    "extensions": ["./index.ts"],
    "setupEntry": "./setup-entry.ts",
    "startup": {
      "deferConfiguredChannelFullLoadUntilAfterListen": true
    }
  }
}
عند التمكين، يحمّل OpenClaw setupEntry فقط أثناء مرحلة بدء التشغيل التي تسبق الاستماع، حتى للقنوات المهيأة بالفعل. ويُحمّل الإدخال الكامل بعد أن تبدأ البوابة في الاستماع.
لا تفعّل التحميل المؤجل إلا عندما يسجل setupEntry الخاص بك كل ما تحتاجه البوابة قبل أن تبدأ الاستماع (تسجيل القناة، ومسارات HTTP، وطرائق البوابة). وإذا كان الإدخال الكامل يملك إمكانات بدء تشغيل مطلوبة، فأبقِ السلوك الافتراضي.
إذا كان إدخال الإعداد/الإدخال الكامل لديك يسجل طرائق Gateway RPC، فأبقِها على بادئة خاصة بالإضافة. وتظل مساحات أسماء الإدارة الأساسية المحجوزة (config.*، exec.approvals.*، wizard.*، update.*) مملوكة للنواة وتُحل دائمًا إلى operator.admin.

Plugin manifest

يجب أن تُرفق كل إضافة أصلية ملف openclaw.plugin.json في جذر الحزمة. ويستخدم OpenClaw هذا للتحقق من config من دون تنفيذ شيفرة الإضافة.
{
  "id": "my-plugin",
  "name": "My Plugin",
  "description": "يضيف إمكانات My Plugin إلى OpenClaw",
  "configSchema": {
    "type": "object",
    "additionalProperties": false,
    "properties": {
      "webhookSecret": {
        "type": "string",
        "description": "سر التحقق من webhook"
      }
    }
  }
}
بالنسبة إلى إضافات القنوات، أضف kind وchannels:
{
  "id": "my-channel",
  "kind": "channel",
  "channels": ["my-channel"],
  "configSchema": {
    "type": "object",
    "additionalProperties": false,
    "properties": {}
  }
}
حتى الإضافات التي لا تحتوي على config يجب أن تُرفق schema. ويُعد المخطط الفارغ صالحًا:
{
  "id": "my-plugin",
  "configSchema": {
    "type": "object",
    "additionalProperties": false
  }
}
راجع Plugin Manifest للاطلاع على المرجع الكامل للمخطط.

النشر على ClawHub

بالنسبة إلى حزم الإضافات، استخدم أمر ClawHub الخاص بالحزمة:
clawhub package publish your-org/your-plugin --dry-run
clawhub package publish your-org/your-plugin
الاسم البديل القديم للنشر الخاص بالـ Skill فقط مخصص لـ Skills. ويجب أن تستخدم حزم الإضافات دائمًا clawhub package publish.

إدخال الإعداد

ملف setup-entry.ts هو بديل خفيف لـ index.ts يحمّله OpenClaw عندما يحتاج فقط إلى أسطح الإعداد (التهيئة الأولية، وإصلاح config، وفحص القنوات المعطلة).
// setup-entry.ts
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
import { myChannelPlugin } from "./src/channel.js";

export default defineSetupPluginEntry(myChannelPlugin);
وهذا يتجنب تحميل شيفرة وقت تشغيل ثقيلة (مكتبات crypto، وتسجيلات CLI، والخدمات الخلفية) أثناء تدفقات الإعداد. متى يستخدم OpenClaw setupEntry بدل الإدخال الكامل:
  • تكون القناة معطلة لكنها تحتاج إلى أسطح إعداد/تهيئة أولية
  • تكون القناة مفعلة لكنها غير مهيأة
  • يكون التحميل المؤجل مفعّلًا (deferConfiguredChannelFullLoadUntilAfterListen)
ما الذي يجب أن يسجله setupEntry:
  • كائن إضافة القناة (عبر defineSetupPluginEntry)
  • أي مسارات HTTP مطلوبة قبل استماع البوابة
  • أي طرائق للبوابة مطلوبة أثناء بدء التشغيل
ويجب أن تتجنب طرائق البوابة الخاصة ببدء التشغيل تلك أيضًا مساحات أسماء الإدارة الأساسية المحجوزة مثل config.* أو update.*. ما الذي يجب ألا يتضمنه setupEntry:
  • تسجيلات CLI
  • الخدمات الخلفية
  • واردات وقت تشغيل ثقيلة (crypto وSDKs)
  • طرائق البوابة المطلوبة فقط بعد بدء التشغيل

واردات مساعدات الإعداد الضيقة

بالنسبة إلى المسارات الساخنة الخاصة بالإعداد فقط، فَضّل واجهات المساعدات الضيقة هذه بدل الواجهة الأوسع plugin-sdk/setup عندما لا تحتاج إلا إلى جزء من سطح الإعداد:
مسار الاستيراداستخدمه من أجلالصادرات الأساسية
plugin-sdk/setup-runtimeمساعدات وقت التشغيل الخاصة بالإعداد التي تبقى متاحة في setupEntry / بدء القناة المؤجلcreatePatchedAccountSetupAdapter, createEnvPatchedAccountSetupAdapter, createSetupInputPresenceValidator, noteChannelLookupFailure, noteChannelLookupSummary, promptResolvedAllowFrom, splitSetupEntries, createAllowlistSetupWizardProxy, createDelegatedSetupWizardProxy
plugin-sdk/setup-adapter-runtimeمحوّلات إعداد الحساب الواعية بالبيئةcreateEnvPatchedAccountSetupAdapter
plugin-sdk/setup-toolsمساعدات CLI/التثبيت/الأرشيف/المستندات الخاصة بالإعدادformatCliCommand, detectBinary, extractArchive, resolveBrewExecutable, formatDocsLink, CONFIG_DIR
استخدم الواجهة الأوسع plugin-sdk/setup عندما تريد صندوق أدوات الإعداد المشترك الكامل، بما في ذلك مساعدات تصحيح config مثل moveSingleAccountChannelSectionToDefaultAccount(...). وتبقى محولات تصحيح الإعداد آمنة في المسار الساخن عند الاستيراد. ويكون البحث عن سطح العقد الخاص بترقية الحساب الواحد المجمّع كسولًا، لذلك لا يؤدي استيراد plugin-sdk/setup-runtime إلى تحميل اكتشاف سطح العقد المجمّع مبكرًا قبل استخدام المحول فعليًا.

ترقية الحساب الواحد المملوكة للقناة

عندما تنتقل القناة من config ذي مستوى أعلى لحساب واحد إلى channels.<id>.accounts.*، يكون السلوك المشترك الافتراضي هو نقل القيم التي تقع ضمن نطاق الحساب المرقّى إلى accounts.default. يمكن للقنوات المجمعة تضييق هذه الترقية أو تجاوزها عبر سطح عقد الإعداد الخاص بها:
  • singleAccountKeysToMove: مفاتيح إضافية ذات مستوى أعلى ينبغي نقلها إلى الحساب المرقّى
  • namedAccountPromotionKeys: عندما تكون الحسابات المسماة موجودة بالفعل، لا تُنقل إلا هذه المفاتيح إلى الحساب المرقّى؛ بينما تبقى مفاتيح السياسة/التسليم المشتركة في جذر القناة
  • resolveSingleAccountPromotionTarget(...): اختيار الحساب الموجود الذي يستقبل القيم المرقّاة
تمثل Matrix المثال المجمّع الحالي. وإذا كان هناك حساب Matrix مسمّى واحد موجود بالفعل، أو إذا كان defaultAccount يشير إلى مفتاح غير قانوني موجود مثل Ops، فإن الترقية تحافظ على ذلك الحساب بدل إنشاء إدخال جديد accounts.default.

مخطط config

يُتحقق من config الإضافة مقابل JSON Schema الموجود في manifest الخاص بك. ويهيّئ المستخدمون الإضافات عبر:
{
  plugins: {
    entries: {
      "my-plugin": {
        config: {
          webhookSecret: "abc123",
        },
      },
    },
  },
}
تتلقى إضافتك هذا config على هيئة api.pluginConfig أثناء التسجيل. أما بالنسبة إلى config الخاص بالقناة، فاستخدم قسم config الخاص بالقناة بدلًا من ذلك:
{
  channels: {
    "my-channel": {
      token: "bot-token",
      allowFrom: ["user1", "user2"],
    },
  },
}

بناء مخططات config القنوات

استخدم buildChannelConfigSchema من openclaw/plugin-sdk/core لتحويل مخطط Zod إلى الغلاف ChannelConfigSchema الذي يتحقق منه OpenClaw:
import { z } from "zod";
import { buildChannelConfigSchema } from "openclaw/plugin-sdk/core";

const accountSchema = z.object({
  token: z.string().optional(),
  allowFrom: z.array(z.string()).optional(),
  accounts: z.object({}).catchall(z.any()).optional(),
  defaultAccount: z.string().optional(),
});

const configSchema = buildChannelConfigSchema(accountSchema);

معالجات الإعداد

يمكن لإضافات القنوات توفير معالجات إعداد تفاعلية لـ openclaw onboard. ويكون المعالج عبارة عن كائن ChannelSetupWizard على ChannelPlugin:
import type { ChannelSetupWizard } from "openclaw/plugin-sdk/channel-setup";

const setupWizard: ChannelSetupWizard = {
  channel: "my-channel",
  status: {
    configuredLabel: "متصل",
    unconfiguredLabel: "غير مهيأ",
    resolveConfigured: ({ cfg }) => Boolean((cfg.channels as any)?.["my-channel"]?.token),
  },
  credentials: [
    {
      inputKey: "token",
      providerHint: "my-channel",
      credentialLabel: "token البوت",
      preferredEnvVar: "MY_CHANNEL_BOT_TOKEN",
      envPrompt: "هل تريد استخدام MY_CHANNEL_BOT_TOKEN من البيئة؟",
      keepPrompt: "هل تريد الاحتفاظ بالـ token الحالي؟",
      inputPrompt: "أدخل token البوت:",
      inspect: ({ cfg, accountId }) => {
        const token = (cfg.channels as any)?.["my-channel"]?.token;
        return {
          accountConfigured: Boolean(token),
          hasConfiguredValue: Boolean(token),
        };
      },
    },
  ],
};
يدعم النوع ChannelSetupWizard الحقول credentials وtextInputs و dmPolicy وallowFrom وgroupAccess وprepare وfinalize وغيرها. راجع حزم الإضافات المجمعة (مثلًا إضافة Discord في src/channel.setup.ts) للحصول على أمثلة كاملة. بالنسبة إلى مطالبات قائمة السماح في الرسائل المباشرة التي تحتاج فقط إلى التدفق القياسي note -> prompt -> parse -> merge -> patch، فَضّل مساعدات الإعداد المشتركة من openclaw/plugin-sdk/setup: وهي createPromptParsedAllowFromForAccount(...)، وcreateTopLevelChannelParsedAllowFromPrompt(...)، و createNestedChannelParsedAllowFromPrompt(...). أما لكتل حالة إعداد القناة التي تختلف فقط في التسميات، والدرجات، والأسطر الإضافية الاختيارية، فَضّل createStandardChannelSetupStatus(...) من openclaw/plugin-sdk/setup بدل بناء كائن status نفسه يدويًا في كل إضافة. وبالنسبة إلى أسطح الإعداد الاختيارية التي ينبغي أن تظهر فقط في سياقات معينة، استخدم createOptionalChannelSetupSurface من openclaw/plugin-sdk/channel-setup:
import { createOptionalChannelSetupSurface } from "openclaw/plugin-sdk/channel-setup";

const setupSurface = createOptionalChannelSetupSurface({
  channel: "my-channel",
  label: "My Channel",
  npmSpec: "@myorg/openclaw-my-channel",
  docsPath: "/channels/my-channel",
});
// Returns { setupAdapter, setupWizard }
يكشف plugin-sdk/channel-setup أيضًا عن البانيين الأدنى مستوى createOptionalChannelSetupAdapter(...) و createOptionalChannelSetupWizard(...) عندما تحتاج إلى نصف واحد فقط من سطح التثبيت الاختياري هذا. يفشل المحول/المعالج الاختياريان المولدان بشكل مغلق عند عمليات كتابة config الحقيقية. كما يعيدان استخدام رسالة واحدة تفيد بأن التثبيت مطلوب عبر validateInput و applyAccountConfig وfinalize، ويُلحقان رابطًا للمستندات عندما يكون docsPath مضبوطًا. أما بالنسبة إلى واجهات إعداد UI المدعومة بملفات تنفيذية، فَضّل المساعدات المشتركة المفوّضة بدل نسخ نفس منطق الملف التنفيذي/الحالة في كل قناة:
  • createDetectedBinaryStatus(...) لكتل الحالة التي تختلف فقط بحسب التسميات، والتلميحات، والدرجات، واكتشاف الملف التنفيذي
  • createCliPathTextInput(...) لمدخلات النص المدعومة بالمسار
  • createDelegatedSetupWizardStatusResolvers(...)، وcreateDelegatedPrepare(...)، وcreateDelegatedFinalize(...)، و createDelegatedResolveConfigured(...) عندما يحتاج setupEntry إلى الإحالة كسولًا إلى معالج أثقل وكامل
  • createDelegatedTextInputShouldPrompt(...) عندما يحتاج setupEntry فقط إلى تفويض قرار textInputs[*].shouldPrompt

النشر والتثبيت

الإضافات الخارجية: انشرها على ClawHub أو npm، ثم ثبّتها:
openclaw plugins install @myorg/openclaw-my-plugin
يحاول OpenClaw استخدام ClawHub أولًا ثم يرجع إلى npm تلقائيًا. ويمكنك أيضًا فرض ClawHub صراحةً:
openclaw plugins install clawhub:@myorg/openclaw-my-plugin   # ClawHub فقط
لا يوجد تجاوز مماثل لـ npm:. استخدم مواصفة حزمة npm العادية عندما تريد مسار npm بعد الرجوع من ClawHub:
openclaw plugins install @myorg/openclaw-my-plugin
الإضافات داخل المستودع: ضعها تحت شجرة مساحة عمل الإضافات المجمعة وسيتم اكتشافها تلقائيًا أثناء البناء. يمكن للمستخدمين التثبيت:
openclaw plugins install <package-name>
بالنسبة إلى التثبيتات القادمة من npm، يشغّل openclaw plugins install الأمر npm install --ignore-scripts (من دون lifecycle scripts). أبقِ شجرة اعتماديات الإضافة JavaScript/TypeScript خالصة وتجنب الحزم التي تتطلب بناء postinstall.

ذو صلة