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 وحفظه في الحالة طوال عمر ذلك التثبيت. ليس سرا أمنيا؛ بل مميز ملكية يُستخدم لتجنب الخلط بين عمليات ACP الخاصة بـ Gateway وعمليات 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: إضافة الهوية والعهد
- أضف
gatewayInstanceIdإلى حالة Gateway. - أضف مخزن عهد ACPX تحت دليل حالة ACPX.
- اكتب عهدة قبل توليد غلاف مولد.
- خزّن
leaseIdفي سجلات جلسات ACPX الجديدة. - أبقِ حقول PID والأمر الحالية للسجلات القديمة.
المرحلة 2: التنظيف وفق العهدة أولا
- غيّر تنظيف الإغلاق ليحمّل
leaseIdأولا. - تحقق من ملكية العملية الحية مقابل العهدة قبل إرسال الإشارات.
- أبقِ احتياطي PID الجذر الحالي وجذر الغلاف للسجلات القديمة فقط.
- علّم العهد بأنها
closedبعد التنظيف المتحقق منه. - علّم العهد بأنها
lostعندما تكون العملية قد اختفت قبل التنظيف.
المرحلة 3: جمع بدء التشغيل وفق العهدة أولا
- يمسح جمع بدء التشغيل العهد المفتوحة.
- لكل عهدة، تحقق من عملية الجذر واجمع التوابع.
- اجمع الأشجار المتحقق منها من الأبناء أولا.
- أنهِ صلاحية العهد القديمة ذات الحالة
closedوlostضمن نافذة احتفاظ محدودة. - أبقِ مسح علامات الأوامر كاحتياطي تراثي مؤقت فقط، محميا بجذر الغلاف ومثيل Gateway حيثما أمكن.
المرحلة 4: صفوف ملكية الجلسات
- أضف بيانات الملكية الوصفية إلى صفوف جلسات Gateway.
- علّم كتّاب ACPX والوكيل الفرعي ومهمة الخلفية ومخزن الجلسات ملء
ownerSessionKeyأوspawnedBy. - حوّل فحوصات رؤية الجلسات لاستخدام البيانات الوصفية للصف.
- أزِل عمليات البحث الثانوية
sessions.list({ spawnedBy })في وقت الرؤية.
المرحلة 5: إزالة الاستدلالات القديمة
بعد نافذة إصدار واحدة:
- أوقف الاعتماد على سلاسل أمر الجذر المخزنة لتنظيف ACPX غير القديم
- أزِل عمليات مسح علامات الأوامر عند بدء التشغيل
- أزِل عمليات البحث الاحتياطية في القوائم للرؤية
- أبقِ سلوك الفشل المغلق الدفاعي للعهد المفقودة أو غير القابلة للتحقق
الاختبارات
أضف مجموعتين قائمتين على الجداول.
محاكي دورة حياة العملية:
- إعادة استخدام PID بواسطة عملية غير مرتبطة
- إعادة استخدام PID بواسطة جذر غلاف Gateway آخر
- أمر الغلاف المخزن مقتبس في الصدفة، وأمر
psالحي ليس كذلك - خروج ابن المهايئ، وبقاء الحفيد في مجموعة العملية
- احتياطي SIGTERM عند موت الأصل يصل إلى SIGKILL
- قائمة العمليات غير متاحة
- عهدة قديمة مع عملية مفقودة
- يتيم بدء تشغيل مع غلاف، وابن مهايئ، وحفيد
مصفوفة رؤية الجلسات:
selfوtreeوagentوall- a2a مفعلة ومعطلة
- صف الوكيل نفسه
- صف عابر للوكلاء
- صف ACP عابر للوكلاء ومولّد ومملوك لمقدم الطلب
- مقدم طلب في صندوق رمل مقيّد إلى
tree - إجراءات القائمة والسجل والإرسال والحالة
الثابت المهم: يكون الفرع المولّد والمملوك لمقدم الطلب مرئيا حيثما تشمل
الرؤية المضبوطة شجرة جلسة مقدم الطلب، ولا تكون all أقل قدرة من tree.
ملاحظات التوافق
قد لا تحتوي سجلات الجلسات القديمة على leaseId. يجب أن تستخدم مسار التنظيف
القديم ذي الفشل المغلق:
- اشتراط وجود عملية جذر حية
- اشتراط ملكية جذر الغلاف عندما يكون غلاف مولد متوقعا
- اشتراط توافق الأمر للجذور غير المغلفة
- عدم إرسال إشارة أبدا بناء فقط على بيانات PID الوصفية المخزنة القديمة
إذا تعذر التحقق من سجل قديم، فاتركه كما هو. يجب أن يؤدي تنظيف العهد عند بدء التشغيل ونافذة الإصدار التالية في النهاية إلى تقاعد الاحتياطي.
معايير النجاح
- لا يمكن لإغلاق جلسة ACPX قديمة أو راكدة أن يقتل عملية Gateway آخر.
- لا يترك موت الأصل أحفاد مهايئ عنيدين قيد التشغيل.
- يجهض
cancelالدور النشط من دون إغلاق الجلسات القابلة لإعادة الاستخدام. - تستطيع
sessions_listعرض أبناء ACP العابرين للوكلاء والمملوكين لمقدم الطلب تحت كل منtreeوall. - يعتمد تنظيف بدء التشغيل على العهد، لا على مسوح واسعة لسلاسل الأوامر.
- تغطي اختبارات مصفوفة العمليات والرؤية المركزة كل حالة حافة كانت تتطلب سابقا إصلاحات مراجعة مخصصة.