Concept internals
TypeBox
TypeBox یک کتابخانهٔ schema با رویکرد TypeScript-first است. ما از آن برای تعریف پروتکل WebSocket مربوط به Gateway استفاده میکنیم (handshake، request/response، server events). این schemaها اعتبارسنجی زمان اجرا، خروجی JSON Schema، و تولید کد Swift برای برنامهٔ macOS را هدایت میکنند. یک منبع حقیقت؛ بقیهٔ چیزها تولید میشوند.
اگر زمینهٔ سطح بالاتر پروتکل را میخواهید، از معماری Gateway شروع کنید.
مدل ذهنی (۳۰ ثانیه)
هر پیام Gateway WS یکی از سه frame است:
- درخواست:
{ type: "req", id, method, params } - پاسخ:
{ type: "res", id, ok, payload | error } - رویداد:
{ type: "event", event, payload, seq?, stateVersion? }
نخستین frame باید یک درخواست connect باشد. پس از آن، clientها میتوانند
methodها را فراخوانی کنند (برای نمونه health، send، chat.send) و در رویدادها مشترک شوند (برای نمونه
presence، tick، agent).
جریان اتصال (حداقلی):
Client Gateway |---- req:connect -------->| |<---- res:hello-ok --------| |<---- event:tick ----------| |---- req:health ---------->| |<---- res:health ----------|methodها و eventهای رایج:
| دسته | نمونهها | یادداشتها |
|---|---|---|
| هسته | connect, health, status |
connect باید اولین مورد باشد |
| پیامرسانی | send, agent, agent.wait, system-event, logs.tail |
side-effectها به idempotencyKey نیاز دارند |
| چت | chat.history, chat.send, chat.abort |
WebChat از اینها استفاده میکند |
| نشستها | sessions.list, sessions.patch, sessions.delete |
مدیریت نشست |
| خودکارسازی | wake, cron.list, cron.run, cron.runs |
کنترل wake + cron |
| Nodeها | node.list, node.invoke, node.pair.* |
Gateway WS + کنشهای node |
| رویدادها | tick, presence, agent, chat, health, shutdown |
ارسال از سمت server |
فهرست معتبر کشف تبلیغشده در
src/gateway/server-methods-list.ts (listGatewayMethods, GATEWAY_EVENTS) قرار دارد.
محل قرارگیری schemaها
- منبع:
packages/gateway-protocol/src/schema.ts - اعتبارسنجهای زمان اجرا (AJV):
packages/gateway-protocol/src/index.ts - رجیستری feature/discovery تبلیغشده:
src/gateway/server-methods-list.ts - handshake سرور + dispatch متد:
src/gateway/server.impl.ts - client مربوط به Node:
src/gateway/client.ts - JSON Schema تولیدشده:
dist/protocol.schema.json - مدلهای Swift تولیدشده:
apps/macos/Sources/OpenClawProtocol/GatewayModels.swift
pipeline فعلی
pnpm protocol:gen- JSON Schema (draft-07) را در
dist/protocol.schema.jsonمینویسد
- JSON Schema (draft-07) را در
pnpm protocol:gen:swift- مدلهای Swift مربوط به gateway را تولید میکند
pnpm protocol:check- هر دو generator را اجرا میکند و بررسی میکند خروجی commit شده باشد
نحوهٔ استفاده از schemaها در زمان اجرا
- سمت سرور: هر frame ورودی با AJV اعتبارسنجی میشود. handshake فقط
درخواست
connectای را میپذیرد که params آن باConnectParamsسازگار باشد. - سمت client: client جاوااسکریپت frameهای event و response را پیش از استفاده اعتبارسنجی میکند.
- کشف feature: Gateway یک فهرست محافظهکارانهٔ
features.methodsوfeatures.eventsرا درhello-okازlistGatewayMethods()وGATEWAY_EVENTSارسال میکند. - آن فهرست کشف، dump تولیدشده از همهٔ helperهای قابل فراخوانی در
coreGatewayHandlersنیست؛ برخی helper RPCها درsrc/gateway/server-methods/*.tsپیادهسازی شدهاند، بدون اینکه در فهرست feature تبلیغشده enumerate شده باشند.
نمونه frameها
Connect (اولین پیام):
{ "type": "req", "id": "c1", "method": "connect", "params": { "minProtocol": 3, "maxProtocol": 4, "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": 4, "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 }client حداقلی (Node.js)
کوچکترین جریان مفید: connect + health.
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: 4, maxProtocol: 4, 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(); }});مثال کارشده: افزودن یک method بهصورت end-to-end
مثال: افزودن یک درخواست جدید system.echo که { ok: true, text } را برمیگرداند.
- Schema (منبع حقیقت)
به packages/gateway-protocol/src/schema.ts اضافه کنید:
export const SystemEchoParamsSchema = Type.Object( { text: NonEmptyString }, { additionalProperties: false },); export const SystemEchoResultSchema = Type.Object( { ok: Type.Boolean(), text: NonEmptyString }, { additionalProperties: false },);هر دو را به ProtocolSchemas اضافه کنید و typeها را export کنید:
SystemEchoParams: SystemEchoParamsSchema, SystemEchoResult: SystemEchoResultSchema,export type SystemEchoParams = Static<typeof SystemEchoParamsSchema>;export type SystemEchoResult = Static<typeof SystemEchoResultSchema>;- اعتبارسنجی
در packages/gateway-protocol/src/index.ts، یک اعتبارسنج AJV را export کنید:
export const validateSystemEchoParams = ajv.compile<SystemEchoParams>(SystemEchoParamsSchema);- رفتار سرور
یک handler در 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 را merge میکند)،
سپس "system.echo" را به ورودی listGatewayMethods در
src/gateway/server-methods-list.ts اضافه کنید.
اگر method توسط operator یا node clientها قابل فراخوانی است، آن را در
src/gateway/method-scopes.ts نیز دستهبندی کنید تا اعمال scope و تبلیغ feature
در hello-ok همراستا بمانند.
- تولید مجدد
pnpm protocol:check- تستها + مستندات
یک تست سرور در src/gateway/server.*.test.ts اضافه کنید و method را در مستندات ذکر کنید.
رفتار تولید کد Swift
generator مربوط به Swift این موارد را emit میکند:
- enum مربوط به
GatewayFrameبا caseهایreq،res،event، وunknown - structها/enumهای payload با typeهای قوی
- مقدارهای
ErrorCode،GATEWAY_PROTOCOL_VERSION، وGATEWAY_MIN_PROTOCOL_VERSION
نوعهای ناشناختهٔ frame برای سازگاری رو به جلو بهصورت raw payload حفظ میشوند.
نسخهبندی + سازگاری
PROTOCOL_VERSIONدرpackages/gateway-protocol/src/version.tsقرار دارد.- clientها
minProtocol+maxProtocolرا ارسال میکنند؛ سرور rangeهایی را که پروتکل فعلی آن را شامل نشوند رد میکند. - مدلهای Swift نوعهای ناشناختهٔ frame را نگه میدارند تا clientهای قدیمیتر دچار شکست نشوند.
الگوها و قراردادهای schema
- بیشتر objectها برای payloadهای سختگیرانه از
additionalProperties: falseاستفاده میکنند. NonEmptyStringمقدار پیشفرض برای IDها و نامهای method/event است.GatewayFrameسطح بالا از یک discriminator رویtypeاستفاده میکند.- methodهایی که side effect دارند معمولاً در params به
idempotencyKeyنیاز دارند (مثال:send،poll،agent،chat.send). agentبرای زمینهٔ orchestration تولیدشده در زمان اجرا،internalEventsاختیاری را میپذیرد (برای نمونه handoff تکمیل subagent/cron task)؛ این را بهعنوان سطح API داخلی در نظر بگیرید.
JSON زندهٔ schema
JSON Schema تولیدشده در repo در dist/protocol.schema.json قرار دارد. فایل raw منتشرشده
معمولاً در این نشانی در دسترس است:
هنگام تغییر schemaها
- schemaهای TypeBox را بهروزرسانی کنید.
- method/event را در
src/gateway/server-methods-list.tsثبت کنید. - وقتی RPC جدید به دستهبندی scope مربوط به operator یا
node نیاز دارد،
src/gateway/method-scopes.tsرا بهروزرسانی کنید. pnpm protocol:checkرا اجرا کنید.- schema تولیدشده + مدلهای Swift را commit کنید.