أتمتة سطح المكتب المُدارة

adk-computer-use هي طبقة حوكمة فوق خادم أتمتة سطح المكتب computer-use-mcp. لا تقوم بأي تنفيذ بنفسها: بل ترتّب الملاحظة، والموافقة، والتعديل، والتحقق على شكل رسم بياني حتمي، وتفحص ما يعيده وقت التشغيل الخارجي.

ربط الاستجابة

يُعدّ وقت التشغيل الخارجي هو المرجع المعتمد، لكن تتم مراجعة استجاباته محليًا قبل دخولها إلى حالة الرسم البياني. تُنفَّذ عمليات الفحص في الرسم البياني المرجعي لكل تطبيق ComputerUseRuntime، ويعيد محول MCP تنفيذها عند حد الاستدعاء المباشر. يثبت إلغاء التسلسل المُمَنعَن البنية، لا المصدر — إذ إن ControlLease وTargetReservation وExecutionReceipt لا تملك مُنشئًا يفرض الثوابت، لذا فإن كائنًا سليم البنية ينتمي إلى جلسة مختلفة يُحلَّل بشكل صحيح.

يُربط كل ردّ من جديد بالطلب الذي أنشأه:

الاستجابةتم التحقق منها مقابل الظرف
ControlLeasesession_id، principal_id، agent_id، execution_mode، الحالة النشطة، expires_at غير منتهٍ، الميزانية المتبقية (actions_used < action_budget)، والهدف ضمن boundaries
TargetReservationsession_id، principal_id، agent_id، execution_group_id، intent_id == action_id، الحالة النشطة، expires_at غير منتهٍ، ونطاق الهدف الدقيق للتطبيق/النافذة
ExecutionReceiptsession_id، action_id، وaction_digest مقابل args_digest الخاص بالظرف

يؤدي عدم التطابق إلى ComputerUseError::IdentityMismatch مع تسمية الحقل، ويُرفَض الرد بدلاً من تخزينه.

use adk_computer_use::runtime::binding::validate_lease;

// Refuses a lease that is well-formed but belongs to another session.
validate_lease(&lease, &envelope)?;

ملاحظة: الملخّص هو أقوى ربط متاح. args_digest هو ما تم منح الموافقة عليه، لذا فإن إيصالًا يحمل ملخّصًا مختلفًا يصف عملًا مختلفًا حتى عندما تتطابق كل المعرفات.

يُعامَل الحقل الاختياري الذي يعود غائبًا على أنه نقص في التحديد، لا تناقضًا؛ أمّا الحقل الموجود والمختلف فهو عدم تطابق.

إعادة التحقق وقت التنفيذ

المعاينة ليست سلطة للتعديل. يعيد الرسم البياني المرجعي التحقق من صحة جميع مدخلات التعديل في عقدة execute مباشرةً قبل استدعاء execute_action:

المدخلفحص فوري
ActionEnvelopeطوابع زمنية RFC 3339، نافذة صلاحية موجبة، وnow < expires_at
ControlLeaseالهوية، الوضع، الحالة النشطة، الميزانية المتبقية، انتهاء الصلاحية، وحدود الهدف
TargetReservationالهوية، نية الإجراء، الحالة النشطة، انتهاء الصلاحية، ونطاق الهدف الدقيق
الموافقةالمسار، ملخص الإجراء، ملخص السياسة، ومصدر تفويض واحد بالضبط (grantId أو الموافقة المحتفظ بها في وقت التشغيل)

يتم أيضًا تشغيل فحص الظرف عند عودة المعاينة، لذلك لا تصل المعاينة التي انتهت صلاحيتها بالفعل إلى الحجز أو الموافقة. ويُعاد تشغيله أثناء التنفيذ لأن مقاطعة الموافقة أو حجز الهدف أو الحصول على الإيجار يمكن أن يستهلك نافذة الصلاحية المتبقية.

ComputerUseMcpRuntime يحتفظ بالظرف نفسه الذي أرجعته preview_action. يتم رفض استدعاء مباشر لـ execute_action إذا تغيّر أي حقل في الظرف بعد المعاينة، حتى عندما يظل معرّف الإجراء مطابقًا.

بالنسبة لاستئناف نقطة التفتيش، يخزّن الرسم البياني معاينة وقت التشغيل في قناة حالة للإضافة فقط. تتطلب الموافقة والتنفيذ أن تحتوي تلك القناة على معاينة واحدة فقط تطابق المعاينة النشطة. يمكن لمدخلات الاستئناف إضافة حالة ولكن لا يمكنها استبدال القيمة المُسجَّلة في نقطة التفتيش: إن محاولة الاستبدال تنشئ إدخالًا ثانيًا وتفشل قبل الحجز أو التعديل.

تنظيف الحجز

بمجرد قبول الحجز، تحاول كل المسارات النهائية تحريره:

  • فشل الحصول على الإيجار أو التفويض أو التحقق أو التنفيذ أو الاستلام أو التحقق النهائي؛
  • التحقق النهائي الناجح؛ و
  • فشلات التحقق من الحجز أو التسلسل عندما كانت بيئة التشغيل قد أرجعت حجزًا.

يظل الفشل الأساسي هو الأساسي عندما ينجح التنظيف. وإذا فشل التنظيف أيضًا، يعيد الرسم البياني خطأً واحدًا حتميًا يحتوي على كلا الفشلين. يُعاد فشل التنظيف بعد تحقق ناجح بخلاف ذلك على أنه خطأ بدلًا من إخفائه.

التحقق ليس التزامًا

ComputerUseRuntime::verify تُرجع VerificationOutcome، لا قيمة منطقية:

النتيجةالمعنىis_verified()is_committed()status()
Verifiedتمت ملاحظة أن الشرط اللاحق المُعلن متحققtruetruecompleted
CommittedUnverifiedنفّذ وقت التشغيل الإجراء؛ لا توجد أدلة على الشرط اللاحقfalsetruecommitted_unverified
Failedغير مُعتمد، أو أن الأدلة تتعارض مع الشرط اللاحقfalsefalseverification_failed

تكتب العقدة verify في الرسم البياني verified وcommitted وresult.verificationDetail تشرح أي شيء يقلّ عن Verified.

مهم: الإيصال المُسجَّل هو تأكيد بأن الإجراء قد تم قبوله وتنفيذه. وهو ليس دليلاً على أن الأثر المقصود قد حدث. كانت verify تُرجع سابقًا receipt.status == Committed، والتي كانت تُبلِغ عن إجراء مُسجَّل لكنه غير فعّال على أنه مكتمل — من عقدة مُعنونة "verify".

ما الذي يُعدّ دليلاً

بالنسبة إلى شرط لاحق يعلن عن ملخّص تجزئة (valueDigest، contentDigest)، تتطلب عملية التحقق وجود verification.observedDigest على نتيجة الإيصال يطابقه. بالنسبة إلى شرط لاحق يعلن الوجود فقط، يلزم وجود verification.satisfied: true صريح.

دليل الاستلامالنتيجة
verification.satisfied: falseFailed — ملاحظة سلبية صريحة
observedDigest يطابق الملخص المتوقعVerified
يختلف observedDigestFailed
لا يوجد كائن verificationCommittedUnverified
verification موجود، لا يوجد observedDigest، يُتوقع digestCommittedUnverified

غياب الدليل لا يُعامَل أبدًا على أنه دليل على النجاح. إذا تحققت computer-use-mcp قبل إصدار إيصال، فذلك هو عقدها؛ هذا المهايئ لا يفترض ذلك.

حدود الإيجار

يُرفض الإيجار ما لم تتحقق جميع الشروط التالية:

التحققيُرفض عندما
انتهاء الصلاحيةexpires_at في الماضي، أو لا يمكن تحليلها وفق RFC 3339
الميزانية المتبقيةactions_used >= action_budget
حدّ الهدفغلاف target.app_id غير موجود في boundaries.app_ids غير فارغ
حدّ النافذةغلاف target.window_id غير موجود في boundaries.window_ids غير فارغ

تعني الحدود الفارغة "غير مُحددة النطاق" وتخوّل أي هدف — إن غياب القيد ليس قيدًا على لا شيء.

مهم: تحققت النسخة الأولى من هذا المصدّق من action_budget == 0، وهو إجمالي الميزانية، لذا اجتازت رسالة الإيجار ذات action_budget: 1, actions_used: 1 مع تخويل لا شيء. كما أنها لم تقرأ أبدًا expires_at أو boundaries، لذلك قُبل كلٌّ من رسالة إيجار منتهية الصلاحية ورسالة إيجار محددة لتطبيق مختلف. يُرفض انتهاء الصلاحية غير القابل للتحليل بدلًا من تجاهله: رسالة الإيجار التي لا يمكن إثبات صلاحيتها ليست صالحة.

أتمتة سطح المكتب المُدارة - وثائق ADK-Rust | ADK-Rust