---
read_when:
    - प्रोवाइडर रनटाइम हुक, चैनल जीवनचक्र या पैकेज पैक लागू करना
    - Plugin लोड क्रम या रजिस्ट्री स्थिति की डीबगिंग
    - नई Plugin क्षमता या कॉन्टेक्स्ट इंजन Plugin जोड़ना
summary: 'Plugin आर्किटेक्चर के आंतरिक भाग: लोड पाइपलाइन, रजिस्ट्री, रनटाइम हुक, HTTP रूट और संदर्भ तालिकाएँ'
title: Plugin आर्किटेक्चर के आंतरिक तंत्र
x-i18n:
    generated_at: "2026-07-27T21:16:44Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    prompt_version: 32
    provider: openai
    source_hash: 278ac23a9454ab69407c59fa197e75756fa0dc5880fcae6c3eecc15bd4733a09
    source_path: plugins/architecture-internals.md
    workflow: 16
---

सार्वजनिक क्षमता मॉडल, Plugin संरचनाओं और स्वामित्व/निष्पादन
अनुबंधों के लिए, [Plugin आर्किटेक्चर](/hi/plugins/architecture) देखें। यह पृष्ठ
आंतरिक कार्यप्रणाली को कवर करता है: लोड पाइपलाइन, रजिस्ट्री, रनटाइम हुक, Gateway HTTP
रूट, इंपोर्ट पथ और स्कीमा तालिकाएँ।

## लोड पाइपलाइन

स्टार्टअप पर, OpenClaw मोटे तौर पर यह करता है:

1. संभावित Plugin रूट खोजता है
2. नेटिव या संगत बंडल मैनिफ़ेस्ट और पैकेज मेटाडेटा पढ़ता है
3. असुरक्षित उम्मीदवारों को अस्वीकार करता है
4. Plugin कॉन्फ़िग को सामान्यीकृत करता है (`plugins.enabled`, `allow`, `deny`, `entries`,
   `slots`, `load.paths`)
5. प्रत्येक उम्मीदवार को सक्षम करना है या नहीं, यह तय करता है
6. सक्षम नेटिव मॉड्यूल लोड करता है: निर्मित बंडल मॉड्यूल नेटिव लोडर का उपयोग करते हैं;
   तृतीय-पक्ष स्थानीय स्रोत TypeScript आपातकालीन Jiti फ़ॉलबैक का उपयोग करता है
7. नेटिव `register(api)` हुक कॉल करता है और पंजीकरणों को Plugin रजिस्ट्री में एकत्र करता है
8. रजिस्ट्री को कमांड/रनटाइम सतहों के लिए उपलब्ध कराता है

सुरक्षा गेट रनटाइम निष्पादन से **पहले** चलते हैं। डिस्कवरी किसी उम्मीदवार को
तब ब्लॉक करती है, जब:

- उसकी रिज़ॉल्व की गई एंट्री 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(...)` का उपयोग करें:

```ts
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+ वैकल्पिक हुक।
  [हुक क्रम और उपयोग](#hook-order-and-usage) देखें।

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` में संगठन या बिलिंग क्रेडेंशियल घोषित करें।
इससे सामान्य खोज और सीक्रेट-साफ़ करने वाली सतहें उन्हें इन्फ़रेंस प्रमाणीकरण
उम्मीदवार बनाए बिना पहचान सकती हैं।

### प्रोवाइडर उदाहरण

```ts
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/` के अंतर्गत रहता है; यह पृष्ठ सूची की प्रतिलिपि
बनाने के बजाय उनके स्वरूपों को दर्शाता है।

<AccordionGroup>
  <Accordion title="पास-थ्रू कैटलॉग प्रोवाइडर">
    OpenRouter, Kilocode, Z.AI, xAI `catalog` के साथ
    `resolveDynamicModel` / `prepareDynamicModel` पंजीकृत करते हैं, ताकि वे OpenClaw की
    स्थिर कैटलॉग से पहले अपस्ट्रीम मॉडल आईडी प्रस्तुत कर सकें।
  </Accordion>
  <Accordion title="OAuth और उपयोग एंडपॉइंट प्रोवाइडर">
    GitHub Copilot, Gemini CLI, ChatGPT Codex, MiniMax, Xiaomi, z.ai
    `prepareRuntimeAuth` या `formatApiKey` को `resolveUsageAuth` +
    `fetchUsageSnapshot` के साथ जोड़ते हैं, ताकि टोकन एक्सचेंज और `/usage`
    एकीकरण का स्वामित्व लिया जा सके।
  </Accordion>
  <Accordion title="रीप्ले और ट्रांसक्रिप्ट सफ़ाई परिवार">
    साझा नामित परिवार (`google-gemini`, `passthrough-gemini`,
    `anthropic-by-model`, `hybrid-anthropic-openai`) प्रोवाइडरों को प्रत्येक Plugin में
    सफ़ाई दोबारा लागू करने के बजाय `buildReplayPolicy` के माध्यम से
    ट्रांसक्रिप्ट नीति अपनाने देते हैं।
  </Accordion>
  <Accordion title="केवल-कैटलॉग प्रोवाइडर">
    `byteplus`, `cloudflare-ai-gateway`, `huggingface`, `kimi-coding`, `nvidia`,
    `qianfan`, `synthetic`, `together`, `venice`, `vercel-ai-gateway`, और
    `volcengine` केवल `catalog` पंजीकृत करते हैं और साझा इन्फ़रेंस लूप का उपयोग करते हैं।
  </Accordion>
  <Accordion title="Anthropic-विशिष्ट स्ट्रीम सहायक">
    बीटा हेडर, `/fast` / `serviceTier`, और `context1m`
    सामान्य SDK के बजाय Anthropic Plugin के सार्वजनिक
    `api.ts` / `contract-api.ts` सीमांत
    (`wrapAnthropicProviderStream`, `resolveAnthropicBetas`,
    `resolveAnthropicFastMode`, `resolveAnthropicServiceTier`) के भीतर रहते हैं।
  </Accordion>
</AccordionGroup>

## रनटाइम सहायक

Plugins `api.runtime` के माध्यम से चुने हुए कोर सहायकों तक पहुँच सकते हैं। TTS के लिए:

```ts
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(...)` के माध्यम से स्पीच प्रोवाइडर भी पंजीकृत कर सकते हैं।

```ts
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 सामान्य कुंजी/मान संग्रह के बजाय एक टाइप किया हुआ
मीडिया-समझ प्रोवाइडर पंजीकृत करते हैं:

```ts
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 यह कॉल कर सकते हैं:

```ts
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 उपनाम में से
किसी एक का उपयोग कर सकते हैं:

```ts
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` के माध्यम से पृष्ठभूमि सबएजेंट रन भी शुरू कर सकते हैं:

```ts
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 एजेंट टूल वायरिंग में सीधे पहुँचने के बजाय
साझा रनटाइम सहायक का उपयोग कर सकते हैं:

```ts
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`

```ts
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 एंडपॉइंट उपलब्ध करा सकते हैं।

```ts
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 के सामान्य सहोदर रूट प्रवेश सीमा के पीछे रहते हैं। WebSocket `handleUpgrade` स्वामित्व समान परमाण्विक प्रवेश सीमा का उपयोग करता है; हैंडलर द्वारा सॉकेट स्वीकार किए जाने के बाद, सॉकेट का आगामी जीवनकाल 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](/hi/plugins/sdk-channel-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`
को प्राथमिकता दें।

<Info>
`openclaw/plugin-sdk/channel-lifecycle`, छोटे चैनल सहायक फ़साड,
`openclaw/plugin-sdk/config-runtime`, और `openclaw/plugin-sdk/infra-runtime`
पुराने Plugins के लिए बहिष्कृत संगतता शिम हैं। नए कोड को इसके बजाय
संकरे सामान्य प्रिमिटिव इंपोर्ट करने चाहिए।
</Info>

रिपॉज़िटरी-आंतरिक एंट्री पॉइंट (प्रत्येक बंडल किए गए 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 लेखक चेकलिस्ट के लिए
[संदेश प्रस्तुति](/hi/plugins/message-presentation) देखें।

प्रेषण-सक्षम 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` दोनों पंजीकृत हैं, तो OpenClaw `catalog` का उपयोग करता है
  और चेतावनी देता है
- `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`, `tokenStatus`
  - `botTokenSource`, `botTokenStatus`
  - `appTokenSource`, `appTokenStatus`
  - `signingSecretSource`, `signingSecretStatus`
- केवल केवल-पढ़ने योग्य उपलब्धता की रिपोर्ट करने के लिए आपको अपरिष्कृत टोकन मान लौटाने की आवश्यकता नहीं है। स्थिति-शैली कमांडों के लिए `tokenStatus: "available"` (और उससे मेल खाता स्रोत फ़ील्ड) लौटाना पर्याप्त है।
- जब कोई क्रेडेंशियल SecretRef के माध्यम से कॉन्फ़िगर हो, लेकिन वर्तमान कमांड मार्ग में अनुपलब्ध हो, तब `configured_unavailable` का उपयोग करें।

इससे केवल-पढ़ने योग्य कमांड क्रैश होने या खाते को कॉन्फ़िगर नहीं किया गया बताने के बजाय "कॉन्फ़िगर किया गया है, लेकिन इस कमांड मार्ग में अनुपलब्ध है" की रिपोर्ट कर सकते हैं।

## पैकेज पैक

किसी Plugin निर्देशिका में `openclaw.extensions` वाला `package.json` शामिल हो सकता है:

```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 को स्टार्टअप के दौरान पूर्ण प्रविष्टि लोड करने दें।

बंडल किए गए चैनल केवल-सेटअप अनुबंध-सतह सहायक भी प्रकाशित कर सकते हैं, जिनसे कोर पूर्ण चैनल रनटाइम लोड होने से पहले परामर्श कर सकता है। वर्तमान सेटअप उन्नयन सतह है:

- `singleAccountKeysToMove`
- `namedAccountPromotionKeys`
- `resolveSingleAccountPromotionTarget(...)`

जब कोर को पूर्ण Plugin प्रविष्टि लोड किए बिना किसी विरासती एकल-खाता चैनल कॉन्फ़िगरेशन को `channels.<id>.accounts.*` में उन्नत करना होता है, तब वह उस सतह का उपयोग करता है। Matrix वर्तमान बंडल किया गया उदाहरण है: नामित खाते पहले से मौजूद होने पर यह केवल प्रमाणीकरण/बूटस्ट्रैप कुंजियों को किसी नामित उन्नत खाते में ले जाता है, और हमेशा `accounts.default` बनाने के बजाय कॉन्फ़िगर की गई गैर-मानक डिफ़ॉल्ट-खाता कुंजी को सुरक्षित रख सकता है।

वे सेटअप पैच एडाप्टर बंडल की गई अनुबंध-सतह खोज को आलसी बनाए रखते हैं। आयात समय हल्का रहता है; मॉड्यूल आयात पर बंडल किए गए चैनल स्टार्टअप में दोबारा प्रवेश करने के बजाय उन्नयन सतह केवल प्रथम उपयोग पर लोड होती है।

जब उन स्टार्टअप सतहों में Gateway RPC विधियाँ शामिल हों, तो उन्हें Plugin-विशिष्ट उपसर्ग पर रखें। कोर व्यवस्थापक नेमस्पेस (`config.*`, `exec.approvals.*`, `wizard.*`, `update.*`) आरक्षित रहते हैं और हमेशा `operator.admin` में हल होते हैं, भले ही कोई Plugin अधिक सीमित स्कोप का अनुरोध करे।

उदाहरण:

```json
{
  "name": "@scope/my-channel",
  "openclaw": {
    "extensions": ["./index.ts"],
    "setupEntry": "./setup-entry.ts",
    "startup": {
      "deferConfiguredChannelFullLoadUntilAfterListen": true
    }
  }
}
```

### चैनल कैटलॉग मेटाडेटा

चैनल plugins `openclaw.channel` के माध्यम से सेटअप/खोज मेटाडेटा और `openclaw.install` के माध्यम से इंस्टॉल संकेत प्रदर्शित कर सकते हैं। इससे कोर कैटलॉग डेटा-मुक्त रहता है।

उदाहरण:

```json
{
  "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 को केवल मेमोरी खोज या हुक जोड़ने के बजाय डिफ़ॉल्ट संदर्भ पाइपलाइन को बदलना या विस्तारित करना हो।

```ts
import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";

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()`
को कार्यान्वित रखें और इसे स्पष्ट रूप से डेलिगेट करें:

```ts
import {
  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 सिस्टम को बायपास न करें। अनुपलब्ध क्षमता जोड़ें।

अनुशंसित क्रम:

1. **कोर अनुबंध परिभाषित करें।** तय करें कि साझा व्यवहार के किन हिस्सों का स्वामित्व कोर के पास होना चाहिए:
   नीति, फ़ॉलबैक, कॉन्फ़िगरेशन मर्ज, जीवनचक्र, चैनल-संबंधी सिमैंटिक्स और
   रनटाइम हेल्पर का आकार।
2. **टाइपयुक्त Plugin पंजीकरण/रनटाइम सतहें जोड़ें।** सबसे छोटी उपयोगी टाइपयुक्त
   क्षमता सतह के साथ `OpenClawPluginApi` और/या `api.runtime` का विस्तार करें।
3. **कोर + चैनल/फ़ीचर उपभोक्ताओं को जोड़ें।** चैनलों और फ़ीचर Plugins को
   किसी विक्रेता कार्यान्वयन को सीधे इंपोर्ट करने के बजाय कोर के माध्यम से नई क्षमता का उपयोग करना चाहिए।
4. **विक्रेता कार्यान्वयन पंजीकृत करें।** इसके बाद विक्रेता Plugins अपने
   बैकएंड को क्षमता के साथ पंजीकृत करते हैं।
5. **अनुबंध कवरेज जोड़ें।** परीक्षण जोड़ें, ताकि स्वामित्व और पंजीकरण का आकार
   समय के साथ स्पष्ट बना रहे।

इसी प्रकार OpenClaw किसी एक प्रदाता के दृष्टिकोण से हार्डकोड हुए बिना
अपना स्पष्ट मत बनाए रखता है। ठोस फ़ाइल चेकलिस्ट और कार्यान्वित उदाहरण के लिए
[क्षमता कुकबुक](/hi/plugins/adding-capabilities) देखें।

### क्षमता चेकलिस्ट

नई क्षमता जोड़ते समय कार्यान्वयन को सामान्यतः इन
सतहों को एक साथ स्पर्श करना चाहिए:

- `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 दस्तावेज़

यदि इनमें से कोई सतह अनुपस्थित है, तो यह सामान्यतः संकेत है कि क्षमता
अभी पूरी तरह एकीकृत नहीं हुई है।

### क्षमता टेम्पलेट

न्यूनतम पैटर्न:

```ts
// core contract
export type VideoGenerationProviderPlugin = {
  id: string;
  label: string;
  generateVideo: (req: VideoGenerationRequest) => Promise<VideoGenerationResult>;
};

// plugin API
api.registerVideoGenerationProvider({
  id: "openai",
  label: "OpenAI",
  async generateVideo(req) {
    return await generateOpenAiVideo(req);
  },
});

// shared runtime helper for feature/channel plugins
const clip = await api.runtime.videoGeneration.generate({
  prompt: "Show the robot walking through the lab.",
  cfg,
});
```

अनुबंध परीक्षण पैटर्न (`src/plugins/contracts/registry.ts` `providerContractPluginIds` जैसी स्वामित्व
लुकअप उपलब्ध कराता है; परीक्षण पुष्टि करते हैं कि किसी Plugin की
`contracts.videoGenerationProviders` सूची उसके वास्तविक पंजीकरण से मेल खाती है):

```ts
expect(pluginManifest.contracts?.videoGenerationProviders).toEqual(["openai"]);
```

इससे नियम सरल बना रहता है:

- क्षमता अनुबंध + ऑर्केस्ट्रेशन का स्वामित्व कोर के पास है
- विक्रेता कार्यान्वयनों का स्वामित्व विक्रेता Plugins के पास है
- फ़ीचर/चैनल Plugins रनटाइम हेल्पर का उपयोग करते हैं
- अनुबंध परीक्षण स्वामित्व को स्पष्ट बनाए रखते हैं

## संबंधित

- [Plugin आर्किटेक्चर](/hi/plugins/architecture) — सार्वजनिक क्षमता मॉडल और आकार
- [Plugin SDK उपपथ](/hi/plugins/sdk-subpaths)
- [Plugin SDK सेटअप](/hi/plugins/sdk-setup)
- [Plugins बनाना](/hi/plugins/building-plugins)
