Plugin maintainer reference
Plugin आर्किटेक्चर के आंतरिक तंत्र
सार्वजनिक क्षमता मॉडल, Plugin संरचनाओं और स्वामित्व/निष्पादन अनुबंधों के लिए, Plugin आर्किटेक्चर देखें। यह पृष्ठ आंतरिक कार्यप्रणाली को कवर करता है: लोड पाइपलाइन, रजिस्ट्री, रनटाइम हुक, Gateway HTTP रूट, इंपोर्ट पथ और स्कीमा तालिकाएँ।
लोड पाइपलाइन
स्टार्टअप पर, OpenClaw मोटे तौर पर यह करता है:
- संभावित Plugin रूट खोजता है
- नेटिव या संगत बंडल मैनिफ़ेस्ट और पैकेज मेटाडेटा पढ़ता है
- असुरक्षित उम्मीदवारों को अस्वीकार करता है
- Plugin कॉन्फ़िग को सामान्यीकृत करता है (
plugins.enabled,allow,deny,entries,slots,load.paths) - प्रत्येक उम्मीदवार को सक्षम करना है या नहीं, यह तय करता है
- सक्षम नेटिव मॉड्यूल लोड करता है: निर्मित बंडल मॉड्यूल नेटिव लोडर का उपयोग करते हैं; तृतीय-पक्ष स्थानीय स्रोत TypeScript आपातकालीन Jiti फ़ॉलबैक का उपयोग करता है
- नेटिव
register(api)हुक कॉल करता है और पंजीकरणों को Plugin रजिस्ट्री में एकत्र करता है - रजिस्ट्री को कमांड/रनटाइम सतहों के लिए उपलब्ध कराता है
सुरक्षा गेट रनटाइम निष्पादन से पहले चलते हैं। डिस्कवरी किसी उम्मीदवार को तब ब्लॉक करती है, जब:
- उसकी रिज़ॉल्व की गई एंट्री Plugin रूट से बाहर निकलती है
- उसका पथ (या उसकी रूट डायरेक्टरी) सभी उपयोगकर्ताओं द्वारा लिखने योग्य है
- गैर-बंडल Plugin के लिए, पथ का स्वामित्व वर्तमान uid (या root) से मेल नहीं खाता
सभी उपयोगकर्ताओं द्वारा लिखने योग्य बंडल डायरेक्टरियों पर गेट की दोबारा
जाँच से पहले उसी स्थान पर chmod सुधार का प्रयास किया जाता है
(npm/ग्लोबल इंस्टॉल पैकेज डायरेक्टरियों को 0777 पर भेज सकते हैं);
बंडल मूल के लिए स्वामित्व जाँच पूरी तरह छोड़ दी जाती है।
ब्लॉक किए गए उम्मीदवारों की जारी की गई डायग्नोस्टिक में भी उनका Plugin id रहता है, जब वह ज्ञात हो (इसमें अन्यथा अस्वीकृत डायरेक्टरी के भीतर मैनिफ़ेस्ट से रिज़ॉल्व किए गए id भी शामिल हैं), इसलिए उस id को संदर्भित करने वाले कॉन्फ़िग को असंबंधित "अज्ञात Plugin" त्रुटि के बजाय पथ-सुरक्षा चेतावनी से जुड़ा ब्लॉक किया गया Plugin दिखाई देता है।
मैनिफ़ेस्ट-प्रथम व्यवहार
मैनिफ़ेस्ट कंट्रोल-प्लेन का प्रामाणिक स्रोत है। OpenClaw इसका उपयोग इनके लिए करता है:
- Plugin की पहचान करना
- घोषित चैनल/Skills/कॉन्फ़िग स्कीमा या बंडल क्षमताएँ खोजना
plugins.entries.<id>.configको सत्यापित करना- Control UI लेबल/प्लेसहोल्डर को विस्तृत करना
- इंस्टॉल/कैटलॉग मेटाडेटा दिखाना
- Plugin रनटाइम लोड किए बिना हल्के सक्रियण और सेटअप विवरण सुरक्षित रखना
नेटिव Plugin के लिए, रनटाइम मॉड्यूल डेटा-प्लेन वाला भाग है। यह हुक, टूल, कमांड या प्रोवाइडर प्रवाह जैसे वास्तविक व्यवहार पंजीकृत करता है।
वैकल्पिक मैनिफ़ेस्ट activation और setup ब्लॉक कंट्रोल प्लेन पर ही रहते हैं।
वे सक्रियण योजना और सेटअप डिस्कवरी के लिए केवल-मेटाडेटा विवरण हैं;
वे रनटाइम पंजीकरण, register(...) या setupEntry का स्थान नहीं लेते।
लाइव सक्रियण उपभोक्ता व्यापक रजिस्ट्री के मूर्त रूप लेने से पहले Plugin लोडिंग को
सीमित करने के लिए मैनिफ़ेस्ट कमांड, चैनल और प्रोवाइडर संकेतों का उपयोग करते हैं:
- CLI लोडिंग उन Plugin तक सीमित होती है जिनके स्वामित्व में अनुरोधित प्राथमिक कमांड है
- चैनल सेटअप/Plugin रिज़ॉल्यूशन उन Plugin तक सीमित होता है जिनके स्वामित्व में अनुरोधित चैनल id है
- स्पष्ट प्रोवाइडर सेटअप/रनटाइम रिज़ॉल्यूशन उन Plugin तक सीमित होता है जिनके स्वामित्व में अनुरोधित प्रोवाइडर id है
- Gateway स्टार्टअप योजना स्पष्ट स्टार्टअप इंपोर्ट के लिए
activation.onStartupका उपयोग करती है; स्टार्टअप मेटाडेटा रहित Plugin केवल अधिक सीमित सक्रियण ट्रिगर के माध्यम से लोड होते हैं
सक्रियण प्लानर मौजूदा कॉलर के लिए केवल-id 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 id सेट निकालते हैं
(src/plugins/effective-plugin-ids.ts में resolveEffectivePluginIds)। यदि निकाला गया
सेट खाली है, तो OpenClaw प्रत्येक खोजे जा सकने वाले Plugin तक विस्तार करने के बजाय
स्कोप को खाली रखता है।
सेटअप डिस्कवरी उम्मीदवार Plugin को सीमित करने के लिए setup.providers और
setup.cliBackends जैसे विवरण-स्वामित्व वाले id को प्राथमिकता देती है, और उसके बाद
उन Plugin के लिए setup-api पर फ़ॉलबैक करती है जिन्हें अभी भी सेटअप-समय के रनटाइम हुक चाहिए।
प्रोवाइडर सेटअप सूचियाँ प्रोवाइडर रनटाइम लोड किए बिना मैनिफ़ेस्ट providerAuthChoices,
विवरण से निकले सेटअप विकल्पों और इंस्टॉल-कैटलॉग मेटाडेटा का उपयोग करती हैं। स्पष्ट
setup.requiresRuntime: false केवल-विवरण कटऑफ़ है; छोड़ा गया
requiresRuntime संगतता के लिए पुराने सेटअप-api फ़ॉलबैक को बनाए रखता है। यदि
एक से अधिक खोजे गए Plugin समान सामान्यीकृत सेटअप प्रोवाइडर या CLI बैकएंड id पर दावा
करते हैं, तो सेटअप लुकअप डिस्कवरी क्रम पर निर्भर होने के बजाय संदिग्ध स्वामी को अस्वीकार
कर देता है। जब सेटअप रनटाइम निष्पादित होता है, तो रजिस्ट्री डायग्नोस्टिक पुराने Plugin को
ब्लॉक किए बिना setup.providers / setup.cliBackends और सेटअप-api द्वारा वास्तव में
पंजीकृत प्रोवाइडर या CLI बैकएंड के बीच अंतर की रिपोर्ट करती है।
Plugin कैश सीमा
OpenClaw समय-आधारित अवधियों के पीछे Plugin डिस्कवरी परिणाम या प्रत्यक्ष मैनिफ़ेस्ट रजिस्ट्री डेटा कैश नहीं करता। इंस्टॉल, मैनिफ़ेस्ट संपादन और लोड-पथ परिवर्तन अगली स्पष्ट मेटाडेटा रीड या स्नैपशॉट पुनर्निर्माण पर दिखाई देने चाहिए। मैनिफ़ेस्ट फ़ाइल पार्सर खोले गए मैनिफ़ेस्ट पथ के साथ डिवाइस/inode, आकार और mtime/ctime द्वारा कुंजीबद्ध एक सीमित फ़ाइल-हस्ताक्षर कैश रखता है; वह कैश केवल अपरिवर्तित बाइट्स को फिर से पार्स करने से बचाता है और उसे डिस्कवरी, रजिस्ट्री, स्वामी या नीति संबंधी उत्तर कैश नहीं करने चाहिए।
सुरक्षित मेटाडेटा फ़ास्ट पाथ स्पष्ट ऑब्जेक्ट स्वामित्व है, छिपा हुआ कैश नहीं।
Gateway स्टार्टअप हॉट पाथ को वर्तमान PluginMetadataSnapshot, निकाला गया
PluginLookUpTable या स्पष्ट मैनिफ़ेस्ट रजिस्ट्री को कॉल शृंखला के माध्यम से पास
करना चाहिए। कॉन्फ़िग सत्यापन, स्टार्टअप स्वतः-सक्षमकरण, Plugin बूटस्ट्रैप और प्रोवाइडर
चयन उन ऑब्जेक्ट का पुनः उपयोग कर सकते हैं, जब तक वे वर्तमान कॉन्फ़िग और
Plugin इन्वेंट्री को दर्शाते हैं। सेटअप लुकअप अभी भी माँग पर मैनिफ़ेस्ट मेटाडेटा का
पुनर्निर्माण करता है, जब तक कि विशिष्ट सेटअप पथ को स्पष्ट मैनिफ़ेस्ट रजिस्ट्री न मिले;
छिपे हुए लुकअप कैश जोड़ने के बजाय इसे कोल्ड-पाथ फ़ॉलबैक बनाए रखें। इनपुट बदलने पर
स्नैपशॉट में बदलाव करने या ऐतिहासिक प्रतियाँ रखने के बजाय उसे पुनर्निर्मित करके बदलें।
सक्रिय Plugin रजिस्ट्री के दृश्य और बंडल चैनल बूटस्ट्रैप हेल्पर वर्तमान
रजिस्ट्री/रूट से दोबारा परिकलित किए जाने चाहिए। एक कॉल के भीतर कार्य की पुनरावृत्ति
हटाने या पुनःप्रवेश रोकने के लिए अल्पकालिक मैप ठीक हैं; उन्हें प्रोसेस मेटाडेटा कैश
नहीं बनना चाहिए।
Plugin लोडिंग के लिए, स्थायी कैश परत रनटाइम लोडिंग है। कोड या इंस्टॉल की गई कलाकृतियाँ वास्तव में लोड होने पर यह लोडर स्थिति का पुनः उपयोग कर सकती है, जैसे:
PluginLoaderCacheStateऔर संगत सक्रिय रनटाइम रजिस्ट्रियाँ- समान रनटाइम सतह को बार-बार इंपोर्ट करने से बचने के लिए उपयोग किए जाने वाले jiti/मॉड्यूल कैश और सार्वजनिक-सतह लोडर कैश
- इंस्टॉल की गई Plugin कलाकृतियों के लिए फ़ाइलसिस्टम कैश
- पथ सामान्यीकरण या डुप्लिकेट रिज़ॉल्यूशन के लिए अल्पकालिक प्रति-कॉल मैप
वे कैश डेटा-प्लेन कार्यान्वयन विवरण हैं। उन्हें "इस प्रोवाइडर का स्वामी कौन-सा Plugin है?" जैसे कंट्रोल-प्लेन प्रश्नों का उत्तर नहीं देना चाहिए, जब तक कॉलर ने जानबूझकर रनटाइम लोडिंग का अनुरोध न किया हो।
इनके लिए स्थायी या समय-आधारित कैश न जोड़ें:
- डिस्कवरी परिणाम
- प्रत्यक्ष मैनिफ़ेस्ट रजिस्ट्रियाँ
- इंस्टॉल किए गए Plugin इंडेक्स से पुनर्निर्मित मैनिफ़ेस्ट रजिस्ट्रियाँ
- प्रोवाइडर स्वामी लुकअप, मॉडल दमन, प्रोवाइडर नीति या सार्वजनिक-कलाकृति मेटाडेटा
- मैनिफ़ेस्ट से निकला कोई भी अन्य उत्तर, जहाँ परिवर्तित मैनिफ़ेस्ट, इंस्टॉल किया गया इंडेक्स या लोड पथ अगली मेटाडेटा रीड पर दिखाई देना चाहिए
स्थायी इंस्टॉल किए गए Plugin इंडेक्स से मैनिफ़ेस्ट मेटाडेटा पुनर्निर्मित करने वाले कॉलर उस रजिस्ट्री को माँग पर पुनर्निर्मित करते हैं। इंस्टॉल किया गया इंडेक्स टिकाऊ स्रोत-प्लेन स्थिति है; यह कोई छिपा हुआ इन-प्रोसेस मेटाडेटा कैश नहीं है।
रजिस्ट्री मॉडल
लोड किए गए Plugin सीधे बेतरतीब कोर ग्लोबल में बदलाव नहीं करते। वे एक केंद्रीय
Plugin रजिस्ट्री (src/plugins/registry-types.ts में PluginRegistry) में पंजीकृत होते हैं,
जो Plugin रिकॉर्ड (पहचान, स्रोत, मूल, स्थिति, डायग्नोस्टिक) के साथ प्रत्येक क्षमता
की सरणियों को ट्रैक करती है: टूल, पुराने हुक और टाइप्ड हुक, चैनल, प्रोवाइडर,
Gateway RPC हैंडलर, HTTP रूट, CLI रजिस्ट्रार, पृष्ठभूमि सेवाएँ, Plugin-स्वामित्व वाले
कमांड और दर्जनों अन्य टाइप्ड प्रोवाइडर परिवार (वाक्, एम्बेडिंग, छवि/वीडियो/संगीत
जनरेशन, वेब फ़ेच/खोज, एजेंट हार्नेस, सत्र क्रियाएँ आदि)।
इसके बाद कोर सुविधाएँ Plugin मॉड्यूल से सीधे संवाद करने के बजाय उस रजिस्ट्री से पढ़ती हैं। इससे लोडिंग एकतरफ़ा रहती है:
- Plugin मॉड्यूल -> रजिस्ट्री पंजीकरण
- कोर रनटाइम -> रजिस्ट्री उपभोग
रखरखाव की दृष्टि से यह पृथक्करण महत्वपूर्ण है। इसका अर्थ है कि अधिकांश कोर सतहों को केवल एक एकीकरण बिंदु चाहिए: "रजिस्ट्री पढ़ें", न कि "प्रत्येक Plugin मॉड्यूल के लिए विशेष स्थिति बनाएँ"।
वार्तालाप बाइंडिंग कॉलबैक
वार्तालाप बाइंड करने वाले Plugin अनुमोदन का समाधान होने पर प्रतिक्रिया दे सकते हैं।
बाइंड अनुरोध स्वीकृत या अस्वीकृत होने के बाद कॉलबैक प्राप्त करने के लिए
api.onConversationBindingResolved(...) का उपयोग करें:
export default { id: "my-plugin", register(api) { api.onConversationBindingResolved(async (event) => { if (event.status === "approved") { // अब इस Plugin + वार्तालाप के लिए एक बाइंडिंग मौजूद है। console.log(event.binding?.conversationId); return; } // अनुरोध अस्वीकार कर दिया गया था; कोई भी स्थानीय लंबित स्थिति साफ़ करें। console.log(event.request.conversation.conversationId); }); },};कॉलबैक पेलोड फ़ील्ड:
status:"approved"या"denied"decision:"allow-once","allow-always"या"deny"binding: स्वीकृत अनुरोधों के लिए रिज़ॉल्व की गई बाइंडिंगrequest: मूल अनुरोध सारांश, अलग करने का संकेत, प्रेषक id और वार्तालाप मेटाडेटा
यह कॉलबैक केवल सूचना के लिए है। यह नहीं बदलता कि वार्तालाप बाइंड करने की अनुमति किसे है, और यह कोर अनुमोदन प्रबंधन पूरा होने के बाद चलता है।
प्रोवाइडर रनटाइम हुक
प्रोवाइडर Plugin की तीन परतें होती हैं:
- रनटाइम से पहले हल्के लुकअप के लिए मैनिफ़ेस्ट मेटाडेटा:
setup.providers[].envVars,providerAuthAliases,providerAuthChoicesऔरchannelConfigs। - कॉन्फ़िग-समय हुक:
catalogतथाapplyConfigDefaults। - रनटाइम हुक: प्रमाणीकरण, मॉडल रिज़ॉल्यूशन, स्ट्रीम रैपिंग, चिंतन स्तर, रीप्ले नीति और उपयोग एंडपॉइंट को कवर करने वाले 40+ वैकल्पिक हुक। हुक क्रम और उपयोग देखें।
OpenClaw अभी भी सामान्य एजेंट लूप, फ़ेलओवर, ट्रांसक्रिप्ट प्रबंधन और टूल नीति का स्वामी है। ये हुक संपूर्ण कस्टम इन्फ़रेंस ट्रांसपोर्ट की आवश्यकता के बिना प्रदाता-विशिष्ट व्यवहार के लिए एक्सटेंशन सतह हैं।
जब प्रदाता के पास env-आधारित क्रेडेंशियल हों, जिन्हें सामान्य
प्रमाणीकरण/स्थिति/मॉडल-पिकर पथों को Plugin रनटाइम लोड किए बिना देखना चाहिए, तब मैनिफ़ेस्ट setup.providers[].envVars का उपयोग करें।
जब एक प्रदाता आईडी को किसी अन्य प्रदाता आईडी के env vars, प्रमाणीकरण प्रोफ़ाइल,
कॉन्फ़िग-समर्थित प्रमाणीकरण और API-कुंजी ऑनबोर्डिंग विकल्प का पुनः उपयोग करना चाहिए, तब मैनिफ़ेस्ट providerAuthAliases
का उपयोग करें। जब ऑनबोर्डिंग/प्रमाणीकरण-विकल्प CLI सतहों को प्रदाता रनटाइम लोड किए बिना
प्रदाता की विकल्प आईडी, समूह लेबल और सरल एक-फ़्लैग प्रमाणीकरण वायरिंग ज्ञात होनी चाहिए,
तब मैनिफ़ेस्ट providerAuthChoices का उपयोग करें। ऑपरेटर के लिए ऑनबोर्डिंग लेबल या OAuth
क्लाइंट-आईडी/क्लाइंट-सीक्रेट सेटअप vars जैसे संकेतों हेतु प्रदाता रनटाइम
envVars बनाए रखें।
env-संचालित चैनल सेटअप और प्रमाणीकरण का वर्णन उसके स्वामी
channelConfigs.<id>.schema और सेटअप डिस्क्रिप्टर के माध्यम से करें।
हुक क्रम और उपयोग
मॉडल/प्रदाता Plugins के लिए, OpenClaw लगभग इस क्रम में हुक कॉल करता है।
"कब उपयोग करें" कॉलम त्वरित निर्णय मार्गदर्शिका है।
केवल संगतता के लिए रखे गए वे प्रदाता फ़ील्ड, जिन्हें OpenClaw अब कॉल नहीं करता, जैसे
ProviderPlugin.capabilities और suppressBuiltInModel, जानबूझकर
यहाँ सूचीबद्ध नहीं हैं।
| Hook | यह क्या करता है | कब उपयोग करें |
|---|---|---|
catalog |
models.json जनरेशन के दौरान प्रदाता कॉन्फ़िगरेशन को models.providers में प्रकाशित करता है |
प्रदाता किसी कैटलॉग या आधार URL के डिफ़ॉल्ट का स्वामी है |
applyConfigDefaults |
कॉन्फ़िगरेशन मटेरियलाइज़ेशन के दौरान प्रदाता-स्वामित्व वाले वैश्विक कॉन्फ़िगरेशन डिफ़ॉल्ट लागू करता है | डिफ़ॉल्ट प्रमाणीकरण मोड, एनवायरनमेंट या प्रदाता मॉडल-फ़ैमिली के अर्थ-विज्ञान पर निर्भर हैं |
| (अंतर्निहित मॉडल लुकअप) | OpenClaw पहले सामान्य रजिस्ट्री/कैटलॉग पथ आज़माता है | (Plugin हुक नहीं है) |
normalizeModelId |
लुकअप से पहले लेगेसी या प्रीव्यू मॉडल-ID उपनामों को सामान्यीकृत करता है | कैनोनिकल मॉडल रिज़ॉल्यूशन से पहले उपनामों की सफ़ाई का स्वामी प्रदाता है |
normalizeTransport |
सामान्य मॉडल असेंबली से पहले प्रदाता-फ़ैमिली के api / baseUrl को सामान्यीकृत करता है |
समान ट्रांसपोर्ट फ़ैमिली में कस्टम प्रदाता ID की ट्रांसपोर्ट सफ़ाई का स्वामी प्रदाता है |
normalizeConfig |
रनटाइम/प्रदाता रिज़ॉल्यूशन से पहले models.providers.<id> को सामान्यीकृत करता है |
प्रदाता को ऐसी कॉन्फ़िगरेशन सफ़ाई चाहिए जो Plugin में रहनी चाहिए; बंडल किए गए Google-फ़ैमिली हेल्पर समर्थित Google कॉन्फ़िगरेशन प्रविष्टियों को भी बैकस्टॉप करते हैं |
applyNativeStreamingUsageCompat |
कॉन्फ़िगरेशन प्रदाताओं पर नेटिव स्ट्रीमिंग-उपयोग संगतता पुनर्लेखन लागू करता है | प्रदाता को एंडपॉइंट-संचालित नेटिव स्ट्रीमिंग उपयोग मेटाडेटा सुधार चाहिए |
resolveConfigApiKey |
रनटाइम प्रमाणीकरण लोड होने से पहले कॉन्फ़िगरेशन प्रदाताओं के लिए एनवायरनमेंट-मार्कर प्रमाणीकरण रिज़ॉल्व करता है | प्रदाता अपने स्वयं के एनवायरनमेंट-मार्कर API-कुंजी रिज़ॉल्यूशन हुक उपलब्ध कराते हैं |
resolveSyntheticAuth |
प्लेनटेक्स्ट को स्थायी किए बिना स्थानीय/स्वयं-होस्टेड या कॉन्फ़िगरेशन-समर्थित प्रमाणीकरण दिखाता है | प्रदाता किसी सिंथेटिक/स्थानीय क्रेडेंशियल मार्कर के साथ काम कर सकता है |
resolveExternalAuthProfiles |
प्रदाता-स्वामित्व वाली बाहरी प्रमाणीकरण प्रोफ़ाइल ओवरले करता है; CLI/ऐप-स्वामित्व वाले क्रेडेंशियल के लिए डिफ़ॉल्ट persistence, runtime-only है |
प्रदाता कॉपी किए गए रीफ़्रेश टोकन स्थायी किए बिना बाहरी प्रमाणीकरण क्रेडेंशियल का पुनः उपयोग करता है; मैनिफ़ेस्ट में contracts.externalAuthProviders घोषित करें |
shouldDeferSyntheticProfileAuth |
एनवायरनमेंट/कॉन्फ़िगरेशन-समर्थित प्रमाणीकरण के पीछे संग्रहीत सिंथेटिक प्रोफ़ाइल प्लेसहोल्डर की प्राथमिकता घटाता है | प्रदाता ऐसी सिंथेटिक प्लेसहोल्डर प्रोफ़ाइल संग्रहीत करता है जिन्हें प्राथमिकता नहीं मिलनी चाहिए |
resolveDynamicModel |
प्रदाता-स्वामित्व वाले उन मॉडल ID के लिए सिंक्रोनस फ़ॉलबैक जो अभी स्थानीय रजिस्ट्री में नहीं हैं | प्रदाता मनमाने अपस्ट्रीम मॉडल ID स्वीकार करता है |
prepareDynamicModel |
एसिंक्रोनस वार्म-अप, फिर resolveDynamicModel दोबारा चलता है |
अज्ञात ID रिज़ॉल्व करने से पहले प्रदाता को नेटवर्क मेटाडेटा चाहिए |
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 की जाँच करते हैं, फिर अन्य हुक-सक्षम प्रोवाइडर Plugins पर आगे बढ़ते हैं,
जब तक उनमें से कोई वास्तव में मॉडल आईडी या ट्रांसपोर्ट/कॉन्फ़िगरेशन को नहीं बदल देता। इससे
कॉलर को यह जाने बिना कि रीराइट का स्वामी कौन-सा बंडल किया गया 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: "उदाहरण प्रॉक्सी", 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: "स्वचालित" }], }, }; }, }, 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); },});अंतर्निहित उदाहरण
बंडल किए गए प्रोवाइडर Plugins प्रत्येक विक्रेता की कैटलॉग, प्रमाणीकरण, चिंतन,
रीप्ले और उपयोग संबंधी आवश्यकताओं के अनुरूप ऊपर दिए गए हुक संयोजित करते हैं। प्रामाणिक हुक सेट
प्रत्येक 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
सामान्य SDK के बजाय Anthropic Plugin के सार्वजनिक
api.ts / contract-api.ts सीमांत
(wrapAnthropicProviderStream, resolveAnthropicBetas,
resolveAnthropicFastMode, resolveAnthropicServiceTier) के भीतर रहते हैं।
रनटाइम सहायक
Plugins api.runtime के माध्यम से चुने हुए कोर सहायकों तक पहुँच सकते हैं। TTS के लिए:
const clip = await api.runtime.tts.textToSpeech({ text: "OpenClaw की ओर से नमस्ते", cfg: api.config,}); const result = await api.runtime.tts.textToSpeechTelephony({ text: "OpenClaw की ओर से नमस्ते", cfg: api.config,}); const voices = await api.runtime.tts.listVoices({ provider: "elevenlabs", cfg: api.config,});टिप्पणियाँ:
textToSpeechफ़ाइल/वॉइस-नोट सतहों के लिए सामान्य कोर TTS आउटपुट पेलोड लौटाता है।- कोर
ttsकॉन्फ़िगरेशन और प्रोवाइडर चयन का उपयोग करता है। - PCM ऑडियो बफ़र + सैंपल दर लौटाता है। Plugins को प्रोवाइडरों के लिए पुनः सैंपल/एनकोड करना होगा।
listVoicesप्रत्येक प्रोवाइडर के लिए वैकल्पिक है। विक्रेता-स्वामित्व वाले वॉइस चयनकर्ताओं या सेटअप प्रवाहों के लिए इसका उपयोग करें।- कोर प्रोवाइडर
listVoicesहुक को समाधान की गई अनुरोध समय-सीमा देता है; प्रोवाइडर-विशिष्ट टाइमआउट सेटिंग इसे ओवरराइड कर सकती हैं। - वॉइस सूचियों में प्रोवाइडर-सजग चयनकर्ताओं के लिए स्थान-विशेष, लिंग और व्यक्तित्व टैग जैसे अधिक समृद्ध मेटाडेटा शामिल हो सकते हैं।
- OpenAI और ElevenLabs वर्तमान में टेलीफ़ोनी का समर्थन करते हैं। Microsoft नहीं करता।
Plugins api.registerSpeechProvider(...) के माध्यम से स्पीच प्रोवाइडर भी पंजीकृत कर सकते हैं।
api.registerSpeechProvider({ id: "acme-speech", label: "Acme स्पीच", 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 टेक्स्ट, स्पीच, इमेज और भविष्य के मीडिया प्रोवाइडरों का स्वामित्व ले सकता है।
इमेज/ऑडियो/वीडियो समझ के लिए, Plugins सामान्य कुंजी/मान संग्रह के बजाय एक टाइप किया हुआ मीडिया-समझ प्रोवाइडर पंजीकृत करते हैं:
api.registerMediaUnderstandingProvider({ id: "google", capabilities: ["image", "audio", "video"], describeImage: async (req) => ({ text: "..." }), transcribeAudio: async (req) => ({ text: "..." }), describeVideo: async (req) => ({ text: "..." }),});टिप्पणियाँ:
- ऑर्केस्ट्रेशन, फ़ॉलबैक, कॉन्फ़िगरेशन और चैनल वायरिंग को कोर में रखें।
- विक्रेता व्यवहार को प्रोवाइडर Plugin में रखें।
- योगात्मक विस्तार टाइप किया हुआ रहना चाहिए: नई वैकल्पिक विधियाँ, नए वैकल्पिक परिणाम फ़ील्ड, नई वैकल्पिक क्षमताएँ।
- वीडियो जनरेशन पहले से इसी पैटर्न का पालन करता है:
- कोर क्षमता अनुबंध और रनटाइम सहायक का स्वामी है
- विक्रेता Plugins
api.registerVideoGenerationProvider(...)पंजीकृत करते हैं - फ़ीचर/चैनल Plugins
api.runtime.videoGeneration.*का उपयोग करते हैं
मीडिया-समझ रनटाइम सहायकों के लिए, Plugins यह कॉल कर सकते हैं:
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: "मुद्रित फ़ील्ड को सत्य का स्रोत मानें।" }, ], instructions: "इकाइयाँ और खोजने योग्य टैग लौटाएँ।", schemaName: "example.evidence", jsonSchema: { type: "object", properties: { entities: { type: "array", items: { type: "string" } }, tags: { type: "array", items: { type: "string" } }, }, }, cfg: api.config,});ऑडियो ट्रांसक्रिप्शन के लिए, Plugins मीडिया-समझ रनटाइम या पुराने STT उपनाम में से किसी एक का उपयोग कर सकते हैं:
const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ filePath: "/tmp/inbound-audio.ogg", cfg: api.config, // जब MIME का विश्वसनीय रूप से अनुमान न लगाया जा सके, तब वैकल्पिक: mime: "audio/ogg",});टिप्पणियाँ:
api.runtime.mediaUnderstanding.*इमेज/ऑडियो/वीडियो समझ के लिए पसंदीदा साझा सतह है।extractStructuredWithModel(...)सीमित प्रोवाइडर-स्वामित्व वाले, इमेज-प्रथम निष्कर्षण के लिए Plugin-सामना करने वाला सीमांत है। कम-से-कम एक इमेज इनपुट शामिल करें; टेक्स्ट इनपुट पूरक संदर्भ हैं। उत्पाद Plugins अपने रूट और स्कीमा के स्वामी हैं, जबकि OpenClaw प्रोवाइडर/रनटाइम सीमा का स्वामी है।- कोर मीडिया-समझ ऑडियो कॉन्फ़िगरेशन (
tools.media.audio) और प्रोवाइडर फ़ॉलबैक क्रम का उपयोग करता है। - जब कोई ट्रांसक्रिप्शन आउटपुट उत्पन्न नहीं होता (उदाहरण के लिए छोड़ा गया/असमर्थित इनपुट), तब
{ text: undefined }लौटाता है।
Plugins api.runtime.subagent के माध्यम से पृष्ठभूमि सबएजेंट रन भी शुरू कर सकते हैं:
const result = await api.runtime.subagent.run({ sessionKey: "agent:main:subagent:search-helper", message: "इस क्वेरी को केंद्रित अनुवर्ती खोजों में विस्तृत करें।", toolsAlsoAllow: ["my_plugin_progress"], provider: "openai", model: "gpt-4.1-mini", deliver: false,});टिप्पणियाँ:
providerऔरmodelप्रत्येक रन के वैकल्पिक ओवरराइड हैं, स्थायी सत्र परिवर्तन नहीं।toolsAlsoAllowकॉल करने वाले Plugin द्वारा पंजीकृत सटीक, विशिष्ट स्वामित्व वाले टूल नाम स्वीकार करता है। कोर और अस्पष्ट नाम अस्वीकार किए जाते हैं। यह सामान्य प्रोफ़ाइल के अतिरिक्त है, लेकिन ऑपरेटर की अनुमति-सूचियाँ और निषेध प्रामाणिक बने रहते हैं।- OpenClaw केवल विश्वसनीय कॉलरों के लिए उन ओवरराइड फ़ील्ड का सम्मान करता है।
- Plugin-स्वामित्व वाले फ़ॉलबैक रन के लिए, ऑपरेटरों को
plugins.entries.<id>.subagent.allowModelOverride: trueके साथ स्पष्ट रूप से सहमति देनी होगी। - विश्वसनीय Plugins को विशिष्ट कैनोनिकल
provider/modelलक्ष्यों तक सीमित करने के लिएplugins.entries.<id>.subagent.allowedModels, या किसी भी लक्ष्य को स्पष्ट रूप से अनुमति देने के लिए"*"का उपयोग करें। - अविश्वसनीय Plugin सबएजेंट रन फिर भी काम करते हैं, लेकिन ओवरराइड अनुरोध चुपचाप फ़ॉलबैक करने के बजाय अस्वीकार किए जाते हैं।
- Plugin द्वारा बनाए गए सबएजेंट सत्रों को बनाने वाले Plugin की आईडी से टैग किया जाता है। फ़ॉलबैक
api.runtime.subagent.deleteSession(...)केवल उन स्वामित्व वाले सत्रों को हटा सकता है; मनमाना सत्र हटाने के लिए अब भी व्यवस्थापक-स्कोप वाला Gateway अनुरोध आवश्यक है।
वेब खोज के लिए, Plugins एजेंट टूल वायरिंग में सीधे पहुँचने के बजाय साझा रनटाइम सहायक का उपयोग कर सकते हैं:
const providers = api.runtime.webSearch.listProviders({ config: api.config,}); const result = await api.runtime.webSearch.search({ config: api.config, args: { query: "OpenClaw Plugin रनटाइम सहायक", count: 5, },});Plugins api.registerWebSearchProvider(...) के माध्यम से वेब-खोज प्रोवाइडर भी
पंजीकृत कर सकते हैं।
टिप्पणियाँ:
- प्रोवाइडर चयन, क्रेडेंशियल समाधान और साझा अनुरोध अर्थविज्ञान को कोर में रखें।
- विक्रेता-विशिष्ट खोज ट्रांसपोर्ट के लिए वेब-खोज प्रोवाइडरों का उपयोग करें।
api.runtime.webSearch.*उन फ़ीचर/चैनल Plugins के लिए पसंदीदा साझा सतह है जिन्हें एजेंट टूल रैपर पर निर्भर हुए बिना खोज व्यवहार चाहिए।
api.runtime.imageGeneration
const result = await api.runtime.imageGeneration.generate({ config: api.config, args: { prompt: "एक मित्रवत लॉब्स्टर शुभंकर", size: "1024x1024" },}); const providers = api.runtime.imageGeneration.listProviders({ config: api.config,});generate(...): कॉन्फ़िगर की गई इमेज-जेनरेशन प्रदाता शृंखला का उपयोग करके एक इमेज जनरेट करें।listProviders(...): उपलब्ध इमेज-जेनरेशन प्रदाताओं और उनकी क्षमताओं की सूची दिखाएँ।
Gateway HTTP रूट
Plugins, 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: Gateway HTTP सर्वर के अंतर्गत रूट पथ।auth: आवश्यक,"gateway"या"plugin"। सामान्य Gateway प्रमाणीकरण आवश्यक बनाने के लिए"gateway"या Plugin-प्रबंधित प्रमाणीकरण/Webhook सत्यापन के लिए"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"रूट को ऑपरेटर रनटाइम स्कोप अपने-आप नहीं मिलते। वे Plugin-प्रबंधित Webhook/हस्ताक्षर सत्यापन के लिए हैं, विशेषाधिकार-प्राप्त Gateway सहायक कॉल के लिए नहीं।auth: "gateway"रूट Gateway अनुरोध रनटाइम स्कोप के भीतर चलते हैं। डिफ़ॉल्ट सतह (gatewayRuntimeScopeSurface: "write-default") जानबूझकर सीमित है:- साझा-सीक्रेट बेयरर प्रमाणीकरण (
gateway.auth.mode = "token"/"password") और किसी भी गैर-विश्वसनीय-प्रॉक्सी प्रमाणीकरण विधि को केवल एकoperator.writeस्कोप मिलता है, भले ही कॉलरx-openclaw-scopesभेजे - स्पष्ट
x-openclaw-scopesहेडर के बिनाtrusted-proxyकॉलर भी पुरानी केवल-operator.writeसतह बनाए रखते हैं x-openclaw-scopesभेजने वालेtrusted-proxyकॉलर को इसके बजाय घोषित स्कोप मिलते हैं- पहचान-युक्त प्रमाणीकरण मोड के लिए
x-openclaw-scopesका हमेशा सम्मान करने हेतु कोई रूटgatewayRuntimeScopeSurface: "trusted-operator"चुन सकता है (हेडर अनुपस्थित होने पर पूर्ण CLI डिफ़ॉल्ट स्कोप सेट का उपयोग किया जाता है)
- साझा-सीक्रेट बेयरर प्रमाणीकरण (
auth: "gateway"रूट द्वारा समर्थित सैंडबॉक्स किए गए बाहरी Control UI टैब, केवल प्रमाणित बूटस्ट्रैप द्वारा जारी अल्पकालिक हस्ताक्षरित कुकी अनुदान का उपयोग करते हैं; Plugin-प्रमाणीकरण टैब अपना सीधा iframe पथ बनाए रखते हैं। माउंट करने से पहले, पैरेंट उसी अपारदर्शी सैंडबॉक्स में रूट-स्वामित्व वाली जाँच चलाता है और ब्राउज़र की गोपनीयता नीति द्वारा कुकी अवरुद्ध होने पर फ़ेल-क्लोज़ करता है। अनुदान स्वामी Plugin, मेल खाने वाले रूट रूट और वर्तमान प्रमाणीकरण जनरेशन से बँधा होता है; इसका प्रक्रिया-यादृच्छिक कुकी नाम समान होस्ट के विश्वसनीय Gateways को एक-दूसरे को अधिलेखित करने से रोकता है, लेकिन कुकी कभी भी TCP पोर्ट को अलग नहीं करती। इसलिए Gateway होस्टनेम एक क्रेडेंशियल सीमा है: उस होस्टनेम पर अलग-अलग पोर्ट सहित, परस्पर अविश्वसनीय सेवाओं को सह-होस्ट न करें। रूट डिस्पैच किसी अन्य Plugin के स्वामित्व वाले नेस्टेड रूट के विरुद्ध पुनः उपयोग को अस्वीकार करता है। चूँकि कुकी के संदर्भ में सैंडबॉक्स वंशज क्रॉस-साइट होते हैं, इसलिए अनुदान केवलoperator.readके साथGETऔरHEADस्वीकार करता है; म्यूटेशन और WebSocket अपग्रेड स्पष्ट Gateway-प्रमाणित सतहों पर बने रहते हैं। कुकी जानबूझकर CHIPS का उपयोग नहीं कर सकती: वर्तमान ब्राउज़र विभाजन कुंजी में क्रॉस-साइट-पूर्वज बिट शामिल करते हैं, इसलिए नेस्टेड अपारदर्शी सैंडबॉक्स फ़्रेम समान-रूट एसेट की पहुँच खो देंगे। कुकी के लिए सुरक्षित कॉन्टेक्स्ट और क्रॉस-साइट कुकी हेतु ब्राउज़र अनुमति आवश्यक है, इसलिए Gateway-प्रमाणीकरण वाले बाहरी टैब सामान्य-HTTP LAN मूल पर या तृतीय-पक्ष कुकी पूर्णतः अवरुद्ध होने पर उपलब्ध नहीं होते; संगत कुकी नीति के साथ HTTPS/Tailscale Serve या ब्राउज़र-विश्वसनीय लूपबैक का उपयोग करें।- अनुदान Gateway बेयरर-टोकन के प्रकटीकरण और आकस्मिक रूट/स्कोप पुनः उपयोग को रोकता है; यह नेटिव Plugins के बीच सुरक्षा सीमा नहीं बनाता। नेटिव Plugin कोड और उसके द्वारा प्रदान की जाने वाली UI सामग्री उसी विश्वसनीय इन-प्रोसेस Plugin सीमा का हिस्सा बने रहते हैं।
- व्यावहारिक नियम: यह न मानें कि Gateway-प्रमाणीकरण वाला Plugin रूट अप्रत्यक्ष एडमिन सतह है। यदि आपके रूट को केवल-एडमिन व्यवहार चाहिए, तो
trusted-operatorस्कोप सतह चुनें, पहचान-युक्त प्रमाणीकरण मोड आवश्यक बनाएँ और स्पष्टx-openclaw-scopesहेडर अनुबंध का दस्तावेज़ीकरण करें। - रूट मिलान और प्रमाणीकरण के बाद, सामान्य हैंडलर Gateway रूट-वर्क प्रवेश में भाग लेते हैं। तैयार हो रहा या पुनः आरंभ हो रहा Gateway हैंडलर को चलाने से पहले
503लौटाता है। इसका सीमित अपवाद मैनिफ़ेस्ट-अधिकृतauth: "gateway"रूट है, जो रूट-विशिष्टtrusted-operatorसतह भी चुनता है; वह पहुँच योग्य रहता है, ताकि निलंबन नियंत्रण डिस्पैच अटक न जाए, जबकि उसी Plugin के सामान्य सहोदर रूट प्रवेश सीमा के पीछे रहते हैं। WebSockethandleUpgradeस्वामित्व समान परमाण्विक प्रवेश सीमा का उपयोग करता है; हैंडलर द्वारा सॉकेट स्वीकार किए जाने के बाद, सॉकेट का आगामी जीवनकाल Plugin-स्वामित्व वाला होता है और इस सीमा द्वारा ट्रैक नहीं किया जाता।
Plugin SDK इंपोर्ट पथ
नए Plugins बनाते समय एकल openclaw/plugin-sdk रूट
बैरल के बजाय संकरे SDK उपपथों का उपयोग करें। मुख्य उपपथ:
| उपपथ | उद्देश्य |
|---|---|
openclaw/plugin-sdk/plugin-entry |
Plugin पंजीकरण प्रिमिटिव |
openclaw/plugin-sdk/channel-core |
चैनल एंट्री/बिल्ड सहायक |
openclaw/plugin-sdk/core |
सामान्य साझा सहायक और व्यापक अनुबंध |
चैनल Plugins संकरे सीम की एक श्रेणी में से चुनते हैं — 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 अनुबंध
पर समेकित करना चाहिए। चैनल Plugins देखें।
रनटाइम और कॉन्फ़िगरेशन सहायक मेल खाते केंद्रित *-runtime उपपथों के अंतर्गत रहते हैं
(approval-runtime, agent-runtime, lazy-runtime, directory-runtime,
text-runtime, runtime-store, system-event-runtime, heartbeat-runtime,
channel-activity-runtime, आदि)। व्यापक config-runtime संगतता बैरल के बजाय
config-contracts, plugin-config-runtime, runtime-config-snapshot, और config-mutation
को प्राथमिकता दें।
रिपॉज़िटरी-आंतरिक एंट्री पॉइंट (प्रत्येक बंडल किए गए Plugin पैकेज रूट के अनुसार):
index.js— बंडल किए गए Plugin की एंट्रीapi.js— सहायक/टाइप बैरलruntime-api.js— केवल-रनटाइम बैरलsetup-entry.js— सेटअप Plugin एंट्री
बाहरी Plugins को केवल openclaw/plugin-sdk/* उपपथ इंपोर्ट करने चाहिए। कोर या किसी अन्य Plugin से
किसी दूसरे Plugin पैकेज का src/* कभी इंपोर्ट न करें।
फ़साड-लोड किए गए एंट्री पॉइंट उपलब्ध होने पर सक्रिय रनटाइम कॉन्फ़िगरेशन स्नैपशॉट को प्राथमिकता
देते हैं, फिर डिस्क पर हल की गई कॉन्फ़िगरेशन फ़ाइल का उपयोग करते हैं।
image-generation, media-understanding,
और speech जैसे क्षमता-विशिष्ट उपपथ मौजूद हैं, क्योंकि बंडल किए गए Plugins आज उनका उपयोग करते हैं। वे
स्वचालित रूप से दीर्घकालिक स्थिर बाहरी अनुबंध नहीं हैं — उन पर निर्भर करते समय संबंधित SDK
संदर्भ पृष्ठ देखें।
संदेश टूल स्कीमा
प्रतिक्रियाओं, रीड और पोल जैसे गैर-संदेश प्रिमिटिव के लिए चैनल-विशिष्ट describeMessageTool(...) स्कीमा
योगदान का स्वामित्व Plugins के पास होना चाहिए।
साझा प्रेषण प्रस्तुति को प्रदाता-नेटिव बटन, कंपोनेंट, ब्लॉक या कार्ड फ़ील्ड के बजाय
सामान्य MessagePresentation अनुबंध का उपयोग करना चाहिए।
अनुबंध, फ़ॉलबैक नियम, प्रदाता मैपिंग और Plugin लेखक चेकलिस्ट के लिए
संदेश प्रस्तुति देखें।
प्रेषण-सक्षम Plugins संदेश क्षमताओं के माध्यम से घोषित करते हैं कि वे क्या रेंडर कर सकते हैं:
- अर्थपूर्ण प्रस्तुति ब्लॉक (
text,context,divider,chart,table,buttons,select) के लिएpresentation - पिन की गई डिलीवरी अनुरोधों के लिए
delivery-pin
कोर तय करता है कि प्रस्तुति को नेटिव रूप से रेंडर करना है या उसे टेक्स्ट में बदलना है। सामान्य संदेश टूल से प्रदाता-नेटिव UI वैकल्पिक मार्ग उपलब्ध न कराएँ। पुरानी नेटिव स्कीमा के लिए बहिष्कृत SDK सहायक मौजूदा तृतीय-पक्ष Plugins के लिए निर्यात किए जाते रहेंगे, लेकिन नए Plugins को उनका उपयोग नहीं करना चाहिए।
चैनल लक्ष्य समाधान
चैनल Plugins के पास चैनल-विशिष्ट लक्ष्य अर्थविज्ञान का स्वामित्व होना चाहिए। साझा आउटबाउंड होस्ट को सामान्य रखें और प्रदाता नियमों के लिए मैसेजिंग अडैप्टर सतह का उपयोग करें:
messaging.inferTargetChatType({ to })तय करता है कि डायरेक्टरी लुकअप से पहले सामान्यीकृत लक्ष्य कोdirect,group, याchannelके रूप में माना जाना चाहिए।messaging.targetResolver.looksLikeId(raw, normalized)कोर को बताता है कि किसी इनपुट को डायरेक्टरी खोज के बजाय सीधे आईडी-जैसे समाधान पर जाना चाहिए या नहीं।messaging.targetResolver.reservedLiteralsउन स्वतंत्र शब्दों को सूचीबद्ध करता है जो उस प्रदाता के लिए चैनल/सेशन संदर्भ हैं। समाधान आरक्षित लिटरल अस्वीकार करने से पहले कॉन्फ़िगर की गई डायरेक्टरी प्रविष्टियों को बनाए रखता है, फिर डायरेक्टरी में मिलान न मिलने पर फ़ेल-क्लोज़ करता है।messaging.targetResolver.resolveTarget(...)तब Plugin फ़ॉलबैक होता है, जब सामान्यीकरण या डायरेक्टरी में मिलान न मिलने के बाद कोर को अंतिम प्रदाता-स्वामित्व वाले समाधान की आवश्यकता होती है।messaging.resolveOutboundSessionRoute(...)लक्ष्य हल हो जाने के बाद प्रदाता-विशिष्ट सेशन रूट निर्माण का स्वामित्व रखता है।
अनुशंसित विभाजन:
- पीयर/ग्रुप खोजने से पहले होने वाले श्रेणी निर्णयों के लिए
inferTargetChatTypeका उपयोग करें। - “इसे स्पष्ट/नेटिव लक्ष्य आईडी मानें” जाँच के लिए
looksLikeIdका उपयोग करें। - प्रदाता-विशिष्ट सामान्यीकरण फ़ॉलबैक के लिए
resolveTargetका उपयोग करें, व्यापक डायरेक्टरी खोज के लिए नहीं। - चैट आईडी, थ्रेड आईडी, JID, हैंडल और रूम आईडी जैसी प्रदाता-नेटिव आईडी को सामान्य SDK
फ़ील्ड में नहीं, बल्कि
targetमानों या प्रदाता-विशिष्ट पैरामीटर में रखें।
कॉन्फ़िगरेशन-समर्थित डायरेक्टरियाँ
कॉन्फ़िगरेशन से डायरेक्टरी प्रविष्टियाँ प्राप्त करने वाले Plugins को वह तर्क
Plugin में रखना चाहिए और
openclaw/plugin-sdk/directory-runtime के साझा सहायकों का पुनः उपयोग करना चाहिए।
इसका उपयोग तब करें, जब किसी चैनल को निम्न जैसे कॉन्फ़िगरेशन-समर्थित पीयर/ग्रुप चाहिए:
- अनुमति-सूची द्वारा संचालित DM पीयर
- कॉन्फ़िगर किए गए चैनल/ग्रुप मैप
- अकाउंट-स्कोप वाले स्थिर डायरेक्टरी फ़ॉलबैक
directory-runtime में साझा सहायक केवल सामान्य ऑपरेशन संभालते हैं:
- क्वेरी फ़िल्टरिंग
- सीमा लागू करना
- डुप्लिकेट हटाने/सामान्यीकरण के सहायक
ChannelDirectoryEntry[]बनाना
चैनल-विशिष्ट अकाउंट निरीक्षण और आईडी सामान्यीकरण को Plugin कार्यान्वयन में रहना चाहिए।
प्रदाता कैटलॉग
प्रदाता Plugins, registerProvider({ catalog: { run(...) { ... } } }) के साथ अनुमान के लिए मॉडल कैटलॉग
परिभाषित कर सकते हैं।
catalog.run(...) वही आकार लौटाता है जिसे OpenClaw
models.providers में लिखता है:
{ provider }एक प्रदाता प्रविष्टि के लिए{ providers }एकाधिक प्रदाता प्रविष्टियों के लिए
जब Plugin प्रदाता-विशिष्ट मॉडल आईडी, आधार URL डिफ़ॉल्ट या प्रमाणीकरण-प्रतिबंधित मॉडल मेटाडेटा का स्वामी हो, तब catalog का उपयोग करें।
catalog.order यह नियंत्रित करता है कि Plugin का कैटलॉग OpenClaw के अंतर्निहित निहित प्रदाताओं के सापेक्ष कब मर्ज होता है:
simple: सामान्य API-कुंजी या परिवेश-संचालित प्रदाताprofile: प्रमाणीकरण प्रोफ़ाइल मौजूद होने पर दिखाई देने वाले प्रदाताpaired: एकाधिक संबंधित प्रदाता प्रविष्टियाँ संश्लेषित करने वाले प्रदाताlate: अन्य निहित प्रदाताओं के बाद अंतिम चरण
कुंजी टकराव होने पर बाद के प्रदाता प्रभावी होते हैं, इसलिए plugins समान प्रदाता आईडी वाली अंतर्निहित प्रदाता प्रविष्टि को जानबूझकर ओवरराइड कर सकते हैं।
Plugins api.registerModelCatalogProvider({ provider, kinds, staticCatalog, liveCatalog }) के माध्यम से केवल-पढ़ने योग्य मॉडल पंक्तियाँ भी प्रकाशित कर सकते हैं। यह सूची/सहायता/चयनकर्ता सतहों के लिए भावी मार्ग है और text, voice, image_generation, video_generation, और music_generation पंक्तियों का समर्थन करता है। प्रदाता plugins अब भी लाइव एंडपॉइंट कॉल, टोकन विनिमय और विक्रेता प्रतिक्रिया मैपिंग के स्वामी हैं; कोर सामान्य पंक्ति आकार, स्रोत लेबल और मीडिया टूल सहायता स्वरूपण का स्वामी है। मीडिया-जनरेशन प्रदाता पंजीकरण defaultModel, models, और capabilities से स्थिर कैटलॉग पंक्तियाँ स्वचालित रूप से संश्लेषित करते हैं।
संगतता:
discoveryअभी भी विरासती उपनाम के रूप में काम करता है, लेकिन अप्रचलन चेतावनी देता है- यदि
catalogऔरdiscoveryदोनों पंजीकृत हैं, तो OpenClawcatalogका उपयोग करता है और चेतावनी देता है augmentModelCatalogअप्रचलित है; बंडल किए गए प्रदाताओं कोregisterModelCatalogProviderके माध्यम से पूरक पंक्तियाँ प्रकाशित करनी चाहिए
केवल-पढ़ने योग्य चैनल निरीक्षण
यदि आपका Plugin कोई चैनल पंजीकृत करता है, तो resolveAccount(...) के साथ plugin.config.inspectAccount(cfg, accountId) लागू करना बेहतर है।
कारण:
resolveAccount(...)रनटाइम मार्ग है। यह मान सकता है कि क्रेडेंशियल पूरी तरह साकार हो चुके हैं और आवश्यक सीक्रेट अनुपलब्ध होने पर तुरंत विफल हो सकता है।openclaw status,openclaw status --all,openclaw channels status,openclaw channels resolve, और डॉक्टर/कॉन्फ़िगरेशन सुधार प्रवाह जैसे केवल-पढ़ने योग्य कमांड मार्गों को केवल कॉन्फ़िगरेशन का वर्णन करने के लिए रनटाइम क्रेडेंशियल साकार करने की आवश्यकता नहीं होनी चाहिए।
अनुशंसित inspectAccount(...) व्यवहार:
- केवल वर्णनात्मक खाता स्थिति लौटाएँ।
enabledऔरconfiguredको सुरक्षित रखें।- प्रासंगिक होने पर क्रेडेंशियल स्रोत/स्थिति फ़ील्ड शामिल करें, जैसे:
tokenSource,tokenStatusbotTokenSource,botTokenStatusappTokenSource,appTokenStatussigningSecretSource,signingSecretStatus
- केवल केवल-पढ़ने योग्य उपलब्धता की रिपोर्ट करने के लिए आपको अपरिष्कृत टोकन मान लौटाने की आवश्यकता नहीं है। स्थिति-शैली कमांडों के लिए
tokenStatus: "available"(और उससे मेल खाता स्रोत फ़ील्ड) लौटाना पर्याप्त है। - जब कोई क्रेडेंशियल SecretRef के माध्यम से कॉन्फ़िगर हो, लेकिन वर्तमान कमांड मार्ग में अनुपलब्ध हो, तब
configured_unavailableका उपयोग करें।
इससे केवल-पढ़ने योग्य कमांड क्रैश होने या खाते को कॉन्फ़िगर नहीं किया गया बताने के बजाय "कॉन्फ़िगर किया गया है, लेकिन इस कमांड मार्ग में अनुपलब्ध है" की रिपोर्ट कर सकते हैं।
पैकेज पैक
किसी Plugin निर्देशिका में openclaw.extensions वाला package.json शामिल हो सकता है:
{ "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, विरासत में मिली वैश्विक npm इंस्टॉल सेटिंग्स को अनदेखा करके, परियोजना-स्थानीय npm install --omit=dev --ignore-scripts के साथ Plugin निर्भरताएँ इंस्टॉल करता है (कोई जीवनचक्र स्क्रिप्ट नहीं, रनटाइम पर कोई विकास निर्भरता नहीं)। Plugin निर्भरता वृक्षों को "शुद्ध JS/TS" रखें और postinstall बिल्ड की आवश्यकता वाले पैकेजों से बचें।
वैकल्पिक: openclaw.setupEntry किसी हल्के, केवल-सेटअप मॉड्यूल की ओर संकेत कर सकता है। जब OpenClaw को अक्षम चैनल Plugin के लिए सेटअप सतहों की आवश्यकता होती है, या जब कोई चैनल Plugin सक्षम लेकिन अभी भी अकॉन्फ़िगर हो, तो वह पूर्ण Plugin प्रविष्टि के बजाय setupEntry लोड करता है। जब आपकी मुख्य Plugin प्रविष्टि टूल, हुक या अन्य केवल-रनटाइम कोड भी जोड़ती है, तब इससे स्टार्टअप और सेटअप हल्के रहते हैं।
वैकल्पिक: openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen
किसी चैनल Plugin को Gateway के सुनना शुरू करने से पहले वाले स्टार्टअप चरण के दौरान उसी setupEntry मार्ग में शामिल कर सकता है, भले ही चैनल पहले से कॉन्फ़िगर हो।
इसका उपयोग केवल तभी करें जब setupEntry उस पूरी स्टार्टअप सतह को समाहित करता हो जिसका Gateway के सुनना शुरू करने से पहले मौजूद होना आवश्यक है। व्यवहार में इसका अर्थ है कि सेटअप प्रविष्टि को चैनल-स्वामित्व वाली प्रत्येक ऐसी क्षमता पंजीकृत करनी होगी जिस पर स्टार्टअप निर्भर है, जैसे:
- स्वयं चैनल पंजीकरण
- Gateway के सुनना शुरू करने से पहले उपलब्ध होना आवश्यक कोई भी HTTP रूट
- उसी अवधि में मौजूद होना आवश्यक कोई भी Gateway विधि, टूल या सेवा
यदि आपकी पूर्ण प्रविष्टि अब भी किसी आवश्यक स्टार्टअप क्षमता की स्वामी है, तो इस फ़्लैग को सक्षम न करें। Plugin को डिफ़ॉल्ट व्यवहार पर रखें और OpenClaw को स्टार्टअप के दौरान पूर्ण प्रविष्टि लोड करने दें।
बंडल किए गए चैनल केवल-सेटअप अनुबंध-सतह सहायक भी प्रकाशित कर सकते हैं, जिनसे कोर पूर्ण चैनल रनटाइम लोड होने से पहले परामर्श कर सकता है। वर्तमान सेटअप उन्नयन सतह है:
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
जब कोर को पूर्ण Plugin प्रविष्टि लोड किए बिना किसी विरासती एकल-खाता चैनल कॉन्फ़िगरेशन को channels.<id>.accounts.* में उन्नत करना होता है, तब वह उस सतह का उपयोग करता है। Matrix वर्तमान बंडल किया गया उदाहरण है: नामित खाते पहले से मौजूद होने पर यह केवल प्रमाणीकरण/बूटस्ट्रैप कुंजियों को किसी नामित उन्नत खाते में ले जाता है, और हमेशा accounts.default बनाने के बजाय कॉन्फ़िगर की गई गैर-मानक डिफ़ॉल्ट-खाता कुंजी को सुरक्षित रख सकता है।
वे सेटअप पैच एडाप्टर बंडल की गई अनुबंध-सतह खोज को आलसी बनाए रखते हैं। आयात समय हल्का रहता है; मॉड्यूल आयात पर बंडल किए गए चैनल स्टार्टअप में दोबारा प्रवेश करने के बजाय उन्नयन सतह केवल प्रथम उपयोग पर लोड होती है।
जब उन स्टार्टअप सतहों में Gateway RPC विधियाँ शामिल हों, तो उन्हें Plugin-विशिष्ट उपसर्ग पर रखें। कोर व्यवस्थापक नेमस्पेस (config.*, exec.approvals.*, wizard.*, update.*) आरक्षित रहते हैं और हमेशा operator.admin में हल होते हैं, भले ही कोई Plugin अधिक सीमित स्कोप का अनुरोध करे।
उदाहरण:
{ "name": "@scope/my-channel", "openclaw": { "extensions": ["./index.ts"], "setupEntry": "./setup-entry.ts", "startup": { "deferConfiguredChannelFullLoadUntilAfterListen": true } }}चैनल कैटलॉग मेटाडेटा
चैनल plugins openclaw.channel के माध्यम से सेटअप/खोज मेटाडेटा और openclaw.install के माध्यम से इंस्टॉल संकेत प्रदर्शित कर सकते हैं। इससे कोर कैटलॉग डेटा-मुक्त रहता है।
उदाहरण:
{ "name": "@openclaw/nextcloud-talk", "openclaw": { "extensions": ["./index.ts"], "channel": { "id": "nextcloud-talk", "label": "Nextcloud Talk", "selectionLabel": "Nextcloud Talk (स्वयं-होस्ट किया गया)", "docsPath": "/channels/nextcloud-talk", "docsLabel": "nextcloud-talk", "blurb": "Nextcloud Talk Webhook बॉट के माध्यम से स्वयं-होस्ट की गई चैट।", "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: दस्तावेज़ नेविगेशन सतहों के लिए चैनल को आंतरिक/निजी चिह्नित करता है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": {...} } } ] } होना चाहिए। पार्सर "entries" कुंजी के विरासती उपनामों के रूप में "packages" या "plugins" भी स्वीकार करता है।
जनरेट की गई चैनल कैटलॉग प्रविष्टियाँ और प्रदाता इंस्टॉल कैटलॉग प्रविष्टियाँ अपरिष्कृत openclaw.install ब्लॉक के साथ सामान्यीकृत इंस्टॉल-स्रोत तथ्य उजागर करती हैं। सामान्यीकृत तथ्य पहचानते हैं कि npm विनिर्देश सटीक संस्करण है या परिवर्तनशील चयनकर्ता, अपेक्षित अखंडता मेटाडेटा मौजूद है या नहीं, और स्थानीय स्रोत पथ भी उपलब्ध है या नहीं। कैटलॉग/पैकेज पहचान ज्ञात होने पर, यदि पार्स किया गया npm पैकेज नाम उस पहचान से अलग होता है, तो सामान्यीकृत तथ्य चेतावनी देते हैं। वे तब भी चेतावनी देते हैं जब defaultChoice अमान्य हो या अनुपलब्ध स्रोत की ओर संकेत करे, और जब वैध npm स्रोत के बिना npm अखंडता मेटाडेटा मौजूद हो। उपभोक्ताओं को installSource को एक योगात्मक वैकल्पिक फ़ील्ड मानना चाहिए ताकि हाथ से बनाई गई प्रविष्टियों और कैटलॉग शिम को इसे संश्लेषित न करना पड़े।
इससे ऑनबोर्डिंग और निदान Plugin रनटाइम आयात किए बिना स्रोत-प्लेन स्थिति समझा सकते हैं।
आधिकारिक बाहरी npm प्रविष्टियों को सटीक npmSpec और expectedIntegrity को प्राथमिकता देनी चाहिए। केवल पैकेज नाम और dist-tags अब भी संगतता के लिए काम करते हैं, लेकिन वे स्रोत-प्लेन चेतावनियाँ दिखाते हैं ताकि कैटलॉग मौजूदा plugins को तोड़े बिना पिन किए गए, अखंडता-जाँचे इंस्टॉल की ओर बढ़ सके। जब ऑनबोर्डिंग स्थानीय कैटलॉग पथ से इंस्टॉल करता है, तो वह source: "path" और जहाँ संभव हो कार्यक्षेत्र-सापेक्ष sourcePath वाली प्रबंधित Plugin Plugin अनुक्रमणिका प्रविष्टि रिकॉर्ड करता है। पूर्ण परिचालन लोड पथ plugins.load.paths में रहता है; इंस्टॉल रिकॉर्ड दीर्घकालिक कॉन्फ़िगरेशन में स्थानीय कार्यस्थान पथों की नकल करने से बचता है। इससे स्थानीय विकास इंस्टॉल स्रोत-प्लेन निदान में दिखाई देते हैं और अपरिष्कृत फ़ाइल-सिस्टम पथ उजागर करने की दूसरी सतह नहीं जुड़ती। स्थायी installed_plugin_index SQLite तालिका इंस्टॉल स्रोत की प्रामाणिक जानकारी है और Plugin रनटाइम मॉड्यूल लोड किए बिना रीफ़्रेश की जा सकती है। इसका installRecords मैप तब भी टिकाऊ रहता है जब Plugin मैनिफ़ेस्ट अनुपलब्ध या अमान्य हो; इसका plugins पेलोड पुनर्निर्माण योग्य मैनिफ़ेस्ट दृश्य है।
संदर्भ इंजन plugins
संदर्भ इंजन plugins अंतर्ग्रहण, संयोजन और 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, agentSessionKey: sessionKey, }), }; }, async compact() { return { ok: true, compacted: false }; }, }));}फ़ैक्टरी ctx निर्माण-समय आरंभीकरण के लिए वैकल्पिक config, agentDir, और workspaceDir
मान उपलब्ध कराती है।
होस्ट किसी गैर-लेगेसी इंजन के assemble() को कॉल करने से पहले पंजीकृत एसिंक्रोनस मेमोरी प्रॉम्प्ट तैयारी पूरी करता है। buildMemorySystemPromptAddition(...)
सिंक्रोनस रहता है और assemble() के सक्रिय रहने के दौरान उस अपरिवर्तनीय रन स्नैपशॉट को पढ़ता है।
दिए गए टूल और उद्धरण संदर्भ को बिना बदलाव के आगे भेजें, ताकि स्नैपशॉट
रन सीमाओं को पार न कर सके।
जब सक्रिय हार्नेस में एक स्थायी बैकएंड थ्रेड हो, तो 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, agentSessionKey: sessionKey, }), }; }, async compact(params) { return await delegateCompactionToRuntime(params); }, }));}नई क्षमता जोड़ना
जब किसी Plugin को ऐसे व्यवहार की आवश्यकता हो जो वर्तमान API में उपयुक्त न हो, तो निजी आंतरिक पहुँच से Plugin सिस्टम को बायपास न करें। अनुपलब्ध क्षमता जोड़ें।
अनुशंसित क्रम:
- कोर अनुबंध परिभाषित करें। तय करें कि साझा व्यवहार के किन हिस्सों का स्वामित्व कोर के पास होना चाहिए: नीति, फ़ॉलबैक, कॉन्फ़िगरेशन मर्ज, जीवनचक्र, चैनल-संबंधी सिमैंटिक्स और रनटाइम हेल्पर का आकार।
- टाइपयुक्त Plugin पंजीकरण/रनटाइम सतहें जोड़ें। सबसे छोटी उपयोगी टाइपयुक्त
क्षमता सतह के साथ
OpenClawPluginApiऔर/याapi.runtimeका विस्तार करें। - कोर + चैनल/फ़ीचर उपभोक्ताओं को जोड़ें। चैनलों और फ़ीचर Plugins को किसी विक्रेता कार्यान्वयन को सीधे इंपोर्ट करने के बजाय कोर के माध्यम से नई क्षमता का उपयोग करना चाहिए।
- विक्रेता कार्यान्वयन पंजीकृत करें। इसके बाद विक्रेता Plugins अपने बैकएंड को क्षमता के साथ पंजीकृत करते हैं।
- अनुबंध कवरेज जोड़ें। परीक्षण जोड़ें, ताकि स्वामित्व और पंजीकरण का आकार समय के साथ स्पष्ट बना रहे।
इसी प्रकार OpenClaw किसी एक प्रदाता के दृष्टिकोण से हार्डकोड हुए बिना अपना स्पष्ट मत बनाए रखता है। ठोस फ़ाइल चेकलिस्ट और कार्यान्वित उदाहरण के लिए क्षमता कुकबुक देखें।
क्षमता चेकलिस्ट
नई क्षमता जोड़ते समय कार्यान्वयन को सामान्यतः इन सतहों को एक साथ स्पर्श करना चाहिए:
src/<capability>/types.tsमें कोर अनुबंध प्रकारsrc/<capability>/runtime.tsमें कोर रनर/रनटाइम हेल्परsrc/plugins/types.tsमें Plugin API पंजीकरण सतहsrc/plugins/registry.tsमें Plugin रजिस्ट्री वायरिंग- जब फ़ीचर/चैनल Plugins को इसका उपयोग करना हो, तब
src/plugins/runtime/*में Plugin रनटाइम एक्सपोज़र src/test-utils/plugin-registration.tsमें कैप्चर/परीक्षण हेल्परsrc/plugins/contracts/registry.tsमें स्वामित्व/अनुबंध अभिकथनdocs/में ऑपरेटर/Plugin दस्तावेज़
यदि इनमें से कोई सतह अनुपस्थित है, तो यह सामान्यतः संकेत है कि क्षमता अभी पूरी तरह एकीकृत नहीं हुई है।
क्षमता टेम्पलेट
न्यूनतम पैटर्न:
// 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 जैसी स्वामित्व
लुकअप उपलब्ध कराता है; परीक्षण पुष्टि करते हैं कि किसी Plugin की
contracts.videoGenerationProviders सूची उसके वास्तविक पंजीकरण से मेल खाती है):
expect(pluginManifest.contracts?.videoGenerationProviders).toEqual(["openai"]);इससे नियम सरल बना रहता है:
- क्षमता अनुबंध + ऑर्केस्ट्रेशन का स्वामित्व कोर के पास है
- विक्रेता कार्यान्वयनों का स्वामित्व विक्रेता Plugins के पास है
- फ़ीचर/चैनल Plugins रनटाइम हेल्पर का उपयोग करते हैं
- अनुबंध परीक्षण स्वामित्व को स्पष्ट बनाए रखते हैं
संबंधित
- Plugin आर्किटेक्चर — सार्वजनिक क्षमता मॉडल और आकार
- Plugin SDK उपपथ
- Plugin SDK सेटअप
- Plugins बनाना