Get started
ACP जीवनचक्र रीफ़ैक्टर
ACP जीवनचक्र वर्तमान में काम करता है, लेकिन इसका बहुत अधिक हिस्सा घटना के बाद अनुमानित किया जाता है।
प्रक्रिया क्लीनअप PIDs, कमांड स्ट्रिंग, रैपर
पाथ और लाइव प्रक्रिया तालिका से स्वामित्व का पुनर्निर्माण करता है। सेशन दृश्यता, सेशन-की स्ट्रिंग के साथ द्वितीयक sessions.list({ spawnedBy }) लुकअप से स्वामित्व
का पुनर्निर्माण करती है।
इससे सीमित दायरे के सुधार संभव होते हैं, लेकिन इससे सीमांत मामलों को चूकना भी आसान हो जाता है:
PID का पुनः उपयोग, उद्धृत कमांड, अडैप्टर की ग्रैंडचाइल्ड प्रक्रियाएँ, मल्टी-Gateway स्टेट रूट,
cancel बनाम close, और tree बनाम all दृश्यता—ये सभी समान स्वामित्व नियमों को फिर से खोजने के अलग-अलग
स्थान बन जाते हैं।
यह रीफ़ैक्टर स्वामित्व को प्रथम-श्रेणी का बनाता है। लक्ष्य कोई नया ACP उत्पाद सतह नहीं है; यह मौजूदा ACP और ACPX व्यवहार के लिए अधिक सुरक्षित आंतरिक अनुबंध है।
लक्ष्य
- क्लीनअप कभी किसी प्रक्रिया को सिग्नल नहीं भेजता, जब तक वर्तमान लाइव साक्ष्य किसी OpenClaw-स्वामित्व वाली लीज़ से मेल न खाए।
cancel,close, और स्टार्टअप रीपिंग के अलग-अलग जीवनचक्र अभिप्राय हैं।sessions_list,sessions_history,sessions_send, और स्थिति जाँच समान अनुरोधकर्ता-स्वामित्व वाले सेशन मॉडल का उपयोग करते हैं।- मल्टी-Gateway इंस्टॉलेशन एक-दूसरे के ACPX रैपर को रीप नहीं कर सकते।
- पुराने ACPX सेशन रिकॉर्ड माइग्रेशन के दौरान काम करते रहते हैं।
- रनटाइम Plugin-स्वामित्व वाला रहता है; कोर ACPX पैकेज के विवरण नहीं सीखता।
गैर-लक्ष्य
- ACPX को बदलना या सार्वजनिक
/acpकमांड सतह में बदलाव करना। - विक्रेता-विशिष्ट ACP अडैप्टर व्यवहार को कोर में ले जाना।
- अपग्रेड से पहले उपयोगकर्ताओं से स्टेट को मैन्युअल रूप से साफ़ करवाना।
cancelसे पुनः उपयोग योग्य ACP सेशन बंद करवाना।
लक्षित मॉडल
Gateway इंस्टेंस पहचान
प्रत्येक Gateway प्रक्रिया की एक स्थिर रनटाइम इंस्टेंस आईडी होनी चाहिए:
type GatewayInstanceId = string;इसे Gateway स्टार्टअप पर जनरेट किया जा सकता है और उस इंस्टॉलेशन के जीवनकाल के लिए स्टेट में स्थायी रखा जा सकता है। यह कोई सुरक्षा सीक्रेट नहीं है; यह एक स्वामित्व विभेदक है जिसका उपयोग एक Gateway की ACP प्रक्रियाओं को दूसरे Gateway की प्रक्रियाओं से भ्रमित होने से बचाने के लिए किया जाता है।
ACP सेशन स्वामित्व
प्रत्येक स्पॉन किए गए ACP सेशन में सामान्यीकृत स्वामित्व मेटाडेटा होना चाहिए:
type AcpSessionOwner = { sessionKey: string; spawnedBy?: string; parentSessionKey?: string; ownerSessionKey: string; agentId: string; backend: "acpx"; gatewayInstanceId: GatewayInstanceId; createdAt: number;};Gateway को सेशन पंक्तियों पर ये फ़ील्ड लौटाने चाहिए, जहाँ वे ज्ञात हों। दृश्यता फ़िल्टरिंग पंक्ति मेटाडेटा पर एक शुद्ध जाँच होनी चाहिए:
canSeeSessionRow({ row, requesterSessionKey, visibility, a2aPolicy,});इससे दृश्यता जाँच से छिपी हुई द्वितीयक sessions.list({ spawnedBy }) कॉल हट जाती हैं।
स्पॉन किया गया क्रॉस-एजेंट ACP चाइल्ड अनुरोधकर्ता-स्वामित्व वाला है क्योंकि
पंक्ति ऐसा कहती है, न कि इसलिए कि कोई दूसरी क्वेरी संयोगवश उसे खोज लेती है।
ACPX प्रक्रिया लीज़
हर जनरेट किए गए रैपर लॉन्च को एक लीज़ रिकॉर्ड बनाना चाहिए:
type AcpxProcessLease = { leaseId: string; gatewayInstanceId: GatewayInstanceId; sessionKey: string; wrapperRoot: string; wrapperPath: string; rootPid: number; processGroupId?: number; commandHash: string; startedAt: number; state: "open" | "closing" | "closed" | "lost";};रैपर प्रक्रिया को लीज़ आईडी और Gateway इंस्टेंस आईडी पोर्टेबल आर्ग्युमेंट के रूप में मिलते हैं:
--openclaw-acpx-lease-id ... --openclaw-gateway-instance-id ...जहाँ प्लेटफ़ॉर्म इसकी अनुमति देता है, सत्यापन को ऐसे लाइव प्रक्रिया मेटाडेटा को प्राथमिकता देनी चाहिए जिसे कमांड उद्धरण के कारण भ्रमित न किया जा सके:
- रूट PID अब भी मौजूद है
- लाइव रैपर पाथ
wrapperRootके अंतर्गत है - उपलब्ध होने पर प्रक्रिया समूह लीज़ से मेल खाता है
- आर्ग्युमेंट में अपेक्षित लीज़ आईडी है
- कमांड हैश या एक्ज़ीक्यूटेबल पाथ लीज़ से मेल खाता है
यदि लाइव प्रक्रिया को सत्यापित नहीं किया जा सकता, तो क्लीनअप बंद-सुरक्षित ढंग से विफल होता है।
जीवनचक्र नियंत्रक
एक ACPX जीवनचक्र नियंत्रक प्रस्तुत करें जो प्रक्रिया लीज़ और क्लीनअप नीति का स्वामी हो:
interface AcpxLifecycleController { ensureSession(input: AcpRuntimeEnsureInput): Promise<AcpRuntimeHandle>; cancelTurn(handle: AcpRuntimeHandle): Promise<void>; closeSession(input: { handle: AcpRuntimeHandle; discardPersistentState?: boolean; reason?: string; }): Promise<void>; reapStartupOrphans(): Promise<void>; verifyOwnedTree(lease: AcpxProcessLease): Promise<OwnedProcessTree | null>;}cancelTurn केवल टर्न रद्द करने का अनुरोध करता है। इसे पुनः उपयोग योग्य रैपर
या अडैप्टर प्रक्रियाओं को रीप नहीं करना चाहिए।
closeSession को रीप करने की अनुमति है, लेकिन केवल सेशन रिकॉर्ड लोड करने,
लीज़ लोड करने और यह सत्यापित करने के बाद कि लाइव प्रक्रिया ट्री अब भी उसी
लीज़ का है।
reapStartupOrphans स्टेट में खुली लीज़ से शुरू होता है। यह वंशजों को
खोजने के लिए प्रक्रिया तालिका का उपयोग कर सकता है, लेकिन इसे पहले मनमाने ACP-जैसे
कमांड स्कैन करके बाद में यह तय नहीं करना चाहिए कि वे संभवतः हमारे हैं।
रैपर अनुबंध
जनरेट किए गए रैपर छोटे रहने चाहिए। उन्हें:
- जहाँ समर्थित हो, अडैप्टर को एक प्रक्रिया समूह में शुरू करना चाहिए
- सामान्य समाप्ति सिग्नल को प्रक्रिया समूह में अग्रेषित करना चाहिए
- पैरेंट की मृत्यु का पता लगाना चाहिए
- पैरेंट की मृत्यु पर SIGTERM भेजना चाहिए, फिर SIGKILL फ़ॉलबैक चलने तक रैपर को जीवित रखना चाहिए
- उपलब्ध होने पर रूट PID और प्रक्रिया समूह आईडी की रिपोर्ट जीवनचक्र नियंत्रक को वापस करनी चाहिए
रैपर को सेशन नीति तय नहीं करनी चाहिए। वे केवल अपने अडैप्टर समूह के लिए स्थानीय प्रक्रिया-ट्री क्लीनअप लागू करते हैं।
सेशन दृश्यता अनुबंध
दृश्यता को सामान्यीकृत पंक्ति स्वामित्व का उपयोग करना चाहिए:
type SessionVisibilityInput = { requesterSessionKey: string; row: { key: string; agentId: string; ownerSessionKey?: string; spawnedBy?: string; parentSessionKey?: string; }; visibility: "self" | "tree" | "agent" | "all"; a2aPolicy: AgentToAgentPolicy;};नियम:
self: केवल अनुरोधकर्ता सेशन।tree: अनुरोधकर्ता सेशन और अनुरोधकर्ता के स्वामित्व वाली या उससे स्पॉन हुई पंक्तियाँ।all: समान एजेंट की सभी पंक्तियाँ, a2a-अनुमत क्रॉस-एजेंट पंक्तियाँ, और अनुरोधकर्ता-स्वामित्व वाली स्पॉन की गई क्रॉस-एजेंट पंक्तियाँ, सामान्य a2a अक्षम होने पर भी।agent: केवल समान एजेंट, जब तक कोई स्पष्ट स्वामी संबंध यह न बताए कि पंक्ति अनुरोधकर्ता की है।
इससे tree और all एकदिशीय हो जाते हैं: all को ऐसे स्वामित्व वाले चाइल्ड को नहीं छिपाना चाहिए
जिसे tree दिखाएगा।
माइग्रेशन योजना
चरण 1: पहचान और लीज़ जोड़ें
- Gateway स्टेट में
gatewayInstanceIdजोड़ें। - ACPX स्टेट डायरेक्टरी के अंतर्गत एक ACPX लीज़ स्टोर जोड़ें।
- जनरेट किया गया रैपर स्पॉन करने से पहले एक लीज़ लिखें।
- नए ACPX सेशन रिकॉर्ड पर
leaseIdसंग्रहित करें। - पुराने रिकॉर्ड के लिए मौजूदा PID और कमांड फ़ील्ड बनाए रखें।
चरण 2: लीज़-प्रथम क्लीनअप
- क्लोज़ क्लीनअप को पहले
leaseIdलोड करने के लिए बदलें। - सिग्नल भेजने से पहले लाइव प्रक्रिया स्वामित्व को लीज़ से सत्यापित करें।
- वर्तमान रूट PID और रैपर-रूट फ़ॉलबैक केवल विरासती रिकॉर्ड के लिए रखें।
- सत्यापित क्लीनअप के बाद लीज़ को
closedचिह्नित करें। - यदि क्लीनअप से पहले प्रक्रिया समाप्त हो चुकी हो, तो लीज़ को
lostचिह्नित करें।
चरण 3: लीज़-प्रथम स्टार्टअप रीपिंग
- स्टार्टअप रीपिंग खुली लीज़ को स्कैन करती है।
- प्रत्येक लीज़ के लिए रूट प्रक्रिया सत्यापित करें और वंशज एकत्र करें।
- सत्यापित ट्री को चाइल्ड-प्रथम क्रम में रीप करें।
- पुरानी
closedऔरlostलीज़ को सीमित अवधारण विंडो के साथ समाप्त करें। - कमांड-मार्कर स्कैनिंग को केवल अस्थायी विरासती फ़ॉलबैक के रूप में रखें, और जहाँ संभव हो उसे रैपर रूट तथा Gateway इंस्टेंस द्वारा सुरक्षित करें।
चरण 4: सेशन स्वामित्व पंक्तियाँ
- Gateway सेशन पंक्तियों में स्वामित्व मेटाडेटा जोड़ें।
- ACPX, सबएजेंट, बैकग्राउंड-टास्क और सेशन-स्टोर राइटर को
ownerSessionKeyयाspawnedByभरना सिखाएँ। - सेशन दृश्यता जाँच को पंक्ति मेटाडेटा का उपयोग करने के लिए बदलें।
- दृश्यता-समय की द्वितीयक
sessions.list({ spawnedBy })लुकअप हटाएँ।
चरण 5: विरासती ह्यूरिस्टिक हटाएँ
एक रिलीज़ विंडो के बाद:
- गैर-विरासती ACPX क्लीनअप के लिए संग्रहित रूट कमांड स्ट्रिंग पर निर्भर रहना बंद करें
- कमांड-मार्कर स्टार्टअप स्कैन हटाएँ
- दृश्यता फ़ॉलबैक सूची लुकअप हटाएँ
- अनुपलब्ध या असत्यापन योग्य लीज़ के लिए रक्षात्मक बंद-सुरक्षित व्यवहार बनाए रखें
परीक्षण
दो तालिका-संचालित सुइट जोड़ें।
प्रक्रिया जीवनचक्र सिम्युलेटर:
- असंबंधित प्रक्रिया द्वारा पुनः उपयोग किया गया PID
- दूसरे Gateway के रैपर रूट द्वारा पुनः उपयोग किया गया PID
- संग्रहित रैपर कमांड शेल-उद्धृत है, लाइव
psकमांड नहीं है - अडैप्टर चाइल्ड समाप्त हो जाता है, ग्रैंडचाइल्ड प्रक्रिया समूह में बनी रहती है
- पैरेंट मृत्यु का SIGTERM फ़ॉलबैक SIGKILL तक पहुँचता है
- प्रक्रिया सूची अनुपलब्ध है
- प्रक्रिया-विहीन बासी लीज़
- रैपर, अडैप्टर चाइल्ड और ग्रैंडचाइल्ड वाला स्टार्टअप ऑर्फ़न
सेशन दृश्यता मैट्रिक्स:
self,tree,agent,all- a2a सक्षम और अक्षम
- समान-एजेंट पंक्ति
- क्रॉस-एजेंट पंक्ति
- अनुरोधकर्ता-स्वामित्व वाली स्पॉन की गई क्रॉस-एजेंट ACP पंक्ति
- सैंडबॉक्स किया गया अनुरोधकर्ता
treeतक सीमित - सूची, इतिहास, भेजने और स्थिति की कार्रवाइयाँ
महत्वपूर्ण अपरिवर्तनीयता: अनुरोधकर्ता-स्वामित्व वाला स्पॉन किया गया चाइल्ड वहाँ हर जगह दृश्यमान है
जहाँ कॉन्फ़िगर की गई दृश्यता अनुरोधकर्ता सेशन ट्री को शामिल करती है, और all,
tree से कम सक्षम नहीं है।
संगतता टिप्पणियाँ
पुराने सेशन रिकॉर्ड में leaseId नहीं हो सकता। उन्हें विरासती
बंद-सुरक्षित क्लीनअप पथ का उपयोग करना चाहिए:
- एक लाइव रूट प्रक्रिया आवश्यक है
- जहाँ जनरेट किया गया रैपर अपेक्षित हो, वहाँ रैपर-रूट स्वामित्व आवश्यक है
- गैर-रैपर रूट के लिए कमांड की सहमति आवश्यक है
- केवल बासी संग्रहित PID मेटाडेटा के आधार पर कभी सिग्नल न भेजें
यदि किसी विरासती रिकॉर्ड को सत्यापित नहीं किया जा सकता, तो उसे वैसा ही छोड़ दें। स्टार्टअप लीज़ क्लीनअप और अगली रिलीज़ विंडो को अंततः फ़ॉलबैक को समाप्त कर देना चाहिए।
सफलता मानदंड
- पुराना या बासी ACPX सेशन बंद करने पर दूसरे Gateway की प्रक्रिया समाप्त नहीं हो सकती।
- पैरेंट की मृत्यु के बाद अड़ियल अडैप्टर ग्रैंडचाइल्ड प्रक्रियाएँ चलती नहीं रहतीं।
cancelपुनः उपयोग योग्य सेशन बंद किए बिना सक्रिय टर्न को निरस्त करता है।sessions_list,treeऔरallदोनों के अंतर्गत अनुरोधकर्ता-स्वामित्व वाले क्रॉस-एजेंट ACP चाइल्ड दिखा सकता है।- स्टार्टअप क्लीनअप लीज़ द्वारा संचालित होता है, व्यापक कमांड-स्ट्रिंग स्कैन द्वारा नहीं।
- केंद्रित प्रक्रिया और दृश्यता मैट्रिक्स परीक्षण उन सभी सीमांत मामलों को कवर करते हैं जिनके लिए पहले एकबारगी समीक्षा सुधारों की आवश्यकता पड़ती थी।