Plugin maintainer reference
جزئیات داخلی معماری Plugin
برای مدل عمومی قابلیتها، ساختارهای Plugin و قراردادهای مالکیت/اجرا، به معماری Plugin مراجعه کنید. این صفحه سازوکارهای داخلی را پوشش میدهد: خط لوله بارگذاری، رجیستری، هوکهای زمان اجرا، مسیرهای HTTP در Gateway، مسیرهای import و جدولهای طرحواره.
خط لوله بارگذاری
هنگام راهاندازی، OpenClaw تقریباً این کارها را انجام میدهد:
- ریشههای کاندیدای Plugin را کشف میکند
- مانیفستهای باندل بومی یا سازگار و فراداده بسته را میخواند
- کاندیداهای ناامن را رد میکند
- پیکربندی Plugin را نرمالسازی میکند (
plugins.enabled،allow،deny،entries،slots،load.paths) - فعالبودن هر کاندیدا را تعیین میکند
- ماژولهای بومی فعالشده را بارگذاری میکند: ماژولهای باندلشده ساختهشده از بارگذار بومی استفاده میکنند؛ کد منبع محلی TypeScript متعلق به شخص ثالث از جایگزین اضطراری Jiti استفاده میکند
- هوکهای بومی
register(api)را فراخوانی و ثبتها را در رجیستری Plugin جمعآوری میکند - رجیستری را در اختیار فرمانها و سطوح زمان اجرا قرار میدهد
دروازههای ایمنی پیش از اجرای زمان اجرا اعمال میشوند. فرایند کشف، یک کاندیدا را در موارد زیر مسدود میکند:
- ورودی resolveشده آن از ریشه Plugin خارج شود
- مسیر آن (یا دایرکتوری ریشهاش) برای همه قابلنوشتن باشد
- برای Pluginهای غیرباندلشده، مالکیت مسیر با uid فعلی (یا root) مطابقت نداشته باشد
برای دایرکتوریهای باندلشدهای که برای همه قابلنوشتن هستند، ابتدا تلاشی برای ترمیم درجا با chmod انجام میشود
(نصبهای npm/سراسری ممکن است دایرکتوریهای بسته را با 0777 ارائه کنند) و سپس دروازه
دوباره بررسی میشود؛ بررسی مالکیت برای مبدأ باندلشده بهطور کامل نادیده گرفته میشود.
کاندیداهای مسدودشده، اگر شناسه Plugin آنها مشخص باشد، همچنان آن را در عیبیابی تولیدشده حمل میکنند (از جمله شناسههایی که از مانیفست درون دایرکتوریای که به دلایل دیگر رد شده است بهدست آمدهاند)؛ بنابراین پیکربندیای که به آن شناسه ارجاع میدهد، بهجای خطای نامرتبط «Plugin ناشناخته»، یک Plugin مسدودشده مرتبط با هشدار ایمنی مسیر را مشاهده میکند.
رفتار مبتنی بر اولویت مانیفست
مانیفست منبع حقیقت صفحه کنترل است. OpenClaw از آن برای این موارد استفاده میکند:
- شناسایی Plugin
- کشف کانالها/Skills/طرحواره پیکربندی یا قابلیتهای باندل اعلامشده
- اعتبارسنجی
plugins.entries.<id>.config - تکمیل برچسبها/جاینگهدارهای Control UI
- نمایش فراداده نصب/کاتالوگ
- حفظ توصیفگرهای کمهزینه فعالسازی و راهاندازی، بدون بارگذاری زمان اجرای Plugin
برای Pluginهای بومی، ماژول زمان اجرا بخش صفحه داده است. این ماژول رفتار واقعی مانند هوکها، ابزارها، فرمانها یا جریانهای ارائهدهنده را ثبت میکند.
بلوکهای اختیاری activation و setup مانیفست در صفحه کنترل باقی میمانند.
آنها فقط توصیفگرهای فرادادهای برای برنامهریزی فعالسازی و کشف راهاندازی هستند؛
جایگزین ثبت در زمان اجرا، register(...) یا setupEntry نمیشوند.
مصرفکنندگان فعالسازی زنده از راهنماییهای مربوط به فرمان، کانال و ارائهدهنده در مانیفست استفاده میکنند تا
پیش از ایجاد گستردهتر رجیستری، دامنه بارگذاری Plugin را محدود کنند:
- بارگذاری CLI به Pluginهایی محدود میشود که مالک فرمان اصلی درخواستشده هستند
- راهاندازی کانال/resolve کردن Plugin به Pluginهایی محدود میشود که مالک شناسه کانال درخواستشده هستند
- راهاندازی صریح ارائهدهنده/resolve کردن زمان اجرا به Pluginهایی محدود میشود که مالک شناسه ارائهدهنده درخواستشده هستند
- برنامهریزی راهاندازی Gateway از
activation.onStartupبرای importهای صریح هنگام راهاندازی استفاده میکند؛ Pluginهای بدون فراداده راهاندازی فقط از طریق محرکهای محدودتر فعالسازی بارگذاری میشوند
برنامهریز فعالسازی هم یک API فقط شامل شناسهها برای فراخوانهای موجود و هم یک
API برنامه برای عیبیابی ارائه میدهد. ورودیهای برنامه دلیل انتخاب یک Plugin را گزارش میکنند و
راهنماییهای صریح activation.* را از بازگشت به مالکیت مانیفست جدا میسازند:
دلیل (از راهنماییهای activation.*) |
دلیل (از مالکیت مانیفست) |
|---|---|
activation-agent-harness-hint |
— |
activation-capability-hint |
— |
activation-channel-hint |
manifest-channel-owner (channels) |
activation-command-hint |
manifest-command-alias (commandAliases) |
activation-provider-hint |
manifest-provider-owner (providers)، manifest-setup-provider-owner (setup.providers) |
activation-route-hint |
— |
| — (محرک هوک نوع راهنمایی ندارد) | manifest-hook-owner (hooks)، manifest-tool-contract (contracts.tools) |
این تفکیک دلیل، مرز سازگاری است: فراداده موجود Plugin همچنان کار میکند، درحالیکه کد جدید میتواند راهنماییهای گسترده یا رفتار بازگشتی را بدون تغییر معنای بارگذاری زمان اجرا تشخیص دهد.
پیشبارگذاریهای زمان اجرا در هنگام درخواست که دامنه گسترده all را درخواست میکنند، همچنان
مجموعهای صریح از شناسههای مؤثر Plugin را از پیکربندی، برنامهریزی راهاندازی، کانالهای
پیکربندیشده، شکافها و قواعد فعالسازی خودکار استخراج میکنند
(resolveEffectivePluginIds در src/plugins/effective-plugin-ids.ts). اگر آن
مجموعه استخراجشده خالی باشد، OpenClaw بهجای گسترش دامنه به
همه Pluginهای قابلکشف، دامنه را خالی نگه میدارد.
کشف راهاندازی، شناسههای متعلق به توصیفگر مانند setup.providers و
setup.cliBackends را برای محدودکردن Pluginهای کاندیدا ترجیح میدهد و فقط پس از آن به
setup-api برای Pluginهایی بازمیگردد که همچنان به هوکهای زمان اجرا هنگام راهاندازی نیاز دارند. فهرستهای
راهاندازی ارائهدهنده از providerAuthChoices مانیفست، گزینههای راهاندازی استخراجشده از توصیفگر
و فراداده کاتالوگ نصب، بدون بارگذاری زمان اجرای ارائهدهنده استفاده میکنند. مقدار صریح
setup.requiresRuntime: false یک مرز صرفاً توصیفگری است؛ حذف
requiresRuntime برای حفظ سازگاری، بازگشت قدیمی به setup-api را نگه میدارد. اگر
بیش از یک Plugin کشفشده مالکیت همان شناسه نرمالشده ارائهدهنده راهاندازی یا
پشتانه CLI را ادعا کند، جستوجوی راهاندازی بهجای اتکا به
ترتیب کشف، مالک مبهم را رد میکند. هنگامی که زمان اجرای راهاندازی اجرا میشود، عیبیابی رجیستری
ناهمگونی میان setup.providers / setup.cliBackends و ارائهدهندگان یا پشتانههای CLI
ثبتشده واقعی توسط setup-api را بدون مسدودکردن Pluginهای قدیمی گزارش میکند.
مرز کش Plugin
OpenClaw نتایج کشف Plugin یا دادههای مستقیم رجیستری مانیفست را پشت بازههای زمانی ساعت دیواری کش نمیکند. نصبها، ویرایشهای مانیفست و تغییرات مسیر بارگذاری باید در خواندن صریح بعدی فراداده یا بازسازی اسنپشات قابلمشاهده شوند. تجزیهگر فایل مانیفست یک کش محدود امضای فایل را نگه میدارد که کلید آن از مسیر مانیفست بازشده بههمراه دستگاه/inode، اندازه و mtime/ctime تشکیل شده است؛ این کش فقط از تجزیه دوباره بایتهای بدون تغییر جلوگیری میکند و نباید پاسخهای مربوط به کشف، رجیستری، مالک یا خطمشی را کش کند.
مسیر سریع و ایمن فراداده، مالکیت صریح شیء است، نه یک کش پنهان.
مسیرهای پرتکرار راهاندازی Gateway باید PluginMetadataSnapshot فعلی،
PluginLookUpTable استخراجشده یا یک رجیستری صریح مانیفست را در زنجیره فراخوانی
عبور دهند. اعتبارسنجی پیکربندی، فعالسازی خودکار هنگام راهاندازی، بوتاسترپ Plugin و انتخاب
ارائهدهنده میتوانند تا زمانی که این اشیا نماینده پیکربندی و موجودی فعلی
Plugin هستند، از آنها دوباره استفاده کنند. جستوجوی راهاندازی همچنان فراداده مانیفست را در صورت نیاز
بازسازی میکند، مگر آنکه مسیر مشخص راهاندازی یک رجیستری صریح مانیفست دریافت کند؛ این را
بهعنوان بازگشت مسیر سرد نگه دارید و کشهای پنهان جستوجو اضافه نکنید. وقتی ورودی
تغییر میکند، بهجای تغییر اسنپشات یا نگهداری نسخههای تاریخی، آن را بازسازی و
جایگزین کنید. نماهای رجیستری فعال Plugin و کمکتابعهای بوتاسترپ کانال باندلشده
باید از رجیستری/ریشه فعلی دوباره محاسبه شوند. نقشههای کوتاهعمر درون یک فراخوانی برای
حذف کار تکراری یا جلوگیری از ورود مجدد مناسب هستند؛ اما نباید به کش فراداده فرایند تبدیل شوند.
برای بارگذاری Plugin، لایه کش پایدار همان بارگذاری زمان اجرا است. این لایه میتواند هنگامی که کد یا مصنوعات نصبشده واقعاً بارگذاری میشوند، از وضعیت بارگذار دوباره استفاده کند؛ مانند:
PluginLoaderCacheStateو رجیستریهای سازگار و فعال زمان اجرا- کشهای jiti/ماژول و کشهای بارگذار سطح عمومی که برای جلوگیری از import مکرر یک سطح زمان اجرای یکسان استفاده میشوند
- کشهای سامانه فایل برای مصنوعات نصبشده Plugin
- نقشههای کوتاهعمر در هر فراخوانی برای نرمالسازی مسیر یا resolve کردن موارد تکراری
این کشها جزئیات پیادهسازی صفحه داده هستند. آنها نباید به پرسشهای صفحه کنترل مانند «کدام Plugin مالک این ارائهدهنده است؟» پاسخ دهند، مگر اینکه فراخوان عمداً بارگذاری زمان اجرا را درخواست کرده باشد.
کشهای پایدار یا مبتنی بر ساعت دیواری را برای موارد زیر اضافه نکنید:
- نتایج کشف
- رجیستریهای مستقیم مانیفست
- رجیستریهای مانیفست بازسازیشده از نمایه Pluginهای نصبشده
- جستوجوی مالک ارائهدهنده، سرکوب مدل، خطمشی ارائهدهنده یا فراداده مصنوعات عمومی
- هر پاسخ دیگر استخراجشده از مانیفست که در آن تغییر مانیفست، نمایه نصبشده یا مسیر بارگذاری باید در خواندن بعدی فراداده قابلمشاهده باشد
فراخوانهایی که فراداده مانیفست را از نمایه پایدارشده Pluginهای نصبشده بازسازی میکنند، آن رجیستری را در صورت نیاز میسازند. نمایه نصبشده، وضعیت پایدار صفحه منبع است؛ یک کش پنهان فراداده درون فرایند نیست.
مدل رجیستری
Pluginهای بارگذاریشده مستقیماً متغیرهای سراسری و تصادفی هسته را تغییر نمیدهند. آنها در یک
رجیستری مرکزی Plugin (PluginRegistry در src/plugins/registry-types.ts)
ثبت میشوند که رکوردهای Plugin (هویت، منبع، مبدأ، وضعیت، عیبیابیها)
و آرایههای مربوط به هر قابلیت را دنبال میکند: ابزارها، هوکهای قدیمی و هوکهای نوعدار،
کانالها، ارائهدهندگان، کنترلکنندههای RPC در Gateway، مسیرهای HTTP، ثبتکنندههای CLI،
سرویسهای پسزمینه، فرمانهای متعلق به Plugin و دهها خانواده نوعدار دیگر از ارائهدهندگان
(گفتار، تعبیهها، تولید تصویر/ویدئو/موسیقی، واکشی/جستوجوی وب،
چارچوبهای عامل، کنشهای نشست و موارد دیگر).
سپس قابلیتهای هسته بهجای ارتباط مستقیم با ماژولهای Plugin، از آن رجیستری میخوانند. این کار بارگذاری را یکطرفه نگه میدارد:
- ماژول Plugin -> ثبت در رجیستری
- زمان اجرای هسته -> مصرف رجیستری
این جداسازی برای نگهداشتپذیری اهمیت دارد. در نتیجه، بیشتر سطوح هسته فقط به یک نقطه یکپارچهسازی نیاز دارند: «خواندن رجیستری»، نه «رسیدگی ویژه به هر ماژول Plugin».
بازخوانیهای اتصال مکالمه
Pluginهایی که یک مکالمه را متصل میکنند، میتوانند هنگام تعیین تکلیف یک تأیید واکنش نشان دهند.
از api.onConversationBindingResolved(...) برای دریافت یک بازخوانی پس از تأیید
یا رد درخواست اتصال استفاده کنید:
export default { id: "my-plugin", register(api) { api.onConversationBindingResolved(async (event) => { if (event.status === "approved") { // A binding now exists for this plugin + conversation. console.log(event.binding?.conversationId); return; } // The request was denied; clear any local pending state. console.log(event.request.conversation.conversationId); }); },};فیلدهای بار داده بازخوانی:
status:"approved"یا"denied"decision:"allow-once"،"allow-always"یا"deny"binding: اتصال تعیینتکلیفشده برای درخواستهای تأییدشدهrequest: خلاصه درخواست اصلی، راهنمای جداسازی، شناسه فرستنده و فراداده مکالمه
این بازخوانی فقط برای اعلان است. مشخص نمیکند چه کسی مجاز به اتصال یک مکالمه است و پس از پایان رسیدگی هسته به تأیید اجرا میشود.
هوکهای زمان اجرای ارائهدهنده
Pluginهای ارائهدهنده سه لایه دارند:
- فراداده مانیفست برای جستوجوی کمهزینه پیش از زمان اجرا:
setup.providers[].envVars، سازگاری منسوخشدهproviderAuthEnvVars،providerAuthAliases،providerAuthChoicesوchannelEnvVars. - هوکهای زمان پیکربندی:
catalog(نسخه قدیمیdiscovery) بههمراهapplyConfigDefaults. - هوکهای زمان اجرا: بیش از ۴۰ هوک اختیاری که احراز هویت، resolve کردن مدل، پوشاندن جریان، سطوح تفکر، خطمشی بازپخش و نقاط پایانی مصرف را پوشش میدهند. به ترتیب و کاربرد هوکها مراجعه کنید.
OpenClaw همچنان مالک حلقه عمومی عامل، تغییر مسیر هنگام خرابی، رسیدگی به رونوشت و خطمشی ابزار است. این هوکها سطح توسعه رفتار مختص ارائهدهنده هستند و نیاز به یک انتقال استنتاج سفارشی کامل را برطرف میکنند.
وقتی ارائهدهنده اعتبارنامههای مبتنی بر متغیر محیطی دارد که مسیرهای عمومی احراز هویت/وضعیت/انتخابگر مدل باید بدون بارگذاری زماناجرای Plugin آنها را ببینند، از setup.providers[].envVars در مانیفست استفاده کنید. providerAuthEnvVars منسوخشده در طول دوره منسوخسازی همچنان توسط سازگارکننده سازگاری خوانده میشود و Pluginهای غیرباندلشدهای که از آن استفاده میکنند، یک عیبیابی مانیفست دریافت میکنند. وقتی شناسه یک ارائهدهنده باید از متغیرهای محیطی، پروفایلهای احراز هویت، احراز هویت مبتنی بر پیکربندی و گزینه راهاندازی اولیه کلید API متعلق به شناسه ارائهدهنده دیگری دوباره استفاده کند، از providerAuthAliases در مانیفست استفاده کنید. وقتی سطوح CLI مربوط به راهاندازی اولیه/انتخاب احراز هویت باید بدون بارگذاری زماناجرای ارائهدهنده از شناسه گزینه ارائهدهنده، برچسبهای گروه و سیمکشی ساده احراز هویت با یک پرچم آگاه باشند، از providerAuthChoices در مانیفست استفاده کنید. envVars زماناجرای ارائهدهنده را برای راهنماییهای ویژه اپراتور، مانند برچسبهای راهاندازی اولیه یا متغیرهای تنظیم شناسه کلاینت/رمز کلاینت OAuth، نگه دارید.
وقتی یک کانال دارای احراز هویت یا راهاندازی مبتنی بر متغیر محیطی است که بازگشت عمومی به متغیرهای محیطی پوسته، بررسیهای پیکربندی/وضعیت یا اعلانهای راهاندازی باید بدون بارگذاری زماناجرای کانال آن را ببینند، از channelEnvVars در مانیفست استفاده کنید.
ترتیب و کاربرد هوکها
برای Pluginهای مدل/ارائهدهنده، OpenClaw هوکها را تقریباً با این ترتیب فراخوانی میکند.
ستون «زمان استفاده» راهنمای تصمیمگیری سریع است.
فیلدهای ارائهدهنده مختص سازگاری که OpenClaw دیگر آنها را فراخوانی نمیکند، مانند
ProviderPlugin.capabilities و suppressBuiltInModel، عمداً در اینجا فهرست نشدهاند.
| هوک | کاری که انجام میدهد | زمان استفاده |
|---|---|---|
catalog |
هنگام تولید models.json، پیکربندی ارائهدهنده را در models.providers منتشر میکند |
ارائهدهنده مالک یک کاتالوگ یا مقادیر پیشفرض URL پایه است |
applyConfigDefaults |
هنگام مادیسازی پیکربندی، مقادیر پیشفرض سراسری متعلق به ارائهدهنده را اعمال میکند | مقادیر پیشفرض به حالت احراز هویت، محیط یا معناشناسی خانواده مدل ارائهدهنده وابستهاند |
| (جستوجوی داخلی مدل) | OpenClaw ابتدا مسیر عادی رجیستری/کاتالوگ را امتحان میکند | (هوک Plugin نیست) |
normalizeModelId |
نامهای مستعار قدیمی یا پیشنمایشی شناسه مدل را پیش از جستوجو نرمالسازی میکند | ارائهدهنده مالک پاکسازی نامهای مستعار پیش از تفکیک مدل کانونی است |
normalizeTransport |
api / baseUrl خانواده ارائهدهنده را پیش از مونتاژ عمومی مدل نرمالسازی میکند |
ارائهدهنده مالک پاکسازی انتقال برای شناسههای سفارشی ارائهدهنده در همان خانواده انتقال است |
normalizeConfig |
models.providers.<id> را پیش از تفکیک زمان اجرا/ارائهدهنده نرمالسازی میکند |
ارائهدهنده به پاکسازی پیکربندیای نیاز دارد که باید در Plugin قرار گیرد؛ کمککنندههای همراه خانواده Google نیز از ورودیهای پشتیبانیشده پیکربندی Google پشتیبانی میکنند |
applyNativeStreamingUsageCompat |
بازنویسیهای سازگاری بومی مصرف استریم را روی ارائهدهندگان پیکربندی اعمال میکند | ارائهدهنده به اصلاحات فراداده مصرف استریم بومی مبتنی بر نقطه پایانی نیاز دارد |
resolveConfigApiKey |
احراز هویت نشانگر محیط را برای ارائهدهندگان پیکربندی، پیش از بارگذاری احراز هویت زمان اجرا، تفکیک میکند | ارائهدهندگان هوکهای اختصاصی خود را برای تفکیک کلید API نشانگر محیط ارائه میکنند |
resolveSyntheticAuth |
احراز هویت محلی/خودمیزبان یا مبتنی بر پیکربندی را بدون ماندگار کردن متن ساده در دسترس قرار میدهد | ارائهدهنده میتواند با یک نشانگر اعتبارنامه مصنوعی/محلی کار کند |
resolveExternalAuthProfiles |
پروفایلهای احراز هویت خارجی متعلق به ارائهدهنده را همپوشانی میکند؛ مقدار پیشفرض persistence برای اعتبارنامههای متعلق به CLI/برنامه، runtime-only است |
ارائهدهنده بدون ماندگار کردن توکنهای تازهسازی کپیشده، از اعتبارنامههای احراز هویت خارجی استفاده مجدد میکند؛ contracts.externalAuthProviders را در مانیفست اعلام کنید |
shouldDeferSyntheticProfileAuth |
جایگاه نشانگرهای موقت پروفایل مصنوعی ذخیرهشده را پایینتر از احراز هویت مبتنی بر محیط/پیکربندی قرار میدهد | ارائهدهنده پروفایلهای نشانگر موقت مصنوعی ذخیره میکند که نباید در اولویت پیروز شوند |
resolveDynamicModel |
بازگشت همگام برای شناسههای مدل متعلق به ارائهدهنده که هنوز در رجیستری محلی نیستند | ارائهدهنده شناسههای دلخواه مدل بالادستی را میپذیرد |
prepareDynamicModel |
گرمسازی ناهمگام، سپس resolveDynamicModel دوباره اجرا میشود |
ارائهدهنده پیش از تفکیک شناسههای ناشناخته به فراداده شبکه نیاز دارد |
normalizeResolvedModel |
بازنویسی نهایی پیش از آنکه اجراکننده تعبیهشده از مدل تفکیکشده استفاده کند | ارائهدهنده به بازنویسیهای انتقال نیاز دارد، اما همچنان از یک انتقال هسته استفاده میکند |
normalizeToolSchemas |
شِماهای ابزار را پیش از مشاهده توسط اجراکننده تعبیهشده نرمالسازی میکند | ارائهدهنده به پاکسازی شِمای خانواده انتقال نیاز دارد |
inspectToolSchemas |
پس از نرمالسازی، عیبیابیهای شِمای متعلق به ارائهدهنده را در دسترس قرار میدهد | ارائهدهنده هشدارهای کلیدواژهای میخواهد، بدون آنکه قواعد خاص ارائهدهنده به هسته آموزش داده شوند |
resolveReasoningOutputMode |
قرارداد خروجی استدلال بومی یا برچسبدار را انتخاب میکند | ارائهدهنده بهجای فیلدهای بومی، به خروجی استدلال/نهایی برچسبدار نیاز دارد |
prepareExtraParams |
پارامترهای درخواست را پیش از پوششدهندههای عمومی گزینههای استریم نرمالسازی میکند | ارائهدهنده به پارامترهای پیشفرض درخواست یا پاکسازی پارامتر برای هر ارائهدهنده نیاز دارد |
createStreamFn |
مسیر عادی استریم را بهطور کامل با یک انتقال سفارشی جایگزین میکند | ارائهدهنده به یک پروتکل سیمی سفارشی نیاز دارد، نه صرفاً یک پوششدهنده |
wrapStreamFn |
پس از اعمال پوششدهندههای عمومی، استریم را پوشش میدهد | ارائهدهنده بدون انتقال سفارشی، به پوششدهندههای سازگاری سرآیند/بدنه/مدل درخواست نیاز دارد |
resolveTransportTurnState |
سرآیندها یا فراداده بومی انتقال را برای هر نوبت پیوست میکند | ارائهدهنده میخواهد انتقالهای عمومی، هویت نوبت بومی ارائهدهنده را ارسال کنند |
resolveWebSocketSessionPolicy |
سرآیندهای بومی WebSocket یا سیاست زمان انتظار نشست را پیوست میکند | ارائهدهنده میخواهد انتقالهای عمومی WS سرآیندهای نشست یا سیاست بازگشت را تنظیم کنند |
formatApiKey |
قالببند پروفایل احراز هویت: پروفایل ذخیرهشده به رشته زمان اجرای apiKey تبدیل میشود |
ارائهدهنده فراداده احراز هویت اضافی ذخیره میکند و به شکل سفارشی توکن زمان اجرا نیاز دارد |
refreshOAuth |
بازنویسی تازهسازی OAuth برای نقاط پایانی سفارشی تازهسازی یا سیاست شکست تازهسازی | ارائهدهنده با تازهسازهای مشترک OpenClaw سازگار نیست |
buildAuthDoctorHint |
راهنمای تعمیر که هنگام شکست تازهسازی OAuth افزوده میشود | ارائهدهنده پس از شکست تازهسازی به راهنمای تعمیر احراز هویت متعلق به خود نیاز دارد |
matchesContextOverflowError |
تطبیقدهنده سرریز پنجره زمینه متعلق به ارائهدهنده | ارائهدهنده خطاهای خام سرریزی دارد که روشهای اکتشافی عمومی آنها را تشخیص نمیدهند |
classifyFailoverReason |
طبقهبندی دلیل تغییر مسیر متعلق به ارائهدهنده | ارائهدهنده میتواند خطاهای خام API/انتقال را به محدودیت نرخ/اضافهبار/و غیره نگاشت کند |
isCacheTtlEligible |
سیاست کش پرامپت برای ارائهدهندگان پراکسی/مسیر برگشتی | ارائهدهنده به دروازهبندی TTL کش مختص پراکسی نیاز دارد |
buildMissingAuthMessage |
جایگزینی برای پیام عمومی بازیابی احراز هویت مفقود | ارائهدهنده به راهنمای بازیابی احراز هویت مفقود مختص خود نیاز دارد |
augmentModelCatalog |
ردیفهای مصنوعی/نهایی کاتالوگ که پس از کشف افزوده میشوند (منسوخشده، پایین را ببینید) | ارائهدهنده به ردیفهای مصنوعی سازگاری آینده در models list و انتخابگرها نیاز دارد |
resolveThinkingProfile |
مجموعه سطوح /think مختص مدل، برچسبهای نمایشی و مقدار پیشفرض |
ارائهدهنده برای مدلهای انتخابشده یک نردبان تفکر سفارشی یا برچسب دودویی ارائه میکند |
isBinaryThinking |
هوک سازگاری کلید روشن/خاموش استدلال | ارائهدهنده فقط تفکر دودویی روشن/خاموش ارائه میکند |
supportsXHighThinking |
هوک سازگاری پشتیبانی استدلال xhigh |
ارائهدهنده میخواهد xhigh فقط روی زیرمجموعهای از مدلها فعال باشد |
resolveDefaultThinkingLevel |
هوک سازگاری سطح پیشفرض /think |
ارائهدهنده مالک سیاست پیشفرض /think برای یک خانواده مدل است |
isModernModelRef |
تطبیقدهنده مدل مدرن برای فیلترهای پروفایل زنده و انتخاب آزمون دود | ارائهدهنده مالک تطبیق مدل ترجیحی برای اجرای زنده/آزمون دود است |
prepareRuntimeAuth |
درست پیش از استنتاج، یک اعتبارنامه پیکربندیشده را به توکن/کلید واقعی زمان اجرا تبدیل میکند | ارائهدهنده به تبادل توکن یا اعتبارنامه کوتاهعمر درخواست نیاز دارد |
resolveUsageAuth |
اعتبارنامههای مصرف/صورتحساب را برای /usage و سطوح وضعیت مرتبط تفکیک میکند |
ارائهدهنده به تجزیه سفارشی توکن مصرف/سهمیه یا اعتبارنامه مصرف متفاوت نیاز دارد |
fetchUsageSnapshot |
پس از تفکیک احراز هویت، تصاویر لحظهای مصرف/سهمیه مختص ارائهدهنده را واکشی و نرمالسازی میکند | ارائهدهنده به نقطه پایانی مصرف یا تجزیهکننده بار داده مختص خود نیاز دارد |
createEmbeddingProvider |
یک آداپتور تعبیهسازی تحت مالکیت ارائهدهنده برای حافظه/جستوجو بسازید | رفتار تعبیهسازی حافظه به Plugin ارائهدهنده تعلق دارد |
buildReplayPolicy |
یک خطمشی بازپخش برای کنترل نحوهٔ مدیریت رونوشت توسط ارائهدهنده برگردانید | ارائهدهنده به خطمشی سفارشی رونوشت نیاز دارد (برای مثال، حذف بلوکهای تفکر) |
sanitizeReplayHistory |
تاریخچهٔ بازپخش را پس از پاکسازی عمومی رونوشت بازنویسی کنید | ارائهدهنده، فراتر از ابزارهای کمکی مشترک Compaction، به بازنویسیهای مختص ارائهدهنده در بازپخش نیاز دارد |
validateReplayTurns |
اعتبارسنجی یا بازشکلدهی نهایی نوبتهای بازپخش را پیش از اجراکنندهٔ تعبیهشده انجام دهید | انتقال ارائهدهنده پس از پاکسازی عمومی به اعتبارسنجی سختگیرانهتری برای نوبتها نیاز دارد |
onModelSelected |
اثرات جانبی پس از انتخاب را که تحت مالکیت ارائهدهنده هستند اجرا کنید | وقتی یک مدل فعال میشود، ارائهدهنده به تلهمتری یا وضعیت تحت مالکیت خود نیاز دارد |
normalizeModelId، normalizeTransport و normalizeConfig ابتدا Plugin ارائهدهنده منطبق را بررسی میکنند، سپس در میان دیگر Pluginهای ارائهدهنده دارای قابلیت هوک پیش میروند تا یکی از آنها واقعاً شناسه مدل یا انتقال/پیکربندی را تغییر دهد. این کار باعث میشود شیمهای ارائهدهنده برای نام مستعار/سازگاری، بدون نیاز به اطلاع فراخوان از اینکه کدام Plugin همراه مالک بازنویسی است، همچنان کار کنند. اگر هیچ هوک ارائهدهندهای ورودی پیکربندی پشتیبانیشده از خانواده Google را بازنویسی نکند، نرمالساز پیکربندی Google همراه همچنان آن پاکسازی سازگاری را اعمال میکند.
اگر ارائهدهنده به یک پروتکل سیمی کاملاً سفارشی یا اجراکننده درخواست سفارشی نیاز داشته باشد، این نوع دیگری از افزونه است. این هوکها برای رفتار ارائهدهندهای هستند که همچنان در حلقه استنتاج عادی OpenClaw اجرا میشود.
resolveUsageAuth تعیین میکند که OpenClaw باید fetchUsageSnapshot را فراخوانی کند یا برای سطوح مصرف/وضعیت به حل عمومی اعتبارنامه بازگردد. هنگامی که ارائهدهنده اعتبارنامه مصرف دارد، { token, accountId?, subscriptionType?, rateLimitTier? } را بازگردانید (فراداده اختیاری طرح به fetchUsageSnapshot منتقل میشود)؛ هنگامی که احراز هویت مصرف متعلق به ارائهدهنده درخواست را مدیریت کرده و باید بازگشت عمومی به کلید API/OAuth را متوقف کند، { handled: true } را بازگردانید؛ و هنگامی که ارائهدهنده احراز هویت مصرف را مدیریت نکرده است، null یا undefined را بازگردانید.
اعتبارنامههای سازمان یا صورتحساب را در providerUsageAuthEnvVars مانیفست اعلام کنید. این کار به سطوح کشف عمومی و پاکسازی اسرار امکان میدهد آنها را بدون تبدیلکردنشان به نامزدهای احراز هویت استنتاج شناسایی کنند.
نمونه ارائهدهنده
api.registerProvider({ id: "example-proxy", label: "Example Proxy", auth: [], catalog: { order: "simple", run: async (ctx) => { const apiKey = ctx.resolveProviderApiKey("example-proxy").apiKey; if (!apiKey) { return null; } return { provider: { baseUrl: "https://proxy.example.com/v1", apiKey, api: "openai-completions", models: [{ id: "auto", name: "Auto" }], }, }; }, }, resolveDynamicModel: (ctx) => ({ id: ctx.modelId, name: ctx.modelId, provider: "example-proxy", api: "openai-completions", baseUrl: "https://proxy.example.com/v1", reasoning: false, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128000, maxTokens: 8192, }), prepareRuntimeAuth: async (ctx) => { const exchanged = await exchangeToken(ctx.apiKey); return { apiKey: exchanged.token, baseUrl: exchanged.baseUrl, expiresAt: exchanged.expiresAt, }; }, resolveUsageAuth: async (ctx) => { const auth = await ctx.resolveOAuthToken(); return auth ? { token: auth.token } : null; }, fetchUsageSnapshot: async (ctx) => { return await fetchExampleProxyUsage(ctx.token, ctx.timeoutMs, ctx.fetchFn); },});نمونههای داخلی
Pluginهای ارائهدهنده همراه، هوکهای بالا را با یکدیگر ترکیب میکنند تا با نیازهای کاتالوگ، احراز هویت، تفکر، بازپخش و مصرف هر عرضهکننده سازگار شوند. مجموعه معتبر هوکها همراه هر Plugin در extensions/ قرار دارد؛ این صفحه بهجای بازتاب فهرست، شکلهای آنها را نمایش میدهد.
ارائهدهندگان کاتالوگ عبوری
OpenRouter، Kilocode، Z.AI و xAI، catalog را همراه با
resolveDynamicModel / prepareDynamicModel ثبت میکنند تا بتوانند
شناسههای مدل بالادستی را پیش از کاتالوگ ایستای OpenClaw ارائه کنند.
ارائهدهندگان نقطه پایانی OAuth و مصرف
GitHub Copilot، Gemini CLI، ChatGPT Codex، MiniMax، Xiaomi و z.ai،
prepareRuntimeAuth یا formatApiKey را با resolveUsageAuth +
fetchUsageSnapshot جفت میکنند تا مالک تبادل توکن و یکپارچهسازی
/usage باشند.
خانوادههای پاکسازی بازپخش و رونوشت
خانوادههای نامگذاریشده مشترک (google-gemini، passthrough-gemini،
anthropic-by-model، hybrid-anthropic-openai) به ارائهدهندگان امکان
میدهند بهجای پیادهسازی مجدد پاکسازی در هر Plugin، از طریق
buildReplayPolicy سیاست رونوشت را فعال کنند.
ارائهدهندگان فقط کاتالوگ
byteplus، cloudflare-ai-gateway، huggingface، kimi-coding، nvidia،
qianfan، synthetic، together، venice، vercel-ai-gateway و
volcengine فقط catalog را ثبت میکنند و از حلقه استنتاج مشترک بهره
میبرند.
یاریگرهای جریان ویژه Anthropic
سرآیندهای بتا، /fast / serviceTier و context1m در مرز عمومی
api.ts / contract-api.ts متعلق به Plugin Anthropic قرار دارند
(wrapAnthropicProviderStream، resolveAnthropicBetas،
resolveAnthropicFastMode، resolveAnthropicServiceTier)، نه در SDK
عمومی.
یاریگرهای زمان اجرا
Pluginها میتوانند از طریق api.runtime به یاریگرهای منتخب هسته دسترسی پیدا کنند. برای TTS:
const clip = await api.runtime.tts.textToSpeech({ text: "Hello from OpenClaw", cfg: api.config,}); const result = await api.runtime.tts.textToSpeechTelephony({ text: "Hello from OpenClaw", cfg: api.config,}); const voices = await api.runtime.tts.listVoices({ provider: "elevenlabs", cfg: api.config,});نکات:
textToSpeechمحموله خروجی عادی TTS هسته را برای سطوح فایل/یادداشت صوتی بازمیگرداند.- از پیکربندی
messages.ttsهسته و انتخاب ارائهدهنده استفاده میکند. - بافر صوتی PCM و نرخ نمونهبرداری را بازمیگرداند. Pluginها باید برای ارائهدهندگان، نمونهبرداری مجدد/رمزگذاری را انجام دهند.
listVoicesبرای هر ارائهدهنده اختیاری است. از آن برای انتخابگرهای صدای متعلق به عرضهکننده یا جریانهای راهاندازی استفاده کنید.- هسته یک مهلت درخواست حلشده را به هوکهای
listVoicesارائهدهنده میفرستد؛ تنظیمات مهلت زمانی مختص ارائهدهنده ممکن است آن را بازنویسی کنند. - فهرستهای صدا میتوانند فراداده غنیتری مانند محلیسازی، جنسیت و برچسبهای شخصیت را برای انتخابگرهای آگاه از ارائهدهنده در بر بگیرند.
- OpenAI و ElevenLabs در حال حاضر از تلفن پشتیبانی میکنند. Microsoft پشتیبانی نمیکند.
Pluginها همچنین میتوانند ارائهدهندگان گفتار را از طریق api.registerSpeechProvider(...) ثبت کنند.
api.registerSpeechProvider({ id: "acme-speech", label: "Acme Speech", isConfigured: ({ config }) => Boolean(config.messages?.tts), synthesize: async (req) => { return { audioBuffer: Buffer.from([]), outputFormat: "mp3", fileExtension: ".mp3", voiceCompatible: false, }; },});نکات:
- سیاست TTS، بازگشت و تحویل پاسخ را در هسته نگه دارید.
- از ارائهدهندگان گفتار برای رفتار ترکیب صدای متعلق به عرضهکننده استفاده کنید.
- ورودی قدیمی Microsoft با مقدار
edgeبه شناسه ارائهدهندهmicrosoftنرمالسازی میشود. - مدل مالکیت ترجیحی، شرکتمحور است: با افزودن قراردادهای قابلیت توسط OpenClaw، یک Plugin عرضهکننده میتواند مالک ارائهدهندگان متن، گفتار، تصویر و رسانههای آینده باشد.
برای درک تصویر/صوت/ویدئو، Pluginها بهجای یک مجموعه عمومی کلید/مقدار، یک ارائهدهنده نوعدار درک رسانه را ثبت میکنند:
api.registerMediaUnderstandingProvider({ id: "google", capabilities: ["image", "audio", "video"], describeImage: async (req) => ({ text: "..." }), transcribeAudio: async (req) => ({ text: "..." }), describeVideo: async (req) => ({ text: "..." }),});نکات:
- هماهنگسازی، بازگشت، پیکربندی و سیمکشی کانال را در هسته نگه دارید.
- رفتار عرضهکننده را در Plugin ارائهدهنده نگه دارید.
- گسترش افزایشی باید نوعدار باقی بماند: متدهای اختیاری جدید، فیلدهای نتیجه اختیاری جدید و قابلیتهای اختیاری جدید.
- تولید ویدئو از قبل همین الگو را دنبال میکند:
- هسته مالک قرارداد قابلیت و یاریگر زمان اجرا است
- Pluginهای عرضهکننده
api.registerVideoGenerationProvider(...)را ثبت میکنند - Pluginهای قابلیت/کانال از
api.runtime.videoGeneration.*استفاده میکنند
برای یاریگرهای زمان اجرای درک رسانه، Pluginها میتوانند فراخوانی کنند:
const image = await api.runtime.mediaUnderstanding.describeImageFile({ filePath: "/tmp/inbound-photo.jpg", cfg: api.config, agentDir: "/tmp/agent",}); const video = await api.runtime.mediaUnderstanding.describeVideoFile({ filePath: "/tmp/inbound-video.mp4", cfg: api.config,}); const extraction = await api.runtime.mediaUnderstanding.extractStructuredWithModel({ provider: "codex", model: "gpt-5.6-sol", input: [ { type: "image", buffer: receiptImageBuffer, fileName: "receipt.png", mime: "image/png", }, { type: "text", text: "Use the printed fields as the source of truth." }, ], instructions: "Return entities and searchable tags.", schemaName: "example.evidence", jsonSchema: { type: "object", properties: { entities: { type: "array", items: { type: "string" } }, tags: { type: "array", items: { type: "string" } }, }, }, cfg: api.config,});برای رونویسی صوتی، Pluginها میتوانند از زمان اجرای درک رسانه یا نام مستعار قدیمیتر STT استفاده کنند:
const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ filePath: "/tmp/inbound-audio.ogg", cfg: api.config, // Optional when MIME cannot be inferred reliably: mime: "audio/ogg",});نکات:
api.runtime.mediaUnderstanding.*سطح مشترک ترجیحی برای درک تصویر/صوت/ویدئو است.extractStructuredWithModel(...)مرز ویژه Plugin برای استخراج محدود و تصویرمحور متعلق به ارائهدهنده است. دستکم یک ورودی تصویر اضافه کنید؛ ورودیهای متنی زمینه تکمیلی هستند. Pluginهای محصول مالک مسیرها و طرحوارههای خود هستند، در حالی که OpenClaw مالک مرز ارائهدهنده/زمان اجرا است.- از پیکربندی صوتی درک رسانه هسته (
tools.media.audio) و ترتیب بازگشت ارائهدهندگان استفاده میکند. - وقتی هیچ خروجی رونویسی تولید نشود (برای مثال ورودی نادیدهگرفتهشده/پشتیبانینشده)،
{ text: undefined }را بازمیگرداند. api.runtime.stt.transcribeAudioFile(...)بهعنوان یک نام مستعار سازگاری باقی میماند.
Pluginها همچنین میتوانند اجراهای پسزمینه زیرعامل را از طریق api.runtime.subagent آغاز کنند:
const result = await api.runtime.subagent.run({ sessionKey: "agent:main:subagent:search-helper", message: "Expand this query into focused follow-up searches.", provider: "openai", model: "gpt-4.1-mini", deliver: false,});نکات:
providerوmodelبازنویسیهای اختیاری هر اجرا هستند، نه تغییرات پایدار نشست.- OpenClaw این فیلدهای بازنویسی را فقط برای فراخوانهای مورد اعتماد میپذیرد.
- برای اجراهای بازگشتی متعلق به Plugin، اپراتورها باید با
plugins.entries.<id>.subagent.allowModelOverride: trueآن را صریحاً فعال کنند. - از
plugins.entries.<id>.subagent.allowedModelsبرای محدودکردن Pluginهای مورد اعتماد به اهداف متعارف مشخصprovider/model، یا از"*"برای مجازکردن صریح هر هدف استفاده کنید. - اجراهای زیرعامل Pluginهای نامطمئن همچنان کار میکنند، اما درخواستهای بازنویسی بهجای بازگشت بیسروصدا رد میشوند.
- نشستهای زیرعامل ایجادشده توسط Plugin با شناسه Plugin سازنده برچسبگذاری میشوند.
api.runtime.subagent.deleteSession(...)بازگشتی فقط میتواند همان نشستهای تحت مالکیت را حذف کند؛ حذف نشست دلخواه همچنان به یک درخواست Gateway با دامنه مدیر نیاز دارد.
برای جستوجوی وب، Pluginها میتوانند بهجای دسترسی مستقیم به سیمکشی ابزار عامل، از یاریگر مشترک زمان اجرا استفاده کنند:
const providers = api.runtime.webSearch.listProviders({ config: api.config,}); const result = await api.runtime.webSearch.search({ config: api.config, args: { query: "OpenClaw plugin runtime helpers", count: 5, },});Pluginها همچنین میتوانند ارائهدهندگان جستوجوی وب را از طریق api.registerWebSearchProvider(...) ثبت کنند.
نکات:
- انتخاب ارائهدهنده، حل اعتبارنامه و معناشناسی مشترک درخواست را در هسته نگه دارید.
- از ارائهدهندگان جستوجوی وب برای انتقالهای جستوجوی مختص عرضهکننده استفاده کنید.
api.runtime.webSearch.*سطح مشترک ترجیحی برای Pluginهای قابلیت/کانال است که بدون وابستگی به پوشش ابزار عامل به رفتار جستوجو نیاز دارند.
api.runtime.imageGeneration
const result = await api.runtime.imageGeneration.generate({ config: api.config, args: { prompt: "A friendly lobster mascot", size: "1024x1024" },}); const providers = api.runtime.imageGeneration.listProviders({ config: api.config,});generate(...): با استفاده از زنجیره پیکربندیشده ارائهدهندگان تولید تصویر، یک تصویر تولید میکند.listProviders(...): ارائهدهندگان تولید تصویر موجود و قابلیتهای آنها را فهرست میکند.
مسیرهای HTTP در Gateway
Pluginها میتوانند با api.registerHttpRoute(...) نقاط پایانی HTTP ارائه کنند.
api.registerHttpRoute({ path: "/acme/webhook", auth: "plugin", match: "exact", handler: async (_req, res) => { res.statusCode = 200; res.end("ok"); return true; },});فیلدهای مسیر:
path: مسیر راه تحت سرور HTTP مربوط به Gateway.auth: الزامی،"gateway"یا"plugin". برای الزام احراز هویت عادی Gateway از"gateway"و برای احراز هویت یا تأیید Webhook مدیریتشده توسط Plugin از"plugin"استفاده کنید.match: اختیاری."exact"(پیشفرض) یا"prefix".handleUpgrade: کنترلکننده اختیاری برای درخواستهای ارتقای WebSocket در همان مسیر.replaceExisting: اختیاری. به همان Plugin اجازه میدهد ثبت مسیر موجود خودش را جایگزین کند.handler: وقتی مسیر درخواست را پردازش کرده است،trueبرگردانید.
نکتهها:
api.registerHttpHandler(...)حذف شده است و باعث خطای بارگذاری Plugin میشود. بهجای آن ازapi.registerHttpRoute(...)استفاده کنید.- مسیرهای Plugin باید
authرا بهصراحت اعلام کنند. - تداخلهای یکسان
path + matchرد میشوند، مگر آنکهreplaceExisting: trueباشد؛ همچنین یک Plugin نمیتواند مسیر Plugin دیگری را جایگزین کند. - مسیرهای همپوشان با سطوح متفاوت
authرد میشوند. زنجیرههای عبورexact/prefixرا فقط در یک سطح احراز هویت نگه دارید. - مسیرهای
auth: "plugin"بهطور خودکار دامنههای زمان اجرای اپراتور را دریافت نمیکنند. این مسیرها برای Webhookها و تأیید امضای مدیریتشده توسط Plugin هستند، نه فراخوانیهای ممتاز کمکتابعهای Gateway. - مسیرهای
auth: "gateway"درون دامنه زمان اجرای یک درخواست Gateway اجرا میشوند. سطح پیشفرض (gatewayRuntimeScopeSurface: "write-default") عمداً محافظهکارانه است:- احراز هویت حامل با راز مشترک (
gateway.auth.mode = "token"/"password") و هر روش احراز هویت غیر از پروکسی مورداعتماد، حتی اگر فراخوانندهx-openclaw-scopesرا ارسال کند، فقط یک دامنهoperator.writeدریافت میکنند - فراخوانندگان
trusted-proxyکه سرآیند صریحx-openclaw-scopesرا ندارند نیز سطح قدیمیِ محدود بهoperator.writeرا حفظ میکنند - فراخوانندگان
trusted-proxyکهx-openclaw-scopesرا ارسال میکنند، بهجای آن دامنههای اعلامشده را دریافت میکنند - یک مسیر میتواند با انتخاب
gatewayRuntimeScopeSurface: "trusted-operator"برای حالتهای احراز هویت دارای هویت، همیشهx-openclaw-scopesرا محترم بشمارد (و اگر سرآیند وجود نداشته باشد، به مجموعه کامل دامنههای پیشفرض CLI بازگردد)
- احراز هویت حامل با راز مشترک (
- قاعده عملی: فرض نکنید یک مسیر Plugin با احراز هویت Gateway بهطور ضمنی سطح مدیریتی دارد. اگر مسیر شما به رفتار مختص مدیر نیاز دارد، سطح دامنه
trusted-operatorرا انتخاب کنید، یک حالت احراز هویت دارای هویت را الزامی کنید و قرارداد صریح سرآیندx-openclaw-scopesرا مستند کنید. - پس از تطبیق مسیر و احراز هویت، کنترلکنندههای عادی در پذیرش کار ریشه Gateway مشارکت میکنند. یک Gateway آمادهسازیشده یا در حال راهاندازی مجدد، پیش از فراخوانی کنترلکننده
503برمیگرداند. استثنای محدود، مسیری با مجوز مانیفست وauth: "gateway"است که سطح اختصاصی مسیرtrusted-operatorرا نیز انتخاب کرده باشد؛ این مسیر همچنان در دسترس میماند تا ارسال کنترل تعلیق بدون مسیر نماند، درحالیکه مسیرهای عادی همسطح از همان Plugin پشت مرز پذیرش باقی میمانند. مالکیتhandleUpgradeمربوط به WebSocket از همان مرز اتمیک پذیرش استفاده میکند؛ پس از آنکه کنترلکننده یک سوکت را پذیرفت، ادامه چرخه عمر سوکت در مالکیت Plugin است و این مرز آن را ردیابی نمیکند.
مسیرهای واردسازی SDK مربوط به Plugin
هنگام ایجاد Pluginهای جدید، بهجای barrel یکپارچه ریشه openclaw/plugin-sdk از زیرمسیرهای محدود SDK استفاده کنید. زیرمسیرهای هسته:
| زیرمسیر | کاربرد |
|---|---|
openclaw/plugin-sdk/plugin-entry |
سازوکارهای پایه ثبت Plugin |
openclaw/plugin-sdk/channel-core |
کمکتابعهای ورودی/ساخت کانال |
openclaw/plugin-sdk/core |
کمکتابعهای مشترک عمومی و قرارداد چتری |
openclaw/plugin-sdk/config-schema |
شِمای Zod ریشه openclaw.json (OpenClawSchema) |
Pluginهای کانال از خانوادهای از درگاههای محدود انتخاب میکنند — channel-setup،
setup-runtime، setup-tools، channel-pairing،
channel-contract، channel-feedback، channel-inbound، channel-outbound،
command-auth، secret-input، webhook-ingress،
channel-targets و channel-actions. رفتار تأیید باید بهجای ترکیبشدن میان
فیلدهای نامرتبط Plugin، در یک قرارداد approvalCapability تجمیع شود.
Pluginهای کانال را ببینید.
کمکتابعهای زمان اجرا و پیکربندی در زیرمسیرهای متمرکز و متناظر *-runtime
قرار دارند (approval-runtime، agent-runtime، lazy-runtime، directory-runtime،
text-runtime، runtime-store، system-event-runtime، heartbeat-runtime،
channel-activity-runtime و غیره). بهجای barrel گسترده سازگاری
config-runtime، استفاده از config-contracts،
plugin-config-runtime، runtime-config-snapshot و config-mutation
را ترجیح دهید.
نقاط ورود داخلی مخزن (برای ریشه بسته هر Plugin همراه):
index.js— ورودی Plugin همراهapi.js— barrel کمکتابعها/نوعهاruntime-api.js— barrel مختص زمان اجراsetup-entry.js— ورودی Plugin راهاندازی
Pluginهای خارجی باید فقط زیرمسیرهای openclaw/plugin-sdk/* را وارد کنند. هرگز
src/* بسته Plugin دیگری را از هسته یا Plugin دیگری وارد نکنید.
نقاط ورودی بارگذاریشده از طریق نما، در صورت وجود، snapshot فعال پیکربندی زمان اجرا
را ترجیح میدهند و سپس به فایل پیکربندی حلشده روی دیسک بازمیگردند.
زیرمسیرهای مختص قابلیت مانند image-generation، media-understanding
و speech وجود دارند، زیرا Pluginهای همراه امروزه از آنها استفاده میکنند. آنها
بهطور خودکار قراردادهای خارجی ثابت و بلندمدت نیستند — هنگام اتکا به آنها،
صفحه مرجع SDK مربوطه را بررسی کنید.
شِماهای ابزار پیام
Pluginها باید مالک مشارکتهای شِمای describeMessageTool(...) مختص کانال
برای سازوکارهای غیرپیامی مانند واکنشها، خواندنها و نظرسنجیها باشند.
نمایش مشترک ارسال باید بهجای فیلدهای بومی ارائهدهنده برای دکمه، مؤلفه، بلوک
یا کارت، از قرارداد عمومی MessagePresentation استفاده کند.
برای قرارداد، قواعد بازگشت، نگاشت ارائهدهنده و فهرست بررسی نویسنده Plugin،
نمایش پیام را ببینید.
Pluginهای دارای قابلیت ارسال، موارد قابل رندر خود را از طریق قابلیتهای پیام اعلام میکنند:
presentationبرای بلوکهای نمایش معنایی (text،context،divider،chart،table،buttons،select)delivery-pinبرای درخواستهای تحویل سنجاقشده
هسته تصمیم میگیرد نمایش را بهصورت بومی رندر کند یا آن را به متن تنزل دهد. راههای گریز رابط کاربری بومی ارائهدهنده را از ابزار عمومی پیام در معرض قرار ندهید. کمکتابعهای منسوخ SDK برای شِماهای بومی قدیمی همچنان برای Pluginهای شخص ثالث موجود صادر میشوند، اما Pluginهای جدید نباید از آنها استفاده کنند.
حل مقصد کانال
Pluginهای کانال باید مالک معنای مقصد مختص کانال باشند. میزبان خروجی مشترک را عمومی نگه دارید و برای قواعد ارائهدهنده از سطح آداپتور پیامرسانی استفاده کنید:
messaging.inferTargetChatType({ to })پیش از جستوجوی فهرست تعیین میکند که یک مقصد نرمالشده باید بهصورتdirect،groupیاchannelدر نظر گرفته شود.messaging.targetResolver.looksLikeId(raw, normalized)به هسته میگوید آیا یک ورودی باید بهجای جستوجوی فهرست، مستقیماً به حل مشابه شناسه منتقل شود.messaging.targetResolver.reservedLiteralsواژههای سادهای را فهرست میکند که برای آن ارائهدهنده ارجاعهای کانال/نشست هستند. فرایند حل، ورودیهای پیکربندیشده فهرست را پیش از رد عبارتهای رزروشده حفظ میکند و سپس در صورت نیافتن مورد در فهرست، بهصورت بسته شکست میخورد.messaging.targetResolver.resolveTarget(...)بازگشت Plugin است، هنگامی که هسته پس از نرمالسازی یا نیافتن مورد در فهرست، به یک حل نهایی تحت مالکیت ارائهدهنده نیاز دارد.messaging.resolveOutboundSessionRoute(...)پس از حل مقصد، مالک ساخت مسیر نشست مختص ارائهدهنده است.
تفکیک توصیهشده:
- برای تصمیمهای دستهبندی که باید پیش از جستوجوی همتاها/گروهها انجام شوند،
از
inferTargetChatTypeاستفاده کنید. - برای بررسیهای «این مورد را یک شناسه مقصد صریح/بومی در نظر بگیر» از
looksLikeIdاستفاده کنید. - از
resolveTargetبرای بازگشت نرمالسازی مختص ارائهدهنده استفاده کنید، نه برای جستوجوی گسترده فهرست. - شناسههای بومی ارائهدهنده مانند شناسههای گفتوگو، شناسههای رشته، JIDها،
نامهای کاربری و شناسههای اتاق را در مقادیر
targetیا پارامترهای مختص ارائهدهنده نگه دارید، نه در فیلدهای عمومی SDK.
فهرستهای مبتنی بر پیکربندی
Pluginهایی که ورودیهای فهرست را از پیکربندی استخراج میکنند باید این منطق را
در Plugin نگه دارند و کمکتابعهای مشترک
openclaw/plugin-sdk/directory-runtime را دوباره استفاده کنند.
هنگامی از این قابلیت استفاده کنید که یک کانال به همتاها/گروههای مبتنی بر پیکربندی مانند موارد زیر نیاز دارد:
- همتاهای پیام مستقیم مبتنی بر فهرست مجاز
- نگاشتهای پیکربندیشده کانال/گروه
- مسیرهای بازگشت ایستای فهرست در محدوده حساب
کمکتابعهای مشترک در directory-runtime فقط عملیات عمومی را مدیریت میکنند:
- فیلترکردن پرسوجو
- اعمال محدودیت
- کمکتابعهای حذف موارد تکراری/نرمالسازی
- ساخت
ChannelDirectoryEntry[]
بررسی حساب مختص کانال و نرمالسازی شناسه باید در پیادهسازی Plugin باقی بمانند.
کاتالوگهای ارائهدهنده
Pluginهای ارائهدهنده میتوانند با
registerProvider({ catalog: { run(...) { ... } } }) کاتالوگهای مدل را
برای استنتاج تعریف کنند.
catalog.run(...) همان ساختاری را برمیگرداند که OpenClaw در
models.providers مینویسد:
{ provider }برای یک ورودی ارائهدهنده{ providers }برای چند ورودی ارائهدهنده
هنگامی از catalog استفاده کنید که Plugin مالک شناسههای مدل مختص ارائهدهنده،
مقادیر پیشفرض نشانی پایه یا فراداده مدل مشروط به احراز هویت باشد.
catalog.order زمان ادغام کاتالوگ یک Plugin را نسبت به ارائهدهندگان ضمنی
داخلی OpenClaw کنترل میکند:
simple: ارائهدهندگان ساده مبتنی بر کلید API یا متغیر محیطیprofile: ارائهدهندگانی که هنگام وجود نمایههای احراز هویت ظاهر میشوندpaired: ارائهدهندگانی که چند ورودی مرتبط ارائهدهنده را میسازندlate: گذر نهایی، پس از سایر ارائهدهندگان ضمنی
در تداخل کلید، ارائهدهندگان بعدی پیروز میشوند؛ بنابراین Pluginها میتوانند عمداً ورودی داخلی ارائهدهندهای با همان شناسه ارائهدهنده را بازنویسی کنند.
Pluginها همچنین میتوانند ردیفهای فقطخواندنی مدل را از طریق
api.registerModelCatalogProvider({ provider, kinds, staticCatalog, liveCatalog }) منتشر کنند. این مسیر آینده برای سطوح فهرست/راهنما/انتخابگر است و از ردیفهای
text، voice، image_generation، video_generation و music_generation
پشتیبانی میکند. Pluginهای ارائهدهنده همچنان مالک فراخوانیهای زنده نقطه پایانی،
تبادل توکن و نگاشت پاسخ فروشنده هستند؛ هسته مالک ساختار مشترک ردیف، برچسبهای
منبع و قالببندی راهنمای ابزار رسانه است. ثبت ارائهدهندگان تولید رسانه،
ردیفهای ایستای کاتالوگ را بهطور خودکار از defaultModel، models و
capabilities میسازد.
سازگاری:
discoveryهمچنان بهعنوان نام مستعار قدیمی کار میکند، اما هشدار منسوخشدن صادر میکند- اگر هر دو
catalogوdiscoveryثبت شده باشند، OpenClaw ازcatalogاستفاده میکند و هشدار میدهد augmentModelCatalogمنسوخ شده است؛ ارائهدهندگان همراه باید ردیفهای تکمیلی را از طریقregisterModelCatalogProviderمنتشر کنند
بررسی فقطخواندنی کانال
اگر Plugin شما یک کانال ثبت میکند، پیادهسازی
plugin.config.inspectAccount(cfg, accountId) در کنار resolveAccount(...)
را ترجیح دهید.
دلیل:
resolveAccount(...)مسیر زمان اجرا است. این مسیر مجاز است فرض کند اطلاعات احراز هویت کاملاً فراهم شدهاند و در صورت نبود رازهای الزامی سریعاً شکست بخورد.- مسیرهای فرمان فقطخواندنی مانند
openclaw status،openclaw status --all،openclaw channels status،openclaw channels resolveو جریانهای اصلاح doctor/پیکربندی نباید صرفاً برای توصیف پیکربندی نیازمند فراهمسازی اطلاعات احراز هویت زمان اجرا باشند.
رفتار توصیهشده inspectAccount(...):
- فقط وضعیت توصیفی حساب را بازگردانید.
enabledوconfiguredرا حفظ کنید.- در صورت مرتبط بودن، فیلدهای منبع/وضعیت اعتبارنامه را درج کنید، مانند:
tokenSource،tokenStatusbotTokenSource،botTokenStatusappTokenSource،appTokenStatussigningSecretSource،signingSecretStatus
- برای گزارش دسترسپذیری فقطخواندنی، نیازی نیست مقادیر خام توکن را بازگردانید.
بازگرداندن
tokenStatus: "available"(همراه با فیلد منبع متناظر) برای فرمانهای وضعیتمحور کافی است. - وقتی یک اعتبارنامه از طریق SecretRef پیکربندی شده اما در مسیر فرمان فعلی
در دسترس نیست، از
configured_unavailableاستفاده کنید.
این کار به فرمانهای فقطخواندنی اجازه میدهد بهجای از کار افتادن یا گزارش نادرست حساب بهعنوان پیکربندینشده، وضعیت «پیکربندیشده اما در این مسیر فرمان در دسترس نیست» را گزارش کنند.
بستههای پکیج
یک دایرکتوری Plugin میتواند شامل یک package.json با openclaw.extensions باشد:
{ "name": "my-pack", "openclaw": { "extensions": ["./src/safety.ts", "./src/tools.ts"], "setupEntry": "./src/setup-entry.ts" }}هر ورودی به یک Plugin تبدیل میشود. اگر بسته چند افزونه را فهرست کند، شناسه
Plugin بهشکل <manifestOrPackageName>/<fileBase> خواهد بود (در صورت وجود،
شناسه مانیفست اولویت دارد؛ در غیر این صورت نام بدون محدوده در package.json
استفاده میشود).
اگر Plugin شما وابستگیهای npm را وارد میکند، آنها را در همان دایرکتوری
نصب کنید تا node_modules در دسترس باشد (npm install / pnpm install).
محافظ امنیتی: هر ورودی openclaw.extensions باید پس از رفع پیوندهای نمادین،
داخل دایرکتوری Plugin باقی بماند. ورودیهایی که از دایرکتوری پکیج خارج شوند،
رد میشوند.
نکته امنیتی: openclaw plugins install وابستگیهای Plugin را با یک
npm install --omit=dev --ignore-scripts محلیِ پروژه نصب میکند (بدون
اسکریپتهای چرخهعمر و بدون وابستگیهای توسعه در زمان اجرا) و تنظیمات سراسری
بهارثرسیده نصب npm را نادیده میگیرد. درخت وابستگی Plugin را «صرفاً JS/TS»
نگه دارید و از پکیجهایی که به ساختهای postinstall نیاز دارند، اجتناب کنید.
اختیاری: openclaw.setupEntry میتواند به یک ماژول سبکوزنِ مخصوص راهاندازی
اشاره کند. وقتی OpenClaw برای یک Plugin کانال غیرفعال به سطوح راهاندازی نیاز
دارد، یا وقتی Plugin کانال فعال است اما هنوز پیکربندی نشده، بهجای ورودی کامل
Plugin، setupEntry را بارگذاری میکند. این کار در مواقعی که ورودی اصلی Plugin
ابزارها، هوکها یا کدهای دیگری را که فقط برای زمان اجرا هستند نیز متصل میکند،
راهاندازی اولیه و فرایند تنظیم را سبکتر نگه میدارد.
اختیاری: openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen
میتواند یک Plugin کانال را حتی زمانی که کانال از قبل پیکربندی شده است، در
مرحله راهاندازی پیش از شنود Gateway به همان مسیر setupEntry وارد کند.
فقط زمانی از این گزینه استفاده کنید که setupEntry تمام سطح راهاندازی لازم
پیش از آغاز شنود Gateway را کاملاً پوشش دهد. در عمل، یعنی ورودی راهاندازی باید
تمام قابلیتهای متعلق به کانال را که راهاندازی به آنها وابسته است ثبت کند،
از جمله:
- خود ثبت کانال
- همه مسیرهای HTTP که باید پیش از آغاز شنود Gateway در دسترس باشند
- همه متدها، ابزارها یا سرویسهای Gateway که باید در همان بازه وجود داشته باشند
اگر ورودی کامل شما همچنان مالک هر قابلیت ضروری راهاندازی است، این پرچم را فعال نکنید. Plugin را روی رفتار پیشفرض نگه دارید و اجازه دهید OpenClaw ورودی کامل را هنگام راهاندازی بارگذاری کند.
کانالهای همراه نیز میتوانند یاریگرهای سطح قراردادِ مخصوص راهاندازی را منتشر کنند تا هسته پیش از بارگذاری زماناجرای کامل کانال به آنها مراجعه کند. سطح فعلی ارتقای راهاندازی عبارت است از:
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
هسته زمانی از این سطح استفاده میکند که لازم باشد پیکربندی قدیمی کانال تکحسابی
را بدون بارگذاری ورودی کامل Plugin به channels.<id>.accounts.* ارتقا دهد.
Matrix نمونه همراه فعلی است: وقتی حسابهای نامگذاریشده از قبل وجود دارند،
فقط کلیدهای احراز هویت/بوتاسترپ را به یک حساب ارتقایافته نامگذاریشده منتقل
میکند و میتواند بهجای ایجاد همیشگی accounts.default، کلید پیکربندیشده
حساب پیشفرضِ غیرمتعارف را حفظ کند.
این آداپتورهای وصله راهاندازی، کشف سطح قرارداد همراه را تنبل نگه میدارند. زمان واردسازی سبک باقی میماند؛ سطح ارتقا بهجای ورود دوباره به راهاندازی کانال همراه هنگام واردسازی ماژول، فقط در نخستین استفاده بارگذاری میشود.
وقتی این سطوح راهاندازی شامل متدهای RPC در Gateway هستند، آنها را در یک
پیشوند مخصوص Plugin نگه دارید. فضاهای نام مدیریتی هسته (config.*،
exec.approvals.*، wizard.*، update.*) رزروشده باقی میمانند و همیشه به
operator.admin نگاشت میشوند، حتی اگر یک Plugin محدوده محدودتری درخواست کند.
مثال:
{ "name": "@scope/my-channel", "openclaw": { "extensions": ["./index.ts"], "setupEntry": "./setup-entry.ts", "startup": { "deferConfiguredChannelFullLoadUntilAfterListen": true } }}فراداده کاتالوگ کانال
Pluginهای کانال میتوانند فراداده راهاندازی/کشف را از طریق openclaw.channel
و راهنمای نصب را از طریق openclaw.install اعلام کنند. این کار کاتالوگ هسته را
فاقد داده اختصاصی نگه میدارد.
مثال:
{ "name": "@openclaw/nextcloud-talk", "openclaw": { "extensions": ["./index.ts"], "channel": { "id": "nextcloud-talk", "label": "Nextcloud Talk", "selectionLabel": "Nextcloud Talk (self-hosted)", "docsPath": "/channels/nextcloud-talk", "docsLabel": "nextcloud-talk", "blurb": "Self-hosted chat via Nextcloud Talk webhook bots.", "order": 65, "aliases": ["nc-talk", "nc"] }, "install": { "npmSpec": "@openclaw/nextcloud-talk", "localPath": "<bundled-plugin-local-path>", "defaultChoice": "npm" } }}فیلدهای مفید openclaw.channel فراتر از نمونه حداقلی:
detailLabel: برچسب ثانویه برای سطوح غنیتر کاتالوگ/وضعیتdocsLabel: بازنویسی متن پیوند برای پیوند مستنداتpreferOver: شناسههای Plugin/کانال با اولویت پایینتر که این ورودی کاتالوگ باید از آنها بالاتر قرار گیردselectionDocsPrefix،selectionDocsOmitLabel،selectionExtras: کنترلهای متن سطح انتخابmarkdownCapable: کانال را برای تصمیمهای قالببندی خروجی، دارای قابلیت Markdown علامتگذاری میکندexposure.configured: وقتی رویfalseتنظیم شود، کانال را از سطوح فهرست کانالهای پیکربندیشده پنهان میکندexposure.setup: وقتی رویfalseتنظیم شود، کانال را از گزینشگرهای تعاملی راهاندازی/پیکربندی پنهان میکندexposure.docs: کانال را برای سطوح پیمایش مستندات داخلی/خصوصی علامتگذاری میکندshowConfigured/showInSetup: نامهای مستعار قدیمی که همچنان برای سازگاری پذیرفته میشوند؛exposureرا ترجیح دهیدquickstartAllowFrom: کانال را به جریان استاندارد شروع سریعallowFromوارد میکندforceAccountBinding: حتی وقتی فقط یک حساب وجود دارد، اتصال صریح حساب را الزامی میکندpreferSessionLookupForAnnounceTarget: هنگام رفع اهداف اعلان، جستوجوی نشست را ترجیح میدهد
OpenClaw همچنین میتواند کاتالوگهای خارجی کانال را ادغام کند (برای مثال، یک خروجی رجیستری MPM). یک فایل JSON را در یکی از مسیرهای زیر قرار دهید:
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
یا OPENCLAW_PLUGIN_CATALOG_PATHS (یا OPENCLAW_MPM_CATALOG_PATHS) را به یک
یا چند فایل JSON اشاره دهید (جداشده با ویرگول/نقطهویرگول/PATH). هر فایل باید
شامل { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }
باشد. تجزیهگر همچنین "packages" یا "plugins" را بهعنوان نامهای مستعار
قدیمی برای کلید "entries" میپذیرد.
ورودیهای تولیدشده کاتالوگ کانال و ورودیهای کاتالوگ نصب ارائهدهنده، در کنار
بلوک خام openclaw.install، اطلاعات نرمالشده منبع نصب را ارائه میکنند.
اطلاعات نرمالشده مشخص میکنند که آیا مشخصه npm یک نسخه دقیق است یا انتخابگر
شناور، آیا فراداده یکپارچگی مورد انتظار وجود دارد، و آیا مسیر منبع محلی نیز
در دسترس است. وقتی هویت کاتالوگ/پکیج معلوم باشد، اطلاعات نرمالشده در صورت
انحراف نام پکیج npm تجزیهشده از آن هویت هشدار میدهند. همچنین وقتی
defaultChoice نامعتبر باشد یا به منبعی اشاره کند که در دسترس نیست، و نیز
وقتی فراداده یکپارچگی npm بدون منبع معتبر npm وجود داشته باشد، هشدار میدهند.
مصرفکنندگان باید installSource را یک فیلد اختیاری افزودهشونده در نظر بگیرند
تا ورودیهای دستساز و شیمهای کاتالوگ مجبور به ساخت مصنوعی آن نباشند.
این کار به فرایند آغاز به کار و ابزارهای عیبیابی اجازه میدهد بدون واردسازی
زماناجرای Plugin، وضعیت لایه منبع را توضیح دهند.
ورودیهای رسمی خارجی npm باید یک npmSpec دقیق همراه با
expectedIntegrity را ترجیح دهند. نامهای ساده پکیج و برچسبهای توزیع همچنان
برای سازگاری کار میکنند، اما هشدارهای لایه منبع را نمایش میدهند تا کاتالوگ
بتواند بدون شکستن Pluginهای موجود بهسمت نصبهای سنجاقشده و بررسیشده از نظر
یکپارچگی حرکت کند. وقتی فرایند آغاز به کار از یک مسیر کاتالوگ محلی نصب میکند،
یک ورودی مدیریتشده در نمایه Plugin با source: "path" و در صورت امکان یک
sourcePath نسبی به فضای کاری ثبت میکند. مسیر عملیاتی مطلق بارگذاری در
plugins.load.paths باقی میماند؛ رکورد نصب از تکرار مسیرهای رایانه محلی در
پیکربندی بلندمدت جلوگیری میکند. این کار نصبهای توسعه محلی را برای ابزارهای
عیبیابی لایه منبع قابل مشاهده نگه میدارد، بدون آنکه سطح افشای دوم برای مسیر
خام فایلسیستم اضافه کند. جدول پایدار SQLite با نام
installed_plugin_index منبع حقیقت نصب است و میتوان آن را بدون بارگذاری
ماژولهای زماناجرای Plugin بهروزرسانی کرد. نگاشت installRecords آن حتی
زمانی که مانیفست Plugin وجود ندارد یا نامعتبر است، ماندگار میماند؛ محتوای
plugins آن نمایی بازسازیپذیر از مانیفست است.
Pluginهای موتور زمینه
Pluginهای موتور زمینه مالک هماهنگسازی زمینه نشست برای دریافت، مونتاژ و
Compaction هستند. آنها را از Plugin خود با
api.registerContextEngine(id, factory) ثبت کنید، سپس موتور فعال را با
plugins.slots.contextEngine انتخاب کنید.
وقتی Plugin شما باید خط لوله پیشفرض زمینه را جایگزین یا گسترش دهد، نه اینکه فقط جستوجوی حافظه یا هوک اضافه کند، از این قابلیت استفاده کنید.
export default function (api) { api.registerContextEngine("lossless-claw", (ctx) => ({ info: { id: "lossless-claw", name: "Lossless Claw", ownsCompaction: true }, async ingest() { return { ingested: true }; }, async assemble({ messages, sessionKey, availableTools, citationsMode }) { return { messages, estimatedTokens: 0, systemPromptAddition: buildMemorySystemPromptAddition({ availableTools: availableTools ?? new Set(), citationsMode, agentId: resolveSessionAgentId({ config: ctx.config, sessionKey }), agentSessionKey: sessionKey, }), }; }, async compact() { return { ok: true, compacted: false }; }, }));}ctx کارخانه، مقادیر اختیاری config، agentDir و workspaceDir را برای
مقداردهی اولیه هنگام ساخت در اختیار میگذارد.
وقتی بستر فعال دارای یک رشته پشتیبان پایدار است، assemble() میتواند
contextProjection را بازگرداند. برای تصویرسازی قدیمی در هر نوبت، آن را حذف
کنید. وقتی زمینه مونتاژشده باید یکبار به یک رشته پشتیبان تزریق شود و تا تغییر
دوره دوباره استفاده شود، { mode: "thread_bootstrap", epoch } را بازگردانید.
پس از تغییر معنایی زمینه موتور، مانند بعد از یک گذر Compaction متعلق به موتور،
دوره را تغییر دهید. میزبانها میتوانند فراداده فراخوانی ابزار، شکل ورودی و
نتایج ویرایششده ابزار را در تصویرسازی بوتاسترپ رشته حفظ کنند تا رشتههای
پشتیبان تازه، بدون کپیکردن محتوای خام حاوی اسرار، پیوستگی ابزار را حفظ کنند.
اگر موتور شما مالک الگوریتم Compaction نیست، پیادهسازی compact() را
حفظ کنید و آن را صراحتاً واگذار کنید:
buildMemorySystemPromptAddition, delegateCompactionToRuntime,} from "openclaw/plugin-sdk/core"; export default function (api) { api.registerContextEngine("my-memory-engine", (ctx) => ({ info: { id: "my-memory-engine", name: "My Memory Engine", ownsCompaction: false, }, async ingest() { return { ingested: true }; }, async assemble({ messages, sessionKey, availableTools, citationsMode }) { return { messages, estimatedTokens: 0, systemPromptAddition: buildMemorySystemPromptAddition({ availableTools: availableTools ?? new Set(), citationsMode, agentId: resolveSessionAgentId({ config: ctx.config, sessionKey }), agentSessionKey: sessionKey, }), }; }, async compact(params) { return await delegateCompactionToRuntime(params); }, }));}افزودن یک قابلیت جدید
هنگامی که یک Plugin به رفتاری نیاز دارد که در API فعلی نمیگنجد، با دسترسی خصوصی مستقیم، سامانهٔ Plugin را دور نزنید. قابلیت مفقود را اضافه کنید.
ترتیب پیشنهادی:
- قرارداد هسته را تعریف کنید. مشخص کنید هسته باید مالک کدام رفتار مشترک باشد: خطمشی، سازوکار جایگزین، ادغام پیکربندی، چرخهٔ حیات، معناشناسی مرتبط با کانال و شکل تابع کمکی زمان اجرا.
- سطوح ثبت و زمان اجرای نوعدار Plugin را اضافه کنید. رابط
OpenClawPluginApiو/یاapi.runtimeرا با کوچکترین سطح قابلیت نوعدار و کاربردی گسترش دهید. - مصرفکنندگان هسته و کانال/ویژگی را متصل کنید. کانالها و Pluginهای ویژگی باید قابلیت جدید را از طریق هسته مصرف کنند، نه با واردکردن مستقیم یک پیادهسازی فروشنده.
- پیادهسازیهای فروشنده را ثبت کنید. سپس Pluginهای فروشنده بکاندهای خود را برای این قابلیت ثبت میکنند.
- پوشش قرارداد را اضافه کنید. آزمونهایی اضافه کنید تا شکل مالکیت و ثبت در گذر زمان صریح باقی بماند.
به این شیوه، OpenClaw بدون آنکه به جهانبینی یک ارائهدهنده بهصورت سختکدشده وابسته شود، رویکرد مشخص خود را حفظ میکند. برای فهرست بررسی مشخص فایلها و یک نمونهٔ عملی، به راهنمای قابلیتها مراجعه کنید.
فهرست بررسی قابلیت
هنگام افزودن یک قابلیت جدید، پیادهسازی معمولاً باید این سطوح را با هم پوشش دهد:
- انواع قرارداد هسته در
src/<capability>/types.ts - اجراکننده/تابع کمکی زمان اجرای هسته در
src/<capability>/runtime.ts - سطح ثبت API مربوط به Plugin در
src/plugins/types.ts - سیمکشی رجیستری Plugin در
src/plugins/registry.ts - ارائهٔ زمان اجرای Plugin در
src/plugins/runtime/*، هنگامی که Pluginهای ویژگی/کانال باید آن را مصرف کنند - توابع کمکی ثبت و آزمون در
src/test-utils/plugin-registration.ts - بررسیهای مالکیت/قرارداد در
src/plugins/contracts/registry.ts - مستندات اپراتور/Plugin در
docs/
اگر یکی از این سطوح وجود نداشته باشد، معمولاً نشانهٔ آن است که قابلیت هنوز بهطور کامل یکپارچه نشده است.
الگوی قابلیت
الگوی حداقلی:
// core contractexport type VideoGenerationProviderPlugin = { id: string; label: string; generateVideo: (req: VideoGenerationRequest) => Promise<VideoGenerationResult>;}; // plugin APIapi.registerVideoGenerationProvider({ id: "openai", label: "OpenAI", async generateVideo(req) { return await generateOpenAiVideo(req); },}); // shared runtime helper for feature/channel pluginsconst clip = await api.runtime.videoGeneration.generate({ prompt: "Show the robot walking through the lab.", cfg,});الگوی آزمون قرارداد (src/plugins/contracts/registry.ts جستوجوهای مالکیت
مانند providerContractPluginIds را ارائه میکند؛ آزمونها بررسی میکنند که فهرست
contracts.videoGenerationProviders یک Plugin با مواردی که واقعاً ثبت میکند
مطابقت داشته باشد):
expect(pluginManifest.contracts?.videoGenerationProviders).toEqual(["openai"]);این کار قاعده را ساده نگه میدارد:
- هسته مالک قرارداد قابلیت و هماهنگسازی است
- Pluginهای فروشنده مالک پیادهسازیهای فروشنده هستند
- Pluginهای ویژگی/کانال توابع کمکی زمان اجرا را مصرف میکنند
- آزمونهای قرارداد، مالکیت را صریح نگه میدارند
مرتبط
- معماری Plugin — مدل و شکلهای عمومی قابلیت
- زیرمسیرهای SDK مربوط به Plugin
- راهاندازی SDK مربوط به Plugin
- ساخت Pluginها