Plugin maintainer reference

चैनल आउटबाउंड API

Channel plugins से आउटबाउंड संदेश व्यवहार उपलब्ध होता है openclaw/plugin-sdk/channel-outbound। प्राप्ति/संदर्भ/डिस्पैच ऑर्केस्ट्रेशन के लिए openclaw/plugin-sdk/channel-inbound का उपयोग करें।

Core कतारबद्ध करना, टिकाऊपन, टिकाऊ इनग्रेस मॉनिटर और ड्रेन (createChannelIngressMonitor, createChannelIngressDrain, और openChannelIngressDrain), सामान्य पुनःप्रयास नीति, टर्न-अडॉप्शन जीवनचक्र (turnAdoptionLifecycle / bindIngressLifecycleToReplyOptions), हुक, रसीदें, और साझा message टूल का स्वामी है। Plugin नेटिव भेजने/संपादित करने/हटाने की कॉल, लक्ष्य सामान्यीकरण, प्लेटफ़ॉर्म थ्रेडिंग, चयनित उद्धरण, सूचना फ़्लैग, अकाउंट स्थिति, इनग्रेस निरीक्षण और पेलोड एन्कोडिंग, लेन कुंजियाँ, पुनःप्रयास-न-योग्य प्रेडिकेट, वैकल्पिक सुपरसिड प्राधिकरण, और प्लेटफ़ॉर्म-विशिष्ट दुष्प्रभावों का स्वामी है।

टिकाऊ इनग्रेस मॉनिटर

जब किसी चैनल को डिस्पैच से पहले स्वीकृत ट्रांसपोर्ट इवेंट को स्थायी रखना हो, तो createChannelIngressMonitor(...) का उपयोग करें। यह चैनल इनग्रेस कतार और ड्रेन को साझा प्रवेश, पोलिंग, प्रूनिंग, डिलीवरी, और शटडाउन जीवनचक्र के साथ संयोजित करता है। निम्न-स्तरीय createChannelIngressDrain(...) का उपयोग केवल तभी करें जब ट्रांसपोर्ट के पास मूल रूप से भिन्न प्रवेश या पंप अनुबंध हो।

आवश्यक विकल्प हैं:

विकल्प अनुबंध
queue एक ChannelIngressQueue, या अकाउंट-स्कोप वाली कतार खोलने वाली लेज़ी फ़ैक्टरी।
inspect(raw, context) स्थिर eventId और क्रमबद्ध laneKey, या उपेक्षित इवेंट के लिए null लौटाता है। क्लेम-समय के तथ्य स्थायी आईडी और लेन से मेल खाने चाहिए।
payload पेलोड संस्करण तथा बॉडी क्रमबद्धता/विक्रमबद्धता प्रदान करता है। मानक { version, rawEvent } स्ट्रिंग एनवलप के लिए storage: "raw-event" का उपयोग करें, या किसी मौजूदा चैनल-विशिष्ट आकार के लिए कस्टम एन्कोड/डीकोड कॉलबैक दें। createClaimError अमान्य संस्करणों या बदली हुई पहचान को वर्गीकृत करता है।
deliver(raw, lifecycle, claim) एक डीकोड किए गए इवेंट को डिस्पैच करता है और पूरा अडॉप्शन जीवनचक्र प्राप्त करता है। यह completed, deferred, failed-retryable, या कुछ भी नहीं लौटा सकता है।
pollIntervalMs मॉनिटर चलने के दौरान रिकवरी/ड्रेन पोल निर्धारित करता है।
retention प्रून की आवृत्ति तथा पूर्ण/विफल TTL और प्रविष्टि सीमाएँ प्रदान करता है।

मॉनिटर प्रवेशों को क्रमिक करता है ताकि एपेंड बैकऑफ़ किसी लेन का क्रम न उलट सके। डिफ़ॉल्ट सीमित एपेंड विलंब 0, 100, और 300 ms हैं; सीमा समाप्त होने पर ट्रांसपोर्ट कॉलबैक अस्वीकार हो जाता है, बजाय ऐसे इवेंट को डिस्पैच करने के जिसे टिकाऊ नहीं बनाया गया था। क्लेम के समय यह संस्करणयुक्त पेलोड को डीकोड करता है, inspect को फिर से चलाता है, और डिलीवरी से पहले आईडी या लेन के बेमेल को अस्वीकार करता है।

deliver को onAdopted, onDeferred, onAdoptionFinalizing, onAbandoned, और abortSignal प्राप्त होते हैं। स्पष्ट हैंडऑफ़ के बिना लौटना टर्मिनल नो-डिस्पैच इवेंट को अपनाया गया चिह्नित करता है। admission हमेशा exclusive होता है। स्थगित हैंडऑफ़ क्लेम को बनाए रखता है, जबकि शटडाउन या एबॉर्ट अपनाए न गए कार्य को पुनःप्रयास योग्य बनाए रखता है। मॉनिटर डिलीवरी को क्लेम निपटान से स्वतंत्र रूप से ट्रैक करता है, क्योंकि चैनल का डिलीवरी प्रॉमिस लौटने से पहले अडॉप्शन किसी पंक्ति को टूमस्टोन कर सकता है।

वैकल्पिक सेटिंग में कस्टम एपेंड विलंब, उन्नत ड्रेन क्रम/समवर्तीता/पुनःप्रयास नीति के लिए drain विकल्प ब्लॉक, बाहरी abortSignal, एक घड़ी, पंप त्रुटि रिपोर्टिंग, स्टॉप्ड-एरर फ़ैक्टरी, और प्रवेश नीति शामिल हैं। लौटाया गया मॉनिटर admit, start, pause, stop, waitForIdle, isRunning, और isStopped उपलब्ध कराता है। stop पहले स्वीकृत प्रवेशों का निपटान करता है, फिर ड्रेन को एबॉर्ट और डिस्पोज़ करता है, पंप और सक्रिय डिलीवरी की प्रतीक्षा करता है, और लेज़ी-निर्माण रेस को बंद करने के लिए फिर से डिस्पोज़ करता है।

ट्रांसपोर्ट-विशिष्ट रिडैक्शन, रॉ-एनवलप सत्यापन, पुनःप्रयास-न-योग्य वर्गीकरण, और स्थायी पेलोड आकार को Plugin में रखें। Webhook ट्रांसपोर्ट को admit के पूरा होने के बाद ही अभिस्वीकृति देनी चाहिए; गैर-रीप्ले ट्रांसपोर्ट को चुपचाप डिस्पैच करने के बजाय टिकाऊ एपेंड सीमा समाप्ति को प्रकट करना चाहिए।

अडैप्टर

अधिकांश plugins एक message अडैप्टर परिभाषित करते हैं:

ts
   defineChannelMessageAdapter,  createMessageReceiptFromOutboundResults,} from "openclaw/plugin-sdk/channel-outbound"; export const demoMessageAdapter = defineChannelMessageAdapter({  id: "demo",  durableFinal: {    capabilities: {      text: true,      replyTo: true,      thread: true,      messageSendingHooks: true,    },  },  send: {    text: async ({ cfg, to, text, accountId, replyToId, threadId, signal }) => {      const sent = await sendDemoMessage({        cfg,        to,        text,        accountId: accountId ?? undefined,        replyToId: replyToId ?? undefined,        threadId: threadId == null ? undefined : String(threadId),        signal,      });       return {        receipt: createMessageReceiptFromOutboundResults({          results: [{ channel: "demo", messageId: sent.id, conversationId: to }],          kind: "text",          threadId: threadId == null ? undefined : String(threadId),          replyToId: replyToId ?? undefined,        }),      };    },  },});

केवल उन्हीं क्षमताओं को घोषित करें जिन्हें नेटिव ट्रांसपोर्ट वास्तव में संरक्षित रखता है। घोषित प्रत्येक भेजने, रसीद, लाइव-प्रीव्यू, और प्राप्ति-अभिस्वीकृति क्षमता को इस सबपाथ से निर्यात किए गए अनुबंध सहायकों द्वारा कवर करें।

आउटबाउंड इको दमन

जब कोई प्लेटफ़ॉर्म Plugin के अपने आउटबाउंड संदेश को इनबाउंड के रूप में फिर से डिलीवर कर सकता है, तो चैनल, अकाउंट, वार्तालाप, और स्थिर प्लेटफ़ॉर्म संदेश या स्रोत पहचान के साथ recordOutboundMessageIdentity(...) को कॉल करें। साझा इनबाउंड टर्न पाथ सत्र रिकॉर्डिंग या एजेंट डिस्पैच से पहले सीमित 30-सेकंड की अवधि में मेल खाती पहचानों को हटा देता है; डिलीवरी रेस को समाप्त करने के लिए किसी स्रोत पहचान को भेजने से पहले आरक्षित किया जा सकता है या चैनल रूट हटाए जाने पर रीफ़्रेश किया जा सकता है। isRecentOutboundMessageIdentity(...) चैनल निदान और परीक्षणों के लिए यही क्वेरी उपलब्ध कराता है। उसी स्थिर पहचान के लिए समानांतर चैनल-स्थानीय TTL कैश न बनाएँ।

प्लेन-टेक्स्ट सैनिटाइज़ेशन

जब किसी आउटबाउंड अडैप्टर को समर्थित HTML फ़ॉर्मैटिंग टैग को हल्के टेक्स्ट मार्कअप में बदलना हो, तो sanitizeForPlainText(...) का उपयोग करें। डिफ़ॉल्ट मौजूदा चैट-शैली के बोल्ड और स्ट्राइकथ्रू मार्कर बनाए रखता है। { style: "markdown" } केवल तभी पास करें जब चैनल परिणाम को Markdown के रूप में पुनः पार्स करता हो:

ts
 const chatText = sanitizeForPlainText(text);const markdownText = sanitizeForPlainText(text, { style: "markdown" });

Markdown शैली **bold** और ~~strikethrough~~ का उपयोग करती है; इटैलिक और इनलाइन कोड दोनों शैलियों में _italic_ और बैकटिक मार्कर बनाए रखते हैं। सैनिटाइज़ेशन के बाद मार्कर टेक्स्ट को फिर से लिखने के बजाय चैनल सीमा पर शैली चुनें।

डिलीवरी प्रमाण

एक MessageReceipt चैनल अडैप्टर द्वारा लौटाए गए परिणाम को रिकॉर्ड करता है। ठोस प्लेटफ़ॉर्म संदेश पहचानकर्ता दिखाते हैं कि प्लेटफ़ॉर्म भेजने के पाथ ने संदेश स्वीकार किया; वे यह सिद्ध नहीं करते कि प्राप्तकर्ता के डिवाइस ने उसे प्रदर्शित किया या पढ़ा। प्लेटफ़ॉर्म संदेश पहचानकर्ताओं के बिना रसीदें केवल स्थानीय रसीद मेटाडेटा हैं। पठन रसीद या डिवाइस-डिलीवरी स्थिति वाले चैनलों को उन तथ्यों को एक अलग चैनल-विशिष्ट पाथ से ट्रैक करना चाहिए।

यदि कोई चैनल अडैप्टर सिद्ध कर सकता है कि किसी विफलता का पुनःप्रयास प्राप्तकर्ता को दिखाई देने वाले भेजने को डुप्लिकेट नहीं कर सकता और अंतिमकरण-सक्षम कोई कॉल शुरू नहीं हुई, तो openclaw/plugin-sdk/error-runtime से new PlatformMessageNotDispatchedError("...", { cause: error }) थ्रो करें। इसके बाद Core पुराना भेजने-प्रयास प्रमाण साफ़ कर सकता है और कतारबद्ध इंटेंट का सुरक्षित रूप से पुनःप्रयास कर सकता है। केवल वही अडैप्टर यह दावा कर सकता है जो अंतिम डिस्पैच सीमा का स्वामी हो। अंतिमकरण/भेजने की कॉल शुरू होने या अस्पष्ट परिणाम लौटाने के बाद कभी भी इस मार्कर का उपयोग न करें; गलत चिह्नांकन संदेशों को डुप्लिकेट कर सकता है।

मौजूदा आउटबाउंड अडैप्टर

यदि चैनल में पहले से संगत outbound अडैप्टर है, तो भेजने के कोड की प्रतिलिपि बनाने के बजाय उससे संदेश अडैप्टर व्युत्पन्न करें:

ts
 export const messageAdapter = createChannelMessageAdapterFromOutbound({  id: "demo",  outbound,  durableFinal: {    capabilities: {      text: true,      media: true,    },  },});

टिकाऊ भेजना

रनटाइम भेजने वाले सहायक भी channel-outbound पर उपलब्ध हैं:

  • sendDurableMessageBatch(...)
  • withDurableMessageSendContext(...)
  • deliverInboundReplyWithMessageSendContext(...)
  • ड्राफ़्ट स्ट्रीमिंग/प्रगति सहायक, जैसे resolveChannelDraftStreamingChunking(...)

sendDurableMessageBatch(...) एक स्पष्ट परिणाम लौटाता है:

परिणाम अर्थ
sent प्लेटफ़ॉर्म भेजने के पाथ ने कम-से-कम एक दृश्यमान प्लेटफ़ॉर्म संदेश स्वीकार किया
suppressed किसी प्लेटफ़ॉर्म संदेश को अनुपलब्ध नहीं माना जाना चाहिए
partial_failed बाद के किसी पेलोड या दुष्प्रभाव के विफल होने से पहले कम-से-कम एक प्लेटफ़ॉर्म संदेश स्वीकार किया गया
failed कोई प्लेटफ़ॉर्म रसीद उत्पन्न नहीं हुई

जब किसी बैच में भेजे गए, दबाए गए, और विफल पेलोड मिश्रित हों, तो payloadOutcomes का उपयोग करें। खाली लेगेसी प्रत्यक्ष-डिलीवरी परिणाम से हुक रद्दीकरण का अनुमान न लगाएँ।

स्थगित डिलीवरी प्रवेश

जब कोई रिज़ॉल्व किया गया अकाउंट Core-प्रबंधित आउटबाउंड या स्थगित डिलीवरी को सुरक्षित रूप से स्वीकार न कर सके, तो message.durableFinal.admitDeferredDelivery(...) का उपयोग करें। Core लाइव आउटबाउंड कार्य से पहले इस हुक को समकालिक रूप से कॉल करता है, जिसमें कतार स्थायित्व छोड़ने वाले पाथ भी शामिल हैं, और पुनर्प्राप्त इंटेंट को रीप्ले करने से पहले इसे फिर से कॉल करता है। संदर्भ में cfg, channel, to, accountId, और live या recovery का एक phase शामिल है।

जारी रखने के लिए { status: "allowed" } लौटाएँ। जब डिलीवरी को स्थायी नहीं किया जाना चाहिए, सीधे नहीं भेजा जाना चाहिए, या रीप्ले नहीं किया जाना चाहिए, तो { status: "permanent_rejection", reason } लौटाएँ। लाइव अस्वीकृति कतार निर्माण, संदेश हुक, या प्लेटफ़ॉर्म कार्य से पहले विफल हो जाती है। रिकवरी अस्वीकृति कतारबद्ध रिकॉर्ड को विफल चिह्नित करती है और समाधान तथा रीप्ले को छोड़ देती है। हुक को छोड़ने का अर्थ अनुमति है।

हुक एक समकालिक प्रवेश निर्णय है, भेजने का पथ नहीं। केवल पहले से लोड किए गए कॉन्फ़िगरेशन या रनटाइम स्थिति को पढ़ें; नेटवर्क, फ़ाइल सिस्टम या अन्य अतुल्यकालिक I/O न करें। अनुबंध परीक्षणों में openclaw/plugin-sdk/channel-outbound के ChannelMessageDurableFinalAdapter के माध्यम से दोनों चरणों और दोनों परिणाम प्रकारों का परीक्षण किया जाना चाहिए।

संगतता डिस्पैच

channel-inbound के dispatchChannelInboundReply(...) के माध्यम से इनबाउंड उत्तर डिस्पैच संयोजित करें। प्लेटफ़ॉर्म डिलीवरी को डिलीवरी अडैप्टर में रखें; संदेश अडैप्टर, टिकाऊ प्रेषण, प्राप्ति-पुष्टियों, लाइव पूर्वावलोकन और उत्तर पाइपलाइन विकल्पों के लिए channel-outbound का उपयोग करें।

Was this useful?
On this page

On this page