إنشاء عميل أو مضيف ACP
استخدم اتجاه العميل عندما تحتاج تطبيقات ADK-Rust إلى تفويض أعمال البرمجة إلى عملية ACP خارجية. يظل التطبيق هو المضيف: فهو يملك اختيار المشروع، وتجربة المستخدم، وقواعد الموافقة، وأي خدمات محلية متاحة لوكيل البرمجة.
التثبيت
[dependencies]
adk-acp = "2.1.0"
مجموعة الميزات الافتراضية هي تنفيذ العميل. لا تكون ميزة server مطلوبة إلا عند إتاحة وكيل ADK-Rust.
اختيار شكل العميل
| شكل المنتج | API |
|---|---|
| مهمة معزولة واحدة مع عملية جديدة | prompt_agent_with_policy |
| مهمة معزولة واحدة مع محتوى غير نصي (صورة، صوت، مورد) | prompt_agent_content_with_policy |
| متخصص برمجة متاح لوكيل LLM | AcpAgentTool |
| عدة متخصصين في البرمجة بأسماء محددة | AcpToolset |
| محادثة مستمرة حول مشروع | AcpSession |
| تقدّم النص والأداة المعروض أثناء تشغيل الدورة | stream_prompt |
مطالبة من دفعة واحدة
use adk_acp::{
AcpAgentConfig, PermissionPolicy, prompt_agent_with_policy,
};
use std::sync::Arc;
let config = AcpAgentConfig::new("my-coding-agent --acp")
.working_dir("/absolute/path/to/project");
let answer = prompt_agent_with_policy(
&config,
"Inspect the failing test and explain the cause.",
Arc::new(PermissionPolicy::DenyAll),
).await?;
DenyAll هو الإعداد الافتراضي لأن وكيل البرمجة المُنشأ يمكنه طلب عمليات
ذات آثار جانبية فعلية. استخدم AutoApprove فقط داخل سير عمل محلي موثوق.
إرسال محتوى مطالبة غني
ينقل prompt_agent_content_with_policy قيمة adk_core::Content كاملة —
وليس مجرد سلسلة نصية — بحيث يمكن للمطالبة أن تحمل محتوى غير نصي. تُحوَّل الأجزاء
المضمَّنة للموارد والصور والصوت إلى كتلة المحتوى المطابقة ACP من خلال
وحدة المحتوى المشتركة بدلاً من إسقاطها؛ ويُحافَظ دائماً على النص. أما الأجزاء
التي لا تملك تمثيلاً قابلاً للنقل لـ ACP فتُتخطى، وتُرفض المطالبة التي لا
تُحوَّل إلى أي كتل على الإطلاق.
use adk_acp::{AcpAgentConfig, PermissionPolicy};
use adk_acp::connection::prompt_agent_content_with_policy;
use adk_core::{Content, Part};
use std::sync::Arc;
let mut content = Content::new("user");
content.parts.push(Part::Text { text: "What is in this image?".into() });
content.parts.push(Part::InlineData { mime_type: "image/png".into(), data: png_bytes });
let config = AcpAgentConfig::new("my-coding-agent --acp")
.working_dir("/absolute/path/to/project");
let answer = prompt_agent_content_with_policy(
&config,
&content,
Arc::new(PermissionPolicy::DenyAll),
).await?;
التفويض من وكيل ADK
use adk_acp::{AcpAgentTool, PermissionDecision, PermissionPolicy};
use adk_agent::LlmAgentBuilder;
use std::sync::Arc;
let policy = PermissionPolicy::Custom(Box::new(|request| {
if request.title.to_ascii_lowercase().contains("delete") {
PermissionDecision::deny()
} else {
PermissionDecision::allow_once()
}
}));
let coding_agent = AcpAgentTool::new("my-coding-agent --acp")
.name("repository_specialist")
.description("Inspect and improve the current Rust repository")
.working_dir("/absolute/path/to/project")
.permission_policy(policy);
let coordinator = LlmAgentBuilder::new("coordinator")
.model(model)
.instruction("Delegate repository changes to repository_specialist.")
.tool(Arc::new(coding_agent))
.build()?;
تبدأ كل استدعاءة لـ AcpAgentTool عملية وجلسة جديدتين. اختر هذا الشكل
عندما تكون المهمة المفوَّضة مستقلة ويحتاج المنسق إلى النص النهائي فقط كنتيجة
للأداة.
الجلسات المستمرة والإلغاء
use adk_acp::{AcpAgentConfig, AcpSession, PermissionPolicy};
use std::sync::Arc;
let config = AcpAgentConfig::new("my-coding-agent --acp")
.working_dir("/absolute/path/to/project");
let mut session = AcpSession::start(
config,
Arc::new(PermissionPolicy::DenyAll),
).await?;
let first = session.prompt("Map the error-handling modules.").await?;
let second = session.prompt("Now inspect the most central one.").await?;
let cancel = session.cancellation_handle()?;
// Move `cancel` into a stop-button, timeout, or shutdown task while another
// task awaits `session.prompt(...)`.
session.close().await?;
ترسل أداة الإلغاء المعرّف الرسمي لإشعار session/cancel. ينبغي أن تظل
المطالبة قيد الانتظار حتى وصول سبب التوقف الناتج عن الإلغاء؛ فهذا يتيح للجلسة
نفسها قبول مطالبة أخرى من دون وجود استجابة قديمة في قائمة الانتظار الخاصة بها.
بث جولة إلى واجهة مستخدم
يُنتج stream_prompt قيماً من OutputChunk لنص الوكيل، والأفكار، وبدء
الأدوات، وقرارات الأذونات، والإكمال، والأخطاء. بالإضافة إلى ذلك، يعرض
منظورين أكثر ثراءً لجولة External_Agent:
OutputChunk::ToolUpdate— External_Agent'sToolCallUpdate، المرتبطة بواسطة استدعاء الأداةid، وتحمل الحالة المُبلّغ عنها، والنوع، والعنوان المحدّث، ونص المحتوى المستخرج، ومواقع الملفات المتأثرة. يتيح ذلك لواجهة المستخدم عرض تقدّم الأداة، والفروقات، وقوائم الملفات المتأثرة بدلاً من عرض النص النهائي فقط.OutputChunk::Usage— External_Agent'sUsageUpdate، وتحمل الرموز المميزةusedونافذة السياقsize، بالإضافة إلىcostوcurrencyالتراكميين عندما يبلّغ عنهما الوكيل، بحيث تتمكن واجهة المستخدم من عرض استهلاك نافذة السياق.
يُعرض نص رسالة الوكيل تماماً كما كان من قبل، لذا لن يتأثر التطبيق الذي يقرأ أجزاء النص فقط. ويمكن للتطبيق إخفاء أجزاء التفكير، وعرض نشاط الأداة بشكل منفصل، وإظهار StatusTracker المشترك في واجهته.
راجع crate القابل للتشغيل acp_client_host للاطلاع على الحلقة الكاملة.
السماح للوكيل بطلب الملفات
نفّذ AcpFileSystem وأرفقه باستخدام AcpAgentConfig::filesystem. ويُعلَن عن إمكانات القراءة
والكتابة بشكل مستقل من خلال supports_read وsupports_write.
يتلقى الاستدعاء مسارات مطلقة. وينبغي للمضيف في بيئة الإنتاج أن:
- يطبّع مساحة العمل المعتمدة والمسار المطلوب؛
- يرفض المسارات الواقعة خارج الجذور المعتمدة، بما في ذلك حالات تجاوز الروابط الرمزية؛
- يحدّد ما إذا كانت مخازن المحرر غير المحفوظة تتجاوز محتوى القرص؛
- يطبّق حدوداً لحجم الملف ونطاق الأسطر؛
- لا يعلن عن إمكانات الكتابة إلا عندما ينفّذ التطبيق هذه الإمكانات ويصرّح بها.
دليل العمل هو سياق وليس بيئة عزل. وتتعامل عملية التحقق من نظام الملفات وحدّ عملية نظام التشغيل مع مشكلتين مختلفتين.
السماح للوكيل بتشغيل الأوامر
نفّذ AcpTerminal وأرفقه باستخدام AcpAgentConfig::terminal. ويعلن ACP
عن الطرفية كإحدى الإمكانات، ولذلك يجب على المضيف تنفيذ دورة الحياة الكاملة
للإنشاء، والإخراج، والانتظار، والإنهاء، والتحرير.
يختار المضيف قوائم السماح للأوامر، وقواعد دليل العمل، ومتغيرات البيئة، وحدود الإخراج، وعزل العمليات، وسلوك التنظيف. تُنفَّذ استدعاءات الطرفية خارج حلقة توزيع JSON-RPC، بحيث لا يؤدي الانتظار الطويل إلى تجميد حركة الأذونات أو الإلغاء.
توفير خادم MCP للجلسة
use adk_acp::AcpAgentConfig;
use adk_acp::agent_client_protocol::schema::v1::{
McpServer, McpServerStdio,
};
let tools = McpServer::Stdio(
McpServerStdio::new("project-tools", "/absolute/path/to/mcp-server")
.args(vec!["--read-only".into()]),
);
let config = AcpAgentConfig::new("my-coding-agent --acp")
.working_dir("/absolute/path/to/project")
.mcp_server(tools);
يتطلب الإصدار v1 المستقر من ACP أن تقبل الوكلاء إعداد MCP عبر stdio. لا تُرسل إدخالات HTTP وSSE إلا عندما يعلن الوكيل الخارجي عن وسائل النقل الاختيارية تلك. يسرد إخراج التصحيح AcpAgentConfig الأسماء ومفاتيح البيئة دون طباعة قيم الأسرار.
سياسات الأذونات
يتضمن كل طلب إذن معرّف الجلسة، ومعرّف استدعاء الأداة الدقيق، ونوع الأداة، والمدخلات الأولية، وجميع الخيارات التي يقدّمها الوكيل. ومعرّفات الخيارات غير شفافة. يطابق ADK-Rust دلالات السماح والرفض، ثم يعيد المعرّف الأصلي؛ ويؤدي الاختيار المُختلق إلى الإلغاء.
يمكن لـ PermissionPolicy::async_custom انتظار مربع حوار على سطح المكتب، أو واجهة موافقة على الويب، أو خدمة سياسة المؤسسة. حافظ على استجابة حلقة التوزيع من خلال انتظار تفاعل المستخدم عبر API بدلًا من حجب سلسلة تنفيذ.