chore(i18n): refresh id translations
This commit is contained in:
parent
40eb955644
commit
0f8bd7fe3d
@ -3,34 +3,34 @@ read_when:
|
||||
- Anda ingin memahami untuk apa Active Memory digunakan
|
||||
- Anda ingin mengaktifkan Active Memory untuk agen percakapan
|
||||
- Anda ingin menyesuaikan perilaku Active Memory tanpa mengaktifkannya di semua tempat
|
||||
summary: Sub-agen memori pemblokiran milik Plugin yang menyuntikkan memori yang relevan ke dalam sesi obrolan interaktif
|
||||
summary: Sub-agen memori pemblokiran milik Plugin yang menyuntikkan memori yang relevan ke dalam sesi chat interaktif
|
||||
title: Active Memory
|
||||
x-i18n:
|
||||
generated_at: "2026-04-14T02:08:42Z"
|
||||
generated_at: "2026-04-16T09:14:37Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: b151e9eded7fc5c37e00da72d95b24c1dc94be22e855c8875f850538392b0637
|
||||
source_hash: ab36c5fea1578348cc2258ea3b344cc7bdc814f337d659cdb790512b3ea45473
|
||||
source_path: concepts/active-memory.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Active Memory
|
||||
|
||||
Active Memory adalah sub-agen memori pemblokiran opsional milik Plugin yang berjalan
|
||||
Active memory adalah sub-agen memori pemblokiran opsional milik Plugin yang berjalan
|
||||
sebelum balasan utama untuk sesi percakapan yang memenuhi syarat.
|
||||
|
||||
Ini ada karena sebagian besar sistem memori mampu tetapi reaktif. Sistem tersebut bergantung pada
|
||||
agen utama untuk memutuskan kapan harus mencari memori, atau pada pengguna untuk mengatakan hal-hal
|
||||
seperti "ingat ini" atau "cari memori." Pada saat itu, momen ketika memori akan
|
||||
membuat balasan terasa alami sudah lewat.
|
||||
agen utama untuk memutuskan kapan harus menelusuri memori, atau pada pengguna untuk mengatakan hal-hal
|
||||
seperti "ingat ini" atau "telusuri memori." Saat itu terjadi, momen ketika memori
|
||||
seharusnya membuat balasan terasa alami sudah terlewat.
|
||||
|
||||
Active Memory memberi sistem satu kesempatan yang dibatasi untuk memunculkan memori yang relevan
|
||||
Active memory memberi sistem satu kesempatan terbatas untuk memunculkan memori yang relevan
|
||||
sebelum balasan utama dibuat.
|
||||
|
||||
## Tempelkan Ini ke Agen Anda
|
||||
## Tempelkan Ini Ke Dalam Agen Anda
|
||||
|
||||
Tempelkan ini ke agen Anda jika Anda ingin mengaktifkan Active Memory dengan
|
||||
pengaturan yang mandiri dan aman secara default:
|
||||
Tempelkan ini ke dalam agen Anda jika Anda ingin mengaktifkan Active Memory dengan
|
||||
pengaturan mandiri yang aman secara default:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -56,7 +56,7 @@ pengaturan yang mandiri dan aman secara default:
|
||||
}
|
||||
```
|
||||
|
||||
Ini mengaktifkan plugin untuk agen `main`, membatasinya ke sesi
|
||||
Ini menyalakan Plugin untuk agen `main`, menjaganya tetap terbatas pada sesi
|
||||
bergaya pesan langsung secara default, memungkinkannya mewarisi model sesi saat ini terlebih dahulu, dan
|
||||
menggunakan model fallback yang dikonfigurasi hanya jika tidak ada model eksplisit atau turunan yang tersedia.
|
||||
|
||||
@ -77,7 +77,7 @@ Untuk memeriksanya secara langsung dalam percakapan:
|
||||
|
||||
Pengaturan yang paling aman adalah:
|
||||
|
||||
1. aktifkan plugin
|
||||
1. aktifkan Plugin
|
||||
2. targetkan satu agen percakapan
|
||||
3. biarkan logging tetap aktif hanya saat penyesuaian
|
||||
|
||||
@ -112,26 +112,111 @@ Lalu mulai ulang Gateway:
|
||||
openclaw gateway
|
||||
```
|
||||
|
||||
Arti dari ini:
|
||||
Artinya:
|
||||
|
||||
- `plugins.entries.active-memory.enabled: true` mengaktifkan plugin
|
||||
- `plugins.entries.active-memory.enabled: true` menyalakan Plugin
|
||||
- `config.agents: ["main"]` hanya mengikutsertakan agen `main` ke active memory
|
||||
- `config.allowedChatTypes: ["direct"]` membuat active memory tetap aktif hanya untuk sesi bergaya pesan langsung secara default
|
||||
- jika `config.model` tidak diatur, active memory mewarisi model sesi saat ini terlebih dahulu
|
||||
- jika `config.model` tidak disetel, active memory mewarisi model sesi saat ini terlebih dahulu
|
||||
- `config.modelFallback` secara opsional menyediakan provider/model fallback Anda sendiri untuk recall
|
||||
- `config.promptStyle: "balanced"` menggunakan gaya prompt tujuan umum default untuk mode `recent`
|
||||
- active memory tetap hanya berjalan pada sesi obrolan persisten interaktif yang memenuhi syarat
|
||||
- `config.promptStyle: "balanced"` menggunakan gaya prompt umum default untuk mode `recent`
|
||||
- active memory tetap hanya berjalan pada sesi chat persisten interaktif yang memenuhi syarat
|
||||
|
||||
## Rekomendasi kecepatan
|
||||
|
||||
Pengaturan paling sederhana adalah membiarkan `config.model` tidak disetel dan membiarkan Active Memory menggunakan
|
||||
model yang sama yang sudah Anda gunakan untuk balasan normal. Itu adalah default paling aman
|
||||
karena mengikuti preferensi provider, autentikasi, dan model yang sudah ada.
|
||||
|
||||
Jika Anda ingin Active Memory terasa lebih cepat, gunakan model inferensi khusus
|
||||
alih-alih meminjam model chat utama.
|
||||
|
||||
Contoh pengaturan provider cepat:
|
||||
|
||||
```json5
|
||||
models: {
|
||||
providers: {
|
||||
cerebras: {
|
||||
baseUrl: "https://api.cerebras.ai/v1",
|
||||
apiKey: "${CEREBRAS_API_KEY}",
|
||||
api: "openai-completions",
|
||||
models: [{ id: "gpt-oss-120b", name: "GPT OSS 120B (Cerebras)" }],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
entries: {
|
||||
"active-memory": {
|
||||
enabled: true,
|
||||
config: {
|
||||
model: "cerebras/gpt-oss-120b",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Opsi model cepat yang layak dipertimbangkan:
|
||||
|
||||
- `cerebras/gpt-oss-120b` untuk model recall khusus yang cepat dengan permukaan tool yang sempit
|
||||
- model sesi normal Anda, dengan membiarkan `config.model` tidak disetel
|
||||
- model fallback berlatensi rendah seperti `google/gemini-3-flash` saat Anda menginginkan model recall terpisah tanpa mengubah model chat utama Anda
|
||||
|
||||
Mengapa Cerebras merupakan opsi berorientasi kecepatan yang kuat untuk Active Memory:
|
||||
|
||||
- permukaan tool Active Memory sempit: hanya memanggil `memory_search` dan `memory_get`
|
||||
- kualitas recall penting, tetapi latensi lebih penting daripada pada jalur jawaban utama
|
||||
- provider cepat khusus menghindari keterikatan latensi recall memori pada provider chat utama Anda
|
||||
|
||||
Jika Anda tidak menginginkan model terpisah yang dioptimalkan untuk kecepatan, biarkan `config.model` tidak disetel
|
||||
dan biarkan Active Memory mewarisi model sesi saat ini.
|
||||
|
||||
### Pengaturan Cerebras
|
||||
|
||||
Tambahkan entri provider seperti ini:
|
||||
|
||||
```json5
|
||||
models: {
|
||||
providers: {
|
||||
cerebras: {
|
||||
baseUrl: "https://api.cerebras.ai/v1",
|
||||
apiKey: "${CEREBRAS_API_KEY}",
|
||||
api: "openai-completions",
|
||||
models: [{ id: "gpt-oss-120b", name: "GPT OSS 120B (Cerebras)" }],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Lalu arahkan Active Memory ke sana:
|
||||
|
||||
```json5
|
||||
plugins: {
|
||||
entries: {
|
||||
"active-memory": {
|
||||
enabled: true,
|
||||
config: {
|
||||
model: "cerebras/gpt-oss-120b",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Catatan:
|
||||
|
||||
- pastikan API key Cerebras benar-benar memiliki akses model untuk model yang Anda pilih, karena visibilitas `/v1/models` saja tidak menjamin akses `chat/completions`
|
||||
|
||||
## Cara melihatnya
|
||||
|
||||
Active memory menyuntikkan awalan prompt tersembunyi yang tidak tepercaya untuk model. Active memory
|
||||
tidak mengekspos tag mentah `<active_memory_plugin>...</active_memory_plugin>` di
|
||||
Active memory menyuntikkan awalan prompt tidak tepercaya tersembunyi untuk model. Fitur ini
|
||||
tidak mengekspos tag mentah `<active_memory_plugin>...</active_memory_plugin>` dalam
|
||||
balasan normal yang terlihat oleh klien.
|
||||
|
||||
## Toggle sesi
|
||||
## Tombol sesi
|
||||
|
||||
Gunakan perintah plugin ketika Anda ingin menjeda atau melanjutkan active memory untuk
|
||||
sesi obrolan saat ini tanpa mengedit konfigurasi:
|
||||
Gunakan perintah Plugin saat Anda ingin menjeda atau melanjutkan active memory untuk
|
||||
sesi chat saat ini tanpa mengedit konfigurasi:
|
||||
|
||||
```text
|
||||
/active-memory status
|
||||
@ -139,11 +224,11 @@ sesi obrolan saat ini tanpa mengedit konfigurasi:
|
||||
/active-memory on
|
||||
```
|
||||
|
||||
Ini berskala sesi. Ini tidak mengubah
|
||||
`plugins.entries.active-memory.enabled`, penargetan agen, atau konfigurasi
|
||||
global lainnya.
|
||||
Ini berlaku pada cakupan sesi. Ini tidak mengubah
|
||||
`plugins.entries.active-memory.enabled`, penargetan agen, atau konfigurasi global
|
||||
lainnya.
|
||||
|
||||
Jika Anda ingin perintah tersebut menulis konfigurasi dan menjeda atau melanjutkan active memory untuk
|
||||
Jika Anda ingin perintah menulis konfigurasi dan menjeda atau melanjutkan active memory untuk
|
||||
semua sesi, gunakan bentuk global yang eksplisit:
|
||||
|
||||
```text
|
||||
@ -157,7 +242,7 @@ Bentuk global menulis `plugins.entries.active-memory.config.enabled`. Bentuk ini
|
||||
mengaktifkan kembali active memory nanti.
|
||||
|
||||
Jika Anda ingin melihat apa yang dilakukan active memory dalam sesi langsung, aktifkan
|
||||
toggle sesi yang sesuai dengan output yang Anda inginkan:
|
||||
tombol sesi yang sesuai dengan keluaran yang Anda inginkan:
|
||||
|
||||
```text
|
||||
/verbose on
|
||||
@ -169,10 +254,10 @@ Dengan itu diaktifkan, OpenClaw dapat menampilkan:
|
||||
- baris status active memory seperti `Active Memory: status=ok elapsed=842ms query=recent summary=34 chars` saat `/verbose on`
|
||||
- ringkasan debug yang mudah dibaca seperti `Active Memory Debug: Lemon pepper wings with blue cheese.` saat `/trace on`
|
||||
|
||||
Baris-baris tersebut berasal dari pass active memory yang sama yang memberi awalan
|
||||
prompt tersembunyi, tetapi diformat untuk manusia alih-alih mengekspos markup prompt mentah.
|
||||
Baris-baris itu dikirim sebagai pesan diagnostik lanjutan setelah balasan normal
|
||||
asisten sehingga klien channel seperti Telegram tidak menampilkan gelembung diagnostik terpisah
|
||||
Baris-baris tersebut berasal dari pass active memory yang sama yang memberi masukan pada
|
||||
awalan prompt tersembunyi, tetapi diformat untuk manusia alih-alih mengekspos markup prompt mentah.
|
||||
Baris-baris tersebut dikirim sebagai pesan diagnostik lanjutan setelah balasan normal
|
||||
asisten sehingga klien saluran seperti Telegram tidak menampilkan gelembung diagnostik terpisah
|
||||
sebelum balasan.
|
||||
|
||||
Jika Anda juga mengaktifkan `/trace raw`, blok `Model Input (User Role)` yang ditelusuri akan
|
||||
@ -193,57 +278,58 @@ Contoh alur:
|
||||
```text
|
||||
/verbose on
|
||||
/trace on
|
||||
sayap apa yang sebaiknya saya pesan?
|
||||
what wings should i order?
|
||||
```
|
||||
|
||||
Bentuk balasan terlihat yang diharapkan:
|
||||
Bentuk balasan yang diharapkan terlihat:
|
||||
|
||||
```text
|
||||
...balasan asisten normal...
|
||||
...normal assistant reply...
|
||||
|
||||
🧩 Active Memory: status=ok elapsed=842ms query=recent summary=34 chars
|
||||
🔎 Active Memory Debug: Lemon pepper wings with blue cheese.
|
||||
```
|
||||
|
||||
## Kapan dijalankan
|
||||
## Kapan berjalan
|
||||
|
||||
Active memory menggunakan dua gerbang:
|
||||
|
||||
1. **Opt-in konfigurasi**
|
||||
Plugin harus diaktifkan, dan id agen saat ini harus muncul di
|
||||
Plugin harus diaktifkan, dan ID agen saat ini harus muncul di
|
||||
`plugins.entries.active-memory.config.agents`.
|
||||
2. **Kelayakan runtime yang ketat**
|
||||
Bahkan ketika diaktifkan dan ditargetkan, active memory hanya berjalan untuk sesi obrolan persisten interaktif yang memenuhi syarat.
|
||||
Bahkan ketika diaktifkan dan ditargetkan, active memory hanya berjalan untuk
|
||||
sesi chat persisten interaktif yang memenuhi syarat.
|
||||
|
||||
Aturan sebenarnya adalah:
|
||||
|
||||
```text
|
||||
plugin diaktifkan
|
||||
plugin enabled
|
||||
+
|
||||
id agen ditargetkan
|
||||
agent id targeted
|
||||
+
|
||||
jenis obrolan diizinkan
|
||||
allowed chat type
|
||||
+
|
||||
sesi obrolan persisten interaktif yang memenuhi syarat
|
||||
eligible interactive persistent chat session
|
||||
=
|
||||
active memory berjalan
|
||||
active memory runs
|
||||
```
|
||||
|
||||
Jika salah satu gagal, active memory tidak berjalan.
|
||||
|
||||
## Jenis sesi
|
||||
|
||||
`config.allowedChatTypes` mengontrol jenis percakapan apa saja yang boleh menjalankan Active
|
||||
`config.allowedChatTypes` mengontrol jenis percakapan mana yang boleh menjalankan Active
|
||||
Memory sama sekali.
|
||||
|
||||
Nilai default-nya adalah:
|
||||
Default-nya adalah:
|
||||
|
||||
```json5
|
||||
allowedChatTypes: ["direct"]
|
||||
```
|
||||
|
||||
Itu berarti Active Memory berjalan secara default dalam sesi bergaya pesan langsung, tetapi
|
||||
tidak dalam sesi grup atau channel kecuali Anda secara eksplisit mengikutsertakannya.
|
||||
Artinya Active Memory berjalan secara default dalam sesi bergaya pesan langsung, tetapi
|
||||
tidak dalam sesi grup atau saluran kecuali Anda secara eksplisit mengikutsertakannya.
|
||||
|
||||
Contoh:
|
||||
|
||||
@ -259,38 +345,38 @@ allowedChatTypes: ["direct", "group"]
|
||||
allowedChatTypes: ["direct", "group", "channel"]
|
||||
```
|
||||
|
||||
## Di mana dijalankan
|
||||
## Di mana berjalan
|
||||
|
||||
Active memory adalah fitur pengayaan percakapan, bukan fitur inferensi
|
||||
seluruh platform.
|
||||
|
||||
| Surface | Menjalankan active memory? |
|
||||
| ------------------------------------------------------------------- | ------------------------------------------------------- |
|
||||
| Sesi persisten UI kontrol / web chat | Ya, jika plugin diaktifkan dan agen ditargetkan |
|
||||
| Sesi channel interaktif lain pada jalur obrolan persisten yang sama | Ya, jika plugin diaktifkan dan agen ditargetkan |
|
||||
| Control UI / sesi persisten web chat | Ya, jika Plugin diaktifkan dan agen ditargetkan |
|
||||
| Sesi saluran interaktif lain pada jalur chat persisten yang sama | Ya, jika Plugin diaktifkan dan agen ditargetkan |
|
||||
| Proses headless sekali jalan | Tidak |
|
||||
| Proses Heartbeat/latar belakang | Tidak |
|
||||
| Jalur `agent-command` internal generik | Tidak |
|
||||
| Jalur internal `agent-command` generik | Tidak |
|
||||
| Eksekusi sub-agen/helper internal | Tidak |
|
||||
|
||||
## Mengapa menggunakannya
|
||||
|
||||
Gunakan active memory ketika:
|
||||
Gunakan active memory saat:
|
||||
|
||||
- sesi bersifat persisten dan menghadap pengguna
|
||||
- agen memiliki memori jangka panjang yang bermakna untuk dicari
|
||||
- kesinambungan dan personalisasi lebih penting daripada determinisme prompt mentah
|
||||
- sesi bersifat persisten dan berhadapan dengan pengguna
|
||||
- agen memiliki memori jangka panjang yang bermakna untuk ditelusuri
|
||||
- kontinuitas dan personalisasi lebih penting daripada determinisme prompt mentah
|
||||
|
||||
Active memory bekerja sangat baik terutama untuk:
|
||||
Fitur ini bekerja sangat baik untuk:
|
||||
|
||||
- preferensi yang stabil
|
||||
- kebiasaan yang berulang
|
||||
- konteks pengguna jangka panjang yang seharusnya muncul secara alami
|
||||
|
||||
Active memory kurang cocok untuk:
|
||||
Fitur ini kurang cocok untuk:
|
||||
|
||||
- otomatisasi
|
||||
- pekerja internal
|
||||
- worker internal
|
||||
- tugas API sekali jalan
|
||||
- tempat di mana personalisasi tersembunyi akan terasa mengejutkan
|
||||
|
||||
@ -312,11 +398,11 @@ Sub-agen memori pemblokiran hanya dapat menggunakan:
|
||||
- `memory_search`
|
||||
- `memory_get`
|
||||
|
||||
Jika koneksinya lemah, sub-agen tersebut harus mengembalikan `NONE`.
|
||||
Jika koneksinya lemah, sub-agen harus mengembalikan `NONE`.
|
||||
|
||||
## Mode kueri
|
||||
|
||||
`config.queryMode` mengontrol seberapa banyak percakapan yang dilihat sub-agen memori pemblokiran.
|
||||
`config.queryMode` mengontrol seberapa banyak percakapan yang dilihat oleh sub-agen memori pemblokiran.
|
||||
|
||||
## Gaya prompt
|
||||
|
||||
@ -325,14 +411,14 @@ saat memutuskan apakah akan mengembalikan memori.
|
||||
|
||||
Gaya yang tersedia:
|
||||
|
||||
- `balanced`: default tujuan umum untuk mode `recent`
|
||||
- `strict`: paling tidak antusias; terbaik saat Anda ingin sangat sedikit kebocoran dari konteks sekitar
|
||||
- `contextual`: paling ramah terhadap kesinambungan; terbaik saat riwayat percakapan harus lebih diperhitungkan
|
||||
- `balanced`: default serbaguna untuk mode `recent`
|
||||
- `strict`: paling tidak antusias; terbaik saat Anda menginginkan sangat sedikit pengaruh dari konteks terdekat
|
||||
- `contextual`: paling ramah kontinuitas; terbaik saat riwayat percakapan harus lebih diperhitungkan
|
||||
- `recall-heavy`: lebih bersedia memunculkan memori pada kecocokan yang lebih lemah tetapi masih masuk akal
|
||||
- `precision-heavy`: sangat memilih `NONE` kecuali kecocokannya jelas
|
||||
- `preference-only`: dioptimalkan untuk favorit, kebiasaan, rutinitas, selera, dan fakta pribadi yang berulang
|
||||
|
||||
Pemetaan default saat `config.promptStyle` tidak diatur:
|
||||
Pemetaan default saat `config.promptStyle` tidak disetel:
|
||||
|
||||
```text
|
||||
message -> strict
|
||||
@ -340,7 +426,7 @@ recent -> balanced
|
||||
full -> contextual
|
||||
```
|
||||
|
||||
Jika Anda mengatur `config.promptStyle` secara eksplisit, override tersebut yang berlaku.
|
||||
Jika Anda menyetel `config.promptStyle` secara eksplisit, override itu yang berlaku.
|
||||
|
||||
Contoh:
|
||||
|
||||
@ -350,16 +436,16 @@ promptStyle: "preference-only"
|
||||
|
||||
## Kebijakan fallback model
|
||||
|
||||
Jika `config.model` tidak diatur, Active Memory mencoba menyelesaikan model dalam urutan ini:
|
||||
Jika `config.model` tidak disetel, Active Memory mencoba menyelesaikan model dalam urutan ini:
|
||||
|
||||
```text
|
||||
model plugin eksplisit
|
||||
-> model sesi saat ini
|
||||
-> model utama agen
|
||||
-> model fallback yang dikonfigurasi secara opsional
|
||||
explicit plugin model
|
||||
-> current session model
|
||||
-> agent primary model
|
||||
-> optional configured fallback model
|
||||
```
|
||||
|
||||
`config.modelFallback` mengontrol langkah fallback yang dikonfigurasi.
|
||||
`config.modelFallback` mengontrol langkah fallback terkonfigurasi.
|
||||
|
||||
Fallback kustom opsional:
|
||||
|
||||
@ -367,17 +453,17 @@ Fallback kustom opsional:
|
||||
modelFallback: "google/gemini-3-flash"
|
||||
```
|
||||
|
||||
Jika tidak ada model eksplisit, turunan, atau fallback yang dikonfigurasi yang dapat diselesaikan, Active Memory
|
||||
Jika tidak ada model eksplisit, turunan, atau fallback terkonfigurasi yang berhasil diselesaikan, Active Memory
|
||||
melewati recall untuk giliran tersebut.
|
||||
|
||||
`config.modelFallbackPolicy` dipertahankan hanya sebagai field kompatibilitas usang
|
||||
untuk konfigurasi lama. Field ini tidak lagi mengubah perilaku runtime.
|
||||
`config.modelFallbackPolicy` dipertahankan hanya sebagai field kompatibilitas
|
||||
usang untuk konfigurasi lama. Field ini tidak lagi mengubah perilaku runtime.
|
||||
|
||||
## Escape hatch lanjutan
|
||||
## Opsi lanjutan untuk situasi khusus
|
||||
|
||||
Opsi-opsi ini sengaja tidak menjadi bagian dari pengaturan yang direkomendasikan.
|
||||
Opsi ini sengaja tidak menjadi bagian dari pengaturan yang direkomendasikan.
|
||||
|
||||
`config.thinking` dapat mengganti tingkat thinking sub-agen memori pemblokiran:
|
||||
`config.thinking` dapat menimpa tingkat thinking sub-agen memori pemblokiran:
|
||||
|
||||
```json5
|
||||
thinking: "medium"
|
||||
@ -392,21 +478,21 @@ thinking: "off"
|
||||
Jangan aktifkan ini secara default. Active Memory berjalan di jalur balasan, jadi waktu
|
||||
thinking tambahan secara langsung meningkatkan latensi yang terlihat oleh pengguna.
|
||||
|
||||
`config.promptAppend` menambahkan instruksi operator tambahan setelah prompt Active
|
||||
Memory default dan sebelum konteks percakapan:
|
||||
`config.promptAppend` menambahkan instruksi operator tambahan setelah prompt default Active
|
||||
Memory dan sebelum konteks percakapan:
|
||||
|
||||
```json5
|
||||
promptAppend: "Utamakan preferensi jangka panjang yang stabil daripada peristiwa sekali jalan."
|
||||
promptAppend: "Prefer stable long-term preferences over one-off events."
|
||||
```
|
||||
|
||||
`config.promptOverride` menggantikan prompt Active Memory default. OpenClaw
|
||||
`config.promptOverride` menggantikan prompt default Active Memory. OpenClaw
|
||||
tetap menambahkan konteks percakapan setelahnya:
|
||||
|
||||
```json5
|
||||
promptOverride: "Anda adalah agen pencarian memori. Kembalikan NONE atau satu fakta pengguna yang ringkas."
|
||||
promptOverride: "You are a memory search agent. Return NONE or one compact user fact."
|
||||
```
|
||||
|
||||
Kustomisasi prompt tidak direkomendasikan kecuali Anda memang sengaja menguji
|
||||
Kustomisasi prompt tidak direkomendasikan kecuali Anda memang sedang menguji
|
||||
kontrak recall yang berbeda. Prompt default disetel untuk mengembalikan `NONE`
|
||||
atau konteks fakta pengguna yang ringkas untuk model utama.
|
||||
|
||||
@ -415,48 +501,48 @@ atau konteks fakta pengguna yang ringkas untuk model utama.
|
||||
Hanya pesan pengguna terbaru yang dikirim.
|
||||
|
||||
```text
|
||||
Hanya pesan pengguna terbaru
|
||||
Latest user message only
|
||||
```
|
||||
|
||||
Gunakan ini ketika:
|
||||
|
||||
- Anda menginginkan perilaku tercepat
|
||||
- Anda menginginkan bias terkuat terhadap recall preferensi yang stabil
|
||||
- giliran tindak lanjut tidak memerlukan konteks percakapan
|
||||
- giliran lanjutan tidak memerlukan konteks percakapan
|
||||
|
||||
Timeout yang direkomendasikan:
|
||||
|
||||
- mulai sekitar `3000` hingga `5000` ms
|
||||
- mulai dari sekitar `3000` hingga `5000` ms
|
||||
|
||||
### `recent`
|
||||
|
||||
Pesan pengguna terbaru ditambah sedikit ekor percakapan terbaru dikirim.
|
||||
Pesan pengguna terbaru ditambah ekor percakapan terbaru yang kecil akan dikirim.
|
||||
|
||||
```text
|
||||
Ekor percakapan terbaru:
|
||||
Recent conversation tail:
|
||||
user: ...
|
||||
assistant: ...
|
||||
user: ...
|
||||
|
||||
Pesan pengguna terbaru:
|
||||
Latest user message:
|
||||
...
|
||||
```
|
||||
|
||||
Gunakan ini ketika:
|
||||
|
||||
- Anda menginginkan keseimbangan yang lebih baik antara kecepatan dan landasan percakapan
|
||||
- pertanyaan tindak lanjut sering bergantung pada beberapa giliran terakhir
|
||||
- Anda menginginkan keseimbangan yang lebih baik antara kecepatan dan pijakan percakapan
|
||||
- pertanyaan lanjutan sering bergantung pada beberapa giliran terakhir
|
||||
|
||||
Timeout yang direkomendasikan:
|
||||
|
||||
- mulai sekitar `15000` ms
|
||||
- mulai dari sekitar `15000` ms
|
||||
|
||||
### `full`
|
||||
|
||||
Percakapan lengkap dikirim ke sub-agen memori pemblokiran.
|
||||
Seluruh percakapan dikirim ke sub-agen memori pemblokiran.
|
||||
|
||||
```text
|
||||
Konteks percakapan lengkap:
|
||||
Full conversation context:
|
||||
user: ...
|
||||
assistant: ...
|
||||
user: ...
|
||||
@ -466,14 +552,14 @@ user: ...
|
||||
Gunakan ini ketika:
|
||||
|
||||
- kualitas recall terkuat lebih penting daripada latensi
|
||||
- percakapan berisi pengaturan penting yang berada jauh di belakang dalam thread
|
||||
- percakapan berisi pengaturan penting jauh di belakang dalam utas
|
||||
|
||||
Timeout yang direkomendasikan:
|
||||
|
||||
- tingkatkan secara signifikan dibandingkan dengan `message` atau `recent`
|
||||
- mulai sekitar `15000` ms atau lebih tinggi, bergantung pada ukuran thread
|
||||
- tingkatkan secara signifikan dibandingkan `message` atau `recent`
|
||||
- mulai dari sekitar `15000` ms atau lebih tinggi tergantung ukuran utas
|
||||
|
||||
Secara umum, timeout harus meningkat seiring ukuran konteks:
|
||||
Secara umum, timeout sebaiknya meningkat seiring ukuran konteks:
|
||||
|
||||
```text
|
||||
message < recent < full
|
||||
@ -481,17 +567,17 @@ message < recent < full
|
||||
|
||||
## Persistensi transkrip
|
||||
|
||||
Proses sub-agen memori pemblokiran Active Memory membuat transkrip `session.jsonl`
|
||||
nyata selama pemanggilan sub-agen memori pemblokiran.
|
||||
Proses sub-agen memori pemblokiran Active memory membuat transkrip `session.jsonl` nyata
|
||||
selama pemanggilan sub-agen memori pemblokiran.
|
||||
|
||||
Secara default, transkrip tersebut bersifat sementara:
|
||||
|
||||
- ditulis ke direktori temp
|
||||
- digunakan hanya untuk proses sub-agen memori pemblokiran
|
||||
- ditulis ke direktori sementara
|
||||
- hanya digunakan untuk proses sub-agen memori pemblokiran
|
||||
- dihapus segera setelah proses selesai
|
||||
|
||||
Jika Anda ingin menyimpan transkrip sub-agen memori pemblokiran tersebut di disk untuk debugging atau
|
||||
inspeksi, aktifkan persistensi secara eksplisit:
|
||||
pemeriksaan, aktifkan persistensi secara eksplisit:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -510,7 +596,7 @@ inspeksi, aktifkan persistensi secara eksplisit:
|
||||
}
|
||||
```
|
||||
|
||||
Saat diaktifkan, active memory menyimpan transkrip di direktori terpisah di bawah
|
||||
Saat diaktifkan, active memory menyimpan transkrip dalam direktori terpisah di bawah
|
||||
folder sesi agen target, bukan di jalur transkrip percakapan pengguna utama.
|
||||
|
||||
Secara konseptual, tata letak default adalah:
|
||||
@ -523,8 +609,8 @@ Anda dapat mengubah subdirektori relatif dengan `config.transcriptDir`.
|
||||
|
||||
Gunakan ini dengan hati-hati:
|
||||
|
||||
- transkrip sub-agen memori pemblokiran dapat cepat menumpuk pada sesi yang sibuk
|
||||
- mode kueri `full` dapat menggandakan banyak konteks percakapan
|
||||
- transkrip sub-agen memori pemblokiran dapat menumpuk dengan cepat pada sesi yang sibuk
|
||||
- mode kueri `full` dapat menduplikasi banyak konteks percakapan
|
||||
- transkrip ini berisi konteks prompt tersembunyi dan memori yang di-recall
|
||||
|
||||
## Konfigurasi
|
||||
@ -537,32 +623,32 @@ plugins.entries.active-memory
|
||||
|
||||
Field yang paling penting adalah:
|
||||
|
||||
| Key | Type | Arti |
|
||||
| --------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| `enabled` | `boolean` | Mengaktifkan plugin itu sendiri |
|
||||
| `config.agents` | `string[]` | Id agen yang dapat menggunakan active memory |
|
||||
| `config.model` | `string` | Ref model sub-agen memori pemblokiran opsional; jika tidak diatur, active memory menggunakan model sesi saat ini |
|
||||
| `config.queryMode` | `"message" \| "recent" \| "full"` | Mengontrol seberapa banyak percakapan yang dilihat sub-agen memori pemblokiran |
|
||||
| Key | Type | Arti |
|
||||
| --------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| `enabled` | `boolean` | Mengaktifkan Plugin itu sendiri |
|
||||
| `config.agents` | `string[]` | ID agen yang dapat menggunakan active memory |
|
||||
| `config.model` | `string` | Ref model sub-agen memori pemblokiran opsional; jika tidak disetel, active memory menggunakan model sesi saat ini |
|
||||
| `config.queryMode` | `"message" \| "recent" \| "full"` | Mengontrol seberapa banyak percakapan yang dilihat sub-agen memori pemblokiran |
|
||||
| `config.promptStyle` | `"balanced" \| "strict" \| "contextual" \| "recall-heavy" \| "precision-heavy" \| "preference-only"` | Mengontrol seberapa antusias atau ketat sub-agen memori pemblokiran saat memutuskan apakah akan mengembalikan memori |
|
||||
| `config.thinking` | `"off" \| "minimal" \| "low" \| "medium" \| "high" \| "xhigh" \| "adaptive"` | Override thinking lanjutan untuk sub-agen memori pemblokiran; default `off` untuk kecepatan |
|
||||
| `config.promptOverride` | `string` | Penggantian prompt penuh lanjutan; tidak direkomendasikan untuk penggunaan normal |
|
||||
| `config.promptAppend` | `string` | Instruksi tambahan lanjutan yang ditambahkan ke prompt default atau yang dioverride |
|
||||
| `config.timeoutMs` | `number` | Timeout keras untuk sub-agen memori pemblokiran |
|
||||
| `config.maxSummaryChars` | `number` | Total karakter maksimum yang diizinkan dalam ringkasan active-memory |
|
||||
| `config.logging` | `boolean` | Menghasilkan log active memory saat penyesuaian |
|
||||
| `config.persistTranscripts` | `boolean` | Menyimpan transkrip sub-agen memori pemblokiran di disk alih-alih menghapus file temp |
|
||||
| `config.transcriptDir` | `string` | Direktori transkrip sub-agen memori pemblokiran relatif di bawah folder sesi agen |
|
||||
| `config.thinking` | `"off" \| "minimal" \| "low" \| "medium" \| "high" \| "xhigh" \| "adaptive"` | Override thinking lanjutan untuk sub-agen memori pemblokiran; default `off` demi kecepatan |
|
||||
| `config.promptOverride` | `string` | Penggantian prompt penuh lanjutan; tidak direkomendasikan untuk penggunaan normal |
|
||||
| `config.promptAppend` | `string` | Instruksi tambahan lanjutan yang ditambahkan ke prompt default atau yang dioverride |
|
||||
| `config.timeoutMs` | `number` | Timeout keras untuk sub-agen memori pemblokiran |
|
||||
| `config.maxSummaryChars` | `number` | Jumlah total karakter maksimum yang diizinkan dalam ringkasan active-memory |
|
||||
| `config.logging` | `boolean` | Menghasilkan log active memory selama penyesuaian |
|
||||
| `config.persistTranscripts` | `boolean` | Menyimpan transkrip sub-agen memori pemblokiran di disk alih-alih menghapus file sementara |
|
||||
| `config.transcriptDir` | `string` | Direktori transkrip sub-agen memori pemblokiran relatif di bawah folder sesi agen |
|
||||
|
||||
Field penyesuaian yang berguna:
|
||||
|
||||
| Key | Type | Arti |
|
||||
| ----------------------------- | -------- | ------------------------------------------------------------- |
|
||||
| `config.maxSummaryChars` | `number` | Total karakter maksimum yang diizinkan dalam ringkasan active-memory |
|
||||
| Key | Type | Arti |
|
||||
| ----------------------------- | -------- | ------------------------------------------------------------------ |
|
||||
| `config.maxSummaryChars` | `number` | Jumlah total karakter maksimum yang diizinkan dalam ringkasan active-memory |
|
||||
| `config.recentUserTurns` | `number` | Giliran pengguna sebelumnya yang disertakan saat `queryMode` adalah `recent` |
|
||||
| `config.recentAssistantTurns` | `number` | Giliran asisten sebelumnya yang disertakan saat `queryMode` adalah `recent` |
|
||||
| `config.recentUserChars` | `number` | Maks karakter per giliran pengguna terbaru |
|
||||
| `config.recentAssistantChars` | `number` | Maks karakter per giliran asisten terbaru |
|
||||
| `config.cacheTtlMs` | `number` | Penggunaan ulang cache untuk kueri identik yang berulang |
|
||||
| `config.recentUserChars` | `number` | Karakter maksimum per giliran pengguna terbaru |
|
||||
| `config.recentAssistantChars` | `number` | Karakter maksimum per giliran asisten terbaru |
|
||||
| `config.cacheTtlMs` | `number` | Penggunaan ulang cache untuk kueri identik berulang |
|
||||
|
||||
## Pengaturan yang direkomendasikan
|
||||
|
||||
@ -588,12 +674,12 @@ Mulailah dengan `recent`.
|
||||
}
|
||||
```
|
||||
|
||||
Jika Anda ingin memeriksa perilaku langsung saat melakukan penyesuaian, gunakan `/verbose on` untuk
|
||||
baris status normal dan `/trace on` untuk ringkasan debug active-memory alih-alih
|
||||
mencari perintah debug active-memory terpisah. Di channel obrolan, baris diagnostik tersebut
|
||||
dikirim setelah balasan asisten utama, bukan sebelumnya.
|
||||
Jika Anda ingin memeriksa perilaku langsung saat penyesuaian, gunakan `/verbose on` untuk
|
||||
baris status normal dan `/trace on` untuk ringkasan debug active-memory
|
||||
alih-alih mencari perintah debug active-memory terpisah. Di saluran chat, baris
|
||||
diagnostik tersebut dikirim setelah balasan utama asisten, bukan sebelumnya.
|
||||
|
||||
Lalu beralih ke:
|
||||
Lalu pindah ke:
|
||||
|
||||
- `message` jika Anda menginginkan latensi yang lebih rendah
|
||||
- `full` jika Anda memutuskan konteks tambahan sepadan dengan sub-agen memori pemblokiran yang lebih lambat
|
||||
@ -602,13 +688,13 @@ Lalu beralih ke:
|
||||
|
||||
Jika active memory tidak muncul di tempat yang Anda harapkan:
|
||||
|
||||
1. Konfirmasikan plugin diaktifkan di `plugins.entries.active-memory.enabled`.
|
||||
2. Konfirmasikan id agen saat ini tercantum di `config.agents`.
|
||||
3. Konfirmasikan Anda menguji melalui sesi obrolan persisten interaktif.
|
||||
1. Pastikan Plugin diaktifkan di `plugins.entries.active-memory.enabled`.
|
||||
2. Pastikan ID agen saat ini tercantum di `config.agents`.
|
||||
3. Pastikan Anda menguji melalui sesi chat persisten interaktif.
|
||||
4. Aktifkan `config.logging: true` dan pantau log Gateway.
|
||||
5. Verifikasi bahwa pencarian memori itu sendiri berfungsi dengan `openclaw memory status --deep`.
|
||||
5. Verifikasi bahwa penelusuran memori itu sendiri berfungsi dengan `openclaw memory status --deep`.
|
||||
|
||||
Jika hasil memori terlalu berisik, perketat:
|
||||
Jika hasil memori terlalu bising, perketat:
|
||||
|
||||
- `maxSummaryChars`
|
||||
|
||||
@ -621,60 +707,60 @@ Jika active memory terlalu lambat:
|
||||
|
||||
## Masalah umum
|
||||
|
||||
### Provider embedding berubah secara tidak terduga
|
||||
### Provider embedding berubah tanpa diduga
|
||||
|
||||
Active Memory menggunakan pipeline `memory_search` normal di bawah
|
||||
`agents.defaults.memorySearch`. Itu berarti penyiapan provider embedding hanya menjadi
|
||||
persyaratan ketika pengaturan `memorySearch` Anda memerlukan embedding untuk perilaku
|
||||
`agents.defaults.memorySearch`. Artinya, pengaturan provider embedding hanya menjadi
|
||||
persyaratan saat pengaturan `memorySearch` Anda memerlukan embedding untuk perilaku
|
||||
yang Anda inginkan.
|
||||
|
||||
Dalam praktiknya:
|
||||
|
||||
- penyiapan provider eksplisit **diperlukan** jika Anda menginginkan provider yang tidak
|
||||
dideteksi otomatis, seperti `ollama`
|
||||
- penyiapan provider eksplisit **diperlukan** jika deteksi otomatis tidak dapat menyelesaikan
|
||||
provider embedding yang dapat digunakan untuk lingkungan Anda
|
||||
- penyiapan provider eksplisit **sangat direkomendasikan** jika Anda menginginkan
|
||||
pemilihan provider yang deterministik alih-alih "yang pertama tersedia menang"
|
||||
- penyiapan provider eksplisit biasanya **tidak diperlukan** jika deteksi otomatis sudah
|
||||
- pengaturan provider eksplisit **diperlukan** jika Anda menginginkan provider yang tidak
|
||||
terdeteksi otomatis, seperti `ollama`
|
||||
- pengaturan provider eksplisit **diperlukan** jika deteksi otomatis tidak berhasil
|
||||
menyelesaikan provider embedding yang dapat digunakan untuk lingkungan Anda
|
||||
- pengaturan provider eksplisit **sangat direkomendasikan** jika Anda menginginkan
|
||||
pemilihan provider yang deterministik alih-alih "yang tersedia pertama menang"
|
||||
- pengaturan provider eksplisit biasanya **tidak diperlukan** jika deteksi otomatis sudah
|
||||
menyelesaikan provider yang Anda inginkan dan provider tersebut stabil dalam deployment Anda
|
||||
|
||||
Jika `memorySearch.provider` tidak diatur, OpenClaw mendeteksi otomatis provider
|
||||
Jika `memorySearch.provider` tidak disetel, OpenClaw mendeteksi otomatis provider
|
||||
embedding pertama yang tersedia.
|
||||
|
||||
Ini bisa membingungkan dalam deployment nyata:
|
||||
Hal itu dapat membingungkan dalam deployment nyata:
|
||||
|
||||
- API key yang baru tersedia dapat mengubah provider mana yang digunakan pencarian memori
|
||||
- satu perintah atau surface diagnostik dapat membuat provider yang dipilih terlihat
|
||||
berbeda dari jalur yang sebenarnya Anda gunakan selama sinkronisasi memori langsung atau
|
||||
bootstrap pencarian
|
||||
- provider yang di-host dapat gagal dengan error kuota atau rate-limit yang baru terlihat
|
||||
setelah Active Memory mulai mengeluarkan pencarian recall sebelum setiap balasan
|
||||
- API key yang baru tersedia dapat mengubah provider mana yang digunakan penelusuran memori
|
||||
- satu perintah atau permukaan diagnostik mungkin membuat provider yang dipilih tampak
|
||||
berbeda dari jalur yang benar-benar Anda gunakan selama sinkronisasi memori langsung atau
|
||||
bootstrap penelusuran
|
||||
- provider ter-host dapat gagal dengan error kuota atau rate limit yang baru terlihat
|
||||
setelah Active Memory mulai mengeluarkan kueri recall sebelum setiap balasan
|
||||
|
||||
Active Memory tetap dapat berjalan tanpa embedding ketika `memory_search` dapat beroperasi
|
||||
dalam mode degradasi hanya leksikal, yang biasanya terjadi ketika tidak ada provider
|
||||
Active Memory tetap dapat berjalan tanpa embedding saat `memory_search` dapat beroperasi
|
||||
dalam mode degradasi leksikal saja, yang biasanya terjadi saat tidak ada provider
|
||||
embedding yang dapat diselesaikan.
|
||||
|
||||
Jangan berasumsi fallback yang sama berlaku pada kegagalan runtime provider seperti kehabisan kuota,
|
||||
rate limit, error jaringan/provider, atau model lokal/jarak jauh yang hilang setelah suatu provider
|
||||
sudah dipilih.
|
||||
Jangan berasumsi fallback yang sama berlaku pada kegagalan runtime provider seperti
|
||||
kuota habis, rate limit, error jaringan/provider, atau model lokal/jarak jauh yang hilang
|
||||
setelah provider sudah dipilih.
|
||||
|
||||
Dalam praktiknya:
|
||||
|
||||
- jika tidak ada provider embedding yang dapat diselesaikan, `memory_search` dapat terdegradasi menjadi
|
||||
pengambilan hanya leksikal
|
||||
- jika suatu provider embedding dapat diselesaikan lalu gagal saat runtime, OpenClaw saat ini
|
||||
- jika tidak ada provider embedding yang dapat diselesaikan, `memory_search` dapat turun menjadi
|
||||
pengambilan leksikal saja
|
||||
- jika provider embedding berhasil diselesaikan lalu gagal saat runtime, OpenClaw saat ini
|
||||
tidak menjamin fallback leksikal untuk permintaan tersebut
|
||||
- jika Anda memerlukan pemilihan provider yang deterministik, pin
|
||||
`agents.defaults.memorySearch.provider`
|
||||
- jika Anda memerlukan failover provider pada error runtime, konfigurasikan
|
||||
- jika Anda memerlukan failover provider saat terjadi error runtime, konfigurasikan
|
||||
`agents.defaults.memorySearch.fallback` secara eksplisit
|
||||
|
||||
Jika Anda bergantung pada recall berbasis embedding, pengindeksan multimodal, atau provider
|
||||
lokal/jarak jauh tertentu, pin provider tersebut secara eksplisit alih-alih mengandalkan
|
||||
lokal/jarak jauh tertentu, pin provider secara eksplisit alih-alih mengandalkan
|
||||
deteksi otomatis.
|
||||
|
||||
Contoh pinning umum:
|
||||
Contoh pinning yang umum:
|
||||
|
||||
OpenAI:
|
||||
|
||||
@ -721,8 +807,8 @@ Ollama:
|
||||
}
|
||||
```
|
||||
|
||||
Jika Anda mengharapkan failover provider pada error runtime seperti kehabisan kuota,
|
||||
pinning provider saja tidak cukup. Konfigurasikan juga fallback eksplisit:
|
||||
Jika Anda mengharapkan failover provider pada error runtime seperti
|
||||
kuota habis, pinning provider saja tidak cukup. Konfigurasikan fallback eksplisit juga:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -739,29 +825,30 @@ pinning provider saja tidak cukup. Konfigurasikan juga fallback eksplisit:
|
||||
|
||||
### Debugging masalah provider
|
||||
|
||||
Jika Active Memory lambat, kosong, atau tampak berpindah provider secara tidak terduga:
|
||||
Jika Active Memory lambat, kosong, atau tampak berpindah provider tanpa diduga:
|
||||
|
||||
- pantau log Gateway saat mereproduksi masalah; cari baris seperti
|
||||
`active-memory: ... start|done`, `memory sync failed (search-bootstrap)`, atau
|
||||
error embedding khusus provider
|
||||
- aktifkan `/trace on` untuk memunculkan ringkasan debug Active Memory milik Plugin di
|
||||
error embedding spesifik provider
|
||||
- aktifkan `/trace on` untuk menampilkan ringkasan debug Active Memory milik Plugin di
|
||||
sesi
|
||||
- aktifkan `/verbose on` jika Anda juga menginginkan baris status normal `🧩 Active Memory: ...`
|
||||
- aktifkan `/verbose on` jika Anda juga ingin baris status normal `🧩 Active Memory: ...`
|
||||
setelah setiap balasan
|
||||
- jalankan `openclaw memory status --deep` untuk memeriksa backend pencarian memori saat ini
|
||||
- jalankan `openclaw memory status --deep` untuk memeriksa backend penelusuran memori saat ini
|
||||
dan kesehatan indeks
|
||||
- periksa `agents.defaults.memorySearch.provider` dan auth/config terkait untuk memastikan
|
||||
- periksa `agents.defaults.memorySearch.provider` serta autentikasi/konfigurasi terkait untuk memastikan
|
||||
provider yang Anda harapkan benar-benar yang dapat diselesaikan saat runtime
|
||||
- jika Anda menggunakan `ollama`, verifikasi model embedding yang dikonfigurasi telah terinstal, misalnya `ollama list`
|
||||
- jika Anda menggunakan `ollama`, verifikasi bahwa model embedding yang dikonfigurasi telah terinstal, misalnya dengan
|
||||
`ollama list`
|
||||
|
||||
Contoh alur debugging:
|
||||
|
||||
```text
|
||||
1. Mulai Gateway dan pantau log-nya
|
||||
2. Di sesi obrolan, jalankan /trace on
|
||||
3. Kirim satu pesan yang seharusnya memicu Active Memory
|
||||
4. Bandingkan baris debug yang terlihat di obrolan dengan baris log Gateway
|
||||
5. Jika pilihan provider ambigu, pin `agents.defaults.memorySearch.provider` secara eksplisit
|
||||
1. Start the gateway and watch its logs
|
||||
2. In the chat session, run /trace on
|
||||
3. Send one message that should trigger Active Memory
|
||||
4. Compare the chat-visible debug line with the gateway log lines
|
||||
5. If provider choice is ambiguous, pin agents.defaults.memorySearch.provider explicitly
|
||||
```
|
||||
|
||||
Contoh:
|
||||
|
||||
@ -1,29 +1,29 @@
|
||||
---
|
||||
read_when:
|
||||
- Mengimplementasikan atau memperbarui klien WS gateway
|
||||
- Mengimplementasikan atau memperbarui klien WS Gateway
|
||||
- Men-debug ketidakcocokan protokol atau kegagalan koneksi
|
||||
- Membuat ulang skema/model protokol
|
||||
summary: 'Protokol WebSocket Gateway: handshake, frame, pembuatan versi'
|
||||
title: Protokol Gateway
|
||||
x-i18n:
|
||||
generated_at: "2026-04-10T09:13:11Z"
|
||||
generated_at: "2026-04-16T09:14:38Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 83c820c46d4803d571c770468fd6782619eaa1dca253e156e8087dec735c127f
|
||||
source_hash: 683e61ebe993a2d739bc34860060b0e3eda36b5c57267a2bcc03d177ec612fb3
|
||||
source_path: gateway/protocol.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Protokol Gateway (WebSocket)
|
||||
|
||||
Protokol WS Gateway adalah **bidang kendali tunggal + transport node** untuk
|
||||
OpenClaw. Semua klien (CLI, UI web, app macOS, node iOS/Android, node headless)
|
||||
terhubung melalui WebSocket dan mendeklarasikan **peran** + **cakupan** mereka
|
||||
saat waktu handshake.
|
||||
Protokol WS Gateway adalah **bidang kontrol tunggal + transport node** untuk
|
||||
OpenClaw. Semua klien (CLI, UI web, aplikasi macOS, node iOS/Android, node
|
||||
headless) terhubung melalui WebSocket dan mendeklarasikan **peran** + **cakupan**
|
||||
mereka saat handshake.
|
||||
|
||||
## Transport
|
||||
|
||||
- WebSocket, frame teks dengan muatan JSON.
|
||||
- WebSocket, frame teks dengan payload JSON.
|
||||
- Frame pertama **harus** berupa permintaan `connect`.
|
||||
|
||||
## Handshake (connect)
|
||||
@ -80,11 +80,25 @@ Gateway → Klien:
|
||||
"type": "res",
|
||||
"id": "…",
|
||||
"ok": true,
|
||||
"payload": { "type": "hello-ok", "protocol": 3, "policy": { "tickIntervalMs": 15000 } }
|
||||
"payload": {
|
||||
"type": "hello-ok",
|
||||
"protocol": 3,
|
||||
"server": { "version": "…", "connId": "…" },
|
||||
"features": { "methods": ["…"], "events": ["…"] },
|
||||
"snapshot": { "…": "…" },
|
||||
"policy": {
|
||||
"maxPayload": 26214400,
|
||||
"maxBufferedBytes": 52428800,
|
||||
"tickIntervalMs": 15000
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Saat token perangkat diterbitkan, `hello-ok` juga mencakup:
|
||||
`server`, `features`, `snapshot`, dan `policy` semuanya wajib menurut skema
|
||||
(`src/gateway/protocol/schema/frames.ts`). `auth` dan `canvasHostUrl` bersifat opsional.
|
||||
|
||||
Saat token perangkat diterbitkan, `hello-ok` juga menyertakan:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -97,7 +111,7 @@ Saat token perangkat diterbitkan, `hello-ok` juga mencakup:
|
||||
```
|
||||
|
||||
Selama handoff bootstrap tepercaya, `hello-ok.auth` juga dapat menyertakan entri
|
||||
peran terbatas tambahan dalam `deviceTokens`:
|
||||
peran tambahan yang dibatasi dalam `deviceTokens`:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -121,7 +135,7 @@ Untuk alur bootstrap node/operator bawaan, token node utama tetap
|
||||
operator bootstrap (`operator.approvals`, `operator.read`,
|
||||
`operator.talk.secrets`, `operator.write`). Pemeriksaan cakupan bootstrap tetap
|
||||
berawalan peran: entri operator hanya memenuhi permintaan operator, dan peran
|
||||
non-operator tetap memerlukan cakupan di bawah awalan peran mereka sendiri.
|
||||
non-operator tetap memerlukan cakupan di bawah awalan perannya sendiri.
|
||||
|
||||
### Contoh node
|
||||
|
||||
@ -160,17 +174,17 @@ non-operator tetap memerlukan cakupan di bawah awalan peran mereka sendiri.
|
||||
|
||||
## Framing
|
||||
|
||||
- **Permintaan**: `{type:"req", id, method, params}`
|
||||
- **Respons**: `{type:"res", id, ok, payload|error}`
|
||||
- **Peristiwa**: `{type:"event", event, payload, seq?, stateVersion?}`
|
||||
- **Request**: `{type:"req", id, method, params}`
|
||||
- **Response**: `{type:"res", id, ok, payload|error}`
|
||||
- **Event**: `{type:"event", event, payload, seq?, stateVersion?}`
|
||||
|
||||
Metode yang memiliki efek samping memerlukan **kunci idempotensi** (lihat skema).
|
||||
Method yang memiliki efek samping memerlukan **idempotency keys** (lihat skema).
|
||||
|
||||
## Peran + cakupan
|
||||
|
||||
### Peran
|
||||
|
||||
- `operator` = klien bidang kendali (CLI/UI/otomasi).
|
||||
- `operator` = klien bidang kontrol (CLI/UI/otomasi).
|
||||
- `node` = host kapabilitas (camera/screen/canvas/system.run).
|
||||
|
||||
### Cakupan (operator)
|
||||
@ -187,18 +201,17 @@ Cakupan umum:
|
||||
`talk.config` dengan `includeSecrets: true` memerlukan `operator.talk.secrets`
|
||||
(atau `operator.admin`).
|
||||
|
||||
Metode RPC gateway yang didaftarkan plugin dapat meminta cakupan operatornya
|
||||
sendiri, tetapi awalan admin inti yang dicadangkan (`config.*`,
|
||||
`exec.approvals.*`, `wizard.*`, `update.*`) selalu diselesaikan ke
|
||||
`operator.admin`.
|
||||
Method RPC Gateway yang didaftarkan Plugin dapat meminta cakupan operatornya
|
||||
sendiri, tetapi awalan admin inti yang dicadangkan (`config.*`, `exec.approvals.*`, `wizard.*`,
|
||||
`update.*`) selalu di-resolve menjadi `operator.admin`.
|
||||
|
||||
Cakupan metode hanyalah gerbang pertama. Beberapa slash command yang dicapai
|
||||
Cakupan method hanyalah gerbang pertama. Beberapa slash command yang dicapai
|
||||
melalui `chat.send` menerapkan pemeriksaan tingkat perintah yang lebih ketat di
|
||||
atasnya. Misalnya, penulisan persisten `/config set` dan `/config unset`
|
||||
memerlukan `operator.admin`.
|
||||
|
||||
`node.pair.approve` juga memiliki pemeriksaan cakupan saat persetujuan tambahan
|
||||
di atas cakupan metode dasar:
|
||||
di atas cakupan method dasar:
|
||||
|
||||
- permintaan tanpa perintah: `operator.pairing`
|
||||
- permintaan dengan perintah node non-exec: `operator.pairing` + `operator.write`
|
||||
@ -211,111 +224,113 @@ Node mendeklarasikan klaim kapabilitas saat waktu connect:
|
||||
|
||||
- `caps`: kategori kapabilitas tingkat tinggi.
|
||||
- `commands`: allowlist perintah untuk invoke.
|
||||
- `permissions`: toggle terperinci (misalnya `screen.record`, `camera.capture`).
|
||||
- `permissions`: toggle granular (misalnya `screen.record`, `camera.capture`).
|
||||
|
||||
Gateway memperlakukan ini sebagai **klaim** dan menegakkan allowlist sisi server.
|
||||
Gateway memperlakukan ini sebagai **klaim** dan menegakkan allowlist di sisi server.
|
||||
|
||||
## Kehadiran
|
||||
|
||||
- `system-presence` mengembalikan entri yang dikunci oleh identitas perangkat.
|
||||
- `system-presence` mengembalikan entri yang dikunci berdasarkan identitas perangkat.
|
||||
- Entri kehadiran mencakup `deviceId`, `roles`, dan `scopes` sehingga UI dapat menampilkan satu baris per perangkat
|
||||
bahkan saat perangkat terhubung sebagai **operator** dan **node**.
|
||||
bahkan ketika perangkat terhubung sebagai **operator** dan **node** sekaligus.
|
||||
|
||||
## Keluarga metode RPC umum
|
||||
## Keluarga method RPC umum
|
||||
|
||||
Halaman ini bukan dump penuh yang dihasilkan, tetapi permukaan WS publik lebih
|
||||
luas daripada contoh handshake/auth di atas. Ini adalah keluarga metode utama
|
||||
yang saat ini diekspos Gateway.
|
||||
luas daripada contoh handshake/auth di atas. Ini adalah keluarga method utama
|
||||
yang diekspos Gateway saat ini.
|
||||
|
||||
`hello-ok.features.methods` adalah daftar penemuan konservatif yang dibangun dari
|
||||
`src/gateway/server-methods-list.ts` ditambah ekspor metode plugin/channel yang dimuat.
|
||||
Perlakukan ini sebagai penemuan fitur, bukan sebagai dump yang dihasilkan dari setiap helper
|
||||
yang dapat dipanggil yang diimplementasikan dalam `src/gateway/server-methods/*.ts`.
|
||||
`src/gateway/server-methods-list.ts` ditambah ekspor method plugin/channel yang dimuat.
|
||||
Perlakukan ini sebagai penemuan fitur, bukan sebagai dump yang dihasilkan dari
|
||||
setiap helper yang dapat dipanggil yang diimplementasikan dalam `src/gateway/server-methods/*.ts`.
|
||||
|
||||
### Sistem dan identitas
|
||||
|
||||
- `health` mengembalikan snapshot kesehatan gateway yang di-cache atau baru diprobe.
|
||||
- `status` mengembalikan ringkasan gateway gaya `/status`; field sensitif hanya
|
||||
disertakan untuk klien operator bercakupan admin.
|
||||
disertakan untuk klien operator dengan cakupan admin.
|
||||
- `gateway.identity.get` mengembalikan identitas perangkat gateway yang digunakan oleh alur relay dan
|
||||
pairing.
|
||||
- `system-presence` mengembalikan snapshot kehadiran saat ini untuk perangkat
|
||||
operator/node yang terhubung.
|
||||
- `system-event` menambahkan peristiwa sistem dan dapat memperbarui/menyiarkan konteks
|
||||
- `system-event` menambahkan event sistem dan dapat memperbarui/menyiarkan konteks
|
||||
kehadiran.
|
||||
- `last-heartbeat` mengembalikan peristiwa heartbeat persisten terbaru.
|
||||
- `set-heartbeats` mengaktifkan atau menonaktifkan pemrosesan heartbeat pada gateway.
|
||||
- `last-heartbeat` mengembalikan event Heartbeat persisten terbaru.
|
||||
- `set-heartbeats` mengaktifkan atau menonaktifkan pemrosesan Heartbeat di gateway.
|
||||
|
||||
### Model dan penggunaan
|
||||
|
||||
- `models.list` mengembalikan katalog model yang diizinkan runtime.
|
||||
- `usage.status` mengembalikan ringkasan jendela penggunaan/kuota tersisa provider.
|
||||
- `usage.cost` mengembalikan ringkasan penggunaan biaya agregat untuk suatu rentang tanggal.
|
||||
- `models.list` mengembalikan katalog model yang diizinkan saat runtime.
|
||||
- `usage.status` mengembalikan ringkasan jendela penggunaan provider/kuota tersisa.
|
||||
- `usage.cost` mengembalikan ringkasan penggunaan biaya agregat untuk rentang tanggal.
|
||||
- `doctor.memory.status` mengembalikan kesiapan vector-memory / embedding untuk
|
||||
workspace agen default aktif.
|
||||
- `sessions.usage` mengembalikan ringkasan penggunaan per sesi.
|
||||
- `sessions.usage.timeseries` mengembalikan timeseries penggunaan untuk satu sesi.
|
||||
- `sessions.usage.timeseries` mengembalikan penggunaan deret waktu untuk satu sesi.
|
||||
- `sessions.usage.logs` mengembalikan entri log penggunaan untuk satu sesi.
|
||||
|
||||
### Channel dan helper login
|
||||
|
||||
- `channels.status` mengembalikan ringkasan status channel/plugin bawaan + bundel.
|
||||
- `channels.logout` melakukan logout pada channel/akun tertentu jika channel
|
||||
- `channels.status` mengembalikan ringkasan status channel/plugin bawaan + bundled.
|
||||
- `channels.logout` melakukan logout untuk channel/akun tertentu ketika channel
|
||||
mendukung logout.
|
||||
- `web.login.start` memulai alur login QR/web untuk provider channel web
|
||||
saat ini yang mendukung QR.
|
||||
berkemampuan QR saat ini.
|
||||
- `web.login.wait` menunggu hingga alur login QR/web tersebut selesai dan memulai
|
||||
channel jika berhasil.
|
||||
- `push.test` mengirim push APNs uji ke node iOS yang terdaftar.
|
||||
- `voicewake.get` mengembalikan pemicu wake-word yang tersimpan.
|
||||
- `voicewake.set` memperbarui pemicu wake-word dan menyiarkan perubahannya.
|
||||
- `voicewake.get` mengembalikan trigger wake-word yang tersimpan.
|
||||
- `voicewake.set` memperbarui trigger wake-word dan menyiarkan perubahannya.
|
||||
|
||||
### Perpesanan dan log
|
||||
### Pesan dan log
|
||||
|
||||
- `send` adalah RPC pengiriman keluar langsung untuk pengiriman yang ditargetkan ke
|
||||
channel/akun/thread di luar chat runner.
|
||||
- `logs.tail` mengembalikan tail log file gateway yang dikonfigurasi dengan cursor/limit dan
|
||||
kontrol byte maksimum.
|
||||
- `logs.tail` mengembalikan tail file log gateway yang dikonfigurasi dengan kontrol cursor/limit dan
|
||||
max-byte.
|
||||
|
||||
### Talk dan TTS
|
||||
|
||||
- `talk.config` mengembalikan muatan konfigurasi Talk yang efektif; `includeSecrets`
|
||||
- `talk.config` mengembalikan payload konfigurasi Talk yang efektif; `includeSecrets`
|
||||
memerlukan `operator.talk.secrets` (atau `operator.admin`).
|
||||
- `talk.mode` menetapkan/menyiarkan status mode Talk saat ini untuk klien
|
||||
WebChat/Control UI.
|
||||
- `talk.speak` mensintesis ucapan melalui provider ucapan Talk yang aktif.
|
||||
- `tts.status` mengembalikan status TTS aktif, provider aktif, provider fallback,
|
||||
- `talk.speak` mensintesis ucapan melalui provider speech Talk yang aktif.
|
||||
- `tts.status` mengembalikan status TTS aktif/nonaktif, provider aktif, provider fallback,
|
||||
dan status konfigurasi provider.
|
||||
- `tts.providers` mengembalikan inventaris provider TTS yang terlihat.
|
||||
- `tts.enable` dan `tts.disable` mengaktifkan atau menonaktifkan status preferensi TTS.
|
||||
- `tts.setProvider` memperbarui provider TTS pilihan.
|
||||
- `tts.convert` menjalankan konversi teks-ke-ucapan sekali jalan.
|
||||
- `tts.convert` menjalankan konversi text-to-speech sekali jalan.
|
||||
|
||||
### Secrets, config, update, dan wizard
|
||||
### Secret, config, update, dan wizard
|
||||
|
||||
- `secrets.reload` me-resolve ulang SecretRef aktif dan menukar status secret runtime
|
||||
hanya jika sepenuhnya berhasil.
|
||||
- `secrets.resolve` me-resolve penetapan secret target-perintah untuk set perintah/target tertentu.
|
||||
hanya jika seluruh proses berhasil.
|
||||
- `secrets.resolve` me-resolve penetapan secret yang ditargetkan perintah untuk
|
||||
set perintah/target tertentu.
|
||||
- `config.get` mengembalikan snapshot config dan hash saat ini.
|
||||
- `config.set` menulis muatan config yang tervalidasi.
|
||||
- `config.set` menulis payload config yang tervalidasi.
|
||||
- `config.patch` menggabungkan pembaruan config parsial.
|
||||
- `config.apply` memvalidasi + mengganti seluruh muatan config.
|
||||
- `config.schema` mengembalikan muatan skema config live yang digunakan oleh Control UI dan
|
||||
- `config.apply` memvalidasi + mengganti seluruh payload config.
|
||||
- `config.schema` mengembalikan payload skema config live yang digunakan oleh Control UI dan
|
||||
tooling CLI: skema, `uiHints`, versi, dan metadata generasi, termasuk
|
||||
metadata skema plugin + channel saat runtime dapat memuatnya. Skema
|
||||
metadata skema plugin + channel ketika runtime dapat memuatnya. Skema ini
|
||||
mencakup metadata field `title` / `description` yang diturunkan dari label yang sama
|
||||
dan teks bantuan yang digunakan oleh UI, termasuk object bertingkat, wildcard,
|
||||
item array, dan cabang komposisi `anyOf` / `oneOf` / `allOf` saat dokumentasi field yang cocok tersedia.
|
||||
- `config.schema.lookup` mengembalikan muatan lookup berbatas jalur untuk satu config
|
||||
path: jalur ternormalisasi, node skema dangkal, hint + `hintPath` yang cocok, dan
|
||||
dan teks bantuan yang digunakan oleh UI, termasuk object bertingkat, wildcard, array-item,
|
||||
dan cabang komposisi `anyOf` / `oneOf` / `allOf` ketika dokumentasi field
|
||||
yang cocok tersedia.
|
||||
- `config.schema.lookup` mengembalikan payload lookup berbatas path untuk satu
|
||||
path config: path yang dinormalisasi, node skema dangkal, hint yang cocok + `hintPath`, dan
|
||||
ringkasan child langsung untuk drill-down UI/CLI.
|
||||
- Node skema lookup mempertahankan dokumentasi yang menghadap pengguna dan field validasi umum:
|
||||
- Node skema lookup mempertahankan dokumentasi yang berhadapan dengan pengguna dan field validasi umum:
|
||||
`title`, `description`, `type`, `enum`, `const`, `format`, `pattern`,
|
||||
batas numerik/string/array/object, dan flag boolean seperti
|
||||
`additionalProperties`, `deprecated`, `readOnly`, `writeOnly`.
|
||||
- Ringkasan child mengekspos `key`, `path` ternormalisasi, `type`, `required`,
|
||||
`hasChildren`, ditambah `hint` / `hintPath` yang cocok.
|
||||
- `update.run` menjalankan alur pembaruan gateway dan menjadwalkan restart hanya saat
|
||||
- Ringkasan child mengekspos `key`, `path` yang dinormalisasi, `type`, `required`,
|
||||
`hasChildren`, serta `hint` / `hintPath` yang cocok.
|
||||
- `update.run` menjalankan alur pembaruan gateway dan menjadwalkan restart hanya ketika
|
||||
pembaruan itu sendiri berhasil.
|
||||
- `wizard.start`, `wizard.next`, `wizard.status`, dan `wizard.cancel` mengekspos
|
||||
wizard onboarding melalui WS RPC.
|
||||
@ -325,29 +340,29 @@ yang dapat dipanggil yang diimplementasikan dalam `src/gateway/server-methods/*.
|
||||
#### Helper agen dan workspace
|
||||
|
||||
- `agents.list` mengembalikan entri agen yang dikonfigurasi.
|
||||
- `agents.create`, `agents.update`, dan `agents.delete` mengelola catatan agen dan
|
||||
- `agents.create`, `agents.update`, dan `agents.delete` mengelola record agen dan
|
||||
wiring workspace.
|
||||
- `agents.files.list`, `agents.files.get`, dan `agents.files.set` mengelola
|
||||
file workspace bootstrap yang diekspos untuk sebuah agen.
|
||||
- `agent.identity.get` mengembalikan identitas asisten yang efektif untuk agen atau
|
||||
- `agents.files.list`, `agents.files.get`, dan `agents.files.set` mengelola file
|
||||
workspace bootstrap yang diekspos untuk sebuah agen.
|
||||
- `agent.identity.get` mengembalikan identitas asisten efektif untuk sebuah agen atau
|
||||
sesi.
|
||||
- `agent.wait` menunggu hingga suatu run selesai dan mengembalikan snapshot terminal saat
|
||||
- `agent.wait` menunggu hingga sebuah run selesai dan mengembalikan snapshot terminal ketika
|
||||
tersedia.
|
||||
|
||||
#### Kontrol sesi
|
||||
|
||||
- `sessions.list` mengembalikan indeks sesi saat ini.
|
||||
- `sessions.subscribe` dan `sessions.unsubscribe` mengaktifkan atau menonaktifkan langganan peristiwa perubahan sesi
|
||||
- `sessions.subscribe` dan `sessions.unsubscribe` mengaktifkan atau menonaktifkan langganan event perubahan sesi
|
||||
untuk klien WS saat ini.
|
||||
- `sessions.messages.subscribe` dan `sessions.messages.unsubscribe` mengaktifkan atau menonaktifkan
|
||||
langganan peristiwa transkrip/pesan untuk satu sesi.
|
||||
- `sessions.preview` mengembalikan pratinjau transkrip terbatas untuk kunci
|
||||
langganan event transkrip/pesan untuk satu sesi.
|
||||
- `sessions.preview` mengembalikan pratinjau transkrip yang dibatasi untuk kunci
|
||||
sesi tertentu.
|
||||
- `sessions.resolve` me-resolve atau mengkanonisasi target sesi.
|
||||
- `sessions.create` membuat entri sesi baru.
|
||||
- `sessions.send` mengirim pesan ke sesi yang sudah ada.
|
||||
- `sessions.steer` adalah varian interupsi-dan-arahkan untuk sesi aktif.
|
||||
- `sessions.abort` membatalkan pekerjaan aktif untuk sebuah sesi.
|
||||
- `sessions.send` mengirim pesan ke dalam sesi yang sudah ada.
|
||||
- `sessions.steer` adalah varian interrupt-and-steer untuk sesi yang aktif.
|
||||
- `sessions.abort` membatalkan pekerjaan aktif untuk suatu sesi.
|
||||
- `sessions.patch` memperbarui metadata/override sesi.
|
||||
- `sessions.reset`, `sessions.delete`, dan `sessions.compact` melakukan
|
||||
pemeliharaan sesi.
|
||||
@ -355,122 +370,123 @@ yang dapat dipanggil yang diimplementasikan dalam `src/gateway/server-methods/*.
|
||||
- eksekusi chat tetap menggunakan `chat.history`, `chat.send`, `chat.abort`, dan
|
||||
`chat.inject`.
|
||||
- `chat.history` dinormalisasi untuk tampilan bagi klien UI: tag direktif inline
|
||||
dihapus dari teks yang terlihat, muatan XML tool-call teks biasa (termasuk
|
||||
dihapus dari teks yang terlihat, payload XML panggilan tool teks biasa (termasuk
|
||||
`<tool_call>...</tool_call>`, `<function_call>...</function_call>`,
|
||||
`<tool_calls>...</tool_calls>`, `<function_calls>...</function_calls>`, dan
|
||||
blok tool-call yang terpotong) serta token kontrol model ASCII/full-width yang
|
||||
bocor dihapus, baris asisten token-senyap murni seperti `NO_REPLY` /
|
||||
`no_reply` yang persis sama dihilangkan, dan baris yang terlalu besar dapat
|
||||
diganti dengan placeholder.
|
||||
blok panggilan tool yang dipotong) serta token kontrol model ASCII/full-width yang bocor
|
||||
dihapus, baris asisten token senyap murni seperti `NO_REPLY` / `no_reply`
|
||||
yang persis sama dihilangkan, dan baris yang terlalu besar dapat diganti dengan placeholder.
|
||||
|
||||
#### Pairing perangkat dan token perangkat
|
||||
|
||||
- `device.pair.list` mengembalikan perangkat yang di-pairing yang tertunda dan disetujui.
|
||||
- `device.pair.list` mengembalikan perangkat berpasangan yang tertunda dan yang disetujui.
|
||||
- `device.pair.approve`, `device.pair.reject`, dan `device.pair.remove` mengelola
|
||||
catatan pairing perangkat.
|
||||
- `device.token.rotate` merotasi token perangkat yang di-pairing dalam batas peran
|
||||
record pairing perangkat.
|
||||
- `device.token.rotate` memutar token perangkat yang telah dipasangkan dalam batas peran
|
||||
dan cakupan yang disetujui.
|
||||
- `device.token.revoke` mencabut token perangkat yang di-pairing.
|
||||
- `device.token.revoke` mencabut token perangkat yang telah dipasangkan.
|
||||
|
||||
#### Pairing node, invoke, dan pekerjaan tertunda
|
||||
|
||||
- `node.pair.request`, `node.pair.list`, `node.pair.approve`,
|
||||
`node.pair.reject`, dan `node.pair.verify` mencakup pairing node dan verifikasi
|
||||
bootstrap.
|
||||
- `node.list` dan `node.describe` mengembalikan status node yang dikenal/terhubung.
|
||||
- `node.rename` memperbarui label node yang di-pairing.
|
||||
- `node.list` dan `node.describe` mengembalikan status node yang diketahui/terhubung.
|
||||
- `node.rename` memperbarui label node yang telah dipasangkan.
|
||||
- `node.invoke` meneruskan perintah ke node yang terhubung.
|
||||
- `node.invoke.result` mengembalikan hasil untuk permintaan invoke.
|
||||
- `node.event` membawa peristiwa yang berasal dari node kembali ke gateway.
|
||||
- `node.canvas.capability.refresh` me-refresh token kapabilitas canvas yang dibatasi cakupan.
|
||||
- `node.pending.pull` dan `node.pending.ack` adalah API antrean node-terhubung.
|
||||
- `node.event` membawa event yang berasal dari node kembali ke gateway.
|
||||
- `node.canvas.capability.refresh` menyegarkan token kapabilitas canvas yang dibatasi cakupan.
|
||||
- `node.pending.pull` dan `node.pending.ack` adalah API antrean node yang terhubung.
|
||||
- `node.pending.enqueue` dan `node.pending.drain` mengelola pekerjaan tertunda yang tahan lama
|
||||
untuk node offline/tidak terhubung.
|
||||
untuk node yang offline/terputus.
|
||||
|
||||
#### Keluarga persetujuan
|
||||
#### Keluarga approval
|
||||
|
||||
- `exec.approval.request`, `exec.approval.get`, `exec.approval.list`, dan
|
||||
`exec.approval.resolve` mencakup permintaan persetujuan exec sekali pakai plus
|
||||
lookup/replay persetujuan tertunda.
|
||||
- `exec.approval.waitDecision` menunggu satu persetujuan exec tertunda dan mengembalikan
|
||||
keputusan final (atau `null` saat timeout).
|
||||
- `exec.approvals.get` dan `exec.approvals.set` mengelola snapshot kebijakan
|
||||
persetujuan exec gateway.
|
||||
- `exec.approvals.node.get` dan `exec.approvals.node.set` mengelola kebijakan exec lokal-node
|
||||
melalui perintah relay node.
|
||||
`exec.approval.resolve` mencakup permintaan approval exec sekali jalan plus
|
||||
lookup/replay approval yang tertunda.
|
||||
- `exec.approval.waitDecision` menunggu satu approval exec yang tertunda dan mengembalikan
|
||||
keputusan akhir (atau `null` saat timeout).
|
||||
- `exec.approvals.get` dan `exec.approvals.set` mengelola snapshot kebijakan approval exec
|
||||
gateway.
|
||||
- `exec.approvals.node.get` dan `exec.approvals.node.set` mengelola kebijakan approval exec
|
||||
lokal node melalui perintah relay node.
|
||||
- `plugin.approval.request`, `plugin.approval.list`,
|
||||
`plugin.approval.waitDecision`, dan `plugin.approval.resolve` mencakup
|
||||
alur persetujuan yang didefinisikan plugin.
|
||||
alur approval yang didefinisikan Plugin.
|
||||
|
||||
#### Keluarga utama lainnya
|
||||
|
||||
- otomasi:
|
||||
- `wake` menjadwalkan injeksi teks bangun segera atau pada heartbeat berikutnya
|
||||
- `wake` menjadwalkan injeksi teks bangun segera atau pada Heartbeat berikutnya
|
||||
- `cron.list`, `cron.status`, `cron.add`, `cron.update`, `cron.remove`,
|
||||
`cron.run`, `cron.runs`
|
||||
- skills/tools: `commands.list`, `skills.*`, `tools.catalog`, `tools.effective`
|
||||
|
||||
### Keluarga peristiwa umum
|
||||
### Keluarga event umum
|
||||
|
||||
- `chat`: pembaruan chat UI seperti `chat.inject` dan peristiwa chat khusus transkrip
|
||||
- `chat`: pembaruan chat UI seperti `chat.inject` dan event chat khusus transkrip
|
||||
lainnya.
|
||||
- `session.message` dan `session.tool`: pembaruan transkrip/aliran-peristiwa untuk sesi
|
||||
- `session.message` dan `session.tool`: pembaruan transkrip/aliran event untuk sesi
|
||||
yang dilanggani.
|
||||
- `sessions.changed`: indeks sesi atau metadata berubah.
|
||||
- `presence`: pembaruan snapshot kehadiran sistem.
|
||||
- `tick`: peristiwa keepalive / liveness berkala.
|
||||
- `tick`: event keepalive / liveness periodik.
|
||||
- `health`: pembaruan snapshot kesehatan gateway.
|
||||
- `heartbeat`: pembaruan aliran peristiwa heartbeat.
|
||||
- `cron`: peristiwa perubahan run/pekerjaan cron.
|
||||
- `heartbeat`: pembaruan aliran event Heartbeat.
|
||||
- `cron`: event perubahan job/run cron.
|
||||
- `shutdown`: notifikasi shutdown gateway.
|
||||
- `node.pair.requested` / `node.pair.resolved`: siklus hidup pairing node.
|
||||
- `node.invoke.request`: siaran permintaan invoke node.
|
||||
- `device.pair.requested` / `device.pair.resolved`: siklus hidup perangkat yang di-pairing.
|
||||
- `voicewake.changed`: konfigurasi pemicu wake-word berubah.
|
||||
- `device.pair.requested` / `device.pair.resolved`: siklus hidup perangkat yang dipasangkan.
|
||||
- `voicewake.changed`: config trigger wake-word berubah.
|
||||
- `exec.approval.requested` / `exec.approval.resolved`: siklus hidup
|
||||
persetujuan exec.
|
||||
- `plugin.approval.requested` / `plugin.approval.resolved`: siklus hidup persetujuan plugin.
|
||||
approval exec.
|
||||
- `plugin.approval.requested` / `plugin.approval.resolved`: siklus hidup
|
||||
approval plugin.
|
||||
|
||||
### Metode helper node
|
||||
### Method helper node
|
||||
|
||||
- Node dapat memanggil `skills.bins` untuk mengambil daftar executable skill saat ini
|
||||
untuk pemeriksaan auto-allow.
|
||||
|
||||
### Metode helper operator
|
||||
### Method helper operator
|
||||
|
||||
- Operator dapat memanggil `commands.list` (`operator.read`) untuk mengambil inventaris perintah runtime bagi sebuah agen.
|
||||
- Operator dapat memanggil `commands.list` (`operator.read`) untuk mengambil inventaris perintah runtime bagi sebuah
|
||||
agen.
|
||||
- `agentId` bersifat opsional; hilangkan untuk membaca workspace agen default.
|
||||
- `scope` mengontrol permukaan mana yang dituju oleh `name` utama:
|
||||
- `scope` mengontrol permukaan yang dituju `name` utama:
|
||||
- `text` mengembalikan token perintah teks utama tanpa awalan `/`
|
||||
- `native` dan jalur default `both` mengembalikan nama native yang sadar-provider
|
||||
jika tersedia
|
||||
- `textAliases` membawa alias slash persis seperti `/model` dan `/m`.
|
||||
- `nativeName` membawa nama perintah native yang sadar-provider jika ada.
|
||||
- `provider` bersifat opsional dan hanya memengaruhi penamaan native plus
|
||||
ketersediaan perintah plugin native.
|
||||
- `includeArgs=false` menghilangkan metadata argumen yang diserialisasi dari respons.
|
||||
- Operator dapat memanggil `tools.catalog` (`operator.read`) untuk mengambil katalog tool runtime bagi sebuah
|
||||
agen. Respons mencakup tool yang dikelompokkan dan metadata provenance:
|
||||
- `provider` bersifat opsional dan hanya memengaruhi penamaan native plus ketersediaan perintah
|
||||
Plugin native.
|
||||
- `includeArgs=false` menghilangkan metadata argumen terserialisasi dari respons.
|
||||
- Operator dapat memanggil `tools.catalog` (`operator.read`) untuk mengambil katalog tool runtime untuk sebuah
|
||||
agen. Responsnya mencakup tool yang dikelompokkan dan metadata asal:
|
||||
- `source`: `core` atau `plugin`
|
||||
- `pluginId`: pemilik plugin saat `source="plugin"`
|
||||
- `pluginId`: pemilik plugin ketika `source="plugin"`
|
||||
- `optional`: apakah tool plugin bersifat opsional
|
||||
- Operator dapat memanggil `tools.effective` (`operator.read`) untuk mengambil inventaris tool efektif-runtime
|
||||
bagi sebuah sesi.
|
||||
- `sessionKey` wajib diisi.
|
||||
untuk suatu sesi.
|
||||
- `sessionKey` wajib.
|
||||
- Gateway menurunkan konteks runtime tepercaya dari sesi di sisi server alih-alih menerima
|
||||
auth atau konteks pengiriman yang disediakan pemanggil.
|
||||
- Respons dibatasi pada sesi dan mencerminkan apa yang dapat digunakan percakapan aktif saat ini,
|
||||
termasuk tool core, plugin, dan channel.
|
||||
auth atau konteks pengiriman yang disuplai pemanggil.
|
||||
- Responsnya dibatasi per sesi dan mencerminkan apa yang dapat digunakan percakapan aktif saat ini,
|
||||
termasuk core, plugin, dan tool channel.
|
||||
- Operator dapat memanggil `skills.status` (`operator.read`) untuk mengambil inventaris
|
||||
skill yang terlihat bagi sebuah agen.
|
||||
Skills yang terlihat untuk sebuah agen.
|
||||
- `agentId` bersifat opsional; hilangkan untuk membaca workspace agen default.
|
||||
- Respons mencakup kelayakan, persyaratan yang hilang, pemeriksaan config, dan
|
||||
opsi instalasi yang telah disanitasi tanpa mengekspos nilai secret mentah.
|
||||
- Operator dapat memanggil `skills.search` dan `skills.detail` (`operator.read`) untuk
|
||||
metadata penemuan ClawHub.
|
||||
- Responsnya mencakup kelayakan, persyaratan yang hilang, pemeriksaan config, dan
|
||||
opsi instalasi yang disanitasi tanpa mengekspos nilai secret mentah.
|
||||
- Operator dapat memanggil `skills.search` dan `skills.detail` (`operator.read`) untuk metadata penemuan
|
||||
ClawHub.
|
||||
- Operator dapat memanggil `skills.install` (`operator.admin`) dalam dua mode:
|
||||
- Mode ClawHub: `{ source: "clawhub", slug, version?, force? }` menginstal
|
||||
folder skill ke direktori `skills/` workspace agen default.
|
||||
- Mode ClawHub: `{ source: "clawhub", slug, version?, force? }` memasang folder
|
||||
skill ke direktori `skills/` workspace agen default.
|
||||
- Mode installer gateway: `{ name, installId, dangerouslyForceUnsafeInstall?, timeoutMs? }`
|
||||
menjalankan aksi `metadata.openclaw.install` yang dideklarasikan pada host gateway.
|
||||
- Operator dapat memanggil `skills.update` (`operator.admin`) dalam dua mode:
|
||||
@ -479,95 +495,128 @@ yang dapat dipanggil yang diimplementasikan dalam `src/gateway/server-methods/*.
|
||||
- Mode config mem-patch nilai `skills.entries.<skillKey>` seperti `enabled`,
|
||||
`apiKey`, dan `env`.
|
||||
|
||||
## Persetujuan exec
|
||||
## Approval exec
|
||||
|
||||
- Saat permintaan exec memerlukan persetujuan, gateway menyiarkan `exec.approval.requested`.
|
||||
- Saat permintaan exec memerlukan approval, gateway menyiarkan `exec.approval.requested`.
|
||||
- Klien operator menyelesaikannya dengan memanggil `exec.approval.resolve` (memerlukan cakupan `operator.approvals`).
|
||||
- Untuk `host=node`, `exec.approval.request` harus menyertakan `systemRunPlan` (metadata `argv`/`cwd`/`rawCommand`/sesi kanonis). Permintaan yang tidak memiliki `systemRunPlan` akan ditolak.
|
||||
- Setelah disetujui, panggilan `node.invoke system.run` yang diteruskan menggunakan kembali
|
||||
- Untuk `host=node`, `exec.approval.request` harus menyertakan `systemRunPlan` (`argv`/`cwd`/`rawCommand`/metadata sesi kanonis). Permintaan yang tidak memiliki `systemRunPlan` akan ditolak.
|
||||
- Setelah approval, panggilan `node.invoke system.run` yang diteruskan menggunakan kembali
|
||||
`systemRunPlan` kanonis tersebut sebagai konteks perintah/cwd/sesi yang otoritatif.
|
||||
- Jika pemanggil mengubah `command`, `rawCommand`, `cwd`, `agentId`, atau
|
||||
`sessionKey` antara prepare dan penerusan `system.run` final yang telah disetujui,
|
||||
gateway menolak run tersebut alih-alih memercayai muatan yang telah diubah.
|
||||
- Jika pemanggil memodifikasi `command`, `rawCommand`, `cwd`, `agentId`, atau
|
||||
`sessionKey` antara prepare dan penerusan `system.run` final yang disetujui, maka
|
||||
gateway menolak eksekusi tersebut alih-alih mempercayai payload yang telah dimodifikasi.
|
||||
|
||||
## Fallback pengiriman agen
|
||||
|
||||
- Permintaan `agent` dapat menyertakan `deliver=true` untuk meminta pengiriman keluar.
|
||||
- `bestEffortDeliver=false` mempertahankan perilaku ketat: target pengiriman yang tidak ter-resolve atau hanya-internal mengembalikan `INVALID_REQUEST`.
|
||||
- `bestEffortDeliver=true` memungkinkan fallback ke eksekusi khusus-sesi saat tidak ada rute pengiriman eksternal yang dapat di-resolve (misalnya sesi internal/webchat atau config multi-channel yang ambigu).
|
||||
- `bestEffortDeliver=false` mempertahankan perilaku ketat: target pengiriman yang tidak terselesaikan atau hanya-internal mengembalikan `INVALID_REQUEST`.
|
||||
- `bestEffortDeliver=true` memungkinkan fallback ke eksekusi khusus sesi ketika tidak ada rute pengiriman eksternal yang dapat diselesaikan (misalnya sesi internal/webchat atau config multi-channel yang ambigu).
|
||||
|
||||
## Pembuatan versi
|
||||
|
||||
- `PROTOCOL_VERSION` berada di `src/gateway/protocol/schema.ts`.
|
||||
- `PROTOCOL_VERSION` berada di `src/gateway/protocol/schema/protocol-schemas.ts`.
|
||||
- Klien mengirim `minProtocol` + `maxProtocol`; server menolak ketidakcocokan.
|
||||
- Skema + model dihasilkan dari definisi TypeBox:
|
||||
- `pnpm protocol:gen`
|
||||
- `pnpm protocol:gen:swift`
|
||||
- `pnpm protocol:check`
|
||||
|
||||
### Konstanta klien
|
||||
|
||||
Klien referensi di `src/gateway/client.ts` menggunakan default berikut. Nilai-nilai ini
|
||||
stabil di seluruh protokol v3 dan merupakan baseline yang diharapkan untuk klien pihak ketiga.
|
||||
|
||||
| Constant | Default | Source |
|
||||
| ----------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------- |
|
||||
| `PROTOCOL_VERSION` | `3` | `src/gateway/protocol/schema/protocol-schemas.ts` |
|
||||
| Timeout permintaan (per RPC) | `30_000` ms | `src/gateway/client.ts` (`requestTimeoutMs`) |
|
||||
| Timeout preauth / connect-challenge | `10_000` ms | `src/gateway/handshake-timeouts.ts` (clamp `250`–`10_000`) |
|
||||
| Backoff reconnect awal | `1_000` ms | `src/gateway/client.ts` (`backoffMs`) |
|
||||
| Backoff reconnect maksimum | `30_000` ms | `src/gateway/client.ts` (`scheduleReconnect`) |
|
||||
| Clamp percobaan ulang cepat setelah device-token close | `250` ms | `src/gateway/client.ts` |
|
||||
| Masa tenggang force-stop sebelum `terminate()` | `250` ms | `FORCE_STOP_TERMINATE_GRACE_MS` |
|
||||
| Timeout default `stopAndWait()` | `1_000` ms | `STOP_AND_WAIT_TIMEOUT_MS` |
|
||||
| Interval tick default (pra `hello-ok`) | `30_000` ms | `src/gateway/client.ts` |
|
||||
| Penutupan karena timeout tick | kode `4000` ketika senyap melebihi `tickIntervalMs * 2` | `src/gateway/client.ts` |
|
||||
| `MAX_PAYLOAD_BYTES` | `25 * 1024 * 1024` (25 MB) | `src/gateway/server-constants.ts` |
|
||||
|
||||
Server mengiklankan `policy.tickIntervalMs`, `policy.maxPayload`,
|
||||
dan `policy.maxBufferedBytes` efektif dalam `hello-ok`; klien harus mematuhi nilai tersebut
|
||||
alih-alih default pra-handshake.
|
||||
|
||||
## Auth
|
||||
|
||||
- Auth gateway shared-secret menggunakan `connect.params.auth.token` atau
|
||||
`connect.params.auth.password`, tergantung pada mode auth yang dikonfigurasi.
|
||||
`connect.params.auth.password`, bergantung pada mode auth yang dikonfigurasi.
|
||||
- Mode yang membawa identitas seperti Tailscale Serve
|
||||
(`gateway.auth.allowTailscale: true`) atau
|
||||
`gateway.auth.mode: "trusted-proxy"` non-loopback memenuhi pemeriksaan auth connect dari
|
||||
header permintaan alih-alih `connect.params.auth.*`.
|
||||
- Ingress privat `gateway.auth.mode: "none"` sepenuhnya melewati auth connect shared-secret;
|
||||
jangan mengekspos mode tersebut pada ingress publik/tidak tepercaya.
|
||||
- Setelah pairing, Gateway menerbitkan **token perangkat** yang dibatasi pada
|
||||
peran + cakupan koneksi. Token ini dikembalikan dalam `hello-ok.auth.deviceToken` dan
|
||||
harus disimpan oleh klien untuk connect berikutnya.
|
||||
(`gateway.auth.allowTailscale: true`) atau `gateway.auth.mode: "trusted-proxy"`
|
||||
non-loopback memenuhi pemeriksaan auth connect dari header permintaan, bukan dari
|
||||
`connect.params.auth.*`.
|
||||
- `gateway.auth.mode: "none"` untuk private-ingress melewati auth connect shared-secret
|
||||
sepenuhnya; jangan mengekspos mode tersebut pada ingress publik/tidak tepercaya.
|
||||
- Setelah pairing, Gateway menerbitkan **token perangkat** yang dibatasi pada peran + cakupan
|
||||
koneksi. Token ini dikembalikan dalam `hello-ok.auth.deviceToken` dan harus
|
||||
disimpan oleh klien untuk koneksi berikutnya.
|
||||
- Klien harus menyimpan `hello-ok.auth.deviceToken` utama setelah setiap
|
||||
connect yang berhasil.
|
||||
- Menghubungkan ulang dengan token perangkat **tersimpan** tersebut juga harus menggunakan kembali set cakupan
|
||||
yang telah disetujui dan tersimpan untuk token itu. Ini mempertahankan akses baca/probe/status
|
||||
yang sudah diberikan dan menghindari koneksi ulang diam-diam menyusut ke
|
||||
cakupan implisit khusus-admin yang lebih sempit.
|
||||
- Prioritas auth connect normal adalah token/password shared eksplisit terlebih dahulu, lalu
|
||||
`deviceToken` eksplisit, lalu token per-perangkat tersimpan, lalu token bootstrap.
|
||||
- Entri `hello-ok.auth.deviceTokens` tambahan adalah token handoff bootstrap.
|
||||
Simpan token ini hanya saat connect menggunakan auth bootstrap pada transport tepercaya
|
||||
koneksi berhasil.
|
||||
- Saat menyambung kembali dengan token perangkat **tersimpan** tersebut, klien juga harus menggunakan kembali
|
||||
set cakupan tersimpan yang telah disetujui untuk token tersebut. Ini mempertahankan akses
|
||||
baca/probe/status yang sudah diberikan dan menghindari reconnect yang diam-diam menyusut ke
|
||||
cakupan implisit khusus admin yang lebih sempit.
|
||||
- Perakitan auth connect sisi klien (`selectConnectAuth` di
|
||||
`src/gateway/client.ts`):
|
||||
- `auth.password` bersifat ortogonal dan selalu diteruskan ketika disetel.
|
||||
- `auth.token` diisi berdasarkan urutan prioritas: shared token eksplisit terlebih dahulu,
|
||||
lalu `deviceToken` eksplisit, lalu token per-perangkat yang tersimpan (dikunci berdasarkan
|
||||
`deviceId` + `role`).
|
||||
- `auth.bootstrapToken` hanya dikirim ketika tidak satu pun dari hal di atas me-resolve
|
||||
sebuah `auth.token`. Shared token atau token perangkat apa pun yang ter-resolve akan menekannya.
|
||||
- Auto-promotion token perangkat tersimpan pada percobaan ulang sekali jalan
|
||||
`AUTH_TOKEN_MISMATCH` dibatasi hanya untuk **endpoint tepercaya** —
|
||||
loopback, atau `wss://` dengan `tlsFingerprint` yang dipin. `wss://` publik
|
||||
tanpa pinning tidak memenuhi syarat.
|
||||
- Entri tambahan `hello-ok.auth.deviceTokens` adalah token handoff bootstrap.
|
||||
Simpan token tersebut hanya ketika connect menggunakan auth bootstrap pada transport tepercaya
|
||||
seperti `wss://` atau loopback/pairing lokal.
|
||||
- Jika klien memberikan `deviceToken` **eksplisit** atau `scopes` eksplisit, set cakupan
|
||||
yang diminta pemanggil tersebut tetap otoritatif; cakupan yang di-cache hanya
|
||||
digunakan kembali saat klien menggunakan kembali token per-perangkat tersimpan.
|
||||
- Token perangkat dapat dirotasi/dicabut melalui `device.token.rotate` dan
|
||||
- Jika klien menyuplai `deviceToken` **eksplisit** atau `scopes` eksplisit, maka
|
||||
set cakupan yang diminta pemanggil tersebut tetap otoritatif; cakupan cache hanya
|
||||
digunakan kembali ketika klien menggunakan ulang token per-perangkat yang tersimpan.
|
||||
- Token perangkat dapat diputar/dicabut melalui `device.token.rotate` dan
|
||||
`device.token.revoke` (memerlukan cakupan `operator.pairing`).
|
||||
- Penerbitan/rotasi token tetap dibatasi pada set peran yang disetujui dan dicatat dalam
|
||||
entri pairing perangkat tersebut; merotasi token tidak dapat memperluas perangkat ke
|
||||
peran yang tidak pernah diberikan oleh persetujuan pairing.
|
||||
- Untuk sesi token perangkat yang di-pairing, pengelolaan perangkat dibatasi pada diri sendiri kecuali
|
||||
pemanggil juga memiliki `operator.admin`: pemanggil non-admin hanya dapat menghapus/mencabut/merotasi
|
||||
entri perangkat **milik mereka sendiri**.
|
||||
- Penerbitan/rotasi token tetap dibatasi pada set peran yang disetujui dan tercatat dalam
|
||||
entri pairing perangkat tersebut; memutar token tidak dapat memperluas perangkat ke
|
||||
peran yang tidak pernah diberikan oleh approval pairing.
|
||||
- Untuk sesi token perangkat berpasangan, pengelolaan perangkat dibatasi untuk dirinya sendiri kecuali
|
||||
pemanggil juga memiliki `operator.admin`: pemanggil non-admin hanya dapat
|
||||
menghapus/mencabut/memutar entri perangkat **miliknya sendiri**.
|
||||
- `device.token.rotate` juga memeriksa set cakupan operator yang diminta terhadap
|
||||
cakupan sesi pemanggil saat ini. Pemanggil non-admin tidak dapat merotasi token ke
|
||||
cakupan sesi saat ini milik pemanggil. Pemanggil non-admin tidak dapat memutar token ke
|
||||
set cakupan operator yang lebih luas daripada yang sudah mereka miliki.
|
||||
- Kegagalan auth mencakup `error.details.code` plus petunjuk pemulihan:
|
||||
- Kegagalan auth menyertakan `error.details.code` plus petunjuk pemulihan:
|
||||
- `error.details.canRetryWithDeviceToken` (boolean)
|
||||
- `error.details.recommendedNextStep` (`retry_with_device_token`, `update_auth_configuration`, `update_auth_credentials`, `wait_then_retry`, `review_auth_configuration`)
|
||||
- Perilaku klien untuk `AUTH_TOKEN_MISMATCH`:
|
||||
- Klien tepercaya dapat mencoba satu kali retry terbatas dengan token per-perangkat yang di-cache.
|
||||
- Jika retry tersebut gagal, klien harus menghentikan loop reconnect otomatis dan menampilkan panduan tindakan operator.
|
||||
- Klien tepercaya dapat mencoba satu percobaan ulang terbatas dengan token per-perangkat yang di-cache.
|
||||
- Jika percobaan ulang itu gagal, klien harus menghentikan loop reconnect otomatis dan menampilkan panduan tindakan operator.
|
||||
|
||||
## Identitas perangkat + pairing
|
||||
|
||||
- Node harus menyertakan identitas perangkat stabil (`device.id`) yang diturunkan dari
|
||||
- Node harus menyertakan identitas perangkat yang stabil (`device.id`) yang diturunkan dari
|
||||
fingerprint keypair.
|
||||
- Gateway menerbitkan token per perangkat + peran.
|
||||
- Persetujuan pairing diperlukan untuk ID perangkat baru kecuali auto-approval lokal
|
||||
- Approval pairing diperlukan untuk ID perangkat baru kecuali auto-approval lokal
|
||||
diaktifkan.
|
||||
- Auto-approval pairing berpusat pada koneksi local loopback langsung.
|
||||
- Auto-approval pairing berpusat pada koneksi loopback lokal langsung.
|
||||
- OpenClaw juga memiliki jalur self-connect backend/container-local yang sempit untuk
|
||||
alur helper shared-secret tepercaya.
|
||||
- Koneksi tailnet host yang sama atau LAN tetap diperlakukan sebagai koneksi jarak jauh untuk pairing dan
|
||||
memerlukan persetujuan.
|
||||
- Koneksi tailnet atau LAN pada host yang sama tetap diperlakukan sebagai koneksi jarak jauh untuk pairing dan
|
||||
memerlukan approval.
|
||||
- Semua klien WS harus menyertakan identitas `device` selama `connect` (operator + node).
|
||||
Control UI dapat menghilangkannya hanya dalam mode berikut:
|
||||
Control UI hanya dapat mengabaikannya dalam mode berikut:
|
||||
- `gateway.controlUi.allowInsecureAuth=true` untuk kompatibilitas HTTP tidak aman khusus localhost.
|
||||
- auth operator Control UI `gateway.auth.mode: "trusted-proxy"` yang berhasil.
|
||||
- `gateway.controlUi.dangerouslyDisableDeviceAuth=true` (break-glass, penurunan keamanan berat).
|
||||
- Semua koneksi harus menandatangani nonce `connect.challenge` yang disediakan server.
|
||||
- auth operator `gateway.auth.mode: "trusted-proxy"` Control UI yang berhasil.
|
||||
- `gateway.controlUi.dangerouslyDisableDeviceAuth=true` (break-glass, penurunan keamanan yang parah).
|
||||
- Semua koneksi harus menandatangani nonce `connect.challenge` yang diberikan server.
|
||||
|
||||
### Diagnostik migrasi auth perangkat
|
||||
|
||||
@ -576,33 +625,33 @@ kode detail `DEVICE_AUTH_*` di bawah `error.details.code` dengan `error.details.
|
||||
|
||||
Kegagalan migrasi umum:
|
||||
|
||||
| Pesan | details.code | details.reason | Arti |
|
||||
| Message | details.code | details.reason | Meaning |
|
||||
| --------------------------- | -------------------------------- | ------------------------ | -------------------------------------------------- |
|
||||
| `device nonce required` | `DEVICE_AUTH_NONCE_REQUIRED` | `device-nonce-missing` | Klien tidak menyertakan `device.nonce` (atau mengirim kosong). |
|
||||
| `device nonce mismatch` | `DEVICE_AUTH_NONCE_MISMATCH` | `device-nonce-mismatch` | Klien menandatangani dengan nonce yang basi/salah. |
|
||||
| `device signature invalid` | `DEVICE_AUTH_SIGNATURE_INVALID` | `device-signature` | Muatan signature tidak cocok dengan muatan v2. |
|
||||
| `device signature expired` | `DEVICE_AUTH_SIGNATURE_EXPIRED` | `device-signature-stale` | Tanda waktu yang ditandatangani berada di luar skew yang diizinkan. |
|
||||
| `device identity mismatch` | `DEVICE_AUTH_DEVICE_ID_MISMATCH` | `device-id-mismatch` | `device.id` tidak cocok dengan fingerprint public key. |
|
||||
| `device public key invalid` | `DEVICE_AUTH_PUBLIC_KEY_INVALID` | `device-public-key` | Format/kanonisasi public key gagal. |
|
||||
| `device nonce required` | `DEVICE_AUTH_NONCE_REQUIRED` | `device-nonce-missing` | Klien mengabaikan `device.nonce` (atau mengirim kosong). |
|
||||
| `device nonce mismatch` | `DEVICE_AUTH_NONCE_MISMATCH` | `device-nonce-mismatch` | Klien menandatangani dengan nonce yang stale/salah. |
|
||||
| `device signature invalid` | `DEVICE_AUTH_SIGNATURE_INVALID` | `device-signature` | Payload tanda tangan tidak cocok dengan payload v2. |
|
||||
| `device signature expired` | `DEVICE_AUTH_SIGNATURE_EXPIRED` | `device-signature-stale` | Stempel waktu yang ditandatangani berada di luar skew yang diizinkan. |
|
||||
| `device identity mismatch` | `DEVICE_AUTH_DEVICE_ID_MISMATCH` | `device-id-mismatch` | `device.id` tidak cocok dengan fingerprint kunci publik. |
|
||||
| `device public key invalid` | `DEVICE_AUTH_PUBLIC_KEY_INVALID` | `device-public-key` | Format/kanonisasi kunci publik gagal. |
|
||||
|
||||
Target migrasi:
|
||||
|
||||
- Selalu tunggu `connect.challenge`.
|
||||
- Tanda tangani muatan v2 yang menyertakan nonce server.
|
||||
- Kirim nonce yang sama dalam `connect.params.device.nonce`.
|
||||
- Muatan signature yang disarankan adalah `v3`, yang mengikat `platform` dan `deviceFamily`
|
||||
selain field device/client/role/scopes/token/nonce.
|
||||
- Signature `v2` lama tetap diterima untuk kompatibilitas, tetapi pinning metadata
|
||||
paired-device tetap mengontrol kebijakan perintah saat reconnect.
|
||||
- Tandatangani payload v2 yang menyertakan nonce server.
|
||||
- Kirim nonce yang sama di `connect.params.device.nonce`.
|
||||
- Payload tanda tangan yang disukai adalah `v3`, yang mengikat `platform` dan `deviceFamily`
|
||||
selain field perangkat/klien/peran/cakupan/token/nonce.
|
||||
- Tanda tangan `v2` lama tetap diterima untuk kompatibilitas, tetapi pinning metadata
|
||||
perangkat berpasangan tetap mengontrol kebijakan perintah saat reconnect.
|
||||
|
||||
## TLS + pinning
|
||||
|
||||
- TLS didukung untuk koneksi WS.
|
||||
- Klien dapat secara opsional melakukan pinning fingerprint sertifikat gateway (lihat config `gateway.tls`
|
||||
serta `gateway.remote.tlsFingerprint` atau CLI `--tls-fingerprint`).
|
||||
- Klien dapat secara opsional mem-pin fingerprint sertifikat gateway (lihat config `gateway.tls`
|
||||
plus `gateway.remote.tlsFingerprint` atau CLI `--tls-fingerprint`).
|
||||
|
||||
## Cakupan
|
||||
|
||||
Protokol ini mengekspos **API gateway lengkap** (status, channel, model, chat,
|
||||
agen, sesi, node, persetujuan, dll.). Permukaan persisnya didefinisikan oleh
|
||||
agent, sesi, node, approval, dll.). Permukaan persisnya didefinisikan oleh
|
||||
skema TypeBox di `src/gateway/protocol/schema.ts`.
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
---
|
||||
read_when:
|
||||
- Anda ingin menggunakan model Google Gemini dengan OpenClaw
|
||||
- Anda memerlukan alur auth API key atau OAuth
|
||||
summary: Penyiapan Google Gemini (API key + OAuth, pembuatan gambar, pemahaman media, pencarian web)
|
||||
- Anda memerlukan kunci API atau alur autentikasi OAuth
|
||||
summary: Penyiapan Google Gemini (kunci API + OAuth, pembuatan gambar, pemahaman media, TTS, pencarian web)
|
||||
title: Google (Gemini)
|
||||
x-i18n:
|
||||
generated_at: "2026-04-12T23:30:55Z"
|
||||
generated_at: "2026-04-16T09:14:37Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 64b848add89061b208a5d6b19d206c433cace5216a0ca4b63d56496aecbde452
|
||||
source_hash: ec2d62855f5e80efda758aad71bcaa95c38b1e41761fa1100d47a06c62881419
|
||||
source_path: providers/google.md
|
||||
workflow: 15
|
||||
---
|
||||
@ -16,7 +16,7 @@ x-i18n:
|
||||
# Google (Gemini)
|
||||
|
||||
Plugin Google menyediakan akses ke model Gemini melalui Google AI Studio, serta
|
||||
pembuatan gambar, pemahaman media (gambar/audio/video), dan pencarian web melalui
|
||||
pembuatan gambar, pemahaman media (gambar/audio/video), text-to-speech, dan pencarian web melalui
|
||||
Gemini Grounding.
|
||||
|
||||
- Provider: `google`
|
||||
@ -26,10 +26,10 @@ Gemini Grounding.
|
||||
|
||||
## Memulai
|
||||
|
||||
Pilih metode auth yang Anda inginkan dan ikuti langkah penyiapannya.
|
||||
Pilih metode autentikasi yang Anda inginkan dan ikuti langkah-langkah penyiapan.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="API key">
|
||||
<Tab title="Kunci API">
|
||||
**Terbaik untuk:** akses API Gemini standar melalui Google AI Studio.
|
||||
|
||||
<Steps>
|
||||
@ -38,7 +38,7 @@ Pilih metode auth yang Anda inginkan dan ikuti langkah penyiapannya.
|
||||
openclaw onboard --auth-choice gemini-api-key
|
||||
```
|
||||
|
||||
Atau berikan key secara langsung:
|
||||
Atau berikan kunci secara langsung:
|
||||
|
||||
```bash
|
||||
openclaw onboard --non-interactive \
|
||||
@ -47,7 +47,7 @@ Pilih metode auth yang Anda inginkan dan ikuti langkah penyiapannya.
|
||||
--gemini-api-key "$GEMINI_API_KEY"
|
||||
```
|
||||
</Step>
|
||||
<Step title="Setel model default">
|
||||
<Step title="Tetapkan model default">
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
@ -58,7 +58,7 @@ Pilih metode auth yang Anda inginkan dan ikuti langkah penyiapannya.
|
||||
}
|
||||
```
|
||||
</Step>
|
||||
<Step title="Verifikasi model tersedia">
|
||||
<Step title="Verifikasi bahwa model tersedia">
|
||||
```bash
|
||||
openclaw models list --provider google
|
||||
```
|
||||
@ -66,13 +66,13 @@ Pilih metode auth yang Anda inginkan dan ikuti langkah penyiapannya.
|
||||
</Steps>
|
||||
|
||||
<Tip>
|
||||
Variabel environment `GEMINI_API_KEY` dan `GOOGLE_API_KEY` sama-sama didukung. Gunakan salah satu yang sudah Anda konfigurasikan.
|
||||
Variabel lingkungan `GEMINI_API_KEY` dan `GOOGLE_API_KEY` keduanya didukung. Gunakan mana saja yang sudah Anda konfigurasi.
|
||||
</Tip>
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="Gemini CLI (OAuth)">
|
||||
**Terbaik untuk:** menggunakan kembali login Gemini CLI yang sudah ada melalui PKCE OAuth alih-alih API key terpisah.
|
||||
**Terbaik untuk:** menggunakan kembali login Gemini CLI yang sudah ada melalui PKCE OAuth alih-alih kunci API terpisah.
|
||||
|
||||
<Warning>
|
||||
Provider `google-gemini-cli` adalah integrasi tidak resmi. Beberapa pengguna
|
||||
@ -81,7 +81,7 @@ Pilih metode auth yang Anda inginkan dan ikuti langkah penyiapannya.
|
||||
|
||||
<Steps>
|
||||
<Step title="Instal Gemini CLI">
|
||||
Perintah `gemini` lokal harus tersedia di `PATH`.
|
||||
Perintah lokal `gemini` harus tersedia di `PATH`.
|
||||
|
||||
```bash
|
||||
# Homebrew
|
||||
@ -91,15 +91,15 @@ Pilih metode auth yang Anda inginkan dan ikuti langkah penyiapannya.
|
||||
npm install -g @google/gemini-cli
|
||||
```
|
||||
|
||||
OpenClaw mendukung instalasi Homebrew maupun instalasi npm global, termasuk
|
||||
tata letak Windows/npm yang umum.
|
||||
OpenClaw mendukung instalasi Homebrew dan instalasi npm global, termasuk
|
||||
tata letak umum Windows/npm.
|
||||
</Step>
|
||||
<Step title="Masuk melalui OAuth">
|
||||
```bash
|
||||
openclaw models auth login --provider google-gemini-cli --set-default
|
||||
```
|
||||
</Step>
|
||||
<Step title="Verifikasi model tersedia">
|
||||
<Step title="Verifikasi bahwa model tersedia">
|
||||
```bash
|
||||
openclaw models list --provider google-gemini-cli
|
||||
```
|
||||
@ -109,7 +109,7 @@ Pilih metode auth yang Anda inginkan dan ikuti langkah penyiapannya.
|
||||
- Model default: `google-gemini-cli/gemini-3-flash-preview`
|
||||
- Alias: `gemini-cli`
|
||||
|
||||
**Variabel environment:**
|
||||
**Variabel lingkungan:**
|
||||
|
||||
- `OPENCLAW_GEMINI_OAUTH_CLIENT_ID`
|
||||
- `OPENCLAW_GEMINI_OAUTH_CLIENT_SECRET`
|
||||
@ -117,17 +117,17 @@ Pilih metode auth yang Anda inginkan dan ikuti langkah penyiapannya.
|
||||
(Atau varian `GEMINI_CLI_*`.)
|
||||
|
||||
<Note>
|
||||
Jika permintaan OAuth Gemini CLI gagal setelah login, setel `GOOGLE_CLOUD_PROJECT` atau
|
||||
`GOOGLE_CLOUD_PROJECT_ID` pada host gateway lalu coba lagi.
|
||||
Jika permintaan OAuth Gemini CLI gagal setelah login, tetapkan `GOOGLE_CLOUD_PROJECT` atau
|
||||
`GOOGLE_CLOUD_PROJECT_ID` pada host Gateway lalu coba lagi.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Jika login gagal sebelum alur browser dimulai, pastikan perintah `gemini` lokal
|
||||
Jika login gagal sebelum alur browser dimulai, pastikan perintah lokal `gemini`
|
||||
terinstal dan ada di `PATH`.
|
||||
</Note>
|
||||
|
||||
Provider `google-gemini-cli` yang khusus OAuth adalah
|
||||
surface inferensi teks yang terpisah. Pembuatan gambar, pemahaman media, dan Gemini Grounding tetap berada pada
|
||||
Provider `google-gemini-cli` yang hanya mendukung OAuth adalah
|
||||
surface inferensi teks terpisah. Pembuatan gambar, pemahaman media, dan Gemini Grounding tetap berada pada
|
||||
id provider `google`.
|
||||
|
||||
</Tab>
|
||||
@ -135,11 +135,12 @@ Pilih metode auth yang Anda inginkan dan ikuti langkah penyiapannya.
|
||||
|
||||
## Kemampuan
|
||||
|
||||
| Capability | Supported |
|
||||
| Kemampuan | Didukung |
|
||||
| ---------------------- | ----------------- |
|
||||
| Chat completions | Ya |
|
||||
| Penyelesaian chat | Ya |
|
||||
| Pembuatan gambar | Ya |
|
||||
| Pembuatan musik | Ya |
|
||||
| Text-to-speech | Ya |
|
||||
| Pemahaman gambar | Ya |
|
||||
| Transkripsi audio | Ya |
|
||||
| Pemahaman video | Ya |
|
||||
@ -149,8 +150,8 @@ Pilih metode auth yang Anda inginkan dan ikuti langkah penyiapannya.
|
||||
|
||||
<Tip>
|
||||
Model Gemma 4 (misalnya `gemma-4-26b-a4b-it`) mendukung mode thinking. OpenClaw
|
||||
menulis ulang `thinkingBudget` ke `thinkingLevel` Google yang didukung untuk Gemma 4.
|
||||
Menyetel thinking ke `off` mempertahankan thinking nonaktif alih-alih memetakannya ke
|
||||
menulis ulang `thinkingBudget` menjadi `thinkingLevel` Google yang didukung untuk Gemma 4.
|
||||
Menetapkan thinking ke `off` akan mempertahankan thinking dalam keadaan nonaktif alih-alih memetakannya ke
|
||||
`MINIMAL`.
|
||||
</Tip>
|
||||
|
||||
@ -160,8 +161,8 @@ Provider pembuatan gambar `google` bawaan secara default menggunakan
|
||||
`google/gemini-3.1-flash-image-preview`.
|
||||
|
||||
- Juga mendukung `google/gemini-3-pro-image-preview`
|
||||
- Generate: hingga 4 gambar per permintaan
|
||||
- Mode edit: aktif, hingga 5 gambar input
|
||||
- Hasilkan: hingga 4 gambar per permintaan
|
||||
- Mode edit: diaktifkan, hingga 5 gambar masukan
|
||||
- Kontrol geometri: `size`, `aspectRatio`, dan `resolution`
|
||||
|
||||
Untuk menggunakan Google sebagai provider gambar default:
|
||||
@ -179,12 +180,12 @@ Untuk menggunakan Google sebagai provider gambar default:
|
||||
```
|
||||
|
||||
<Note>
|
||||
Lihat [Image Generation](/id/tools/image-generation) untuk parameter tool bersama, pemilihan provider, dan perilaku failover.
|
||||
Lihat [Pembuatan Gambar](/id/tools/image-generation) untuk parameter alat bersama, pemilihan provider, dan perilaku failover.
|
||||
</Note>
|
||||
|
||||
## Pembuatan video
|
||||
|
||||
Plugin `google` bawaan juga mendaftarkan pembuatan video melalui tool bersama
|
||||
Plugin `google` bawaan juga mendaftarkan pembuatan video melalui alat bersama
|
||||
`video_generate`.
|
||||
|
||||
- Model video default: `google/veo-3.1-fast-generate-preview`
|
||||
@ -207,20 +208,20 @@ Untuk menggunakan Google sebagai provider video default:
|
||||
```
|
||||
|
||||
<Note>
|
||||
Lihat [Video Generation](/id/tools/video-generation) untuk parameter tool bersama, pemilihan provider, dan perilaku failover.
|
||||
Lihat [Pembuatan Video](/id/tools/video-generation) untuk parameter alat bersama, pemilihan provider, dan perilaku failover.
|
||||
</Note>
|
||||
|
||||
## Pembuatan musik
|
||||
|
||||
Plugin `google` bawaan juga mendaftarkan pembuatan musik melalui tool bersama
|
||||
Plugin `google` bawaan juga mendaftarkan pembuatan musik melalui alat bersama
|
||||
`music_generate`.
|
||||
|
||||
- Model musik default: `google/lyria-3-clip-preview`
|
||||
- Juga mendukung `google/lyria-3-pro-preview`
|
||||
- Kontrol prompt: `lyrics` dan `instrumental`
|
||||
- Format output: `mp3` secara default, ditambah `wav` pada `google/lyria-3-pro-preview`
|
||||
- Input referensi: hingga 10 gambar
|
||||
- Eksekusi berbasis sesi dilepas melalui alur task/status bersama, termasuk `action: "status"`
|
||||
- Format keluaran: `mp3` secara default, ditambah `wav` pada `google/lyria-3-pro-preview`
|
||||
- Masukan referensi: hingga 10 gambar
|
||||
- Proses berbasis sesi dilepas melalui alur tugas/status bersama, termasuk `action: "status"`
|
||||
|
||||
Untuk menggunakan Google sebagai provider musik default:
|
||||
|
||||
@ -237,21 +238,65 @@ Untuk menggunakan Google sebagai provider musik default:
|
||||
```
|
||||
|
||||
<Note>
|
||||
Lihat [Music Generation](/id/tools/music-generation) untuk parameter tool bersama, pemilihan provider, dan perilaku failover.
|
||||
Lihat [Pembuatan Musik](/id/tools/music-generation) untuk parameter alat bersama, pemilihan provider, dan perilaku failover.
|
||||
</Note>
|
||||
|
||||
## Text-to-speech
|
||||
|
||||
Provider ucapan `google` bawaan menggunakan jalur TTS Google Gemini API dengan
|
||||
`gemini-3.1-flash-tts-preview`.
|
||||
|
||||
- Suara default: `Kore`
|
||||
- Auth: `messages.tts.providers.google.apiKey`, `models.providers.google.apiKey`, `GEMINI_API_KEY`, atau `GOOGLE_API_KEY`
|
||||
- Keluaran: WAV untuk lampiran TTS biasa, PCM untuk Talk/teleponi
|
||||
- Keluaran catatan suara native: tidak didukung pada jalur Gemini API ini karena API mengembalikan PCM, bukan Opus
|
||||
|
||||
Untuk menggunakan Google sebagai provider TTS default:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
tts: {
|
||||
auto: "always",
|
||||
provider: "google",
|
||||
providers: {
|
||||
google: {
|
||||
model: "gemini-3.1-flash-tts-preview",
|
||||
voiceName: "Kore",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Gemini API TTS menerima tag audio ekspresif dalam tanda kurung siku di dalam teks, seperti
|
||||
`[whispers]` atau `[laughs]`. Agar tag tidak muncul di balasan chat yang terlihat sambil
|
||||
tetap mengirimkannya ke TTS, letakkan tag tersebut di dalam blok `[[tts:text]]...[[/tts:text]]`:
|
||||
|
||||
```text
|
||||
Berikut adalah teks balasan yang bersih.
|
||||
|
||||
[[tts:text]][whispers] Berikut adalah versi yang diucapkan.[[/tts:text]]
|
||||
```
|
||||
|
||||
<Note>
|
||||
Kunci API Google Cloud Console yang dibatasi untuk Gemini API valid untuk
|
||||
provider ini. Ini bukan jalur Cloud Text-to-Speech API yang terpisah.
|
||||
</Note>
|
||||
|
||||
## Konfigurasi lanjutan
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Reuse cache Gemini langsung">
|
||||
Untuk eksekusi API Gemini langsung (`api: "google-generative-ai"`), OpenClaw
|
||||
<Accordion title="Penggunaan ulang cache Gemini langsung">
|
||||
Untuk proses Gemini API langsung (`api: "google-generative-ai"`), OpenClaw
|
||||
meneruskan handle `cachedContent` yang dikonfigurasi ke permintaan Gemini.
|
||||
|
||||
- Konfigurasikan parameter per-model atau global dengan
|
||||
- Konfigurasikan parameter per model atau global dengan
|
||||
`cachedContent` atau `cached_content` lama
|
||||
- Jika keduanya ada, `cachedContent` yang diprioritaskan
|
||||
- Nilai contoh: `cachedContents/prebuilt-context`
|
||||
- Penggunaan cache-hit Gemini dinormalisasi ke `cacheRead` OpenClaw dari
|
||||
- Contoh nilai: `cachedContents/prebuilt-context`
|
||||
- Penggunaan cache-hit Gemini dinormalisasi menjadi `cacheRead` OpenClaw dari
|
||||
`cachedContentTokenCount` upstream
|
||||
|
||||
```json5
|
||||
@ -274,17 +319,17 @@ Lihat [Music Generation](/id/tools/music-generation) untuk parameter tool bersam
|
||||
|
||||
<Accordion title="Catatan penggunaan JSON Gemini CLI">
|
||||
Saat menggunakan provider OAuth `google-gemini-cli`, OpenClaw menormalisasi
|
||||
output JSON CLI sebagai berikut:
|
||||
keluaran JSON CLI sebagai berikut:
|
||||
|
||||
- Teks balasan berasal dari field JSON `response` milik CLI.
|
||||
- Penggunaan fallback ke `stats` saat CLI membiarkan `usage` kosong.
|
||||
- `stats.cached` dinormalisasi ke `cacheRead` OpenClaw.
|
||||
- Jika `stats.input` tidak ada, OpenClaw menurunkan token input dari
|
||||
- Teks balasan berasal dari field `response` pada JSON CLI.
|
||||
- Penggunaan akan menggunakan `stats` jika CLI membiarkan `usage` kosong.
|
||||
- `stats.cached` dinormalisasi menjadi `cacheRead` OpenClaw.
|
||||
- Jika `stats.input` tidak ada, OpenClaw menurunkan token masukan dari
|
||||
`stats.input_tokens - stats.cached`.
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Environment dan penyiapan daemon">
|
||||
<Accordion title="Penyiapan lingkungan dan daemon">
|
||||
Jika Gateway berjalan sebagai daemon (launchd/systemd), pastikan `GEMINI_API_KEY`
|
||||
tersedia untuk proses tersebut (misalnya, di `~/.openclaw/.env` atau melalui
|
||||
`env.shellEnv`).
|
||||
@ -295,15 +340,15 @@ Lihat [Music Generation](/id/tools/music-generation) untuk parameter tool bersam
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Pemilihan model" href="/id/concepts/model-providers" icon="layers">
|
||||
Memilih provider, ref model, dan perilaku failover.
|
||||
Memilih provider, referensi model, dan perilaku failover.
|
||||
</Card>
|
||||
<Card title="Pembuatan gambar" href="/id/tools/image-generation" icon="image">
|
||||
Parameter tool gambar bersama dan pemilihan provider.
|
||||
Parameter alat gambar bersama dan pemilihan provider.
|
||||
</Card>
|
||||
<Card title="Pembuatan video" href="/id/tools/video-generation" icon="video">
|
||||
Parameter tool video bersama dan pemilihan provider.
|
||||
Parameter alat video bersama dan pemilihan provider.
|
||||
</Card>
|
||||
<Card title="Pembuatan musik" href="/id/tools/music-generation" icon="music">
|
||||
Parameter tool musik bersama dan pemilihan provider.
|
||||
Parameter alat musik bersama dan pemilihan provider.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@ -0,0 +1,132 @@
|
||||
---
|
||||
x-i18n:
|
||||
generated_at: "2026-04-16T09:14:29Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 95e56c5411204363676f002059c942201503e2359515d1a4b409882cc2e04920
|
||||
source_path: refactor/async-exec-duplicate-completion-investigation.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Investigasi Penyelesaian Duplikat Async Exec
|
||||
|
||||
## Cakupan
|
||||
|
||||
- Sesi: `agent:main:telegram:group:-1003774691294:topic:1`
|
||||
- Gejala: completion async exec yang sama untuk session/run `keen-nexus` tercatat dua kali di LCM sebagai giliran pengguna.
|
||||
- Tujuan: mengidentifikasi apakah ini kemungkinan besar merupakan injeksi sesi duplikat atau sekadar retry pengiriman outbound biasa.
|
||||
|
||||
## Kesimpulan
|
||||
|
||||
Kemungkinan besar ini adalah **injeksi sesi duplikat**, bukan retry pengiriman outbound murni.
|
||||
|
||||
Celah sisi gateway yang paling kuat ada di **jalur penyelesaian exec node**:
|
||||
|
||||
1. Penyelesaian exec di sisi node memancarkan `exec.finished` dengan `runId` lengkap.
|
||||
2. Gateway `server-node-events` mengubahnya menjadi system event dan meminta heartbeat.
|
||||
3. Heartbeat run menyuntikkan blok system event yang telah dikuras ke dalam prompt agen.
|
||||
4. Embedded runner menyimpan prompt tersebut sebagai giliran pengguna baru dalam transkrip sesi.
|
||||
|
||||
Jika `exec.finished` yang sama mencapai gateway dua kali untuk `runId` yang sama karena alasan apa pun (replay, duplikat saat reconnect, resend dari upstream, producer terduplikasi), OpenClaw saat ini **tidak memiliki pemeriksaan idempotensi yang dikunci oleh `runId`/`contextKey`** pada jalur ini. Salinan kedua akan menjadi pesan pengguna kedua dengan konten yang sama.
|
||||
|
||||
## Jalur Kode yang Tepat
|
||||
|
||||
### 1. Produser: event penyelesaian exec node
|
||||
|
||||
- `src/node-host/invoke.ts:340-360`
|
||||
- `sendExecFinishedEvent(...)` memancarkan `node.event` dengan event `exec.finished`.
|
||||
- Payload mencakup `sessionKey` dan `runId` lengkap.
|
||||
|
||||
### 2. Ingesti event gateway
|
||||
|
||||
- `src/gateway/server-node-events.ts:574-640`
|
||||
- Menangani `exec.finished`.
|
||||
- Membangun teks:
|
||||
- `Exec finished (node=..., id=<runId>, code ...)`
|
||||
- Mengantrikannya melalui:
|
||||
- `enqueueSystemEvent(text, { sessionKey, contextKey: runId ? \`exec:${runId}\` : "exec", trusted: false })`
|
||||
- Segera meminta wake:
|
||||
- `requestHeartbeatNow(scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event" }))`
|
||||
|
||||
### 3. Kelemahan dedupe system event
|
||||
|
||||
- `src/infra/system-events.ts:90-115`
|
||||
- `enqueueSystemEvent(...)` hanya menekan **teks duplikat yang berurutan**:
|
||||
- `if (entry.lastText === cleaned) return false`
|
||||
- Ia menyimpan `contextKey`, tetapi **tidak** menggunakan `contextKey` untuk idempotensi.
|
||||
- Setelah drain, penekanan duplikat di-reset.
|
||||
|
||||
Artinya, `exec.finished` yang direplay dengan `runId` yang sama bisa diterima lagi nanti, walaupun kode sudah memiliki kandidat idempotensi yang stabil (`exec:<runId>`).
|
||||
|
||||
### 4. Penanganan wake bukan pengganda utama
|
||||
|
||||
- `src/infra/heartbeat-wake.ts:79-117`
|
||||
- Wake digabungkan berdasarkan `(agentId, sessionKey)`.
|
||||
- Permintaan wake duplikat untuk target yang sama runtuh menjadi satu entri wake tertunda.
|
||||
|
||||
Ini membuat **penanganan wake duplikat saja** menjadi penjelasan yang lebih lemah daripada ingesti event duplikat.
|
||||
|
||||
### 5. Heartbeat mengonsumsi event dan mengubahnya menjadi input prompt
|
||||
|
||||
- `src/infra/heartbeat-runner.ts:535-574`
|
||||
- Preflight mengintip system event tertunda dan mengklasifikasikan run exec-event.
|
||||
- `src/auto-reply/reply/session-system-events.ts:86-90`
|
||||
- `drainFormattedSystemEvents(...)` menguras antrean untuk sesi tersebut.
|
||||
- `src/auto-reply/reply/get-reply-run.ts:400-427`
|
||||
- Blok system event yang telah dikuras didahulukan ke badan prompt agen.
|
||||
|
||||
### 6. Titik injeksi transkrip
|
||||
|
||||
- `src/agents/pi-embedded-runner/run/attempt.ts:2000-2017`
|
||||
- `activeSession.prompt(effectivePrompt)` mengirim prompt lengkap ke sesi PI embedded.
|
||||
- Itulah titik ketika prompt turunan completion menjadi giliran pengguna yang tersimpan.
|
||||
|
||||
Jadi begitu system event yang sama dibangun ulang ke dalam prompt dua kali, pesan pengguna LCM duplikat memang diharapkan.
|
||||
|
||||
## Mengapa retry pengiriman outbound biasa lebih kecil kemungkinannya
|
||||
|
||||
Ada jalur kegagalan outbound yang nyata di heartbeat runner:
|
||||
|
||||
- `src/infra/heartbeat-runner.ts:1194-1242`
|
||||
- Balasan dibuat lebih dulu.
|
||||
- Pengiriman outbound terjadi kemudian melalui `deliverOutboundPayloads(...)`.
|
||||
- Kegagalan di sana mengembalikan `{ status: "failed" }`.
|
||||
|
||||
Namun, untuk entri antrean system event yang sama, ini saja **tidak cukup** untuk menjelaskan giliran pengguna duplikat:
|
||||
|
||||
- `src/auto-reply/reply/session-system-events.ts:86-90`
|
||||
- Antrean system event sudah dikuras sebelum pengiriman outbound.
|
||||
|
||||
Jadi retry kirim kanal dengan sendirinya tidak akan membuat ulang event antrean yang sama secara persis. Itu bisa menjelaskan pengiriman eksternal yang hilang/gagal, tetapi tidak dengan sendirinya menjelaskan pesan pengguna sesi identik kedua.
|
||||
|
||||
## Kemungkinan sekunder dengan keyakinan lebih rendah
|
||||
|
||||
Ada loop retry full-run di runner agen:
|
||||
|
||||
- `src/auto-reply/reply/agent-runner-execution.ts:741-1473`
|
||||
- Kegagalan transien tertentu dapat me-retry seluruh run dan mengirim ulang `commandBody` yang sama.
|
||||
|
||||
Ini dapat menggandakan prompt pengguna yang tersimpan **dalam eksekusi balasan yang sama** jika prompt sudah ditambahkan sebelum kondisi retry terpicu.
|
||||
|
||||
Saya menempatkannya lebih rendah daripada ingest `exec.finished` duplikat karena:
|
||||
|
||||
- jeda yang diamati sekitar 51 detik, yang terlihat lebih seperti giliran/wake kedua daripada retry dalam proses;
|
||||
- laporan sudah menyebut kegagalan pengiriman pesan berulang, yang lebih mengarah ke giliran terpisah yang terjadi kemudian daripada retry model/runtime yang langsung.
|
||||
|
||||
## Hipotesis Akar Masalah
|
||||
|
||||
Hipotesis dengan keyakinan tertinggi:
|
||||
|
||||
- Completion `keen-nexus` datang melalui **jalur event exec node**.
|
||||
- `exec.finished` yang sama dikirim ke `server-node-events` dua kali.
|
||||
- Gateway menerima keduanya karena `enqueueSystemEvent(...)` tidak melakukan dedupe berdasarkan `contextKey` / `runId`.
|
||||
- Setiap event yang diterima memicu heartbeat dan disuntikkan sebagai giliran pengguna ke transkrip PI.
|
||||
|
||||
## Usulan Perbaikan Bedah Kecil
|
||||
|
||||
Jika perbaikan diinginkan, perubahan kecil dengan nilai tinggi adalah:
|
||||
|
||||
- buat idempotensi exec/system-event menghormati `contextKey` untuk horizon singkat, setidaknya untuk pengulangan `(sessionKey, contextKey, text)` yang persis;
|
||||
- atau tambahkan dedupe khusus di `server-node-events` untuk `exec.finished` yang dikunci oleh `(sessionKey, runId, jenis event)`.
|
||||
|
||||
Itu akan langsung memblokir duplikat `exec.finished` yang direplay sebelum berubah menjadi giliran sesi.
|
||||
@ -1,56 +1,55 @@
|
||||
---
|
||||
read_when:
|
||||
- Mengaktifkan text-to-speech untuk balasan
|
||||
- Mengonfigurasi provider atau batas TTS
|
||||
- Menggunakan perintah `/tts`
|
||||
- Mengonfigurasi penyedia TTS atau batasan
|
||||
- Menggunakan perintah /tts
|
||||
summary: Text-to-speech (TTS) untuk balasan keluar
|
||||
title: Text-to-Speech
|
||||
x-i18n:
|
||||
generated_at: "2026-04-12T23:33:41Z"
|
||||
generated_at: "2026-04-16T09:14:37Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: ad79a6be34879347dc73fdab1bd219823cd7c6aa8504e3e4c73e1a0554c837c5
|
||||
source_hash: de7c1dc8831c1ba307596afd48cb4d36f844724887a13b17e35f41ef5174a86f
|
||||
source_path: tools/tts.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Text-to-speech (TTS)
|
||||
|
||||
OpenClaw dapat mengubah balasan keluar menjadi audio menggunakan ElevenLabs, Microsoft, MiniMax, atau OpenAI.
|
||||
OpenClaw dapat mengonversi balasan keluar menjadi audio menggunakan ElevenLabs, Google Gemini, Microsoft, MiniMax, atau OpenAI.
|
||||
Fitur ini berfungsi di mana pun OpenClaw dapat mengirim audio.
|
||||
|
||||
## Layanan yang didukung
|
||||
|
||||
- **ElevenLabs** (provider utama atau fallback)
|
||||
- **Microsoft** (provider utama atau fallback; implementasi bawaan saat ini menggunakan `node-edge-tts`)
|
||||
- **MiniMax** (provider utama atau fallback; menggunakan API T2A v2)
|
||||
- **OpenAI** (provider utama atau fallback; juga digunakan untuk ringkasan)
|
||||
- **ElevenLabs** (penyedia utama atau cadangan)
|
||||
- **Google Gemini** (penyedia utama atau cadangan; menggunakan Gemini API TTS)
|
||||
- **Microsoft** (penyedia utama atau cadangan; implementasi bawaan saat ini menggunakan `node-edge-tts`)
|
||||
- **MiniMax** (penyedia utama atau cadangan; menggunakan API T2A v2)
|
||||
- **OpenAI** (penyedia utama atau cadangan; juga digunakan untuk ringkasan)
|
||||
|
||||
### Catatan speech Microsoft
|
||||
|
||||
Provider speech Microsoft bawaan saat ini menggunakan layanan TTS neural online Microsoft Edge melalui library `node-edge-tts`. Ini adalah layanan hosted (bukan
|
||||
lokal), menggunakan endpoint Microsoft, dan tidak memerlukan API key.
|
||||
`node-edge-tts` mengekspos opsi konfigurasi speech dan format output, tetapi
|
||||
tidak semua opsi didukung oleh layanan tersebut. Input directive dan config lama yang
|
||||
menggunakan `edge` tetap berfungsi dan dinormalisasi ke `microsoft`.
|
||||
Penyedia speech Microsoft bawaan saat ini menggunakan layanan neural TTS online Microsoft Edge melalui library `node-edge-tts`. Ini adalah layanan yang di-hosting (bukan lokal), menggunakan endpoint Microsoft, dan tidak memerlukan API key.
|
||||
`node-edge-tts` mengekspos opsi konfigurasi speech dan format output, tetapi tidak semua opsi didukung oleh layanan tersebut. Konfigurasi lama dan input directive yang menggunakan `edge` masih berfungsi dan dinormalisasi menjadi `microsoft`.
|
||||
|
||||
Karena jalur ini adalah layanan web publik tanpa SLA atau kuota yang dipublikasikan,
|
||||
anggap ini sebagai best-effort. Jika Anda memerlukan batas dan dukungan yang terjamin, gunakan OpenAI
|
||||
anggap ini sebagai upaya terbaik. Jika Anda memerlukan batas yang terjamin dan dukungan, gunakan OpenAI
|
||||
atau ElevenLabs.
|
||||
|
||||
## Key opsional
|
||||
## Kunci opsional
|
||||
|
||||
Jika Anda ingin OpenAI, ElevenLabs, atau MiniMax:
|
||||
Jika Anda ingin menggunakan OpenAI, ElevenLabs, Google Gemini, atau MiniMax:
|
||||
|
||||
- `ELEVENLABS_API_KEY` (atau `XI_API_KEY`)
|
||||
- `GEMINI_API_KEY` (atau `GOOGLE_API_KEY`)
|
||||
- `MINIMAX_API_KEY`
|
||||
- `OPENAI_API_KEY`
|
||||
|
||||
Speech Microsoft **tidak** memerlukan API key.
|
||||
|
||||
Jika beberapa provider dikonfigurasi, provider yang dipilih digunakan terlebih dahulu dan yang lainnya menjadi opsi fallback.
|
||||
Jika beberapa penyedia dikonfigurasi, penyedia yang dipilih akan digunakan terlebih dahulu dan yang lainnya menjadi opsi cadangan.
|
||||
Ringkasan otomatis menggunakan `summaryModel` yang dikonfigurasi (atau `agents.defaults.model.primary`),
|
||||
jadi provider tersebut juga harus diautentikasi jika Anda mengaktifkan ringkasan.
|
||||
jadi penyedia tersebut juga harus diautentikasi jika Anda mengaktifkan ringkasan.
|
||||
|
||||
## Tautan layanan
|
||||
|
||||
@ -64,18 +63,18 @@ jadi provider tersebut juga harus diautentikasi jika Anda mengaktifkan ringkasan
|
||||
|
||||
## Apakah ini diaktifkan secara default?
|
||||
|
||||
Tidak. Auto‑TTS **nonaktif** secara default. Aktifkan di config dengan
|
||||
Tidak. Auto‑TTS **nonaktif** secara default. Aktifkan di konfigurasi dengan
|
||||
`messages.tts.auto` atau secara lokal dengan `/tts on`.
|
||||
|
||||
Saat `messages.tts.provider` tidak disetel, OpenClaw memilih provider
|
||||
speech pertama yang dikonfigurasi sesuai urutan auto-select registri.
|
||||
Saat `messages.tts.provider` tidak disetel, OpenClaw memilih penyedia
|
||||
speech pertama dalam urutan pemilihan otomatis registry.
|
||||
|
||||
## Config
|
||||
## Konfigurasi
|
||||
|
||||
Config TTS berada di bawah `messages.tts` di `openclaw.json`.
|
||||
Konfigurasi TTS berada di bawah `messages.tts` dalam `openclaw.json`.
|
||||
Skema lengkap ada di [Konfigurasi Gateway](/id/gateway/configuration).
|
||||
|
||||
### Config minimal (aktifkan + provider)
|
||||
### Konfigurasi minimal (aktifkan + penyedia)
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -88,7 +87,7 @@ Skema lengkap ada di [Konfigurasi Gateway](/id/gateway/configuration).
|
||||
}
|
||||
```
|
||||
|
||||
### OpenAI utama dengan fallback ElevenLabs
|
||||
### OpenAI utama dengan cadangan ElevenLabs
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -176,7 +175,33 @@ Skema lengkap ada di [Konfigurasi Gateway](/id/gateway/configuration).
|
||||
}
|
||||
```
|
||||
|
||||
### Nonaktifkan speech Microsoft
|
||||
### Google Gemini utama
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
tts: {
|
||||
auto: "always",
|
||||
provider: "google",
|
||||
providers: {
|
||||
google: {
|
||||
apiKey: "gemini_api_key",
|
||||
model: "gemini-3.1-flash-tts-preview",
|
||||
voiceName: "Kore",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Google Gemini TTS menggunakan jalur API key Gemini. API key Google Cloud Console
|
||||
yang dibatasi untuk Gemini API valid di sini, dan ini adalah jenis key yang sama
|
||||
yang digunakan oleh penyedia pembuatan gambar Google bawaan. Urutan resolusinya adalah
|
||||
`messages.tts.providers.google.apiKey` -> `models.providers.google.apiKey` ->
|
||||
`GEMINI_API_KEY` -> `GOOGLE_API_KEY`.
|
||||
|
||||
### Menonaktifkan speech Microsoft
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -192,7 +217,7 @@ Skema lengkap ada di [Konfigurasi Gateway](/id/gateway/configuration).
|
||||
}
|
||||
```
|
||||
|
||||
### Batas kustom + path prefs
|
||||
### Batas khusus + jalur prefs
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -219,7 +244,7 @@ Skema lengkap ada di [Konfigurasi Gateway](/id/gateway/configuration).
|
||||
}
|
||||
```
|
||||
|
||||
### Nonaktifkan ringkasan otomatis untuk balasan panjang
|
||||
### Menonaktifkan ringkasan otomatis untuk balasan panjang
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -243,57 +268,61 @@ Lalu jalankan:
|
||||
- `inbound` hanya mengirim audio setelah pesan suara masuk.
|
||||
- `tagged` hanya mengirim audio saat balasan menyertakan directive `[[tts:key=value]]` atau blok `[[tts:text]]...[[/tts:text]]`.
|
||||
- `enabled`: toggle lama (doctor memigrasikan ini ke `auto`).
|
||||
- `mode`: `"final"` (default) atau `"all"` (termasuk balasan alat/blok).
|
||||
- `provider`: id provider speech seperti `"elevenlabs"`, `"microsoft"`, `"minimax"`, atau `"openai"` (fallback otomatis).
|
||||
- Jika `provider` **tidak disetel**, OpenClaw menggunakan provider speech pertama yang dikonfigurasi sesuai urutan auto-select registri.
|
||||
- `provider: "edge"` lama tetap berfungsi dan dinormalisasi ke `microsoft`.
|
||||
- `mode`: `"final"` (default) atau `"all"` (termasuk balasan tool/blok).
|
||||
- `provider`: id penyedia speech seperti `"elevenlabs"`, `"google"`, `"microsoft"`, `"minimax"`, atau `"openai"` (cadangan bersifat otomatis).
|
||||
- Jika `provider` **tidak disetel**, OpenClaw menggunakan penyedia speech pertama yang dikonfigurasi dalam urutan pemilihan otomatis registry.
|
||||
- `provider: "edge"` lama masih berfungsi dan dinormalisasi menjadi `microsoft`.
|
||||
- `summaryModel`: model murah opsional untuk ringkasan otomatis; default ke `agents.defaults.model.primary`.
|
||||
- Menerima `provider/model` atau alias model yang dikonfigurasi.
|
||||
- `modelOverrides`: izinkan model memancarkan directive TTS (aktif secara default).
|
||||
- `allowProvider` default ke `false` (peralihan provider bersifat opt-in).
|
||||
- `providers.<id>`: pengaturan milik provider yang dikunci dengan id provider speech.
|
||||
- Blok provider langsung lama (`messages.tts.openai`, `messages.tts.elevenlabs`, `messages.tts.microsoft`, `messages.tts.edge`) dimigrasikan otomatis ke `messages.tts.providers.<id>` saat dimuat.
|
||||
- `maxTextLength`: batas keras untuk input TTS (karakter). `/tts audio` gagal jika terlampaui.
|
||||
- `timeoutMs`: timeout permintaan (md).
|
||||
- `prefsPath`: timpa path JSON prefs lokal (provider/batas/ringkasan).
|
||||
- Nilai `apiKey` fallback ke env var (`ELEVENLABS_API_KEY`/`XI_API_KEY`, `MINIMAX_API_KEY`, `OPENAI_API_KEY`).
|
||||
- `providers.elevenlabs.baseUrl`: timpa base URL API ElevenLabs.
|
||||
- `providers.openai.baseUrl`: timpa endpoint OpenAI TTS.
|
||||
- `modelOverrides`: izinkan model mengeluarkan directive TTS (aktif secara default).
|
||||
- `allowProvider` default ke `false` (peralihan penyedia bersifat opt-in).
|
||||
- `providers.<id>`: pengaturan milik penyedia yang dikunci dengan id penyedia speech.
|
||||
- Blok penyedia langsung lama (`messages.tts.openai`, `messages.tts.elevenlabs`, `messages.tts.microsoft`, `messages.tts.edge`) dimigrasikan otomatis ke `messages.tts.providers.<id>` saat dimuat.
|
||||
- `maxTextLength`: batas keras untuk input TTS (karakter). `/tts audio` gagal jika melebihi batas.
|
||||
- `timeoutMs`: batas waktu permintaan (ms).
|
||||
- `prefsPath`: ganti jalur JSON prefs lokal (penyedia/batas/ringkasan).
|
||||
- Nilai `apiKey` menggunakan fallback ke env vars (`ELEVENLABS_API_KEY`/`XI_API_KEY`, `GEMINI_API_KEY`/`GOOGLE_API_KEY`, `MINIMAX_API_KEY`, `OPENAI_API_KEY`).
|
||||
- `providers.elevenlabs.baseUrl`: ganti base URL API ElevenLabs.
|
||||
- `providers.openai.baseUrl`: ganti endpoint OpenAI TTS.
|
||||
- Urutan resolusi: `messages.tts.providers.openai.baseUrl` -> `OPENAI_TTS_BASE_URL` -> `https://api.openai.com/v1`
|
||||
- Nilai non-default diperlakukan sebagai endpoint TTS yang kompatibel dengan OpenAI, sehingga nama model dan suara kustom diterima.
|
||||
- Nilai non-default diperlakukan sebagai endpoint TTS yang kompatibel dengan OpenAI, sehingga nama model dan voice khusus diterima.
|
||||
- `providers.elevenlabs.voiceSettings`:
|
||||
- `stability`, `similarityBoost`, `style`: `0..1`
|
||||
- `useSpeakerBoost`: `true|false`
|
||||
- `speed`: `0.5..2.0` (1.0 = normal)
|
||||
- `providers.elevenlabs.applyTextNormalization`: `auto|on|off`
|
||||
- `providers.elevenlabs.languageCode`: ISO 639-1 2 huruf (misalnya `en`, `de`)
|
||||
- `providers.elevenlabs.seed`: integer `0..4294967295` (determinisme best-effort)
|
||||
- `providers.minimax.baseUrl`: timpa base URL API MiniMax (default `https://api.minimax.io`, env: `MINIMAX_API_HOST`).
|
||||
- `providers.elevenlabs.languageCode`: ISO 639-1 2 huruf (mis. `en`, `de`)
|
||||
- `providers.elevenlabs.seed`: bilangan bulat `0..4294967295` (determinisme upaya terbaik)
|
||||
- `providers.minimax.baseUrl`: ganti base URL API MiniMax (default `https://api.minimax.io`, env: `MINIMAX_API_HOST`).
|
||||
- `providers.minimax.model`: model TTS (default `speech-2.8-hd`, env: `MINIMAX_TTS_MODEL`).
|
||||
- `providers.minimax.voiceId`: pengenal suara (default `English_expressive_narrator`, env: `MINIMAX_TTS_VOICE_ID`).
|
||||
- `providers.minimax.voiceId`: pengenal voice (default `English_expressive_narrator`, env: `MINIMAX_TTS_VOICE_ID`).
|
||||
- `providers.minimax.speed`: kecepatan pemutaran `0.5..2.0` (default 1.0).
|
||||
- `providers.minimax.vol`: volume `(0, 10]` (default 1.0; harus lebih besar dari 0).
|
||||
- `providers.minimax.pitch`: pergeseran pitch `-12..12` (default 0).
|
||||
- `providers.google.model`: model TTS Gemini (default `gemini-3.1-flash-tts-preview`).
|
||||
- `providers.google.voiceName`: nama voice bawaan Gemini (default `Kore`; `voice` juga diterima).
|
||||
- `providers.google.baseUrl`: ganti base URL API Gemini. Hanya `https://generativelanguage.googleapis.com` yang diterima.
|
||||
- Jika `messages.tts.providers.google.apiKey` dihilangkan, TTS dapat menggunakan kembali `models.providers.google.apiKey` sebelum fallback ke env.
|
||||
- `providers.microsoft.enabled`: izinkan penggunaan speech Microsoft (default `true`; tanpa API key).
|
||||
- `providers.microsoft.voice`: nama suara neural Microsoft (misalnya `en-US-MichelleNeural`).
|
||||
- `providers.microsoft.lang`: kode bahasa (misalnya `en-US`).
|
||||
- `providers.microsoft.outputFormat`: format output Microsoft (misalnya `audio-24khz-48kbitrate-mono-mp3`).
|
||||
- `providers.microsoft.voice`: nama voice neural Microsoft (mis. `en-US-MichelleNeural`).
|
||||
- `providers.microsoft.lang`: kode bahasa (mis. `en-US`).
|
||||
- `providers.microsoft.outputFormat`: format output Microsoft (mis. `audio-24khz-48kbitrate-mono-mp3`).
|
||||
- Lihat format output Microsoft Speech untuk nilai yang valid; tidak semua format didukung oleh transport bawaan berbasis Edge.
|
||||
- `providers.microsoft.rate` / `providers.microsoft.pitch` / `providers.microsoft.volume`: string persen (misalnya `+10%`, `-5%`).
|
||||
- `providers.microsoft.saveSubtitles`: tulis subtitle JSON di samping berkas audio.
|
||||
- `providers.microsoft.rate` / `providers.microsoft.pitch` / `providers.microsoft.volume`: string persentase (mis. `+10%`, `-5%`).
|
||||
- `providers.microsoft.saveSubtitles`: tulis subtitle JSON di samping file audio.
|
||||
- `providers.microsoft.proxy`: URL proxy untuk permintaan speech Microsoft.
|
||||
- `providers.microsoft.timeoutMs`: override timeout permintaan (md).
|
||||
- `providers.microsoft.timeoutMs`: ganti batas waktu permintaan (ms).
|
||||
- `edge.*`: alias lama untuk pengaturan Microsoft yang sama.
|
||||
|
||||
## Override yang digerakkan model (aktif secara default)
|
||||
## Override berbasis model (aktif secara default)
|
||||
|
||||
Secara default, model **dapat** memancarkan directive TTS untuk satu balasan.
|
||||
Saat `messages.tts.auto` adalah `tagged`, directive ini wajib untuk memicu audio.
|
||||
Secara default, model **dapat** mengeluarkan directive TTS untuk satu balasan.
|
||||
Saat `messages.tts.auto` adalah `tagged`, directive ini diperlukan untuk memicu audio.
|
||||
|
||||
Saat diaktifkan, model dapat memancarkan directive `[[tts:...]]` untuk menimpa suara
|
||||
untuk satu balasan, ditambah blok `[[tts:text]]...[[/tts:text]]` opsional untuk
|
||||
menyediakan tag ekspresif (tawa, isyarat bernyanyi, dll.) yang seharusnya hanya muncul
|
||||
di audio.
|
||||
Saat diaktifkan, model dapat mengeluarkan directive `[[tts:...]]` untuk mengganti voice
|
||||
untuk satu balasan, ditambah blok opsional `[[tts:text]]...[[/tts:text]]` untuk
|
||||
memberikan tag ekspresif (tawa, isyarat bernyanyi, dll.) yang seharusnya hanya muncul dalam
|
||||
audio.
|
||||
|
||||
Directive `provider=...` diabaikan kecuali `modelOverrides.allowProvider: true`.
|
||||
|
||||
@ -306,11 +335,11 @@ Ini dia.
|
||||
[[tts:text]](tertawa) Bacakan lagunya sekali lagi.[[/tts:text]]
|
||||
```
|
||||
|
||||
Key directive yang tersedia (saat diaktifkan):
|
||||
Kunci directive yang tersedia (saat diaktifkan):
|
||||
|
||||
- `provider` (id provider speech yang terdaftar, misalnya `openai`, `elevenlabs`, `minimax`, atau `microsoft`; memerlukan `allowProvider: true`)
|
||||
- `voice` (suara OpenAI) atau `voiceId` (ElevenLabs / MiniMax)
|
||||
- `model` (model TTS OpenAI, id model ElevenLabs, atau model MiniMax)
|
||||
- `provider` (id penyedia speech terdaftar, misalnya `openai`, `elevenlabs`, `google`, `minimax`, atau `microsoft`; memerlukan `allowProvider: true`)
|
||||
- `voice` (voice OpenAI), `voiceName` / `voice_name` / `google_voice` (voice Google), atau `voiceId` (ElevenLabs / MiniMax)
|
||||
- `model` (model TTS OpenAI, id model ElevenLabs, atau model MiniMax) atau `google_model` (model TTS Google)
|
||||
- `stability`, `similarityBoost`, `style`, `speed`, `useSpeakerBoost`
|
||||
- `vol` / `volume` (volume MiniMax, 0-10)
|
||||
- `pitch` (pitch MiniMax, -12 hingga 12)
|
||||
@ -332,7 +361,7 @@ Nonaktifkan semua override model:
|
||||
}
|
||||
```
|
||||
|
||||
Allowlist opsional (aktifkan peralihan provider sambil menjaga knob lain tetap dapat dikonfigurasi):
|
||||
Allowlist opsional (aktifkan peralihan penyedia sambil tetap menjaga knob lain dapat dikonfigurasi):
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -350,8 +379,8 @@ Allowlist opsional (aktifkan peralihan provider sambil menjaga knob lain tetap d
|
||||
|
||||
## Preferensi per pengguna
|
||||
|
||||
Perintah slash menulis override lokal ke `prefsPath` (default:
|
||||
`~/.openclaw/settings/tts.json`, timpa dengan `OPENCLAW_TTS_PREFS` atau
|
||||
Slash command menulis override lokal ke `prefsPath` (default:
|
||||
`~/.openclaw/settings/tts.json`, ganti dengan `OPENCLAW_TTS_PREFS` atau
|
||||
`messages.tts.prefsPath`).
|
||||
|
||||
Field yang disimpan:
|
||||
@ -361,23 +390,24 @@ Field yang disimpan:
|
||||
- `maxLength` (ambang ringkasan; default 1500 karakter)
|
||||
- `summarize` (default `true`)
|
||||
|
||||
Field ini menimpa `messages.tts.*` untuk host tersebut.
|
||||
Ini menimpa `messages.tts.*` untuk host tersebut.
|
||||
|
||||
## Format output (tetap)
|
||||
|
||||
- **Feishu / Matrix / Telegram / WhatsApp**: pesan suara Opus (`opus_48000_64` dari ElevenLabs, `opus` dari OpenAI).
|
||||
- 48kHz / 64kbps adalah kompromi yang baik untuk pesan suara.
|
||||
- **Channel lain**: MP3 (`mp3_44100_128` dari ElevenLabs, `mp3` dari OpenAI).
|
||||
- **Saluran lain**: MP3 (`mp3_44100_128` dari ElevenLabs, `mp3` dari OpenAI).
|
||||
- 44.1kHz / 128kbps adalah keseimbangan default untuk kejernihan ucapan.
|
||||
- **MiniMax**: MP3 (model `speech-2.8-hd`, sample rate 32kHz). Format catatan suara tidak didukung secara native; gunakan OpenAI atau ElevenLabs untuk pesan suara Opus yang terjamin.
|
||||
- **Google Gemini**: Gemini API TTS mengembalikan PCM 24kHz mentah. OpenClaw membungkusnya sebagai WAV untuk lampiran audio dan mengembalikan PCM secara langsung untuk Talk/telephony. Format catatan suara Opus native tidak didukung oleh jalur ini.
|
||||
- **Microsoft**: menggunakan `microsoft.outputFormat` (default `audio-24khz-48kbitrate-mono-mp3`).
|
||||
- Transport bawaan menerima `outputFormat`, tetapi tidak semua format tersedia dari layanan.
|
||||
- Transport bawaan menerima `outputFormat`, tetapi tidak semua format tersedia dari layanan tersebut.
|
||||
- Nilai format output mengikuti format output Microsoft Speech (termasuk Ogg/WebM Opus).
|
||||
- `sendVoice` Telegram menerima OGG/MP3/M4A; gunakan OpenAI/ElevenLabs jika Anda memerlukan
|
||||
- Telegram `sendVoice` menerima OGG/MP3/M4A; gunakan OpenAI/ElevenLabs jika Anda memerlukan
|
||||
pesan suara Opus yang terjamin.
|
||||
- Jika format output Microsoft yang dikonfigurasi gagal, OpenClaw mencoba ulang dengan MP3.
|
||||
- Jika format output Microsoft yang dikonfigurasi gagal, OpenClaw akan mencoba lagi dengan MP3.
|
||||
|
||||
Format output OpenAI/ElevenLabs bersifat tetap per channel (lihat di atas).
|
||||
Format output OpenAI/ElevenLabs tetap per saluran (lihat di atas).
|
||||
|
||||
## Perilaku auto-TTS
|
||||
|
||||
@ -385,7 +415,7 @@ Saat diaktifkan, OpenClaw:
|
||||
|
||||
- melewati TTS jika balasan sudah berisi media atau directive `MEDIA:`.
|
||||
- melewati balasan yang sangat pendek (< 10 karakter).
|
||||
- merangkum balasan panjang saat diaktifkan menggunakan `agents.defaults.model.primary` (atau `summaryModel`).
|
||||
- meringkas balasan panjang saat diaktifkan menggunakan `agents.defaults.model.primary` (atau `summaryModel`).
|
||||
- melampirkan audio yang dihasilkan ke balasan.
|
||||
|
||||
Jika balasan melebihi `maxLength` dan ringkasan nonaktif (atau tidak ada API key untuk
|
||||
@ -397,19 +427,19 @@ dilewati dan balasan teks normal dikirim.
|
||||
```
|
||||
Balasan -> TTS diaktifkan?
|
||||
tidak -> kirim teks
|
||||
ya -> ada media / MEDIA: / pendek?
|
||||
ya -> kirim teks
|
||||
tidak -> panjang > batas?
|
||||
tidak -> TTS -> lampirkan audio
|
||||
ya -> ringkasan diaktifkan?
|
||||
tidak -> kirim teks
|
||||
ya -> ringkas (summaryModel atau agents.defaults.model.primary)
|
||||
ya -> ada media / MEDIA: / pendek?
|
||||
ya -> kirim teks
|
||||
tidak -> panjang > batas?
|
||||
tidak -> TTS -> lampirkan audio
|
||||
ya -> ringkasan diaktifkan?
|
||||
tidak -> kirim teks
|
||||
ya -> ringkas (summaryModel atau agents.defaults.model.primary)
|
||||
-> TTS -> lampirkan audio
|
||||
```
|
||||
|
||||
## Penggunaan perintah slash
|
||||
## Penggunaan slash command
|
||||
|
||||
Ada satu perintah: `/tts`.
|
||||
Hanya ada satu perintah: `/tts`.
|
||||
Lihat [Slash commands](/id/tools/slash-commands) untuk detail pengaktifannya.
|
||||
|
||||
Catatan Discord: `/tts` adalah perintah bawaan Discord, jadi OpenClaw mendaftarkan
|
||||
@ -427,24 +457,24 @@ Catatan Discord: `/tts` adalah perintah bawaan Discord, jadi OpenClaw mendaftark
|
||||
|
||||
Catatan:
|
||||
|
||||
- Perintah memerlukan pengirim yang berwenang (aturan allowlist/owner tetap berlaku).
|
||||
- Perintah memerlukan pengirim yang diotorisasi (aturan allowlist/owner tetap berlaku).
|
||||
- `commands.text` atau pendaftaran perintah native harus diaktifkan.
|
||||
- Config `messages.tts.auto` menerima `off|always|inbound|tagged`.
|
||||
- `/tts on` menulis preferensi TTS lokal ke `always`; `/tts off` menulisnya ke `off`.
|
||||
- Gunakan config jika Anda menginginkan default `inbound` atau `tagged`.
|
||||
- `limit` dan `summary` disimpan di prefs lokal, bukan config utama.
|
||||
- Konfigurasi `messages.tts.auto` menerima `off|always|inbound|tagged`.
|
||||
- `/tts on` menulis preferensi TTS lokal menjadi `always`; `/tts off` menulisnya menjadi `off`.
|
||||
- Gunakan konfigurasi jika Anda menginginkan default `inbound` atau `tagged`.
|
||||
- `limit` dan `summary` disimpan di prefs lokal, bukan konfigurasi utama.
|
||||
- `/tts audio` menghasilkan balasan audio sekali pakai (tidak mengaktifkan TTS).
|
||||
- `/tts status` menyertakan visibilitas fallback untuk percobaan terbaru:
|
||||
- `/tts status` mencakup visibilitas fallback untuk percobaan terbaru:
|
||||
- fallback berhasil: `Fallback: <primary> -> <used>` plus `Attempts: ...`
|
||||
- kegagalan: `Error: ...` plus `Attempts: ...`
|
||||
- diagnostik rinci: `Attempt details: provider:outcome(reasonCode) latency`
|
||||
- Kegagalan API OpenAI dan ElevenLabs kini menyertakan detail galat provider yang telah di-parse dan request id (saat dikembalikan oleh provider), yang ditampilkan dalam galat/log TTS.
|
||||
- gagal: `Error: ...` plus `Attempts: ...`
|
||||
- diagnostik terperinci: `Attempt details: provider:outcome(reasonCode) latency`
|
||||
- Kegagalan API OpenAI dan ElevenLabs sekarang menyertakan detail error penyedia yang sudah diurai dan request id (saat dikembalikan oleh penyedia), yang ditampilkan dalam error/log TTS.
|
||||
|
||||
## Alat agen
|
||||
## Tool agen
|
||||
|
||||
Alat `tts` mengubah teks menjadi ucapan dan mengembalikan lampiran audio untuk
|
||||
pengiriman balasan. Saat channel adalah Feishu, Matrix, Telegram, atau WhatsApp,
|
||||
audio dikirim sebagai pesan suara, bukan sebagai lampiran berkas.
|
||||
Tool `tts` mengonversi teks menjadi ucapan dan mengembalikan lampiran audio untuk
|
||||
pengiriman balasan. Saat salurannya adalah Feishu, Matrix, Telegram, atau WhatsApp,
|
||||
audio dikirim sebagai pesan suara, bukan lampiran file.
|
||||
|
||||
## Gateway RPC
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user