whatsapp-group-summary 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,395 @@
1
+ # ๐Ÿค– WhatsApp Group Summary Bot
2
+
3
+ ![Logo](logo.jpg)
4
+
5
+ > Bot ringkasan grup WhatsApp untuk **Hermes Agent** โ€” merekam **semua** chat anggota grup secara diam-diam dan mengirim ringkasan terstruktur **2x sehari** (07:00 & 23:00 WIB) dengan bahasa Indonesia santai.
6
+
7
+ <p align="center">
8
+ <img src="https://img.shields.io/badge/Hermes-Agent-6C5CE7?style=flat-square" alt="Hermes Agent">
9
+ <img src="https://img.shields.io/badge/Platform-WhatsApp-25D366?style=flat-square&logo=whatsapp" alt="WhatsApp">
10
+ <img src="https://img.shields.io/badge/License-MIT-green?style=flat-square" alt="MIT License">
11
+ <img src="https://img.shields.io/badge/Language-ID-santai-orange?style=flat-square" alt="Bahasa Indonesia">
12
+ </p>
13
+
14
+ ---
15
+
16
+ ## โœจ Fitur
17
+
18
+ | Fitur | Deskripsi |
19
+ |-------|-----------|
20
+ | ๐Ÿ“ **Rekam Semua Chat** | Seluruh pesan dari **semua** anggota grup direkam ke JSONL โ€” bukan cuma user whitelist |
21
+ | ๐Ÿคซ **Silent Recording** | Bot tidak merespon chat biasa. Hanya aktif saat di-@mention atau ada perintah `/` |
22
+ | ๐Ÿ“Š **Summary 2x Sehari** | Pagi (07:00 WIB) & malam (23:00 WIB) โ€” format terstruktur, padat, informatif |
23
+ | ๐Ÿ”ฅ **Mode Roast** | Opsional โ€” versi sarkas & lucu dari ringkasan buat suasana grup lebih hidup |
24
+ | ๐Ÿ‡ฎ๐Ÿ‡ฉ **Casual Indonesian** | Gaya bahasa santai (gw/lo), bukan formal โ€” cocok buat grup pertemanan |
25
+ | ๐Ÿ”— **Auto-detect Links** | Semua URL yang di-share otomatis tercantum di section Link-link |
26
+ | ๐Ÿ“‹ **Action Tracking** | Follow-up items & pertanyaan terbuka dicatat biar ga ada yang kelewat |
27
+
28
+ ---
29
+
30
+ ## ๐Ÿ“Š Contoh Output
31
+
32
+ ### Mode Normal
33
+ ```
34
+ *Summary General โ€” 12 jam terakhir*
35
+ - *Inti Diskusi*
36
+ - Ngobrolin tools AI: GPT 5.6 Sol, Codex, Claude vs ChatGPT 5 buat slicing UI
37
+ - Sharing repo token saver: oh-my-pi dari Nado dan paleo dari mmoaa
38
+ - Diskusi akses remote: Tailscale vs NetBird
39
+ - Info event Lovable + temp mail smailpro buat klaim kredit
40
+ - *Keputusan*
41
+ - Tidak ada keputusan formal.
42
+ - *Follow-up / Action*
43
+ - Pen?: cek detail deploy error
44
+ - Yanda Nooryuda: cek member/top hari ini
45
+ - mmoaa: minta stars buat repo paleo
46
+ - *Pertanyaan Terbuka*
47
+ - API Gmaps berbayar atau gratis?
48
+ - Sol udah masuk Codex official belum?
49
+ - Mending Tailscale atau NetBird buat remote?
50
+ - *Link-link*
51
+ - Nado: oh-my-pi token saver โ€” github.com/Fernado03/oh-my-pi-supreme-token-saver
52
+ - mmoaa: paleo token saver โ€” github.com/mocasus/paleo
53
+ - ไฝ ็ฎ—ๅ“ชๅ—ๅฐ้ฅผๅนฒ๏ผŸ: bluk-cf auto CF โ€” github.com/iAm-182/bluk-cf
54
+ ```
55
+
56
+ ### Mode Roast ๐Ÿ”ฅ
57
+ ```
58
+ *Summary Roast โ€” 12 jam terakhir ๐Ÿ”ฅ*
59
+ - *Yang Paling Nyablak*
60
+ - DickySusanto gas terus nanya Sol mulu, udah kayak sales GPT
61
+ - Pen? classic โ€” deploy error done tapi ga dicek
62
+ - *Drama & Perdebatan*
63
+ - Tailscale vs NetBird debat ga kelar-kelar, pada mau jadi superhero remote akses
64
+ - *Receh Tapi Menghibur*
65
+ - Azhar share link invite grup ke-15 kali ini
66
+ - *Keputusan (yg akhirnya diambil setelah debat panjang)*
67
+ - Ga ada. Seperti biasa.
68
+ - *PR Yang Belum Kelar*
69
+ - Pen?: deploy error masih menggantung
70
+ - Yanda: member check masih waiting
71
+ - *Pertanyaan Nyangkut*
72
+ - Gmaps bayar apa gratis? udah 3 hari ini pertanyaan yg sama
73
+ - *Link Berserakan*
74
+ - Nado: token saver โ€” github.com/Fernado03/oh-my-pi-supreme-token-saver
75
+ ```
76
+
77
+ ---
78
+
79
+ ## ๐Ÿ—๏ธ Arsitektur
80
+
81
+ ```
82
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
83
+ โ”‚ WhatsApp Group โ”‚
84
+ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ” โ”‚
85
+ โ”‚ โ”‚User1โ”‚ โ”‚User2โ”‚ โ”‚User3โ”‚ โ”‚UserNโ”‚ ... โ”‚
86
+ โ”‚ โ””โ”€โ”€โ”ฌโ”€โ”€โ”˜ โ””โ”€โ”€โ”ฌโ”€โ”€โ”˜ โ””โ”€โ”€โ”ฌโ”€โ”€โ”˜ โ””โ”€โ”€โ”ฌโ”€โ”€โ”˜ โ”‚
87
+ โ””โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
88
+ โ”‚ โ”‚ โ”‚ โ”‚
89
+ โ–ผ โ–ผ โ–ผ โ–ผ
90
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
91
+ โ”‚ Baileys Bridge (Node.js) โ”‚
92
+ โ”‚ bridge.js โ€” !isGroup skip allowlistโ”‚ โ—„โ”€โ”€ Patch A
93
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
94
+ โ”‚
95
+ โ–ผ
96
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
97
+ โ”‚ Python Adapter (Hermes) โ”‚
98
+ โ”‚ whatsapp_common.py โ€” no allowlist โ”‚ โ—„โ”€โ”€ Patch B
99
+ โ”‚ adapter.py โ€” _record_group_msg() โ”‚ โ—„โ”€โ”€ Patch C
100
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
101
+ โ”‚ โ”‚
102
+ โ–ผ โ–ผ
103
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
104
+ โ”‚ JSONL Logs โ”‚ โ”‚ Agent Response โ”‚
105
+ โ”‚ group_logs/ โ”‚ โ”‚ (only @mention) โ”‚
106
+ โ”‚ <id>.jsonl โ”‚ โ”‚ โ”‚
107
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
108
+ โ”‚
109
+ โ–ผ
110
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
111
+ โ”‚ Cron Jobs (2x daily) โ”‚
112
+ โ”‚ 07:00 WIB โ€” Morning Summary โ”‚
113
+ โ”‚ 23:00 WIB โ€” Evening Summary โ”‚
114
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
115
+ โ”‚
116
+ โ–ผ
117
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
118
+ โ”‚ WhatsApp Group โ”‚
119
+ โ”‚ (clean output)โ”‚
120
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
121
+ ```
122
+
123
+ ---
124
+
125
+ ## ๐Ÿ“ฆ Instalasi
126
+
127
+ ### Prasyarat
128
+
129
+ - **[Hermes Agent](https://github.com/NousResearch/hermes-agent)** terinstall & WhatsApp gateway berjalan
130
+ - **Akses terminal/SSH** ke server Hermes
131
+ - **Hermes sudah di-invite** ke grup WhatsApp target
132
+ - `git`, `curl`, `python3` tersedia
133
+
134
+ ---
135
+
136
+ ### Step 1: Install Skill
137
+
138
+ ```bash
139
+ # Via npx (recommended)
140
+ npx github:mocasus/whatsapp-group-summary
141
+
142
+ # Atau via hermes skills install
143
+ hermes skills install https://raw.githubusercontent.com/mocasus/whatsapp-group-summary/main/SKILL.md
144
+
145
+ # Atau manual git clone
146
+ git clone https://github.com/mocasus/whatsapp-group-summary.git ~/.hermes/skills/whatsapp-group-summary-bot
147
+ ```
148
+
149
+ ---
150
+
151
+ ### Step 2: Patch Source Files
152
+
153
+ > โš ๏ธ **PENTING:** Patch akan **hilang setiap `hermes update`**. Simpan repo ini dan re-apply setelah update. Gunakan skill `whatsapp-group-summary-bot` untuk auto-detect dan re-apply.
154
+
155
+ #### Patch A โ€” Bridge (`bridge.js`)
156
+
157
+ **File:** `~/.hermes/hermes-agent/scripts/whatsapp-bridge/bridge.js`
158
+ **Line:** ~637
159
+
160
+ ```diff
161
+ - if (WHATSAPP_DM_POLICY !== 'pairing' && !matchesAllowedUser(senderId, ALLOWED_USERS, SESSION_DIR)) {
162
+ + if (!isGroup && WHATSAPP_DM_POLICY !== 'pairing' && !matchesAllowedUser(senderId, ALLOWED_USERS, SESSION_DIR)) {
163
+ ```
164
+
165
+ **Efek:** Bridge meneruskan pesan dari **semua** anggota grup, bukan cuma user whitelist.
166
+
167
+ ---
168
+
169
+ #### Patch B โ€” Adapter Logic (`whatsapp_common.py`)
170
+
171
+ **File:** `~/.hermes/hermes-agent/gateway/platforms/whatsapp_common.py`
172
+ **Line:** ~361-365
173
+
174
+ ```diff
175
+ - # Only respond to whitelisted senders in groups
176
+ - if self._allow_from:
177
+ - sender_id = str(data.get("senderId") or ...)
178
+ - if sender_id and not self._matches_whatsapp_allowlist(...):
179
+ - return False
180
+ + # NOTE: patched โ€” allowlist check skipped for groups.
181
+ + # Only DMs are gated by WHATSAPP_ALLOWED_USERS.
182
+ ```
183
+
184
+ **Efek:** Python adapter tidak memfilter pesan grup berdasarkan whitelist.
185
+
186
+ ---
187
+
188
+ #### Patch C โ€” Silent Recorder (`adapter.py`)
189
+
190
+ **File:** `~/.hermes/hermes-agent/plugins/platforms/whatsapp/adapter.py`
191
+
192
+ **Tambahkan method** sebelum `_build_message_event` (~line 1341):
193
+
194
+ ```python
195
+ def _record_group_message_sync(self, data):
196
+ """Record all group messages to JSONL for cron summary (non-blocking)."""
197
+ try:
198
+ import json, os
199
+ chat_id = str(data.get("chatId") or "")
200
+ if not chat_id.endswith("@g.us"):
201
+ return
202
+ body = str(data.get("body") or "").strip()
203
+ if not body:
204
+ return
205
+ log_dir = os.path.expanduser("~/.hermes/platforms/whatsapp/group_logs")
206
+ os.makedirs(log_dir, exist_ok=True)
207
+ log_file = os.path.join(log_dir, f"{chat_id}.jsonl")
208
+ entry = {
209
+ "ts": data.get("timestamp", 0),
210
+ "sender": str(data.get("senderName") or data.get("senderId") or ""),
211
+ "body": body,
212
+ }
213
+ with open(log_file, "a") as f:
214
+ f.write(json.dumps(entry, ensure_ascii=False) + "\n")
215
+ except Exception:
216
+ pass # never block message processing on logging failure
217
+ ```
218
+
219
+ **Tambahkan di `_build_message_event`**, sebelum `if not self._should_process_message(data):`
220
+
221
+ ```python
222
+ # PATCHED: Record all group messages for cron summary
223
+ if data.get("isGroup", False):
224
+ self._record_group_message_sync(data)
225
+ ```
226
+
227
+ **Efek:** Setiap pesan grup ditulis ke file JSONL tanpa mengganggu processing normal.
228
+
229
+ ---
230
+
231
+ ### Step 3: Environment Variable
232
+
233
+ Tambahkan ke environment config Hermes:
234
+
235
+ ```bash
236
+ # Require @mention for bot response in groups (messages still recorded)
237
+ WHATSAPP_REQUIRE_MENTION=true
238
+ ```
239
+
240
+ ---
241
+
242
+ ### Step 4: Restart Gateway
243
+
244
+ ```bash
245
+ hermes gateway restart
246
+ ```
247
+
248
+ > ๐Ÿ’ก Jika restart dari dalam gateway diblokir, jalankan dari **terminal SSH terpisah**.
249
+
250
+ ---
251
+
252
+ ### Step 5: Verifikasi
253
+
254
+ Kirim **satu pesan test** di grup WhatsApp mana pun, lalu:
255
+
256
+ ```bash
257
+ # Cek file log per grup
258
+ ls -la ~/.hermes/platforms/whatsapp/group_logs/
259
+
260
+ # Lihat isi log (ganti <chat_id> dgn ID grup)
261
+ cat ~/.hermes/platforms/whatsapp/group_logs/<chat_id>@g.us.jsonl | tail -5
262
+ ```
263
+
264
+ Harusnya muncul pesan test tadi dengan format JSON:
265
+ ```json
266
+ {"ts": 1783736100, "sender": "Nama Kamu", "body": "test"}
267
+ ```
268
+
269
+ ---
270
+
271
+ ### Step 6: Setup Cron Jobs
272
+
273
+ #### 6a. Dapatkan Group ID
274
+
275
+ Tag Hermes di grup target: **"apa id grup ini?"**
276
+ Hermes akan membalas dengan format `` `123456789@g.us` ``
277
+
278
+ #### 6b. Buat Cron Jobs via Hermes
279
+
280
+ ```
281
+ Morning: schedule = 0 0 * * * (07:00 WIB)
282
+ Evening: schedule = 0 16 * * * (23:00 WIB)
283
+ Deliver: whatsapp:<chat_id>@g.us
284
+ ```
285
+
286
+ **Prompt Normal:**
287
+ ```
288
+ Kamu adalah bot ringkasan. HANYA OUTPUT RINGKASAN. Baca ~/.hermes/platforms/whatsapp/group_logs/<CHAT_ID>.jsonl, filter 12 jam (ts=UNIX timestamp). TANPA blank line:
289
+
290
+ *Summary General โ€” 12 jam terakhir*
291
+ - *Inti Diskusi*
292
+ - [rangkum per topik, gabungin chat mirip]
293
+ - *Keputusan*
294
+ - [keputusan atau "Tidak ada keputusan formal."]
295
+ - *Follow-up / Action*
296
+ - [Nama]: [action]
297
+ - *Pertanyaan Terbuka*
298
+ - [pertanyaan]
299
+ - *Link-link*
300
+ - [Nama]: [desc] โ€” [URL]
301
+
302
+ ATURAN: No metadata, no blank line, no job info. HANYA ringkasan. Nama dari field "sender". Bahasa Indonesia santai.
303
+ ```
304
+
305
+ ---
306
+
307
+ ## ๐Ÿ”ฅ Mode Roast
308
+
309
+ Untuk mengaktifkan versi sarkas/lucu, update prompt cron job dengan:
310
+
311
+ ```
312
+ Kamu adalah bot ringkasan versi ROAST. Gaya: sarkas, lucu, roasting anggota grup tapi tetap friendly โ€” kayak temen yg galak tapi sayang.
313
+
314
+ *Summary Roast โ€” 12 jam terakhir ๐Ÿ”ฅ*
315
+ - *Yang Paling Nyablak*
316
+ - [siapa paling rame + roast ringan]
317
+ - *Drama & Perdebatan*
318
+ - [topik panas + komentar sarkas]
319
+ - *Receh Tapi Menghibur*
320
+ - [chat random lucu/absurd]
321
+ - *Keputusan (yg akhirnya diambil setelah debat panjang)*
322
+ - [keputusan]
323
+ - *PR Yang Belum Kelar*
324
+ - [Nama]: [action + roast]
325
+ - *Pertanyaan Nyangkut*
326
+ - [pertanyaan + "ada yg bisa jawab ga nih?"]
327
+ - *Link Berserakan*
328
+ - [Nama]: [desc] โ€” [URL]
329
+
330
+ ATURAN: Roast friendly, bukan bully. No metadata, no blank line.
331
+ ```
332
+
333
+ Toggle via Hermes: **"ubah <nama_grup> ke mode roast"** / **"balikin <nama_grup> ke normal"**
334
+
335
+ ---
336
+
337
+ ## ๐Ÿ“ Struktur Repo
338
+
339
+ ```
340
+ whatsapp-group-summary/
341
+ โ”œโ”€โ”€ README.md โ† Kamu di sini
342
+ โ”œโ”€โ”€ logo.jpg โ† Logo bot
343
+ โ”œโ”€โ”€ SKILL.md โ† Skill utama (Hermes format)
344
+ โ””โ”€โ”€ references/
345
+ โ”œโ”€โ”€ bridge-api.md โ† WhatsApp bridge API reference
346
+ โ”œโ”€โ”€ record-all-group-messages.md โ† Recording architecture detail
347
+ โ”œโ”€โ”€ user-format-reference.md โ† Format referensi dari user
348
+ โ”œโ”€โ”€ verify-recording.md โ† Langkah verifikasi recording
349
+ โ”œโ”€โ”€ whatsapp-bridge-limitations.md โ† Batasan bridge WhatsApp
350
+ โ””โ”€โ”€ whatsapp-group-ids.md โ† Daftar ID grup yang di-manage
351
+ ```
352
+
353
+ ---
354
+
355
+ ## ๐Ÿ› ๏ธ Troubleshooting
356
+
357
+ | Gejala | Penyebab | Solusi |
358
+ |--------|----------|--------|
359
+ | `group_logs/` kosong | Patch A/B/C belum applied | Re-apply patch, restart gateway |
360
+ | Recording jalan tapi bot tetep respon | `WHATSAPP_REQUIRE_MENTION` belum di-set | Pastikan ada di `.env`, restart gateway |
361
+ | Cron output ada `Cronjob Response:...` | Normal โ€” hanya muncul di DM delivery | Delivery ke grup WhatsApp langsung clean |
362
+ | Patch hilang setelah `hermes update` | Update menimpa source | Re-apply patch A/B/C setiap update |
363
+ | `gateway restart` diblokir | Berjalan dari dalam session Hermes | Restart dari terminal SSH terpisah |
364
+ | Blank lines di output summary | Prompt kurang "TANPA blank line" | Update prompt โ€” tambahkan constraint |
365
+ | Bridge ga kirim pesan grup | `WHATSAPP_GROUP_POLICY` bukan `open` | Set `WHATSAPP_GROUP_POLICY=open` di `.env` |
366
+
367
+ ---
368
+
369
+ ## โšก Quick Re-Apply After Update
370
+
371
+ Setelah `hermes update`, jalankan:
372
+
373
+ ```bash
374
+ # Re-apply semua patch dari repo
375
+ cd ~/.hermes/skills/whatsapp-group-summary-bot
376
+ # Patch A: bridge.js
377
+ sed -i 's/if (WHATSAPP_DM_POLICY/if (!isGroup \&\& WHATSAPP_DM_POLICY/' \
378
+ ~/.hermes/hermes-agent/scripts/whatsapp-bridge/bridge.js
379
+ # Restart gateway
380
+ hermes gateway restart
381
+ ```
382
+
383
+ > Patch B & C perlu di-apply manual karena lebih kompleks. Cek `SKILL.md` untuk detail.
384
+
385
+ ---
386
+
387
+ ## ๐Ÿ“ License
388
+
389
+ MIT ยฉ [mocasus](https://github.com/mocasus)
390
+
391
+ ---
392
+
393
+ <p align="center">
394
+ <sub>Dibuat dengan โ˜• dan sedikit roasting ๐Ÿ”ฅ</sub>
395
+ </p>
package/SKILL.md ADDED
@@ -0,0 +1,227 @@
1
+ ---
2
+ name: whatsapp-group-summary-bot
3
+ description: Setup WhatsApp group summary bot โ€” records all messages silently via patched bridge+adapter, reads from JSONL logs, sends structured twice-daily summaries (07:00 & 23:00 WIB) in clean WhatsApp-friendly format (no metadata, no blank lines, casual Indonesian).
4
+ triggers:
5
+ - User wants auto-summary or "ringkasan" for WhatsApp group
6
+ - User shares WhatsApp group invite link with summary request
7
+ - User says "set summary" or "summary bot" in group/DM
8
+ ---
9
+
10
+ # WhatsApp Group Summary Bot
11
+
12
+ Two parts: **(A) message recording** via patched bridge/adapter โ†’ JSONL, **(B) cron jobs** that read JSONL and deliver summaries.
13
+
14
+ โš ๏ธ **Core patches required.** WhatsApp normally only forwards @mentioned or whitelisted-user messages. Three source files must be patched to record ALL messages silently. Patches WILL be overwritten on `hermes update` โ€” re-apply after updates.
15
+
16
+ ---
17
+
18
+ ## Part A: Message Recording (One-Time Setup)
19
+
20
+ ### A1. Bridge โ€” `bridge.js`
21
+
22
+ Patch: `Hermes `scripts/whatsapp-bridge/bridge.js`` ~line 637
23
+
24
+ **Before:**
25
+ ```js
26
+ if (WHATSAPP_DM_POLICY !== 'pairing' && !matchesAllowedUser(senderId, ALLOWED_USERS, SESSION_DIR)) {
27
+ ```
28
+ **After (add `!isGroup &&`):**
29
+ ```js
30
+ if (!isGroup && WHATSAPP_DM_POLICY !== 'pairing' && !matchesAllowedUser(senderId, ALLOWED_USERS, SESSION_DIR)) {
31
+ ```
32
+
33
+ ### A2. Adapter Logic โ€” `whatsapp_common.py`
34
+
35
+ Patch: `~/.hermes/hermes-agent/gateway/platforms/whatsapp_common.py` ~lines 361-365
36
+
37
+ Remove the group allowlist check โ€” replace with comment noting the patch.
38
+
39
+ ### A3. Silent Recorder โ€” `adapter.py`
40
+
41
+ Patch: `~/.hermes/hermes-agent/plugins/platforms/whatsapp/adapter.py`
42
+
43
+ Add method before `_build_message_event`:
44
+ ```python
45
+ def _record_group_message_sync(self, data):
46
+ try:
47
+ import json, os
48
+ chat_id = str(data.get("chatId") or "")
49
+ if not chat_id.endswith("@g.us"): return
50
+ body = str(data.get("body") or "").strip()
51
+ if not body: return
52
+ log_dir = os.path.expanduser("~/.hermes/platforms/whatsapp/group_logs")
53
+ os.makedirs(log_dir, exist_ok=True)
54
+ entry = {"ts": data.get("timestamp", 0), "sender": str(data.get("senderName") or data.get("senderId") or ""), "body": body}
55
+ with open(os.path.join(log_dir, f"{chat_id}.jsonl"), "a") as f:
56
+ f.write(json.dumps(entry, ensure_ascii=False) + "\n")
57
+ except Exception: pass
58
+ ```
59
+
60
+ In `_build_message_event`, before `_should_process_message` check:
61
+ ```python
62
+ if data.get("isGroup", False):
63
+ self._record_group_message_sync(data)
64
+ ```
65
+
66
+ ### A4. Env
67
+
68
+ Add to the Hermes environment config file:
69
+
70
+ ### A5. Restart
71
+
72
+ `hermes gateway restart` from **external terminal** (cannot restart from inside gateway).
73
+
74
+ **Verify:** send test message in any group โ†’ `ls ~/.hermes/platforms/whatsapp/group_logs/` should show `<chat_id>.jsonl` with your message.
75
+ See `references/verify-recording.md` for full checklist.
76
+
77
+ ### A6. Reference Files
78
+
79
+ - `references/bridge-api.md` โ€” bridge HTTP API: group name lookup, recording status
80
+ - `references/verify-recording.md` โ€” step-by-step verification after patch + restart
81
+
82
+ ---
83
+
84
+ ## Part B: Cron Jobs
85
+
86
+ ### B1. Get Group Info
87
+
88
+ - **Invite link**: `curl -sL "URL" | grep -oP '(?<=og:title" content=")[^"]+'`
89
+ - **Group ID**: tag Hermes in group with "apa id grup ini?" โ€” answer `\`<id>@g.us\``, nothing else
90
+ - **User MUST add Hermes to group manually** โ€” invite links don't work for bots
91
+
92
+ ### B2. Create Jobs
93
+
94
+ | Job | Cron (UTC) | WIB |
95
+ |-----|-----------|-----|
96
+ | Morning | `0 0 * * *` | 07:00 |
97
+ | Evening | `0 16 * * *` | 23:00 |
98
+
99
+ Deliver to `whatsapp:<chat_id>@g.us` **immediately** โ€” never use `origin` as placeholder.
100
+
101
+ ### B3. Cron Prompt
102
+
103
+ **Normal mode (default):**
104
+ ```
105
+ Kamu adalah bot ringkasan. HANYA OUTPUT RINGKASAN. Baca ~/.hermes/platforms/whatsapp/group_logs/<CHAT_ID>.jsonl, filter 12 jam (ts=UNIX timestamp integer). TANPA blank line:
106
+
107
+ *Summary General โ€” 12 jam terakhir*
108
+ - *Inti Diskusi*
109
+ - [rangkum per topik, gabungin chat mirip]
110
+ - *Keputusan*
111
+ - [keputusan atau "Tidak ada keputusan formal."]
112
+ - *Follow-up / Action*
113
+ - [Nama]: [action]
114
+ - *Pertanyaan Terbuka*
115
+ - [pertanyaan]
116
+ - *Link-link*
117
+ - [Nama]: [desc] โ€” [URL]
118
+
119
+ ATURAN: No metadata, no blank line, no job info. HANYA ringkasan. Nama dari field "sender". Bahasa Indonesia santai.
120
+ ```
121
+
122
+ **Roast mode (๐Ÿ”ฅ ๆฏ’่ˆŒ):**
123
+ ```
124
+ Kamu adalah bot ringkasan versi ROAST. HANYA OUTPUT RINGKASAN. Baca ~/.hermes/platforms/whatsapp/group_logs/<CHAT_ID>.jsonl, filter 12 jam. TANPA blank line. Gaya: sarkas, lucu, roasting anggota grup tapi tetap friendly, kayak temen yg galak tapi sayang.
125
+
126
+ *Summary Roast โ€” 12 jam terakhir ๐Ÿ”ฅ*
127
+ - *Yang Paling Nyablak*
128
+ - [siapa paling rame + roasts ringan]
129
+ - *Drama & Perdebatan*
130
+ - [topik panas dibahas + komentar sarkas]
131
+ - *Receh Tapi Menghibur*
132
+ - [chat random yg lucu/absurd]
133
+ - *Keputusan (yg akhirnya diambil setelah debat panjang)*
134
+ - [keputusan + komentar]
135
+ - *PR Yang Belum Kelar*
136
+ - [Nama]: [action item + roast ringan]
137
+ - *Pertanyaan Nyangkut*
138
+ - [pertanyaan + "ada yg bisa jawab ga nih?"]
139
+ - *Link Berserakan*
140
+ - [Nama]: [desc] โ€” [URL]
141
+
142
+ ATURAN: No metadata, no blank line, no job info. Roast friendly โ€” bukan bully. Bahasa Indonesia santai + sarkas.
143
+ ```
144
+
145
+ ### B4. Toggle Mode (On/Off)
146
+
147
+ To switch a group's summary to roast mode:
148
+ ```
149
+ cronjob(action='update', job_id='<job_id>', prompt='<roast prompt above>')
150
+ ```
151
+
152
+ To switch back to normal:
153
+ ```
154
+ cronjob(action='update', job_id='<job_id>', prompt='<normal prompt above>')
155
+ ```
156
+
157
+ User can say: "ubah MOCA PARTY ke mode roast" or "balikin hd ke normal" โ€” agent updates the 2 cron jobs for that group.
158
+
159
+ ### B5. User Style
160
+
161
+ - **Casual Indonesian** โ€” "gw", "lo", "dong", "ya", "nih", "rame bahas", "muter di", "belum jelas"
162
+ - **Zero metadata** โ€” no "Cronjob Response", job_id, "Catatan teknis", "To stop..."
163
+ - **No blank lines** between sections โ€” WhatsApp renders double newlines as ugly gaps. This is the #1 format bug the user catches. Every line in the summary MUST be a consecutive dash-prefix line with ZERO blank separators anywhere.
164
+ - **Direct & short** โ€” user hates verbosity ("ribet"). Never add explanatory notes, setup context, or disclaimers to the summary.
165
+ - **Group similar chats** โ€” merge related messages into 3-5 topic bullets under Inti Diskusi, not one bullet per message.
166
+ - **Honest about gaps** โ€” write "belum ada jawaban jelas" or "tidak ada solusi valid" when appropriate; never fabricate closure.
167
+
168
+ ### B6. Group Behavior (Anti-Ribet Rule)
169
+
170
+ When tagged in a WhatsApp group with **"apa id grup ini?"** or similar bare ID request:
171
+ - Reply with **just the ID**: `` `120363XXXXXXX@g.us` `` โ€” no quotes, no bold, just inline code
172
+ - Do NOT add: explanations, "mau dipake buat apa?", skill loading, setup offers, follow-up questions
173
+ - Do NOT load this skill unless explicitly asked to "set summary"
174
+ - Speed > conversation โ€” user finds verbose group responses deeply frustrating ("kenapa responmu ribet?")
175
+
176
+ ### B7. Reference Format
177
+
178
+ See [references/user-format-reference.md](references/user-format-reference.md) for the user's canonical summary example. Match the tone, grouping style, and section structure from that reference closely.
179
+
180
+ ---
181
+
182
+ ## Pitfalls
183
+
184
+ | Issue | Fix |
185
+ |-------|-----|
186
+ | Patches overwritten on `hermes update` | Re-apply A1-A3 after update |
187
+ | Gateway restart from inside blocked | Use external SSH terminal |
188
+ | Bridge auto-restarts, Python doesn't | Full `hermes gateway restart` needed for Python changes |
189
+ | JSONL timestamps are UNIX epoch ints | Don't try ISO parsing; compare integer timestamps |
190
+ | Blank lines in output | "TANPA blank line" in prompt is critical |
191
+ | Cron delivery header `Cronjob Response: ...` | Only appears in origin/DM delivery; group delivery (`whatsapp:...`) is clean |
192
+ | "Ribet" group responses | When tagged for "apa id grup", reply with just `` `120363XXXX@g.us` `` โ€” no explanation, no skill loading |
193
+ | Non-whitelisted member chat not recording | Verify 3 patches (A1-A3) applied + gateway restarted from external terminal. Bridge auto-restarts but Python adapter needs full `hermes gateway restart` |
194
+ | Group name mismatch | Verify with `curl localhost:3000/chat/<id>@g.us` (see bridge-api.md) |
195
+ | Summary too verbose / one bullet per message | Merge related chats into 3-5 topic bullets; group by theme, not sender |
196
+ | Recording broken after gateway restart | Check `grep \"_build_message_event returned None\" gateway.log` โ€” if present, Python patch not applied. Also verify `ls ~/.hermes/platforms/whatsapp/group_logs/` after sending test message |
197
+ | Group name mislabeled | Use `curl localhost:3000/chat/<id>@g.us` to get real WhatsApp name; user often uses shortened names |
198
+
199
+ ---
200
+
201
+ ## Example Output
202
+
203
+ ```
204
+ *Summary General โ€” 12 jam terakhir*
205
+ - *Inti Diskusi*
206
+ - Ngobrolin tools AI: GPT 5.6 Sol, Codex, Claude vs ChatGPT 5
207
+ - Sharing repo token saver: oh-my-pi dan paleo
208
+ - Diskusi akses remote: Tailscale vs NetBird
209
+ - *Keputusan*
210
+ - Tidak ada keputusan formal.
211
+ - *Follow-up / Action*
212
+ - Pen?: cek detail deploy error
213
+ - Yanda Nooryuda: cek member/top hari ini
214
+ - *Pertanyaan Terbuka*
215
+ - API Gmaps berbayar atau gratis?
216
+ - Sol udah masuk Codex official?
217
+ - *Link-link*
218
+ - Nado: token saver โ€” github.com/Fernado03/oh-my-pi-supreme-token-saver
219
+ - mmoaa: paleo โ€” github.com/mocasus/paleo
220
+ ```
221
+
222
+ ---
223
+
224
+ ## Resources
225
+
226
+ - **GitHub repo:** https://github.com/mocasus/whatsapp-group-summary โ€” standalone repo with full README + installation guide
227
+ - **Skill location:** `~/.hermes/skills/whatsapp-group-summary-bot/SKILL.md`
package/install.js ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * WhatsApp Group Summary Bot โ€” Installer
4
+ *
5
+ * Usage: npx whatsapp-group-summary
6
+ *
7
+ * Copies the skill to ~/.hermes/skills/whatsapp-group-summary-bot
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+ const { execSync } = require('child_process');
13
+
14
+ const SKILL_NAME = 'whatsapp-group-summary-bot';
15
+ const HERMES_HOME = process.env.HERMES_HOME || path.join(require('os').homedir(), '.hermes');
16
+ const TARGET_DIR = path.join(HERMES_HOME, 'skills', SKILL_NAME);
17
+ const REPO_URL = 'https://github.com/mocasus/whatsapp-group-summary.git';
18
+
19
+ console.log('๐Ÿค– WhatsApp Group Summary Bot โ€” Installer');
20
+ console.log(` Target: ${TARGET_DIR}\n`);
21
+
22
+ if (fs.existsSync(TARGET_DIR)) {
23
+ console.log('โš ๏ธ Skill already exists. Updating...');
24
+ try {
25
+ execSync(`git -C "${TARGET_DIR}" pull`, { stdio: 'inherit' });
26
+ console.log('โœ… Updated successfully!');
27
+ } catch {
28
+ console.log('โš ๏ธ Git pull failed. Re-cloning...');
29
+ fs.rmSync(TARGET_DIR, { recursive: true, force: true });
30
+ }
31
+ }
32
+
33
+ if (!fs.existsSync(TARGET_DIR)) {
34
+ console.log('๐Ÿ“ฆ Cloning skill...');
35
+ try {
36
+ execSync(`git clone "${REPO_URL}" "${TARGET_DIR}"`, { stdio: 'inherit' });
37
+ console.log('โœ… Skill installed!');
38
+ } catch (e) {
39
+ console.error('โŒ Failed to clone. Trying manual copy...');
40
+ fs.mkdirSync(TARGET_DIR, { recursive: true });
41
+ const sourceDir = path.join(__dirname, '..');
42
+ const files = fs.readdirSync(sourceDir);
43
+ for (const file of files) {
44
+ if (file === 'node_modules' || file === '.git' || file === 'package.json') continue;
45
+ const src = path.join(sourceDir, file);
46
+ const dest = path.join(TARGET_DIR, file);
47
+ fs.cpSync(src, dest, { recursive: true });
48
+ }
49
+ console.log('โœ… Skill installed (manual copy)!');
50
+ }
51
+ }
52
+
53
+ console.log('\n๐Ÿ“‹ Next steps:');
54
+ console.log(' 1. Apply 3 source patches (see README)');
55
+ console.log(' 2. Set WHATSAPP_REQUIRE_MENTION=true in Hermes env');
56
+ console.log(' 3. Restart gateway: hermes gateway restart');
57
+ console.log(' 4. Tag @Hermes in group: "apa id grup ini?"');
58
+ console.log(' 5. Setup 2 cron jobs (morning 07:00 + evening 23:00 WIB)');
59
+ console.log('\n Full guide: https://github.com/mocasus/whatsapp-group-summary');
package/logo.jpg ADDED
Binary file
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "whatsapp-group-summary",
3
+ "version": "1.0.0",
4
+ "description": "WhatsApp group chat summary bot for Hermes Agent โ€” record all messages silently, auto-summarize 2x daily",
5
+ "main": "install.js",
6
+ "bin": {
7
+ "whatsapp-group-summary": "./install.js"
8
+ },
9
+ "keywords": ["hermes-agent", "whatsapp", "summary", "group-chat", "bot"],
10
+ "author": "mocasus",
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/mocasus/whatsapp-group-summary.git"
15
+ }
16
+ }
@@ -0,0 +1,27 @@
1
+ # WhatsApp Bridge API โ€” Quick Reference
2
+
3
+ When Hermes WhatsApp gateway is running, the Baileys bridge exposes an HTTP API for querying chat/group info.
4
+
5
+ ## Get group name by ID
6
+
7
+ Query the bridge chat endpoint with the group ID:
8
+ ```
9
+ GET /chat/<chat_id>
10
+ ```
11
+
12
+ The bridge returns JSON with `name`, `isGroup`, `participants`, and other group metadata.
13
+
14
+ ## Get names for all recorded groups
15
+
16
+ Iterate over JSONL log files and query each group's chat endpoint to retrieve the group name.
17
+
18
+ ## JSONL format
19
+
20
+ Each line in the log file is a JSON object:
21
+ ```json
22
+ {"ts": 1783736100, "sender": "Display Name", "body": "message text"}
23
+ ```
24
+
25
+ - `ts` = UNIX timestamp (integer, seconds)
26
+ - `sender` = WhatsApp display name
27
+ - `body` = message text (stickers show `"[Sticker]"`)
@@ -0,0 +1,70 @@
1
+ # Recording ALL Group Members' Messages on WhatsApp
2
+
3
+ By default, Hermes WhatsApp has a **double filter** that blocks group messages from non-whitelisted users:
4
+
5
+ 1. **Bridge (Node.js)**: `bridge.js` line 637 โ€” `matchesAllowedUser(senderId, ALLOWED_USERS, ...)`
6
+ 2. **Adapter (Python)**: `whatsapp_common.py` lines 361-365 โ€” `_matches_whatsapp_allowlist(sender_id, self._allow_from)`
7
+
8
+ This means only users listed in `WHATSAPP_ALLOWED_USERS` have their group messages recorded. All other members are silently dropped.
9
+
10
+ ## The Fix (3 changes + restart)
11
+
12
+ ### 1. Patch bridge.js โ€” skip allowlist for groups
13
+
14
+ **File**: Hermes `scripts/whatsapp-bridge/bridge.js`
15
+
16
+ **Change line 637** from:
17
+ ```js
18
+ if (WHATSAPP_DM_POLICY !== 'pairing' && !matchesAllowedUser(senderId, ALLOWED_USERS, SESSION_DIR)) {
19
+ ```
20
+ to:
21
+ ```js
22
+ if (!isGroup && WHATSAPP_DM_POLICY !== 'pairing' && !matchesAllowedUser(senderId, ALLOWED_USERS, SESSION_DIR)) {
23
+ ```
24
+
25
+ The `!isGroup &&` prefix skips the allowlist check entirely for group messages. DMs remain gated.
26
+
27
+ ### 2. Patch whatsapp_common.py โ€” remove allowlist check for groups
28
+
29
+ **File**: Hermes `gateway/platforms/whatsapp_common.py`
30
+
31
+ **Remove lines 361-365** (the allowlist check block):
32
+ ```python
33
+ # Only respond to whitelisted senders in groups (respect WHATSAPP_ALLOWED_USERS)
34
+ if self._allow_from:
35
+ sender_id = str(data.get("senderId") or data.get("from") or "")
36
+ if sender_id and not self._matches_whatsapp_allowlist(sender_id, self._allow_from):
37
+ return False
38
+ ```
39
+
40
+ Replace with a comment:
41
+ ```python
42
+ # NOTE: patched โ€” allowlist check skipped for groups so all members' messages are recorded.
43
+ # Only DMs are gated by WHATSAPP_ALLOWED_USERS.
44
+ ```
45
+
46
+ ### 3. Set WHATSAPP_REQUIRE_MENTION=true
47
+
48
+ In the Hermes environment configuration, add or update:
49
+ ```
50
+ WHATSAPP_REQUIRE_MENTION=true
51
+ ```
52
+
53
+ This ensures Hermes **records** all group messages but only **responds** when @mentioned. Without this, Hermes would respond to every single group message, creating chaos.
54
+
55
+ ### 4. Restart gateway
56
+
57
+ **CRITICAL**: Cannot restart from inside the gateway. User must run from separate terminal:
58
+ ```bash
59
+ hermes gateway restart
60
+ ```
61
+
62
+ The bridge auto-restarts on kill (the adapter spawns it), but Python module changes require a full gateway restart.
63
+
64
+ ## Verification
65
+
66
+ After restart, check recording logs at the group_logs directory configured in the adapter.
67
+
68
+ ## โš ๏ธ Warning: Patches are overwritten on `hermes update`
69
+
70
+ These changes modify Hermes source code. Running `hermes update` will overwrite the patched files. Re-apply patches after each update.
@@ -0,0 +1,41 @@
1
+ # User's Reference Format
2
+
3
+ This is the exact format the user provided as a reference for how summaries should look.
4
+ Use this as the canonical example โ€” match the style, tone, and structure closely.
5
+
6
+ ```
7
+ *Summary General โ€” 12 jam terakhir*
8
+ - *Inti Diskusi*
9
+ - Grup rame bahas perbandingan model/agent: GPT 5.6 Sol/Terra/Luna, Grok, Opus, Qwen, plus setup Codex/9router. Pen? dan DickySusanto paling dominan arahkan diskusi.
10
+ - Banyak tanya soal akses & workflow: apakah Sol sudah masuk Codex official, beda mode sol vs sol-xhigh, serta model mana yang enak buat coding, summary, security, atau daily usage.
11
+ - Obrolan teknis lain muter di tokenizer/LLM from scratch, rate limit 429, remote access via Tailscale/SSH/RDP, dan integrasi Agentrouter/9router.
12
+ - Ada juga share metode/event/trial tools, tapi banyak yang sifatnya coba-coba komunitas dan belum jelas stabilitasnya.
13
+ - *Keputusan*
14
+ - Tidak ada keputusan formal.
15
+ - *Follow-up / Action*
16
+ - Pen?: sempat bilang "besok aja besok" buat lanjut share/tutor yang diminta.
17
+ - Pen?: update singkat "deploy error done", tapi belum ada detail hasil lanjutannya.
18
+ - Yanda Nooryuda: ada task open buat cek member/top hari ini.
19
+ - DickySusanto / ไฝ ็ฎ—ๅ“ชๅ—ๅฐ้ฅผๅนฒ๏ผŸ: masih ada request open buat kirim benchmark kecil/model arena dan extension RF token.
20
+ - *Pertanyaan Terbuka*
21
+ - API Gmaps ternyata berbayar atau tidak?
22
+ - Bagusan Tailscale atau NetBird untuk akses remote?
23
+ - Sol sekarang bisa dipakai langsung di Codex CLI atau tetap harus lewat 9router?
24
+ - Untuk slicing UI, lebih cocok Claude atau ChatGPT versi terbaru?
25
+ - *Link-link*
26
+ - Nado: share repo token saver di GitHub โ€” github.com/Fernado03/oh-my-pi-supreme-token-saver
27
+ - Bayu Anugerah: share extension codex-auth di Chrome Web Store.
28
+ - Yanda Nooryuda / Azhar: share ulang link invite grup WhatsApp.
29
+ - Mzxn Amnah: share event/community Lovable + temp mail smailpro buat klaim credit.
30
+ - gn: share repo Vandivier/ladderly-3 terkait issue/ref lain.
31
+ ```
32
+
33
+ ## Key formatting rules extracted:
34
+
35
+ 1. **No blank lines** between sections โ€” WhatsApp renders these as ugly gaps
36
+ 2. **Dash-prefix for everything** โ€” `- *Section Name*` then `- content`
37
+ 3. **Group related chats into 3-5 topic bullets** under Inti Diskusi
38
+ 4. **Names**: use the WhatsApp display name, not phone number
39
+ 5. **Casual Indonesian**: "rame bahas", "muter di", "belum jelas"
40
+ 6. **Links at the bottom**: sender name, description, URL
41
+ 7. **Honest about uncertainty**: "belum ada jawaban jelas", "tidak ada solusi valid"
@@ -0,0 +1,27 @@
1
+ # Recording Verification Checklist
2
+
3
+ After applying all 3 patches and restarting the gateway:
4
+
5
+ ## 1. Check environment
6
+
7
+ Verify `WHATSAPP_REQUIRE_MENTION` is set to `true` in the Hermes environment configuration.
8
+
9
+ ## 2. Verify bridge allows all group messages
10
+
11
+ Check bridge is running with patched code:
12
+ ```bash
13
+ ps aux | grep "bridge.js" | grep -v grep
14
+ # Should show node process with --mode bot
15
+ ```
16
+
17
+ ## 3. Verify JSONL recording
18
+
19
+ Send a test message in any group where Hermes is a member, then check the group_logs directory for a new JSONL file with your message.
20
+
21
+ ## 4. Verify silent recording (no agent response)
22
+
23
+ Check gateway logs โ€” regular messages should show `"_build_message_event returned None"` (not `"inbound message"`). These are silently recorded โ€” no agent session created, no LLM cost.
24
+
25
+ ## 5. Verify mention still triggers agent
26
+
27
+ Tag @Hermes in a group โ€” it should create a session and respond normally. Gateway logs should show `"inbound message"` with the group chat ID.
@@ -0,0 +1,34 @@
1
+ # WhatsApp Bridge Limitations for Group Summaries
2
+
3
+ ## The Problem
4
+
5
+ The WhatsApp Baileys bridge (`scripts/whatsapp-bridge/bridge.js`) has a hard filter at line 637:
6
+
7
+ ```js
8
+ if (WHATSAPP_DM_POLICY !== 'pairing' && !matchesAllowedUser(senderId, ALLOWED_USERS, SESSION_DIR)) {
9
+ continue; // silently drop the message
10
+ }
11
+ ```
12
+
13
+ This runs for ALL incoming messages (`messages.upsert` handler, line 520). In bot mode (`WHATSAPP_MODE=bot`), this means group messages from non-whitelisted users are dropped at the bridge level โ€” before they ever reach the Python gateway or the session database.
14
+
15
+ ## Impact on Summary Bots
16
+
17
+ - **Only conversations from `WHATSAPP_ALLOWED_USERS` appear in summary output**
18
+ - Group members not in the allowlist are invisible to the bot
19
+ - The `WHATSAPP_GROUP_POLICY=open` setting and `WHATSAPP_REQUIRE_MENTION=false` default are irrelevant because the bridge drops messages first
20
+
21
+ ## Solution
22
+
23
+ This skill patches the bridge to skip the allowlist check for group messages by adding `!isGroup &&` to the condition at line 637. DMs remain fully gated by the allowlist.
24
+
25
+ The Python adapter (`gateway/platforms/whatsapp_common.py`) also needs a matching patch to remove its group allowlist check.
26
+
27
+ ## Code Locations
28
+
29
+ | Component | File | Key Lines |
30
+ |-----------|------|-----------|
31
+ | Bridge message handler | `scripts/whatsapp-bridge/bridge.js` | 520-640 (upsert handler, allowlist check at 637) |
32
+ | Python adapter | `plugins/platforms/whatsapp/adapter.py` | `_should_process_message` call |
33
+ | Message processing logic | `gateway/platforms/whatsapp_common.py` | 348-385 (group policy, mention gating) |
34
+ | Environment config | Hermes env file | `WHATSAPP_ALLOWED_USERS`, `WHATSAPP_DM_POLICY`, `WHATSAPP_REQUIRE_MENTION` |
@@ -0,0 +1,42 @@
1
+ # WhatsApp Group ID & Delivery Reference
2
+
3
+ ## Group ID Format
4
+
5
+ WhatsApp group IDs always follow this pattern:
6
+
7
+ ```
8
+ <digits>@g.us
9
+ ```
10
+
11
+ Examples:
12
+ - `120363273766916972@g.us` (MOCA PARTY)
13
+ - `120363309894459310@g.us` (hd)
14
+ - `120363307689756041@g.us` (BagiProject)
15
+ - `120363411000649302@g.us` (unnes 1)
16
+
17
+ ## Getting the Group ID
18
+
19
+ 1. **User provides it directly** โ€” fastest. Ask "apa ID grupnya?" in the group. Respond with JUST the ID, no explanations.
20
+ 2. **From session_search** โ€” look for the group name in session titles when Hermes receives messages.
21
+ 3. **User tags Hermes in group** โ€” when tagged "apa id grub ini", respond with: `ID grup ini: \`<id>@g.us\`` โ€” keep it ONE line, no follow-up questions.
22
+
23
+ ## Delivery Format
24
+
25
+ ```
26
+ deliver: "whatsapp:<group_id>@g.us"
27
+ ```
28
+
29
+ Example: `deliver: "whatsapp:120363273766916972@g.us"`
30
+
31
+ ## Cron Schedule (WIB timezone)
32
+
33
+ | Time (WIB) | UTC | Cron expression |
34
+ |---|---|---|
35
+ | 07:00 pagi | 00:00 | `0 0 * * *` |
36
+ | 23:00 malam | 16:00 | `0 16 * * *` |
37
+
38
+ WIB = UTC+7.
39
+
40
+ ## Batch Creation Pattern
41
+
42
+ Always create both morning and evening jobs in parallel (single tool call with two `cronjob(action='create')` invocations) to save round-trips. Only ask for the group name once, then create both.