Concept internals
TypeBox
TypeBox یک کتابخانهٔ schema با رویکرد TypeScript-first است. ما از آن برای تعریف پروتکل WebSocket Gateway (handshake، request/response، رویدادهای سرور) استفاده میکنیم. این schemaها اعتبارسنجی runtime، خروجی JSON Schema، و تولید کد Swift برای اپلیکیشن macOS را هدایت میکنند. یک منبع حقیقت؛ هر چیز دیگر تولید میشود.
اگر زمینهٔ سطحبالاتر پروتکل را میخواهید، از معماری Gateway شروع کنید.
مدل ذهنی (۳۰ ثانیه)
هر پیام Gateway WS یکی از سه frame است:
- Request:
{ type: "req", id, method, params } - Response:
{ type: "res", id, ok, payload | error } - Event:
{ type: "event", event, payload, seq?, stateVersion? }
اولین frame باید یک request از نوع connect باشد. پس از آن، کلاینتها میتوانند
methodها را فراخوانی کنند (مثلاً health، send، chat.send) و در رویدادها subscribe شوند (مثلاً
presence، tick، agent).
جریان اتصال (حداقلی):
Client Gateway |---- req:connect -------->| |<---- res:hello-ok --------| |<---- event:tick ----------| |---- req:health ---------->| |<---- res:health ----------|methodها + رویدادهای رایج:
| دستهبندی | نمونهها | نکات |
|---|---|---|
| Core | connect, health, status |
connect باید اولین باشد |
| پیامرسانی | send, agent, agent.wait, system-event, logs.tail |
side-effectها به idempotencyKey نیاز دارند |
| Chat | chat.history, chat.send, chat.abort |
WebChat از اینها استفاده میکند |
| Sessionها | sessions.list, sessions.patch, sessions.delete |
مدیریت session |
| Automation | 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 |
push سرور |
فهرست discovery تبلیغشدهٔ معتبر در
src/gateway/server-methods-list.ts (listGatewayMethods, GATEWAY_EVENTS) قرار دارد.
محل schemaها
- منبع:
src/gateway/protocol/schema.ts - اعتبارسنجهای runtime (AJV):
src/gateway/protocol/index.ts - رجیستری قابلیت/feature discovery تبلیغشده:
src/gateway/server-methods-list.ts - handshake سرور + dispatch متدها:
src/gateway/server.impl.ts - کلاینت 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ها در runtime
- سمت سرور: هر frame ورودی با AJV اعتبارسنجی میشود. handshake فقط
request از نوع
connectرا میپذیرد که params آن باConnectParamsمنطبق باشد. - سمت کلاینت: کلاینت JS پیش از استفاده از frameهای event و response آنها را اعتبارسنجی میکند.
- Feature discovery: Gateway فهرست محافظهکارانهٔ
features.methodsوfeatures.eventsرا درhello-okازlistGatewayMethods()وGATEWAY_EVENTSارسال میکند. - این فهرست discovery یک dump تولیدشده از همهٔ helperهای قابلفراخوانی در
coreGatewayHandlersنیست؛ برخی helper RPCها درsrc/gateway/server-methods/*.tsپیادهسازی شدهاند بدون اینکه در فهرست feature تبلیغشده شمارش شوند.
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" } }}response از نوع 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 } }}Request + response:
{ "type": "req", "id": "r1", "method": "health" }{ "type": "res", "id": "r1", "ok": true, "payload": { "ok": true } }Event:
{ "type": "event", "event": "tick", "payload": { "ts": 1730000000 }, "seq": 12 }کلاینت حداقلی (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
نمونه: یک request جدید به نام system.echo اضافه کنید که { ok: true, text } برمیگرداند.
- Schema (منبع حقیقت)
به 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 اضافه کنید و typeها را export کنید:
SystemEchoParams: SystemEchoParamsSchema, SystemEchoResult: SystemEchoResultSchema,export type SystemEchoParams = Static<typeof SystemEchoParamsSchema>;export type SystemEchoResult = Static<typeof SystemEchoResultSchema>;- اعتبارسنجی
در src/gateway/protocol/index.ts، یک validator از 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 قابلفراخوانی است، آن را در
src/gateway/method-scopes.ts نیز طبقهبندی کنید تا scope enforcement و تبلیغ feature در hello-ok
همراستا بمانند.
- تولید دوباره
pnpm protocol:check- تستها + مستندات
یک تست سرور در src/gateway/server.*.test.ts اضافه کنید و method را در مستندات ذکر کنید.
رفتار تولید کد Swift
generator مربوط به Swift این موارد را تولید میکند:
- enum به نام
GatewayFrameبا caseهایreq،res،event، وunknown - structها/enumهای payload با type قوی
- مقدارهای
ErrorCode،GATEWAY_PROTOCOL_VERSION، وGATEWAY_MIN_PROTOCOL_VERSION
نوعهای ناشناختهٔ frame بهعنوان payload خام برای سازگاری رو به جلو حفظ میشوند.
نسخهبندی + سازگاری
PROTOCOL_VERSIONدرsrc/gateway/protocol/version.tsقرار دارد.- کلاینتها
minProtocol+maxProtocolرا ارسال میکنند؛ سرور rangeهایی را که پروتکل فعلی آن را شامل نمیشوند رد میکند. - مدلهای Swift نوعهای ناشناختهٔ frame را نگه میدارند تا کلاینتهای قدیمیتر نشکنند.
الگوها و قراردادهای schema
- بیشتر objectها برای payloadهای سختگیرانه از
additionalProperties: falseاستفاده میکنند. NonEmptyStringپیشفرض برای IDها و نامهای method/event است.GatewayFrameسطح بالا از یک discriminator رویtypeاستفاده میکند.- methodهایی که side effect دارند معمولاً به یک
idempotencyKeyدر params نیاز دارند (نمونه:send،poll،agent،chat.send). agentمقدار اختیاریinternalEventsرا برای context orchestration تولیدشده در runtime میپذیرد (برای مثال تحویل تکمیل task مربوط به subagent/cron)؛ با این مورد بهعنوان سطح 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 کنید.