forked from bots-garden/ori
| ✨ Workspace panel, selectors, previews, desktop app, sandbox template, resizable file tree, light/dark theme | 1 | # Référence : protocole WebSocket |
| 2 | ||
| 3 | > Description neutre et exhaustive des messages échangés entre le navigateur et le backend ori sur `GET /ws`. Un objet JSON par trame texte. Les payloads ACP sont relayés tels quels ; leurs formes sont spécifiées par l'[Agent Client Protocol](https://agentclientprotocol.com). | |
| 4 | ||
| 5 | ## Séquence de connexion | |
| 6 | ||
| 7 | À chaque connexion, le serveur envoie `hello`, puis rejoue l'historique enregistré de la session (jusqu'à 4096 événements), puis toute demande de permission encore en attente de réponse, puis les événements au fil de l'eau. | |
| 8 | ||
| 9 | ## Messages navigateur → serveur | |
| 10 | ||
| 11 | ### `prompt` | |
| 12 | ||
| 13 | Démarre un tour. | |
| 14 | ||
| 15 | | Champ | Type | Requis | Description | | |
| 16 | | --- | --- | --- | --- | | |
| 17 | | `type` | chaîne | oui | `"prompt"` | | |
| 18 | | `text` | chaîne | oui | Le message de l'utilisateur. | | |
| 19 | | `attachments` | tableau | non | Fichiers mentionnés avec `@` dans le texte : `{ "path": "<chemin absolu ou relatif à la racine>", "name": "<libellé>" }`. | | |
| 20 | ||
| 21 | ```json | |
| 22 | { "type": "prompt", "text": "Explique @src/main.go", "attachments": [ { "path": "/travail/src/main.go", "name": "src/main.go" } ] } | |
| 23 | ``` | |
| 24 | ||
| 25 | Le serveur envoie le prompt ACP sous forme d'un bloc de contenu `text` suivi d'un bloc `resource_link` par pièce jointe (`uri: "file://<chemin absolu>"`, `name` tel que fourni, par défaut le chemin). Les chemins relatifs sont joints au `--cwd` du serveur ; les pièces jointes au `path` vide sont écartées. La mention `@name` reste dans le texte. | |
| 26 | ||
| 27 | ### `cancel` | |
| 28 | ||
| 29 | Interrompt le tour en cours. | |
| 30 | ||
| 31 | | Champ | Type | Requis | Description | | |
| 32 | | --- | --- | --- | --- | | |
| 33 | | `type` | chaîne | oui | `"cancel"` | | |
| 34 | ||
| 35 | ### `permission_response` | |
| 36 | ||
| 37 | Répond à une `permission_request`. | |
| 38 | ||
| 39 | | Champ | Type | Requis | Description | | |
| 40 | | --- | --- | --- | --- | | |
| 41 | | `type` | chaîne | oui | `"permission_response"` | | |
| 42 | | `requestId` | chaîne | oui | L'identifiant reçu dans l'événement `permission_request`. | | |
| 43 | | `optionId` | chaîne | l'un des deux | L'option de permission ACP choisie. | | |
| 44 | | `cancelled` | booléen | l'un des deux | `true` écarte la demande sans choisir. | | |
| 45 | ||
| 46 | ## Messages serveur → navigateur | |
| 47 | ||
| 48 | ### `hello` | |
| 49 | ||
| 50 | | Champ | Type | Description | | |
| 51 | | --- | --- | --- | | |
| 52 | | `sessionId` | chaîne | L'identifiant de session ACP, vide si aucun agent n'est attaché. | | |
| 53 | | `turnActive` | booléen | `true` si un tour est en cours. | | |
| 54 | ||
| 55 | ### `user_message` | |
| 56 | ||
| 57 | Écho du prompt qui a démarré un tour ; présent aussi dans les rejeux. | |
| 58 | ||
| 59 | | Champ | Type | Description | | |
| 60 | | --- | --- | --- | | |
| 61 | | `text` | chaîne | Le message de l'utilisateur. | | |
| 62 | | `attachments` | tableau | Les `attachments` du prompt, tels quels (absent s'il n'y en avait pas). | | |
| 63 | ||
| 64 | ### `turn_started` / `turn_ended` | |
| 65 | ||
| 66 | | Champ | Type | Description | | |
| 67 | | --- | --- | --- | | |
| 68 | | `stopReason` | chaîne | `turn_ended` uniquement : la raison d'arrêt ACP (`end_turn`, `cancelled`, `refusal`, `max_tokens`, `max_turn_requests`). | | |
| 69 | ||
| 70 | ### `session_update` | |
| 71 | ||
| 72 | | Champ | Type | Description | | |
| 73 | | --- | --- | --- | | |
| 74 | | `update` | objet | Une `SessionUpdate` ACP brute, discriminée par son champ `sessionUpdate` (`agent_message_chunk`, `agent_thought_chunk`, `tool_call`, `tool_call_update`, `plan`, `available_commands_update`, …). | | |
| 75 | ||
| 76 | La SPA rend les fragments de message et de réflexion, les tool calls et le plan, et conserve les `availableCommands` du dernier `available_commands_update` pour le sélecteur `/` du composer (l'agent mock en envoie un à l'ouverture de session ; l'adaptateur Claude Code envoie les commandes slash de Claude Code). Les autres genres sont ignorés. | |
| 77 | ||
| 78 | ```json | |
| 79 | { "type": "session_update", "update": { "sessionUpdate": "agent_message_chunk", "content": { "type": "text", "text": "Bonjour" } } } | |
| 80 | ``` | |
| 81 | ||
| 82 | ### `permission_request` | |
| 83 | ||
| 84 | | Champ | Type | Description | | |
| 85 | | --- | --- | --- | | |
| 86 | | `requestId` | chaîne | Corrèle avec `permission_response` et `permission_resolved`. | | |
| 87 | | `request` | objet | La `RequestPermissionRequest` ACP brute (`toolCall`, `options`). | | |
| 88 | ||
| 89 | ### `permission_resolved` | |
| 90 | ||
| 91 | | Champ | Type | Description | | |
| 92 | | --- | --- | --- | | |
| 93 | | `requestId` | chaîne | La demande qui a reçu une réponse (d'un des clients connectés, ou annulée par l'agent). | | |
| 94 | ||
| 95 | ### `error` | |
| 96 | ||
| 97 | | Champ | Type | Description | | |
| 98 | | --- | --- | --- | | |
| 99 | | `message` | chaîne | Erreur lisible (`"a turn is already running"`, `"no agent session"`, `"prompt failed: …"`, `"cancel failed: …"`, `"malformed message: …"`, `"unknown message type …"`). | | |
| 100 | ||
| 101 | ## Événements enregistrés vs transitoires | |
| 102 | ||
| 103 | Événements rejoués aux clients qui arrivent en cours de session : `user_message`, `turn_started`, `turn_ended`, `session_update`, `permission_resolved`, plus les `permission_request` en attente. Non enregistrés : `hello` (régénéré à chaque connexion) et les événements `error` émis hors échec d'un tour. |