TypeBox
TypeBox comme source de vérité du protocole
Section intitulée « TypeBox comme source de vérité du protocole »Dernière mise à jour : 2026-01-10
TypeBox est une bibliothèque de schémas centrée sur TypeScript. Nous l’utilisons pour définir le protocole WebSocket Gateway (poignée de main, demande/réponse, événements serveur). Ces schémas pilotent la validation à l’exécution, l’exportation JSON Schema et la génération de code Swift pour l’application macOS. Une source de vérité ; tout le reste est généré.
Si vous souhaitez obtenir le contexte de protocole de plus haut niveau, commencez par Architecture de la passerelle.
Modèle mental (30 secondes)
Section intitulée « Modèle mental (30 secondes) »Chaque message WS Gateway est l’un des trois types de trames :
- Demande :
{ type: "req", id, method, params } - Réponse :
{ type: "res", id, ok, payload | error } - Événement :
{ type: "event", event, payload, seq?, stateVersion? }
La première trame doit être une demande connect. Après cela, les clients peuvent appeler
des méthodes (ex. health, send, chat.send) et s’abonner à des événements (ex.
presence, tick, agent).
Flux de connexion (minimal) :
Client Gateway |---- req:connect -------->| |<---- res:hello-ok --------| |<---- event:tick ----------| |---- req:health ---------->| |<---- res:health ----------|Méthodes courantes + événements :
| Catégorie | Exemples | Notes |
|---|---|---|
| Cœur | connect, health, status | connect doit être en premier |
| Messagerie | send, poll, agent, agent.wait | les effets secondaires nécessitent idempotencyKey |
| Chat | chat.history, chat.send, chat.abort, chat.inject | WebChat les utilise |
| Sessions | sessions.list, sessions.patch, sessions.delete | administrateur de session |
| Nœuds | node.list, node.invoke, node.pair.* | Gateway WS + node actions |
| Événements | tick, presence, agent, chat, health, shutdown | push serveur |
La liste faisant autorité se trouve dans src/gateway/server.ts (METHODS, EVENTS).
Où se trouvent les schémas
Section intitulée « Où se trouvent les schémas »- Source :
src/gateway/protocol/schema.ts - Validateurs d’exécution (AJV) :
src/gateway/protocol/index.ts - Handshake serveur + répartition des méthodes :
src/gateway/server.ts - Client Node :
src/gateway/client.ts - Schéma JSON généré :
dist/protocol.schema.json - Modèles Swift générés :
apps/macos/Sources/OpenClawProtocol/GatewayModels.swift
Pipeline actuel
Section intitulée « Pipeline actuel »pnpm protocol:gen- écrit le JSON Schema (draft‑07) dans
dist/protocol.schema.json
- écrit le JSON Schema (draft‑07) dans
pnpm protocol:gen:swift- génère les modèles de passerelle Swift
pnpm protocol:check- exécute les deux générateurs et vérifie que la sortie est validée
Comment les schémas sont utilisés à l’exécution
Section intitulée « Comment les schémas sont utilisés à l’exécution »- Côté serveur : chaque trame entrante est validée avec AJV. Le handshake n’accepte
qu’une requête
connectdont les paramètres correspondent àConnectParams. - Côté client : le client JS valide les trames d’événement et de réponse avant de les utiliser.
- Surface de méthodes : le Gateway annonce les
methodseteventspris en charge danshello-ok.
Exemples de trames
Section intitulée « Exemples de trames »Connexion (premier message) :
{ "type": "req", "id": "c1", "method": "connect", "params": { "minProtocol": 2, "maxProtocol": 2, "client": { "id": "openclaw-macos", "displayName": "macos", "version": "1.0.0", "platform": "macos 15.1", "mode": "ui", "instanceId": "A1B2" } }}Réponse Hello-ok :
{ "type": "res", "id": "c1", "ok": true, "payload": { "type": "hello-ok", "protocol": 2, "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 } }}Requête + réponse :
{ "type": "req", "id": "r1", "method": "health" }{ "type": "res", "id": "r1", "ok": true, "payload": { "ok": true } }Événement :
{ "type": "event", "event": "tick", "payload": { "ts": 1730000000 }, "seq": 12 }Client minimal (Node.js)
Section intitulée « Client minimal (Node.js) »Plus petit flux utile : connexion + santé.
import { WebSocket } from "ws";
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(); }});Exemple pratique : ajouter une méthode de bout en bout
Section intitulée « Exemple pratique : ajouter une méthode de bout en bout »Exemple : ajouter une nouvelle requête system.echo qui renvoie { ok: true, text }.
- Schéma (source de vérité)
Ajouter à 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 });Ajouter les deux à ProtocolSchemas et exporter les types :
SystemEchoParams: SystemEchoParamsSchema, SystemEchoResult: SystemEchoResultSchema,export type SystemEchoParams = Static<typeof SystemEchoParamsSchema>;export type SystemEchoResult = Static<typeof SystemEchoResultSchema>;- Validation
Dans src/gateway/protocol/index.ts, exporter un validateur AJV :
export const validateSystemEchoParams = ajv.compile<SystemEchoParams>(SystemEchoParamsSchema);- Comportement du serveur
Ajoutez un gestionnaire dans src/gateway/server-methods/system.ts :
export const systemHandlers: GatewayRequestHandlers = { "system.echo": ({ params, respond }) => { const text = String(params.text ?? ""); respond(true, { ok: true, text }); },};Inscrivez-le dans src/gateway/server-methods.ts (fusionne déjà systemHandlers),
puis ajoutez "system.echo" à METHODS dans src/gateway/server.ts.
- Régénérer
pnpm protocol:check- Tests + documentation
Ajoutez un test serveur dans src/gateway/server.*.test.ts et notez la méthode dans la documentation.
Comportement de la génération de code Swift
Section intitulée « Comportement de la génération de code Swift »Le générateur Swift émet :
- énumération
GatewayFrameavec les casreq,res,eventetunknown - Structures/énumérations de charge utile fortement typées
- valeurs
ErrorCodeetGATEWAY_PROTOCOL_VERSION
Les types de trames inconnus sont conservés sous forme de charges utiles brutes pour assurer la compatibilité ascendante.
Gestion des versions + compatibilité
Section intitulée « Gestion des versions + compatibilité »PROTOCOL_VERSIONréside danssrc/gateway/protocol/schema.ts.- Les clients envoient
minProtocol+maxProtocol; le serveur rejette les incohérences. - Les modèles Swift conservent les types de trames inconnus pour éviter de casser les anciens clients.
Modèles et conventions de schémas
Section intitulée « Modèles et conventions de schémas »- La plupart des objets utilisent
additionalProperties: falsepour les charges utiles strictes. NonEmptyStringest la valeur par défaut pour les ID et les noms de méthodes/événements.- L’
GatewayFramede niveau supérieur utilise un discriminant surtype. - Les méthodes ayant des effets secondaires nécessitent généralement un
idempotencyKeydans les paramètres (exemple :send,poll,agent,chat.send). agentaccepte uninternalEventsoptionnel pour le contexte d’orchestration généré à l’exécution (par exemple, transfert lors de l’achèvement d’une tâche de sous-agent/cron) ; traitez cela comme une surface de API interne.
JSON de schéma en direct
Section intitulée « JSON de schéma en direct »Le JSON Schema généré se trouve dans le dépôt à dist/protocol.schema.json. Le
fichier brut publié est généralement disponible à l’adresse :
Lorsque vous modifiez les schémas
Section intitulée « Lorsque vous modifiez les schémas »- Mettez à jour les schémas TypeBox.
- Exécutez
pnpm protocol:check. - Validez le schéma régénéré + les modèles Swift.