# Sesiuni partajate (/ro/docs/sessions)

O conversație, mai multe dispozitive — gateway-ul păstrează jurnalul ordonat de evenimente; dispozitivul cu uneltele execută; toți ceilalți urmăresc sau ghidează.

O **sesiune partajată** este o conversație ținută pe server. Store-ul gateway-ului este sursa de adevăr pentru **jurnalul ordonat de evenimente**; fiecare dispozitiv păstrează un cache local și se reconciliază după `seq`. Conversația călătorește; execuția rămâne acolo unde sunt uneltele — laptopul tău rulează shell-ul, telefonul urmărește și răspunde la întrebările agentului, un coleg citește în paralel.

Acesta este protocolul din spatele lui „continuă pe telefon”, al vizualizării de sesiuni din hub și al oglinzii live de pe desktop. Este public, versionat (`v1`, stabil) și publicat cu JSON Schema-uri la [github.com/codai-ro/codai-protocol](https://github.com/codai-ro/codai-protocol).

## Piesele în mișcare [#piesele-în-mișcare]

```text
                     ┌──────────────── gateway (ai.codai.ro) ────────────────┐
                     │  sesiune ──▶ events[seq 1..n]  controls    lease     │
                     └──────▲──────────────┬──────────────▲────────┬────────┘
     adaugă events   POST   │              │ SSE / WS      │ POST   │ push (FCM)
     ia lease-ul            │              ▼               │        ▼
   ┌────────────────┐   ┌───────────┐   ┌───────────┐   ┌────────────┐
   │   EXECUTOR     │   │  VIEWER   │   │  EDITOR   │   │ DISPATCHED │
   │ desktop / CLI  │   │ hub, web  │   │  telefon  │   │ dispozitiv │
   │ deține lease-ul│   │ read-only │   │ trimite   │   │ trezit cu  │
   │ rulează unelte │   │ urmărește │   │ controls  │   │ un `send`  │
   └────────────────┘   └───────────┘   └───────────┘   └────────────┘
```

| Obiect | Ce este |
| --- | --- |
| **Session** | Containerul. Are un `id` (UUID de server) și propriul tău `session_key`, un owner, un titlu, `last_seq` și cine deține lease-ul. |
| **Event** | O intrare în jurnal, cu un `seq` dens atribuit de server, un `kind` (`turn_start`, `tool_call`, `ask`, `assistant`, …) și un `payload` opac. Doar executorul adaugă. |
| **Control** | O instrucțiune *către* executor — `send`, `answer`, `approve`, `deny`, `cancel`, `steer`, `inject`. Persistată, ca un executor întârziat să le poată consuma; ecou în jurnal, ca fiecare viewer să le vadă. |
| **Lease** | Dreptul de a adăuga. Exact un dispozitiv îl deține, câte 30 de secunde, reînnoit prin heartbeat la fiecare 10 secunde. |
| **Device** | Orice instalare de client — un UUID ales de tine, trimis ca `x-codai-device`, înregistrat lazy sub contul tău. |
| **Share** | O acordare de `viewer`, `editor` sau `owner` pe o sesiune către un utilizator, o organizație sau un token de link. |
| **Presence** | Cine este conectat acum și dacă conduce. Doar în memorie. |
| **Dispatch** | Un `send` țintit către unul dintre dispozitivele tale, plus o notificare push care să-l trezească. |

## Roluri [#roluri]

| Rol | Poate |
| --- | --- |
| `viewer` | Să citească sesiunea, evenimentele și controls; să urmărească stream-ul live. |
| `editor` | Tot ce poate un viewer, plus să trimită controls și dispatch. |
| `owner` | Totul, plus redenumire, arhivare, ștergere, gestionarea share-urilor și preluarea lease-ului. |

Ești `owner` pe sesiunile create de tine. Pe o sesiune partajată rolul tău este cel mai înalt dintre share-urile care ți se potrivesc — direct, printr-o organizație din care faci parte sau printr-un token de link pe care îl prezinți.

## Un round trip minimal [#un-round-trip-minimal]

Fiecare request poartă cheia ta și, la scrieri, id-ul dispozitivului:

```bash
export DEV=$(uuidgen)   # o dată per instalare; refolosește-l

# 1. creezi (sau redeschizi) o sesiune după propria cheie
curl -X POST https://ai.codai.ro/v1/sessions \
  -H "Authorization: Bearer $CODAI_API_KEY" \
  -H "x-codai-device: $DEV" -H "x-codai-device-platform: cli" \
  -H "Content-Type: application/json" \
  -d '{ "session_key": "laptop-2026-09-23", "title": "Fix the flaky test" }'

# 2. iei lease-ul — acum ești executorul
curl -X POST https://ai.codai.ro/v1/sessions/laptop-2026-09-23/lease \
  -H "Authorization: Bearer $CODAI_API_KEY" -H "x-codai-device: $DEV"

# 3. adaugi ce s-a întâmplat
curl -X POST https://ai.codai.ro/v1/sessions/laptop-2026-09-23/events \
  -H "Authorization: Bearer $CODAI_API_KEY" -H "x-codai-device: $DEV" \
  -H "Content-Type: application/json" \
  -d '{ "events": [
        { "kind": "turn_start", "turn_id": "t1", "client_event_id": "t1-start", "payload": { "text": "Fix the flaky test" } },
        { "kind": "assistant",  "turn_id": "t1", "client_event_id": "t1-a1",    "payload": { "text": "Reading test_retry.py…" } }
      ] }'

# 4. de pe orice alt dispozitiv: urmărești
curl -N "https://ai.codai.ro/v1/sessions/laptop-2026-09-23/stream?after=0" \
  -H "Authorization: Bearer $CODAI_API_KEY" -H "x-codai-device: $(uuidgen)"
```

Stream-ul redă cele două evenimente, apoi un frame `lease` care numește laptopul tău ca deținător, apoi rămâne deschis pentru ce urmează.

## Unde mergi mai departe [#unde-mergi-mai-departe]

<Cards>
  <Card title="Referința protocolului" href="./protocol.mdx" description="Fiecare obiect, rută, eroare și limită din v1." />
  <Card title="Streaming" href="./streaming.mdx" description="Frame-uri SSE și WebSocket, reluare cu ?after=, scrieri idempotente." />
  <Card title="Partajare și organizații" href="./sharing-and-orgs.mdx" description="Invită o persoană, o echipă sau un link; gestionează organizațiile." />
  <Card title="Releul de host-uri" href="./hosts.mdx" description="Rulează o comandă shell sau citește un fișier pe desktopul tău de pe telefon." />
</Cards>

<Callout type="info">
Stocarea și streaming-ul **propriilor** sesiuni sunt disponibile pe orice tier plătit. Entitlement-ul `persistent_memory` condiționează doar memoria și căutarea pe server, nu acest protocol. O sesiune creată cu `e2e: true` este criptată pe client (HIDE — experimental, neauditat) și gateway-ul stochează ciphertext.
</Callout>
