Concept internals
TypeBox
TypeBox هي مكتبة مخططات مصممة أولا لـ TypeScript. نستخدمها لتعريف بروتوكول Gateway WebSocket (المصافحة، الطلب/الاستجابة، أحداث الخادم). تقود هذه المخططات التحقق في وقت التشغيل، وتصدير JSON Schema، وتوليد كود Swift لتطبيق macOS. مصدر حقيقة واحد؛ وكل ما عداه مولد.
إذا أردت سياق البروتوكول الأعلى مستوى، فابدأ من معمارية Gateway.
النموذج الذهني (30 ثانية)
كل رسالة Gateway WS هي أحد ثلاثة إطارات:
- طلب:
{ type: "req", id, method, params } - استجابة:
{ type: "res", id, ok, payload | error } - حدث:
{ type: "event", event, payload, seq?, stateVersion? }
يجب أن يكون الإطار الأول حتما طلب connect. بعد ذلك، يمكن للعملاء استدعاء
الطرق (مثل health، وsend، وchat.send) والاشتراك في الأحداث (مثل
presence، وtick، وagent).
تدفق الاتصال (الحد الأدنى):
Client Gateway
|---- req:connect -------->|
|<---- res:hello-ok --------|
|<---- event:tick ----------|
|---- req:health ---------->|
|<---- res:health ----------|
الطرق والأحداث الشائعة:
| الفئة | أمثلة | ملاحظات |
|---|---|---|
| الأساس | connect, health, status |
يجب أن يكون connect أولا |
| المراسلة | send, agent, agent.wait, system-event, logs.tail |
تحتاج الآثار الجانبية إلى idempotencyKey |
| الدردشة | chat.history, chat.send, chat.abort |
يستخدم WebChat هذه |
| الجلسات | sessions.list, sessions.patch, sessions.delete |
إدارة الجلسات |
| الأتمتة | wake, cron.list, cron.run, cron.runs |
التحكم في wake وcron |
| العقد | node.list, node.invoke, node.pair.* |
Gateway WS + إجراءات العقد |
| الأحداث | tick, presence, agent, chat, health, shutdown |
دفع من الخادم |
مخزون الاكتشاف المعلن والموثوق موجود في
src/gateway/server-methods-list.ts (listGatewayMethods, GATEWAY_EVENTS).
أين توجد المخططات
- المصدر:
src/gateway/protocol/schema.ts - أدوات التحقق في وقت التشغيل (AJV):
src/gateway/protocol/index.ts - سجل الميزات/الاكتشاف المعلن:
src/gateway/server-methods-list.ts - مصافحة الخادم + توزيع الطرق:
src/gateway/server.impl.ts - عميل Node:
src/gateway/client.ts - JSON Schema المولد:
dist/protocol.schema.json - نماذج Swift المولدة:
apps/macos/Sources/OpenClawProtocol/GatewayModels.swift
المسار الحالي
pnpm protocol:gen- يكتب JSON Schema (draft-07) إلى
dist/protocol.schema.json
- يكتب JSON Schema (draft-07) إلى
pnpm protocol:gen:swift- يولد نماذج Swift الخاصة بـ Gateway
pnpm protocol:check- يشغل كلا المولدين ويتحقق من أن المخرجات ملتزم بها
كيف تستخدم المخططات في وقت التشغيل
- جانب الخادم: يتم التحقق من كل إطار وارد باستخدام AJV. لا تقبل المصافحة إلا
طلب
connectتطابق معاملاتهConnectParams. - جانب العميل: يتحقق عميل JS من إطارات الأحداث والاستجابات قبل استخدامها.
- اكتشاف الميزات: يرسل Gateway قائمة محافظة من
features.methodsوfeatures.eventsضمنhello-okمنlistGatewayMethods()وGATEWAY_EVENTS. - قائمة الاكتشاف هذه ليست تفريغا مولدا لكل مساعد قابل للاستدعاء في
coreGatewayHandlers؛ بعض مساعدات RPC منفذة فيsrc/gateway/server-methods/*.tsمن دون إدراجها في قائمة الميزات المعلنة.
أمثلة على الإطارات
Connect (الرسالة الأولى):
{
"type": "req",
"id": "c1",
"method": "connect",
"params": {
"minProtocol": 3,
"maxProtocol": 3,
"client": {
"id": "openclaw-macos",
"displayName": "macos",
"version": "1.0.0",
"platform": "macos 15.1",
"mode": "ui",
"instanceId": "A1B2"
}
}
}
استجابة Hello-ok:
{
"type": "res",
"id": "c1",
"ok": true,
"payload": {
"type": "hello-ok",
"protocol": 3,
"server": { "version": "dev", "connId": "ws-1" },
"features": { "methods": ["health"], "events": ["tick"] },
"snapshot": {
"presence": [],
"health": {},
"stateVersion": { "presence": 0, "health": 0 },
"uptimeMs": 0
},
"policy": { "maxPayload": 1048576, "maxBufferedBytes": 1048576, "tickIntervalMs": 30000 }
}
}
طلب + استجابة:
{ "type": "req", "id": "r1", "method": "health" }
{ "type": "res", "id": "r1", "ok": true, "payload": { "ok": true } }
حدث:
{ "type": "event", "event": "tick", "payload": { "ts": 1730000000 }, "seq": 12 }
عميل بسيط (Node.js)
أصغر تدفق مفيد: الاتصال + الصحة.
const ws = new WebSocket("ws://127.0.0.1:18789");
ws.on("open", () => {
ws.send(
JSON.stringify({
type: "req",
id: "c1",
method: "connect",
params: {
minProtocol: 3,
maxProtocol: 3,
client: {
id: "cli",
displayName: "example",
version: "dev",
platform: "node",
mode: "cli",
},
},
}),
);
});
ws.on("message", (data) => {
const msg = JSON.parse(String(data));
if (msg.type === "res" && msg.id === "c1" && msg.ok) {
ws.send(JSON.stringify({ type: "req", id: "h1", method: "health" }));
}
if (msg.type === "res" && msg.id === "h1") {
console.log("health:", msg.payload);
ws.close();
}
});
مثال عملي: إضافة طريقة من البداية إلى النهاية
مثال: أضف طلب system.echo جديدا يعيد { ok: true, text }.
- المخطط (مصدر الحقيقة)
أضف إلى src/gateway/protocol/schema.ts:
export const SystemEchoParamsSchema = Type.Object(
{ text: NonEmptyString },
{ additionalProperties: false },
);
export const SystemEchoResultSchema = Type.Object(
{ ok: Type.Boolean(), text: NonEmptyString },
{ additionalProperties: false },
);
أضف الاثنين إلى ProtocolSchemas وصدّر الأنواع:
SystemEchoParams: SystemEchoParamsSchema,
SystemEchoResult: SystemEchoResultSchema,
export type SystemEchoParams = Static<typeof SystemEchoParamsSchema>;
export type SystemEchoResult = Static<typeof SystemEchoResultSchema>;
- التحقق
في src/gateway/protocol/index.ts، صدّر أداة تحقق AJV:
export const validateSystemEchoParams = ajv.compile<SystemEchoParams>(SystemEchoParamsSchema);
- سلوك الخادم
أضف معالجا في src/gateway/server-methods/system.ts:
export const systemHandlers: GatewayRequestHandlers = {
"system.echo": ({ params, respond }) => {
const text = String(params.text ?? "");
respond(true, { ok: true, text });
},
};
سجله في src/gateway/server-methods.ts (يدمج systemHandlers بالفعل)،
ثم أضف "system.echo" إلى دخل listGatewayMethods في
src/gateway/server-methods-list.ts.
إذا كانت الطريقة قابلة للاستدعاء من عملاء المشغل أو العقد، فصنفها أيضا في
src/gateway/method-scopes.ts حتى يظل فرض النطاق وإعلان ميزات hello-ok
متوافقين.
- إعادة التوليد
pnpm protocol:check
- الاختبارات + المستندات
أضف اختبار خادم في src/gateway/server.*.test.ts واذكر الطريقة في المستندات.
سلوك توليد كود Swift
ينشئ مولد Swift ما يلي:
- تعداد
GatewayFrameمع حالاتreq، وres، وevent، وunknown - بنيات/تعدادات payload ذات أنواع قوية
- قيم
ErrorCodeوGATEWAY_PROTOCOL_VERSION
تحتفظ أنواع الإطارات غير المعروفة كحمولات خام من أجل التوافق المستقبلي.
تعيين الإصدارات + التوافق
- يوجد
PROTOCOL_VERSIONفيsrc/gateway/protocol/schema.ts. - يرسل العملاء
minProtocol+maxProtocol؛ ويرفض الخادم حالات عدم التطابق. - تحتفظ نماذج Swift بأنواع الإطارات غير المعروفة لتجنب كسر العملاء الأقدم.
أنماط المخططات والاصطلاحات
- تستخدم معظم الكائنات
additionalProperties: falseللحمولات الصارمة. NonEmptyStringهو الافتراضي للمعرفات وأسماء الطرق/الأحداث.- يستخدم
GatewayFrameفي المستوى الأعلى مميزا علىtype. - تتطلب الطرق ذات الآثار الجانبية عادة
idempotencyKeyضمن المعاملات (مثال:send، وpoll، وagent، وchat.send). - يقبل
agentاختيارياinternalEventsلسياق التنسيق المولد في وقت التشغيل (مثل تسليم إكمال مهمة الوكيل الفرعي/cron)؛ تعامل مع هذا كسطح API داخلي.
JSON Schema المباشر
يوجد JSON Schema المولد في المستودع عند dist/protocol.schema.json. يكون
الملف الخام المنشور متاحا عادة عند:
عند تغيير المخططات
- حدّث مخططات TypeBox.
- سجل الطريقة/الحدث في
src/gateway/server-methods-list.ts. - حدّث
src/gateway/method-scopes.tsعندما يحتاج RPC الجديد إلى تصنيف نطاق المشغل أو العقدة. - شغل
pnpm protocol:check. - التزم بالمخطط المعاد توليده + نماذج Swift.