الوثائق
اكتب مكونًا إضافيًا للأداة المساعدة
أنشئ أداة قراءة قائمة بذاتها، وتحقق من صحة بيانها ووسائطها، وقم بتمكينها عمدًا، واختبر حدود العامل التي تتلقاها بالفعل.
مترجم تلقائيًا من الإنجليزية. عرض الأصل بالإنجليزية
اختر تنسيق ملحق المساعد
يقبل مُحمل ملحق مساعد الإنتاج دليلاً يحتوي على plugin.json وإدخال JavaScript مُجمّع. يقوم باستيراد الوحدة إلى عامل Bun ويكشف عن الوظائف المعلنة من سجل aiTools الخاص به إلى المساعد. القدرة المدعومة حاليًا هي ai:tool. ينشئ هذا الدليل حاسبة لدائرة الترباس للقراءة فقط والتي تُرجع الإحداثيات؛ ولا يقوم بإدراج الشكل الهندسي في الرسم.
يوجد أيضًا مكون إضافي للمتصفح ZIP API ضمن /api/plugins مع البيان.json والرئيسي وأذونات المتصفح وأصول التمهيد. لا يقوم هذا المثبت بتمكين المكون الإضافي العامل الموضح هنا. ال مرجع HTTP المساعد المستندات التي تفصل بين التنسيق؛ الإضافات يشرح كلا السطحين. لا تترجم بينهما بمجرد إعادة تسمية البيان.
الأداة المساعدة هي تعليمات برمجية يتم تنفيذها داخل حدود وقت تشغيل التطبيق. تعمل عمليات التحقق من قدرة المضيف على تقييد الوصول من خلال RPC المضيف، ولكن العامل الحالي ليس بمثابة وضع حماية لنظام التشغيل. استخدم رمز الامتداد الذي يكون تنفيذه مناسبًا لتلك البيئة، واجعل سلوك القراءة/الكتابة المعلن عنه يتوافق مع ما تفعله الوظيفة بالفعل.
قم بإنشاء الدليل وسجل الموافقة
استخدم دليل بيانات التطبيق الدقيق للعربة السايدكار التي تنوي توسيعها. قم بإنشاء هذه البنية، مع الحفاظ على معرف الدليل مطابقًا لمعرف DNS العكسي للبيان:
<dataDir>/plugins/
enabled.json
com.example.bolt-circle/
plugin.json
index.js يقوم مُحمل الإنتاج بقراءة Enabled.json كمصفوفة JSON من المعرفات الآمنة. فهو يتجاهل الإدخالات المكررة/غير الصالحة، ويعني وجود JSON المشوه أو المفقود أنه لم يتم تمكين أي مكونات إضافية. لم يتم تحميل مجلد غير مدرج. يرفض المُحمل أيضًا عدم تطابق معرف المجلد/البيان والبيانات التي تتطلب إمكانات غير مدعومة.
يحدث التحميل عند تهيئة خدمة البرنامج المساعد المساعد. لا يقوم بتكوين مراقب نظام الملفات لإعادة التحميل السريع. قم بإعداد الملفات والتحقق من صحتها أولاً، ثم قم بتمكين/إعادة تشغيل هذا المثيل. يقوم المكون الإضافي الفاشل بتسجيل تحذير أثناء استمرار تشغيل المكونات الإضافية والتطبيقات الأخرى؛ قم بفحص هذه التحذيرات بدلاً من افتراض أن إدخال الملف الممكّن يضمن وجود أداة قيد التشغيل.
أعلن عن عقد أداة دقيقة
يسمي هذا البيان الكامل أداة قراءة واحدة. معرف المساهمة هو المعرف المحلي الذي يواجه النموذج؛ يسمي الإدخال الوظيفة المصدرة بواسطة الوحدة. قد تختلف هذه السلاسل، كما تفعل هنا Bolt_circle وboltCircle.
{
"id": "com.example.bolt-circle",
"name": "Bolt circle calculator",
"version": "1.0.0",
"apiVersion": "1",
"entry": "index.js",
"capabilities": ["ai:tool"],
"contributes": {
"aiTools": [{
"id": "bolt_circle",
"description": "Calculate equally spaced XY hole centers around the origin for a bolt circle. Returns coordinates without changing a drawing.",
"kind": "read",
"entry": "boltCircle",
"parameters": {
"type": "object",
"properties": {
"count": { "type": "integer", "minimum": 1, "maximum": 64 },
"radius": { "type": "number", "exclusiveMinimum": 0 }
},
"required": ["count", "radius"],
"additionalProperties": false
}
}]
}
} يتطلب SDK معرفات DNS العكسية المكونة من 3–128 من الأحرف، وإصدار main.minor.patch الدلالي مع إصدار تجريبي اختياري، وإصدار API "1"، واسم/إدخال غير فارغ، وإمكانيات معروفة. تبدأ معرفات الأدوات بحرف صغير وتستخدم أحرفًا صغيرة أو أرقامًا أو شرطات سفلية تصل إلى 40 حرفًا. تحتوي الأوصاف على 10–2،000 أحرف. نوع الأداة للقراءة أو الكتابة؛ لا يوجد نوع امتداد مدمر.
اجعل مخطط المعلمة صغيرًا ووصفيًا. ويتمثل دورها في مساعدة النموذج على إنتاج وسائط صالحة والسماح للمحول برفض الأخطاء العادية قبل التنفيذ. ولا يحل محل التحقق من الصحة داخل التعليمات البرمجية.
تنفيذ الوحدة القائمة بذاتها
يقوم الإدخال بتصدير aiTools مع وظيفة الإدخال المذكورة في البيان. يقوم بالتحقق من صحة وسيطات وقت التشغيل مرة أخرى ويعيد نتيجة صغيرة متوافقة مع JSON. يعمل حساب الإحداثيات المحدود والعد المحدود على منع المدخلات المشوهة من إنتاج قائمة غير محدودة أو مخرجات لا معنى لها.
export const aiTools = {
boltCircle: async (args) => {
if (!args || typeof args !== "object") {
return { ok: false, error: "Expected count and radius" }
}
const { count, radius } = args
if (!Number.isInteger(count) || count < 1 || count > 64) {
return { ok: false, error: "count must be an integer from 1 to 64" }
}
if (typeof radius !== "number" || !Number.isFinite(radius) || radius <= 0) {
return { ok: false, error: "radius must be a positive finite number" }
}
const holes = Array.from({ length: count }, (_, index) => {
const angle = 2 * Math.PI * index / count
return {
x: Number((radius * Math.cos(angle)).toFixed(4)),
y: Number((radius * Math.sin(angle)).toFixed(4))
}
})
return { ok: true, units: "mm", holes }
}
} Count 4 and radius 10 return centers at approximately (10,0), (0,10), (−10,0), and (0,−10), in counter-clockwise order around the origin. The result deliberately contains no database mutation or drawing identifier. A client wanting to insert holes must use a separate supported application action with its own access and permission behavior.
قم بتجميع التبعيات في الإدخال بدلاً من افتراض حل الواردات النسبية لنمط العقدة. يقرأ المضيف نص الإدخال ويستورده من خلال وحدة blob. يتم تشغيل التعليمات البرمجية ذات المستوى الأعلى للوحدة عند الاستيراد، لذا تجنب الآثار الجانبية الناجمة عن مجرد تحميل الآلة الحاسبة.
التحقق من صحة البيان ومساري الوسيطة
تحقق من صحة الأمر قبل إضافة المكوّن الإضافي إلى Enable.json. يستخدم فحص التطوير هذا نفس محلل بيان SDK ومحول مخطط AI مثل التطبيق. ضع البرنامج النصي في مساحة عمل تحتوي على تلك التبعيات، مثل التطبيقات/السايدكار، وقم بتمرير دليل البرنامج الإضافي المطلق كوسيطة له.
import { join } from "node:path"
import { Effect } from "effect"
import { parseManifest } from "@cadcamfun/plugin-sdk"
import { pluginParameters } from "@cadcamfun/ai"
const directory = process.argv[2]
if (!directory) throw new Error("Pass the absolute plugin directory")
const manifest = await Effect.runPromise(parseManifest(
await Bun.file(join(directory, "plugin.json")).text()))
if (manifest.capabilities.some((capability) => capability !== "ai:tool")) {
throw new Error("This production loader accepts only ai:tool")
}
const contribution = manifest.contributes?.aiTools?.[0]
if (!contribution) throw new Error("No tool contribution")
const parameters = pluginParameters(contribution.parameters)
console.log(parameters.safeParse({ count: 4, radius: 10 }).success) // true
console.log(parameters.safeParse({ count: 0, radius: 10 }).success) // false
const module = await import(join(directory, manifest.entry))
console.log(await module.aiTools[contribution.entry]({ count: 4, radius: 10 }))
console.log(await module.aiTools[contribution.entry]({ count: 0, radius: 10 })) تقوم آخر مكالمتين باختبار سلوك مستوى الوظيفة بشكل مستقل عن رفض المحول. تتحقق SDK من صحة بنية البيان، لكن أداة تحميل الإنتاج تضيف إمكاناتها الخاصة وقواعد معرف المجلد. اختبر الحدود الثلاثة كلها: الإعلان، ومحول الوسيطة، ووظيفة الوحدة الفعلية.
تمكين واكتشاف معرف الأداة الفعلي
بعد التحقق من الصحة، قم بتمكين المعرف في دليل بيانات التطبيق:
["com.example.bolt-circle"] أعد تشغيل/إعادة تهيئة الخدمة السايدكار المقصودة وافحص السجلات بحثًا عن تحذيرات التحميل. ثم القائمة GET /api/ai/actions. يتم عرض أدوات القراءة الإضافية هناك وكذلك للمساعد المضمن؛ يمكن للسياسة تضييق الكتالوج. يتم إنشاء معرف الأداة من معرف البرنامج المساعد ومعرف الأداة المحلية، ويتم تطبيعه وتقييده بحجم معرف المضيف.
بالنسبة لهذا البيان، المعرف المشتق الحالي هو plugin_com_example_bolt_circle_bolt_circle. اكتشفها بدلاً من إعادة تطبيق قاعدة التسمية في كل عميل. قد يتم اقتطاع معرف البرنامج الإضافي الطويل لإفساح المجال للاحقة الأداة. يتضمن وصف الكتالوج اسم البرنامج المساعد حتى يتمكن المستخدم من تحديد المصدر.
يتم وضع علامة على أداة الكتابة للموافقة البشرية في المساعد المضمن، بغض النظر عن وضع الإذن العادي. يعرض الجسر الخارجي أدوات المكونات الإضافية للقراءة فقط ويرفض مكالمات تمديد الكتابة حتى باستخدام رمز القراءة/الكتابة. حافظ على دقة النوع؛ لا يمكن للتطبيق استنتاج تأثيرات جانبية عشوائية للوحدة من مخطط JSON.
استدعاء أداة القراءة من خلال الوصول الخارجي المحدد
استخدم رمز الجسر الصادر عن التطبيق لمشروع حقيقي. يفتح حامله فقط GET /api/ai/actions وPOST /api/ai/actions/invoc. ولا يسمح للمتصلين بتثبيت المكونات الإضافية أو تحرير بيانات الاعتماد أو تعداد المشاريع غير ذات الصلة. يتم فحص مشروع/وضع الرمز المميز بواسطة معالج الإجراء؛ الرمز المميز على مستوى التطبيق غير ضروري لعميل الآلة الحاسبة المستقل.
{
"projectId": "replace-with-your-project-id",
"tool": "plugin_com_example_bolt_circle_bolt_circle",
"input": { "count": 4, "radius": 10 }
} curl --fail-with-body \
-H "Authorization: Bearer $CADCAMFUN_BRIDGE_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @bridge-call.json \
"$CADCAMFUN_URL/api/ai/actions/invoke" مدخلات البرنامج المساعد هي كائن الوسيطة المعلنة؛ على عكس الأدوات المجمعة المضمنة، لا يتطلب ملحق القراءة هذا أداة تمييز الإجراء داخل الإدخال. يقوم الجسر بتغليف القيمة التي تم إرجاعها ببيانات تعريف الأداة/الإجراء؛ يتم تشغيل الإجراء. يظل مستوى الوظيفة ok=false نتيجة قابلة للقراءة بدلاً من نجاح نقل HTTP الذي يثبت قائمة إحداثيات مفيدة.
تتحقق سياسة Bridge من أداة استخدام وbridge.use. يؤدي الرمز المميز المفقود أو منتهي الصلاحية أو الملغي أو الخاطئ إلى فشل التفويض. الرمز المميز المرتبط بمشروع آخر ليس وسيلة لتوسيع نطاق هذه المكالمة.
فهم تحويل المخطط وحدود القدرة
يقوم المحول بتحويل مخطط JSON الخاص بالمساهمة إلى zod عندما يكون قابلاً للتمثيل. إذا فشل التحويل، فإن المخطط يتجاوز 20،000 من الأحرف المتسلسلة، أو أنه لا يصف كائنًا، فإنه يعود إلى مخطط كائن عشوائي. هذا هو السبب في أن دالة المثال تتحقق من العدد ونصف القطر نفسه. لا يثبت تمرير التثبيت السلبي للمخطط المدعوم محليًا أن كل ميزة للمخطط ستظل قابلة للتمثيل.
يتعرف SDK على الرسم: القراءة، والرسم: الكتابة، ومسار الأداة: القراءة، والتخزين، وui:panel، وai:tool؛ رسم الكتابة يعني رسم القراءة. لا يقبل مُحمل مساعد الإنتاج حاليًا سوى أداة ai:tool. تؤدي إضافة رسم: كتابة إلى هذا البيان إلى تخطيه، وعدم منحه سياق محرر الرسم.
يحتوي التمهيد العام للعامل على معالجات الرسم/مسار الأدوات/واجهة المستخدم النائبة. لا تمثل هذه المعالجات تكاملًا هندسيًا للإنتاج. وبالمثل، فإن الإعلان عن مساهمات ما بعد المعالج أو التشغيل لا يجعل المُحمل المساعد يربطها بسجلات التصنيع. اختر إجراء تطبيق مدعومًا عندما تحتاج الميزة إلى تغيير بيانات CAD/CAM الحقيقية.
التصميم حول دورة حياة العامل المنفذة
يصف SDK وحدة تحتوي على خطافات البيان والتنشيط والتنظيف الاختياري وإلغاء التنشيط. يستورد مسار AI للإنتاج الحالي الإدخال ويستدعي وظائف aiTools المصدرة. يقوم عامله بتنشيط/إلغاء تنشيط معالجات RPC التي تعترف برسائل دورة الحياة ولكنها لا تستدعي خطافات الوحدة المصدرة. وبالتالي، يمكن للآلة الحاسبة استخدام الوحدة النمطية الدنيا الموضحة هنا دون الاعتماد على عمليات رد اتصال التنشيط.
يبدأ المضيف عاملاً واحدًا لكل مكون إضافي ممكّن، ويربط الردود بمعرفات RPC، ويتتبع المكالمات المعلقة. يفشل استثناء الدالة في هذا الاستدعاء؛ تظهر اختبارات العامل الحقيقي المركزة أن المكالمات اللاحقة لا تزال قادرة على النجاح. قم بإرجاع حالات الرفض المنظمة للإدخال غير الصالح المتوقع، واحتجاز حالات الفشل التي تم طرحها بسبب أخطاء الحساب غير المتوقعة.
تؤدي مهلة المكالمة إلى إنهاء العامل الخاص بها وإحداث خطأ في المكون الإضافي على الفور. تؤدي أعطال العامل وفشل النشر أيضًا إلى إزالة المثيل قيد التشغيل ووضع علامة عليه كخطأ. يحتوي سجل الأعطال على نافذة مدتها عشر دقائق، لكن المعالج الحالي يخطئ عند التعطل الأول؛ ولا ينتظر ثلاث محاولات إعادة تشغيل ناجحة. قم بتصحيح المصدر وإعادة التحميل/إعادة التمكين عمدًا بدلاً من افتراض إعادة التشغيل التلقائي.
حافظ على ضمانات وقت التشغيل بشكل متناسب
يوفر مُحمل الإنتاج ميزانية مضيف تبلغ 10 ثانية لدورة الحياة العادية/RPC للأوامر. استدعاءات أدوات الذكاء الاصطناعي لها موعد نهائي منفصل يبلغ 30 ثانية. يحدد المضيف المكون الإضافي بـ 2 و000 من المكالمات في الدقيقة و64 من المكالمات المعلقة. يقوم بتمرير إعداد حد الموارد 256 ميغابايت إلى Bun عند إنشاء العامل. هذه هي ضوابط وقت التشغيل، وليست عملية منفصلة أو سياسة احتواء نظام التشغيل.
يبدأ التمهيد ببيئة فارغة ويحاول حذف العمليات/الشبكة العالمية المحددة. يعد الحذف أفضل جهد، وتظل بعض أجزاء الBun العالمية قابلة للوصول. ولذلك فإن التحقق من القدرة مفيد لواجهات برمجة التطبيقات التي يوفرها المضيف، ولكن لا يمكن تقديمه كعزل كامل لجافا سكريبت العشوائي.
توجد حقول التوقيع والتطوير الاختيارية في مخطط البيان. يسجل مسار تثبيت العامل الحالي نص التوقيع دون التحقق من التشفير. لا تقم بتصنيف ناشر تم التحقق منه لأن هذا الحقل موجود. تظل مراجعة المصدر المستقل وسياسة التثبيت قرارات منفصلة عن قبول المخطط.
يتم تعطيل المكونات الإضافية التي تتعطل ثلاث مرات خلال عشر دقائق تلقائيًا، ويتم إيقاف استدعاء الأداة المساعدة بعد 30 ثانية. كلتا القيمتين ثوابت في apps/sidecar/src/plugins/host.ts.
تحديث الأداة وإزالتها وتشخيصها
للحصول على تحديث، قم بتحرير الوحدة/البيان المجمعة والتحقق من صحتها قبل إعادة تشغيل الخدمة المستهدفة. احتفظ بمعرفه ثابتًا عندما يكون هو نفس الامتداد وقم بزيادة الإصدار لتحديد ما تم تحميله. لإيقاف تحميله عند التهيئة المستقبلية، قم بإزالة معرفه من Enable.json وأعد تشغيله/إعادة تهيئته. إن تغيير الملف وحده لا يؤدي إلى التخلص من عامل قيد التشغيل بالفعل.
إذا كانت الأداة مفقودة، فتحقق من المصفوفة الممكّنة، والمساواة الدقيقة في معرف المجلد/البيان، وقائمة الإمكانات المدعومة، وخطأ فك التشفير الواضح في السجلات. يعني NoSuchTool عادةً أن الإدخال لا يذكر اسم وظيفة aiTools المُصدَّرة. يشير رفض الوسيطة إلى المخطط أو حارس الوظيفة. تشير المهلة إلى عرقلة العمل أو الوعد الذي لم يتم حله. لا تدير نقاط نهاية تمكين/تكوين ZIP الخاصة بالمتصفح ملف موافقة العامل هذا.
التغطية المركزة موجودة apps/sidecar/test/plugins-ai-tools.test.ts للعمال الفعليين و ai-plugin-tools.test.ts لتحميل الإنتاج، والتحقق من صحة الوسيطة، والتعرض للقراءة/الكتابة، وسلوك الجسر. مصادر التنفيذ هي packages/plugin-sdk/src/manifest.ts, packages/ai/src/tools/plugin-tool.ts, apps/sidecar/src/plugins/host.ts، و services/ai-plugins.ts. استخدم هذه الحدود لتحديد ما أثبته الاختبار الناجح بالفعل.
قواعد العقد في لمحة
| غرض | القيد | ماذا يحدث إذا تم انتهاكها |
|---|---|---|
أداة id | ^[a-z][a-z0-9_]{0,39}$ | فشل فك التشفير الظاهر؛ لم يتم تحميل البرنامج المساعد. |
description | 10–2،000 حرف | فشل فك التشفير. |
kind | read أو write; لا يوجد نوع مدمر | فشل فك التشفير. |
parameters | كائن مخطط JSON، بحد أقصى 20،000 من الأحرف عند إجراء تسلسل | تعود المخططات كبيرة الحجم أو غير القابلة للتحويل إلى قبول أي كائن. |
| القدرات | فقط ai:tool في المضيف المساعد | تم تخطي البرنامج المساعد مع تحذير. |
| اسم المجلد | يساوي البيان id | يتم تخطي المكون الإضافي مع تحذير يذكر كلا القيمتين. |
| ميزانية المكالمة العادية | 5 ثانية لكل مكالمة بشكل افتراضي | يتم إيقاف العامل مثل أي مكون إضافي غير مستجيب. |
| مساعد استدعاء أداة الميزانية | 30 s | ترجع المكالمة نتيجة الفشل. |
| ذاكرة | 256 كومة ميغابايت | العامل يقتل. |
| معدل | 2،000 مكالمات لكل مكون إضافي في الدقيقة، و64 مكالمات معلقة | يتم رفض المكالمات التي تتجاوز السعر؛ فشل قائمة انتظار كاملة مع plugin RPC queue is full. |
| الأعطال والمهلة | تم حسابه على مدى 10 دقيقة، الحد 3 | يؤدي كل تعطل أو انتهاء مهلة إلى إنهاء العامل ووضع علامة على أن البرنامج المساعد معطل. |
اكتب الوصف للنموذج. اذكر ما تحسبه الأداة، ووحداتها، ومتى تستخدمها؛ على سبيل المثال، "إرجاع مراكز الثقب لدائرة الترباس بالملليمتر. يُستخدم عندما يطلب المستخدم فتحات متباعدة بشكل متساوٍ على القطر." تؤدي الأوصاف الغامضة إلى استدعاء الأدوات في الوقت الخطأ أو عدم استدعائها على الإطلاق.
قائمة التحقق قبل الإصدار
- قم بتجميع الإدخال في وحدة نمطية واحدة قائمة بذاتها. لا يمكن للعامل حل عمليات استيراد مساحة العمل في وقت التشغيل.
- يجري
parseManifestفي المباراة النهائيةplugin.jsonوإصلاح كل مشكلة تم الإبلاغ عنها. - قم باستدعاء كل وظيفة أداة تم تصديرها مباشرةً باستخدام وسيطات صالحة وحدية وغير صالحة، وتأكد من أن الإدخال غير الصالح ينتج نتيجة خطأ قابلة للقراءة بدلاً من استثناء يتم الهروب منه.
- اجعل النتائج صغيرة ومتوافقة مع JSON. يقرأها المساعد، وتزدحم المخرجات الكبيرة بالسياق.
- يختار
readما لم تغير الأداة شيئًا ما. أwriteتطالب الأداة المستخدم قبل كل مكالمة. - ضع المجلد تحت
<data dir>/plugins/<id>/، أضف المعرف إلىenabled.json، وأعد تشغيل السايدكار، وقم بتأكيد معرف الأداة المشتقة من قائمة أدوات المساعد. - نتوء
versionلكل تغيير تقوم بشحنه، واحتفظ بهidمستقر بحيث لا يتغير معرف الأداة المشتقة.
لينت بيان قبل التثبيت
import { decodeManifest, requestedCapabilities } from "@cadcamfun/plugin-sdk"
import { Effect } from "effect"
const raw = JSON.parse(await Bun.file(process.argv[2] ?? "plugin.json").text())
const manifest = await Effect.runPromise(decodeManifest(raw)) // throws a SchemaError naming the bad field
console.log(manifest.id, manifest.version, requestedCapabilities(manifest))
for (const tool of manifest.contributes?.aiTools ?? [])
console.log(`plugin_${manifest.id}_${tool.id}`, tool.kind) | خطأ شائع | يصلح |
|---|---|
"version": "1.0" | استخدم ثلاثة أرقام: 1.0.0 |
"apiVersion": 1 | إنها سلسلة: "1" |
معرف البرنامج المساعد gear أو My.Plugin | عكس DNS، الأحرف الصغيرة: com.example.gear |
معرف الأداة Lookup-Thread | أحرف صغيرة، أرقام وشرطات سفلية، الحرف الأول، ≥ 40 أحرف |
| وصف الأداة أقصر من 10 حرفًا | وصف ماذا يفعل ومتى يستخدمه |
التصريح بكلا الأمرين drawing:read و drawing:write | مسموح ولكن drawing:write وحده يعني بالفعل القراءة |
مفتاح التخزين يبدأ بـ / أو تحتوي .. | استخدم المفاتيح النسبية مثل presets/m2 |