# Connector

Connector mengirim dan menerima pesan antara satu kanal luar (platform chat, ruang siaran langsung) dan Gateway Cowork. Daftarkan dengan `api.registerConnector(definition)`.

## ConnectorDefinition

| Field | Tipe | Wajib | Deskripsi |
|---|---|---|---|
| `id` | `string` | Ya di 0.1.41; Tidak <Badge type="warning" text="Belum dirilis" /> | Huruf kecil, angka, dan tanda hubung. Jika `dozin.connectors` mencantumkan ID, `id` harus salah satunya; tanpa daftar itu ID valid apa pun bisa dipakai, hingga 16 Connector. Di 0.1.41 wajib dan harus tercantum. Mulai versi berikutnya default-nya nama paket |
| `systemPrompt` <Badge type="warning" text="Belum dirilis" /> | `string` | Tidak | Aturan yang diikuti setiap obrolan Connector ini, paling banyak 4000 karakter; pengguna tidak bisa mengubahnya |
| `chat` <Badge type="warning" text="Belum dirilis" /> | `{ title, roles?, maxLength?, maxPerMinute? }` | Tidak | Pesan masuk ke satu obrolan yang membalas dengan `gateway_send`. `title` 1–80 karakter; `roles` hingga 16 entri, ID huruf kecil (`host`, `viewer`, `self`) → label 1–24 karakter; `maxLength` 1–4000 (default 500); `maxPerMinute` 1–30 (default 6). `chat` yang tidak valid ditolak seluruhnya |
| `start(ctx)` | function | Ya | Lihat di bawah |
| `stop()` | function | Ya | Lihat di bawah |
| `send(reply)` | function | Ya | Lihat di bawah |

## start(ctx)

Dipanggil saat Connector mulai. Buka koneksi, timer, dan pengamat halaman di sini.

| Nama | Tipe | Deskripsi |
|---|---|---|
| `ctx` | `ConnectorContext` | `emit`, `log`, dan `browser` jika punya capability itu |

Mengembalikan `void` atau promise. Batas: 5 detik.

## stop()

Dipanggil saat Connector berhenti. Tutup semua yang dibuka oleh `start`. Harus aman dipanggil lebih dari sekali. Batas: 5 detik.

## send(reply)

Mengirim satu balasan dari Cowork ke kanal.

| Nama | Tipe | Deskripsi |
|---|---|---|
| `reply.text` | `string` | Balasannya |
| `reply.channelKey` | `string` | Tujuannya, seperti yang diberikan oleh `emit` |
| `reply.idempotencyKey` | `string` | Key yang sama dikirim paling banyak sekali |
| `reply.replyTo` <Badge type="warning" text="Belum dirilis" /> | `{ id, senderId, senderName, role }` | Dengan `chat`: pesan yang dijawab |

Mengembalikan `Promise<{ ok: boolean, error?: string, externalKey?: string, verified?: boolean }>`. `externalKey` adalah key milik platform untuk percakapan ini. `verified` <Badge type="warning" text="Belum dirilis" /> berarti balasan sudah terlihat di sisi lain (default-nya sama dengan `ok`).

| `error` hasil | Kapan |
|---|---|
| `send_timeout` | `send` memakan waktu lebih dari 30 detik |
| `unknown_connector` | Tidak ada Connector terdaftar dengan ID itu |
| `invalid_reply` | Balasan yang diberikan Cowork tidak bisa dibaca |
| `invalid_send_result` | `send` mengembalikan sesuatu tanpa `ok` bertipe boolean |
| Pesan yang dilempar | `send` melempar error |

## ctx.emit(message)

Menyerahkan satu pesan masuk ke Cowork.

| Field | Tipe | Wajib | Deskripsi |
|---|---|---|---|
| `text` | `string` | Ya | Yang ditampilkan di obrolan |
| `channelKey` | `string` | Tidak | `<connectorId>/<kind>/<channelId>`; default `<connectorId>/group/default` |
| `senderId` | `string` | Tidak | ID tetap pengirim dari platform |
| `senderName` | `string` | Tidak | Nama tampilan |
| `msgId` | `string` | Tidak | Dipakai untuk membuang duplikat |
| `at` | `number` | Tidak | Waktu platform dalam milidetik |
| `trigger` | `boolean` | Tidak | `false`: hanya konteks, dikirim bersama pesan berikutnya yang mendapat balasan |
| `contextText` | `string` | Tidak | Yang dibaca model sebagai pengganti `text` |
| `role` <Badge type="warning" text="Belum dirilis" /> | `string` | Tidak | Dengan `chat`: siapa yang berbicara (`host`, `viewer`, `self`); `self` hanya konteks |
| `modality` <Badge type="warning" text="Belum dirilis" /> | `'text' \| 'voice'` | Tidak | `voice`: ditranskripsi dari ucapan |

Tidak mengembalikan apa pun.

## ctx.log(text)

Menulis satu baris ke log Extension. Tidak mengembalikan apa pun.

```js
ctx.log('connected to room 42');
```

## Contoh

```js
export function activate(api) {
  let timer;
  api.registerConnector({
    id: 'demo',
    start(ctx) { timer = setInterval(() => ctx.emit({ text: 'ping', senderId: 'bot' }), 60000); },
    stop() { clearInterval(timer); },
    async send(reply) { return { ok: true }; }
  });
}
```

## Terkait

- [Entri dan Pendaftaran](https://docs.micromeet.ai/id/extension-sdk/entry.md): `registerConnector`
- [Browser](https://docs.micromeet.ai/id/extension-sdk/browser.md): `ctx.browser`, untuk Connector yang membaca halaman web
- [Gateway: Pesan dari Luar](https://docs.micromeet.ai/id/connections/gateway.md): Ke mana pesan pergi
