@ryuu-reinzz/ryuu-cli 0.4.3 → 0.5.1

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/README.md +26 -0
  3. package/docs/drive.md +484 -0
  4. package/docs/github.md +464 -0
  5. package/package.json +4 -1
  6. package/plugins/github/README.md +151 -0
  7. package/plugins/github/api.js +78 -0
  8. package/plugins/github/auth.js +45 -0
  9. package/plugins/github/backend.js +191 -0
  10. package/plugins/github/command.js +307 -0
  11. package/plugins/github/config.js +209 -0
  12. package/plugins/github/credentials.js +161 -0
  13. package/plugins/github/errors.js +49 -0
  14. package/plugins/github/index.js +41 -0
  15. package/plugins/github/manager.js +613 -0
  16. package/plugins/github/tool-helpers.js +259 -0
  17. package/plugins/github/tools-account.js +64 -0
  18. package/plugins/github/tools-actions.js +126 -0
  19. package/plugins/github/tools-issues.js +214 -0
  20. package/plugins/github/tools-pulls.js +267 -0
  21. package/plugins/github/tools-releases.js +87 -0
  22. package/plugins/github/tools-repos.js +392 -0
  23. package/plugins/github/tools.js +25 -0
  24. package/plugins/google-drive/auth.js +57 -0
  25. package/plugins/google-drive/backup.js +282 -0
  26. package/plugins/google-drive/command.js +266 -0
  27. package/plugins/google-drive/config.js +252 -0
  28. package/plugins/google-drive/credentials.js +171 -0
  29. package/plugins/google-drive/drive-api.js +304 -0
  30. package/plugins/google-drive/index.js +26 -0
  31. package/plugins/google-drive/manager.js +507 -0
  32. package/plugins/google-drive/oauth-backend.js +161 -0
  33. package/plugins/google-drive/secret.js +50 -0
  34. package/plugins/google-drive/token-client.js +80 -0
  35. package/plugins/google-drive/tool-helpers.js +46 -0
  36. package/plugins/google-drive/tools-backup.js +204 -0
  37. package/plugins/google-drive/tools-files.js +315 -0
  38. package/plugins/google-drive/tools.js +13 -0
  39. package/plugins/google-drive/zip-reader.js +217 -0
  40. package/plugins/google-drive/zip-writer.js +204 -0
  41. package/plugins/index.js +58 -0
  42. package/src/agent/agent.js +12 -2
  43. package/src/cli/app.js +16 -0
  44. package/src/cli/commands.js +44 -0
  45. package/src/cli/markdown.js +10 -5
  46. package/src/cli/renderer.js +38 -5
  47. package/src/cli/tui.js +80 -9
  48. package/src/tools/registry.js +13 -0
package/docs/github.md ADDED
@@ -0,0 +1,464 @@
1
+ # Integrasi GitHub — Ryuu CLI
2
+
3
+ Dokumen ini menjelaskan cara memasang, mengonfigurasi, memakai, dan menguji
4
+ integrasi GitHub pada Ryuu CLI. Integrasi terdiri dari dua bagian:
5
+
6
+ 1. **Backend** (`/root/website/api`, modul `lib/github/`) — Integration Gateway
7
+ yang memegang seluruh kredensial GitHub App dan token pengguna.
8
+ 2. **Plugin CLI** (`/root/agents/ryuu/plugins/github/`) — command `/github` dan
9
+ 35 tool AI yang memanggil GitHub melalui gateway.
10
+
11
+ Tidak ada Client Secret, Private Key, Webhook Secret, access token, atau refresh
12
+ token di sisi CLI. CLI hanya memegang `cliToken` per akun yang disimpan
13
+ terenkripsi.
14
+
15
+ ---
16
+
17
+ ## 1. Arsitektur
18
+
19
+ ```
20
+ ┌──────────────────────────┐ ┌─────────────────────────────────┐
21
+ │ Ryuu CLI │ │ Backend Ryuu (lib/github) │
22
+ │ plugins/github │ │ │
23
+ │ /github login ──────────┼───────▶│ POST /integrations/github/connect│
24
+ │ browser / device flow │ │ state + PKCE + URL otorisasi │
25
+ │ polling sesi ───────────┼───────▶│ GET /integrations/github/session│
26
+ │ cliToken (terenkripsi) │◀───────┤ cliToken (sekali ambil) │
27
+ │ │ │ │
28
+ │ tools GitHub ───────────┼───────▶│ ALL /integrations/github/api/* │
29
+ │ │ │ token pengguna + safelist │
30
+ └──────────────────────────┘ └───────────────┬─────────────────┘
31
+ │ HTTPS
32
+ ┌──────────────▼──────────────┐
33
+ │ github.com / api.github.com │
34
+ │ GitHub App + instalasi │
35
+ └─────────────────────────────┘
36
+
37
+ GitHub ── webhook ──▶ POST /webhooks/github (signature HMAC SHA-256)
38
+ ```
39
+
40
+ Prinsip:
41
+
42
+ - **Satu akun GitHub = satu record token** di backend. Tidak ada token global.
43
+ - Backend memakai penyimpanan JSON yang sudah menjadi pola proyek
44
+ (`~/.config/ryuu/github/data/tokens.json`) dengan atomic write + lock; bukan
45
+ database baru.
46
+ - Token disimpan dengan AES-256-GCM; kunci enkripsi terpisah dari data.
47
+ - CLI memanggil GitHub hanya lewat proxy backend, sehingga token tidak pernah
48
+ meninggalkan server.
49
+
50
+ ---
51
+
52
+ ## 2. Prasyarat
53
+
54
+ - Node.js ≥ 22 di mesin CLI dan server backend.
55
+ - GitHub App sudah dibuat dan diinstal ke akun/organisasi.
56
+ - Backend dapat diakses publik pada domain yang terdaftar di GitHub App.
57
+ - `express` (sudah menjadi dependensi backend).
58
+
59
+ ---
60
+
61
+ ## 3. Membuat GitHub App
62
+
63
+ Buka **GitHub → Settings → Developer settings → GitHub Apps → New GitHub App**.
64
+
65
+ | Field | Nilai |
66
+ | --- | --- |
67
+ | App name | `Ryuu CLI` |
68
+ | Homepage URL | `https://restapi.ryuu-dev.my.id/site` |
69
+ | Callback URL | `https://restapi.ryuu-dev.my.id/integrations/github/callback` |
70
+ | Webhook URL | `https://restapi.ryuu-dev.my.id/webhooks/github` |
71
+ | Webhook secret | string acak panjang; simpan di konfigurasi backend |
72
+ | Expire user authorization tokens | **aktifkan** agar refresh token diterbitkan |
73
+ | Device flow | aktifkan bila ingin `login --device` |
74
+ | Request user authorization during installation | opsional |
75
+
76
+ Catat **App ID**, **Client ID**, dan buat **Client Secret** + **Private Key**
77
+ (`.pem`). Client ID bukan rahasia; Client Secret dan Private Key hanya boleh ada
78
+ di server.
79
+
80
+ ### Permission minimum
81
+
82
+ | Permission | Level | Dipakai untuk |
83
+ | --- | --- | --- |
84
+ | Metadata | Read | Wajib untuk semua akses repository |
85
+ | Contents | Read | File, branch, commit, release |
86
+ | Contents | Write | Buat/ubah/hapus file, buat release |
87
+ | Issues | Read & Write | Issue dan komentar |
88
+ | Pull requests | Read & Write | PR, review, merge |
89
+ | Actions | Read | Workflow dan workflow run |
90
+ | Actions | Write | Menjalankan ulang workflow |
91
+ | Administration | Write | Membuat/mengubah repository |
92
+
93
+ Tidak meminta permission yang tidak dipakai (Secrets, Checks, Statuses,
94
+ Workflows, Packages, dll). Tidak ada tool penghapusan repository.
95
+
96
+ ### Event webhook
97
+
98
+ Pilih minimal: **Push**, **Issues**, **Issue comment**, **Pull request**,
99
+ **Pull request review**, **Release**, **Installation**,
100
+ **Installation repositories**, **GitHub App authorization**.
101
+
102
+ ### Instalasi
103
+
104
+ Setelah App dibuat, klik **Install App** dan pilih akun/organisasi serta
105
+ repository yang boleh diakses. Login saja tidak memberi akses ke seluruh
106
+ repository: akses adalah irisan antara permission App, persetujuan pengguna,
107
+ dan repository yang tercakup instalasi.
108
+
109
+ ---
110
+
111
+ ## 4. Konfigurasi backend
112
+
113
+ Default file: `~/.config/ryuu/github/server.json` (Linux:
114
+ `$XDG_CONFIG_HOME`/`~/.config`; macOS: `~/Library/Application Support`;
115
+ Windows: `%APPDATA%`). Override: `RYUU_GITHUB_CONFIG=/path/server.json`.
116
+
117
+ ```json
118
+ {
119
+ "appId": "<App ID>",
120
+ "clientId": "<Client ID>",
121
+ "clientSecret": "<Client Secret>",
122
+ "privateKeyPath": "/path/ryuu-cli.private-key.pem",
123
+ "webhookSecret": "<Webhook Secret>",
124
+ "redirectUri": "https://<domain>/integrations/github/callback",
125
+ "webhookUrl": "https://<domain>/webhooks/github",
126
+ "apiVersion": "2022-11-28"
127
+ }
128
+ ```
129
+
130
+ Field wajib: `appId`, `clientId`, `clientSecret`, `privateKeyPath`,
131
+ `webhookSecret`, `redirectUri`, `webhookUrl`. `apiVersion` default
132
+ `2022-11-28` (versi REST GitHub yang didukung implementasi ini).
133
+
134
+ Permission yang disarankan:
135
+
136
+ ```bash
137
+ chmod 700 ~/.config/ryuu/github
138
+ chmod 600 ~/.config/ryuu/github/server.json
139
+ chmod 600 /path/ryuu-cli.private-key.pem
140
+ ```
141
+
142
+ Kunci enkripsi token berada di `~/.config/ryuu/github/.keys/tokens.key` (0600)
143
+ atau dari `RYUU_GITHUB_TOKEN_KEY` (hex 64 karakter / base64 32 byte). Kunci tidak
144
+ boleh disimpan bersama file data token.
145
+
146
+ Backend membaca ulang konfigurasi saat mtime berubah; rotasi credential tidak
147
+ memerlukan restart. Jika field belum lengkap, endpoint menjawab HTTP 503 dengan
148
+ **nama field** yang belum diisi — bukan nilainya.
149
+
150
+ ---
151
+
152
+ ## 5. Konfigurasi CLI
153
+
154
+ CLI hanya menyimpan pengaturan non-rahasia:
155
+
156
+ ```
157
+ <config>/integrations/github/config.json (0600)
158
+ <config>/integrations/github/state.json (0600)
159
+ <config>/integrations/github/credentials.enc (0600, cliToken terenkripsi)
160
+ <config>/.keys/github.key (0600)
161
+ ```
162
+
163
+ Key yang dapat diubah:
164
+
165
+ ```bash
166
+ ryuu /github config set enabled true
167
+ ryuu /github config set confirmDestructive false
168
+ ryuu /github config set defaultRepo ryuu-reinzz/ryuu-cli
169
+ ```
170
+
171
+ `clientId` boleh tampil (publik). `clientSecret`, `privateKeyPath`,
172
+ `webhookSecret`, `accessToken`, `refreshToken`, dan `cliToken` tidak dapat
173
+ diubah dari CLI.
174
+
175
+ ---
176
+
177
+ ## 6. Login
178
+
179
+ ### Browser (utama)
180
+
181
+ ```bash
182
+ ryuu /github login
183
+ ```
184
+
185
+ Alur:
186
+
187
+ 1. CLI meminta backend membuat sesi sementara (`sessionId`, `pairingSecret`,
188
+ `state`, PKCE challenge, URL otorisasi).
189
+ 2. Browser dibuka. Jika tidak ada browser, URL dicetak untuk dibuka manual.
190
+ 3. Pengguna menyetujui akses di GitHub.
191
+ 4. GitHub mengarahkan ke `/integrations/github/callback`.
192
+ 5. Backend memvalidasi `state`, menukar `code` (client secret + PKCE verifier),
193
+ mengambil `GET /user`, dan menyimpan token terenkripsi.
194
+ 6. Backend menerbitkan `cliToken` per akun dan menandai sesi `authorized`.
195
+ 7. CLI polling dengan `pairingSecret`, menerima hasil **sekali**, lalu sesi
196
+ dihapus. Sesi kedaluwarsa setelah 10 menit.
197
+
198
+ Login otomatis mengaktifkan integrasi dan mendaftarkan tool pada sesi berjalan.
199
+
200
+ ### Device flow (headless)
201
+
202
+ ```bash
203
+ ryuu /github login --device
204
+ ```
205
+
206
+ CLI menampilkan `verification_uri` dan `user_code`, lalu benar-benar melakukan
207
+ polling sampai GitHub menyelesaikan otorisasi (bukan hanya menampilkan kode).
208
+ Device flow harus diaktifkan pada pengaturan GitHub App.
209
+
210
+ Catatan PKCE: challenge dan verifier dikirim pada flow browser. GitHub belum
211
+ mendokumentasikan dukungan PKCE untuk OAuth App, sehingga jaminan utama adalah
212
+ `state` acak sekali pakai + Client Secret yang hanya ada di server. Dokumentasi
213
+ ini tidak mengklaim PKCE diverifikasi oleh GitHub.
214
+
215
+ ---
216
+
217
+ ## 7. Status, akun, dan test
218
+
219
+ ```bash
220
+ ryuu /github status
221
+ ryuu /github account
222
+ ryuu /github test
223
+ ```
224
+
225
+ `status` menampilkan status integrasi, login, enable/disable, respons backend,
226
+ masa berlaku access token, ketersediaan refresh token, jumlah instalasi, dan
227
+ lokasi file konfigurasi. Tidak ada token yang dicetak.
228
+
229
+ `account` menampilkan username, nama, tipe akun, URL profil, avatar, scope, dan
230
+ status autentikasi.
231
+
232
+ `test` memeriksa konfigurasi, sesi CLI, respons backend, `GET /user`, instalasi,
233
+ rate limit, App JWT/private key, dan status token. **Tidak** membuat, mengubah,
234
+ atau menghapus repository.
235
+
236
+ ---
237
+
238
+ ## 8. Enable dan disable
239
+
240
+ ```bash
241
+ ryuu /github enable
242
+ ryuu /github disable
243
+ ```
244
+
245
+ - `enable` mendaftarkan tool ke registry agent. Konfigurasi dan sesi harus valid.
246
+ - `disable` hanya melepas tool. Akun, token, dan instalasi GitHub App tetap ada.
247
+ - Tool memeriksa ulang status saat eksekusi, jadi model yang memegang daftar tool
248
+ lama tidak bisa bertindak setelah disable.
249
+
250
+ ---
251
+
252
+ ## 9. Logout dan disconnect
253
+
254
+ ```bash
255
+ ryuu /github logout
256
+ ```
257
+
258
+ Logout:
259
+
260
+ 1. Meminta backend mencabut token (`DELETE /applications/{client_id}/token`).
261
+ 2. Menghapus `cliToken` lokal dan kunci enkripsi CLI.
262
+ 3. Menonaktifkan integrasi.
263
+ 4. Tidak menghapus repository, issue, release, atau instalasi GitHub App.
264
+
265
+ Jika backend tidak dapat dihubungi, kredensial lokal tetap dihapus dan CLI
266
+ memberi tahu bahwa token di server mungkin masih tersimpan. Untuk memutus
267
+ instalasi sepenuhnya, lakukan dari **GitHub → Settings → Applications** atau
268
+ halaman instalasi App.
269
+
270
+ ---
271
+
272
+ ## 10. Tools
273
+
274
+ | Kelompok | Tool |
275
+ | --- | --- |
276
+ | Akun | `github_get_me`, `github_get_user`, `github_get_rate_limit` |
277
+ | Repository | `github_list_repositories`, `github_get_repository`, `github_create_repository`, `github_update_repository`, `github_list_branches`, `github_get_branch`, `github_list_commits`, `github_get_commit`, `github_get_file_contents`, `github_create_or_update_file`, `github_delete_file`, `github_compare_commits` |
278
+ | Issue | `github_list_issues`, `github_get_issue`, `github_create_issue`, `github_update_issue`, `github_comment_issue`, `github_list_issue_comments` |
279
+ | Pull request | `github_list_pull_requests`, `github_get_pull_request`, `github_create_pull_request`, `github_update_pull_request`, `github_merge_pull_request`, `github_list_pull_request_files`, `github_review_pull_request` |
280
+ | Release | `github_list_releases`, `github_get_release`, `github_create_release` |
281
+ | Actions | `github_list_workflows`, `github_list_workflow_runs`, `github_get_workflow_run`, `github_rerun_workflow` |
282
+
283
+ Setiap tool memiliki schema input yang divalidasi registry, pemeriksaan
284
+ autentikasi, pembatasan output, dan deskripsi permission yang dibutuhkan.
285
+
286
+ Operasi yang mengubah data selalu melewati approval Ryuu:
287
+
288
+ - membuat/mengubah repository;
289
+ - membuat/mengubah/menghapus file;
290
+ - membuat/mengubah issue dan komentar;
291
+ - membuat/mengubah/merge pull request dan review;
292
+ - membuat release;
293
+ - menjalankan ulang workflow.
294
+
295
+ `github_delete_file` dan `github_merge_pull_request` berisiko `destructive`.
296
+ `confirmDestructive: false` memblokirnya sepenuhnya.
297
+
298
+ ---
299
+
300
+ ## 11. Token kedaluwarsa dan refresh
301
+
302
+ GitHub App dapat menerbitkan access token yang kedaluwarsa (default 8 jam) dan
303
+ refresh token (default 6 bulan) bila opsi expire user authorization tokens
304
+ aktif. Jangan mengasumsikan durasi: backend memakai `expires_in` dan
305
+ `refresh_token_expires_in` dari respons aktual.
306
+
307
+ - Backend me-refresh otomatis bila access token tinggal ≤ 5 menit.
308
+ - Refresh memakai single-flight per akun, sehingga request paralel tidak
309
+ melakukan dua rotasi refresh token.
310
+ - Refresh token yang dirotasi disimpan; jika GitHub tidak mengirim yang baru,
311
+ token lama dipertahankan.
312
+ - `invalid_grant`/`bad_refresh_token` menandai akun `needsReconnect`; pengguna
313
+ diminta `/github login` lagi.
314
+ - Bila token tidak punya expiry (opsi expire dimatikan), token dipakai tanpa
315
+ refresh dan status menampilkan “tanpa masa berlaku”.
316
+
317
+ Perintah manual:
318
+
319
+ ```bash
320
+ ryuu /github test
321
+ ryuu /github status
322
+ ```
323
+
324
+ `/github test` melakukan pemeriksaan; refresh paksa tersedia di endpoint backend
325
+ `POST /integrations/github/refresh` (dipakai untuk diagnostik).
326
+
327
+ ---
328
+
329
+ ## 12. Mengganti credential
330
+
331
+ 1. **Client Secret baru**: buat di GitHub App settings, lalu perbarui
332
+ `clientSecret` di `server.json`. File dibaca ulang otomatis (mtime).
333
+ 2. **Private Key baru**: generate, simpan dengan mode 0600, perbarui
334
+ `privateKeyPath`, lalu hapus key lama.
335
+ 3. **Webhook Secret baru**: perbarui di GitHub dan `server.json`; delivery lama
336
+ yang belum diproses akan ditolak jika signature-nya memakai secret lama.
337
+ 4. **Client ID/App ID berubah**: perbarui `clientId`/`appId`, lalu login ulang.
338
+ 5. **Mengganti akun pengguna**: `/github logout`, lalu `/github login`.
339
+
340
+ Tidak ada perubahan source code yang diperlukan. Jangan menaruh nilai rahasia di
341
+ dokumentasi, issue, commit, atau log.
342
+
343
+ ---
344
+
345
+ ## 13. Webhook
346
+
347
+ Endpoint: `POST /webhooks/github` (dipasang sebelum parser JSON global).
348
+
349
+ - Signature `X-Hub-Signature-256` (HMAC SHA-256, constant-time) wajib valid.
350
+ - `X-GitHub-Event` dan `X-GitHub-Delivery` divalidasi.
351
+ - Delivery duplikat diabaikan (`202 { duplicate: true }`).
352
+ - Event diproses asynchronous; respons `202` dikirim lebih dulu.
353
+ - Event yang didukung: `push`, `issues`, `issue_comment`, `pull_request`,
354
+ `pull_request_review`, `release`, `installation`,
355
+ `installation_repositories`, `github_app_authorization`.
356
+ - Handler hanya mencatat dan memperbarui data instalasi. Tidak ada aksi otomatis
357
+ yang mengubah repository.
358
+ - Payload dicatat dalam bentuk ter-redaksi.
359
+
360
+ ---
361
+
362
+ ## 14. Batasan akses
363
+
364
+ - Login GitHub **tidak** berarti akses ke seluruh repository. Akses adalah
365
+ irisan permission App, persetujuan pengguna, dan repository yang tercakup
366
+ instalasi.
367
+ - Repository privat hanya terlihat bila instalasi mencakupnya.
368
+ - Organisasi dapat membatasi atau meninjau instalasi; administrator organisasi
369
+ mungkin perlu menyetujui.
370
+ - Endpoint tertentu memerlukan permission tambahan (mis. Administration write
371
+ untuk membuat repository).
372
+ - GitHub REST rate limit tetap berlaku; gunakan `github_get_rate_limit`.
373
+
374
+ ---
375
+
376
+ ## 15. Catatan keamanan
377
+
378
+ - Client Secret, Private Key, dan Webhook Secret hanya ada di backend.
379
+ - Token pengguna disimpan terenkripsi (AES-256-GCM); kunci terpisah dari data.
380
+ - `cliToken` disimpan sebagai hash SHA-256, maksimal 5 per akun, dan memiliki
381
+ masa berlaku (default 30 hari).
382
+ - `pairingSecret` hanya dikembalikan ke CLI pembuat sesi dan dibandingkan
383
+ constant-time; sesi berumur 10 menit dan hasil login hanya bisa diambil sekali.
384
+ - Proxy API memakai safelist method+path; CLI tidak bisa memanggil endpoint
385
+ sembarang.
386
+ - Log tidak memuat Authorization header, token, atau secret.
387
+ - Approval Ryuu tidak bisa dilewati oleh tool; `confirmDestructive=false`
388
+ menambahkan lapisan blokir di handler.
389
+ - File rahasia dan data runtime tidak masuk Git (`lib/github/data/`, `.pem`,
390
+ `.env`, kunci).
391
+
392
+ ---
393
+
394
+ ## 16. Testing lokal
395
+
396
+ Backend:
397
+
398
+ ```bash
399
+ cd /root/website/api
400
+ npm test
401
+ ```
402
+
403
+ CLI:
404
+
405
+ ```bash
406
+ cd /root/agents/ryuu
407
+ node --test tests/unit/github.test.js tests/integration/github.test.js
408
+ npm run check
409
+ ```
410
+
411
+ Test memakai mock `fetch`/server lokal. **Jangan** menguji konektivitas domain
412
+ `restapi.ryuu-dev.my.id` dari VPS LXC: domain dan jaringan dikelola VPS induk.
413
+ Pengujian callback/webhook dari perangkat eksternal dapat dilakukan dengan:
414
+
415
+ ```bash
416
+ curl -i "https://restapi.ryuu-dev.my.id/integrations/github/callback?state=invalid"
417
+ # harapan: 404 + halaman HTML "sesi tidak ditemukan", bukan error 500
418
+ ```
419
+
420
+ ---
421
+
422
+ ## 17. Troubleshooting
423
+
424
+ | Gejala | Penyebab umum | Tindakan |
425
+ | --- | --- | --- |
426
+ | 503 konfigurasi belum lengkap | `server.json` belum diisi | Isi field yang disebut pada pesan |
427
+ | `invalid_client` saat callback | Client Secret salah/berputar | Perbarui `clientSecret`, login ulang |
428
+ | `redirect_uri` mismatch | Callback URL di GitHub berbeda | Samakan `redirectUri` di App dan `server.json` |
429
+ | 401 signature webhook | Webhook Secret berbeda | Samakan secret di GitHub dan backend |
430
+ | 403 akses repository | Instalasi tidak mencakup repo | Instal/ubah akses App |
431
+ | Tool tidak muncul | Belum login atau disable | `/github login`, `/github enable` |
432
+ | Token perlu login ulang | Refresh token dicabut/kedaluwarsa | `/github login` |
433
+ | Rate limit | Kuota GitHub habis | Tunggu reset, cek `/github test` |
434
+
435
+ ---
436
+
437
+ ## 18. Struktur file
438
+
439
+ ```
440
+ /root/website/api/
441
+ ├── index.js # memasang webhook + router
442
+ ├── lib/github/
443
+ │ ├── index.js # factory integrasi
444
+ │ ├── config.js # konfigurasi server + validasi
445
+ │ ├── data/ # hanya jika diarahkan ke repo (di-ignore)
446
+ │ ├── encryption.js # AES-256-GCM + kunci terpisah
447
+ │ ├── store.js # atomic write + lock
448
+ │ ├── token-storage.js # record per akun + cliToken hash
449
+ │ ├── session.js # sesi login sementara
450
+ │ ├── oauth.js # PKCE, exchange, refresh, device flow
451
+ │ ├── app-token.js # App JWT + installation token
452
+ │ ├── token-manager.js # auto-refresh single-flight
453
+ │ ├── api.js # GitHub REST client
454
+ │ ├── signature.js # verifikasi webhook
455
+ │ ├── webhook.js # handler + dedupe + antrean
456
+ │ ├── router.js # endpoint + proxy
457
+ │ └── README.md
458
+ └── tests/github/ # 48 test lokal
459
+
460
+ /root/agents/ryuu/
461
+ ├── plugins/github/ # plugin CLI
462
+ ├── docs/github.md # dokumen ini
463
+ └── tests/{unit,integration}/github.test.js
464
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryuu-reinzz/ryuu-cli",
3
- "version": "0.4.3",
3
+ "version": "0.5.1",
4
4
  "description": "Ryuu Agent CLI - an autonomous, approval-gated AI coding agent for your terminal",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,6 +12,8 @@
12
12
  },
13
13
  "files": [
14
14
  "src",
15
+ "plugins",
16
+ "docs",
15
17
  "README.md",
16
18
  "CHANGELOG.md"
17
19
  ],
@@ -41,6 +43,7 @@
41
43
  "dependencies": {
42
44
  "@modelcontextprotocol/sdk": "^1.32.1",
43
45
  "chalk": "^6.0.1",
46
+ "googleapis": "^189.0.0",
44
47
  "openai": "^7.39.0",
45
48
  "ora": "^9.4.1"
46
49
  }
@@ -0,0 +1,151 @@
1
+ # Plugin GitHub — Ryuu CLI
2
+
3
+ Integrasi GitHub untuk agent Ryuu: akun, repository, file, issue, pull request,
4
+ release, dan GitHub Actions. Plugin ini mengikuti pola `plugins/google-drive/`
5
+ dan **tidak memegang kredensial GitHub rahasia apa pun**.
6
+
7
+ ## Arsitektur singkat
8
+
9
+ ```
10
+ ryuu /github login
11
+ │ POST /integrations/github/connect (sesi + URL)
12
+ ▼
13
+ Backend Ryuu (Integration Gateway) ──HTTPS──▶ github.com / api.github.com
14
+ │ Client Secret, Private Key, Webhook Secret, token pengguna
15
+ │
16
+ └─ menerbitkan cliToken per akun
17
+ CLI menyimpan cliToken terenkripsi, lalu semua tools lewat backend.
18
+ ```
19
+
20
+ - **Backend** memiliki Client Secret, Private Key, Webhook Secret, access token,
21
+ dan refresh token.
22
+ - **CLI** hanya memiliki Client ID publik (boleh tampil), `cliToken` per akun
23
+ (AES-256-GCM di disk), dan cache identitas akun.
24
+ - Tools tidak pernah menerima access token GitHub; backend memasangnya saat
25
+ meneruskan request ke `api.github.com`.
26
+
27
+ ## Struktur modul
28
+
29
+ | File | Tanggung jawab |
30
+ | --- | --- |
31
+ | `index.js` | Deskriptor plugin untuk host |
32
+ | `manager.js` | Lifecycle: login, logout, status, enable/disable, test |
33
+ | `config.js` | Konfigurasi non-rahasia + path OS + state cache |
34
+ | `credentials.js` | Penyimpanan `cliToken` terenkripsi |
35
+ | `auth.js` | Membuka browser + pesan kegagalan login |
36
+ | `backend.js` | HTTP client ke backend (connect, session, status, proxy) |
37
+ | `api.js` | Klien GitHub REST melalui gateway + pagination |
38
+ | `tools*.js` | 35 tool AI, dikelompokkan per domain |
39
+ | `tool-helpers.js` | Validasi owner/repo/ref/path + pembatasan output |
40
+ | `errors.js` | Error plugin + kode yang stabil |
41
+ | `command.js` | Handler `/github` |
42
+
43
+ ## Konfigurasi lokal
44
+
45
+ Mengikuti direktori konfigurasi OS lewat `settingsDir()`:
46
+
47
+ ```
48
+ <config>/integrations/github/config.json (0600, non-rahasia)
49
+ <config>/integrations/github/state.json (0600, cache status)
50
+ <config>/integrations/github/credentials.enc (0600, cliToken terenkripsi)
51
+ <config>/.keys/github.key (0600, kunci enkripsi CLI)
52
+ ```
53
+
54
+ Linux memakai `$XDG_CONFIG_HOME` atau `~/.config`, macOS memakai
55
+ `~/Library/Application Support`, Windows memakai `%APPDATA%`.
56
+
57
+ Key yang dapat diubah:
58
+
59
+ ```
60
+ /github config set enabled true|false
61
+ /github config set autoRefresh true|false
62
+ /github config set confirmDestructive true|false
63
+ /github config set defaultRepo owner/repo
64
+ ```
65
+
66
+ Client Secret, Private Key, Webhook Secret, endpoint backend, dan token tidak
67
+ dapat diubah dari CLI dan tidak pernah ditulis ke file konfigurasi.
68
+
69
+ ## Command
70
+
71
+ ```
72
+ /github login login lewat browser (utama)
73
+ /github login --device device flow untuk mesin headless
74
+ /github logout putuskan akun + hapus kredensial lokal
75
+ /github status status integrasi, akun, token, backend
76
+ /github account identitas akun GitHub terhubung
77
+ /github test diagnostik aman (tanpa mengubah repository)
78
+ /github enable daftarkan tool ke agent
79
+ /github disable lepas tool (akun/token tetap)
80
+ /github config tampilkan konfigurasi non-rahasia
81
+ /github config set ... ubah satu key
82
+ ```
83
+
84
+ `/github status`, `/github account`, dan `/github config` tidak pernah
85
+ menampilkan Client Secret, Private Key, Webhook Secret, access token, refresh
86
+ token, atau `cliToken`.
87
+
88
+ ## Tool yang tersedia (35)
89
+
90
+ **Akun (3)** — `github_get_me`, `github_get_user`, `github_get_rate_limit`
91
+
92
+ **Repository (12)** — `github_list_repositories`, `github_get_repository`,
93
+ `github_create_repository`, `github_update_repository`, `github_list_branches`,
94
+ `github_get_branch`, `github_list_commits`, `github_get_commit`,
95
+ `github_get_file_contents`, `github_create_or_update_file`,
96
+ `github_delete_file`, `github_compare_commits`
97
+
98
+ **Issue (6)** — `github_list_issues`, `github_get_issue`,
99
+ `github_create_issue`, `github_update_issue`, `github_comment_issue`,
100
+ `github_list_issue_comments`
101
+
102
+ **Pull request (7)** — `github_list_pull_requests`, `github_get_pull_request`,
103
+ `github_create_pull_request`, `github_update_pull_request`,
104
+ `github_merge_pull_request`, `github_list_pull_request_files`,
105
+ `github_review_pull_request`
106
+
107
+ **Release (3)** — `github_list_releases`, `github_get_release`,
108
+ `github_create_release`
109
+
110
+ **GitHub Actions (4)** — `github_list_workflows`,
111
+ `github_list_workflow_runs`, `github_get_workflow_run`,
112
+ `github_rerun_workflow`
113
+
114
+ Tidak ada tool penghapusan repository. Penghapusan file dan merge pull request
115
+ berisiko `destructive` dan selalu melewati approval Ryuu.
116
+
117
+ ## Approval & keamanan
118
+
119
+ - `risk: read` berjalan tanpa prompt.
120
+ - Semua tool `write` memakai `requiresApproval: true`.
121
+ - `github_delete_file` dan `github_merge_pull_request` memakai
122
+ `risk: destructive` (approval wajib).
123
+ - `confirmDestructive: false` memblokir operasi destruktif di handler, bukan
124
+ hanya mengandalkan prompt.
125
+ - Tool memanggil `plugin.requireClient()` setiap kali, sehingga model yang
126
+ memegang daftar tool lama tidak bisa bertindak setelah `/github disable`.
127
+ - Output dibatasi: list dipotong, body panjang diringkas, isi file > 200 KB
128
+ hanya metadata.
129
+
130
+ ## Testing
131
+
132
+ ```bash
133
+ cd /root/agents/ryuu
134
+ node --test tests/unit/github.test.js tests/integration/github.test.js
135
+ ```
136
+
137
+ Test memakai mock backend lokal. Tidak ada koneksi ke domain produksi dan tidak
138
+ ada perubahan data GitHub nyata.
139
+
140
+ ## Troubleshooting
141
+
142
+ | Gejala | Tindakan |
143
+ | --- | --- |
144
+ | `Belum ada akun GitHub yang terhubung` | `/github login` |
145
+ | `Integrasi GitHub sedang nonaktif` | `/github enable` |
146
+ | `Sesi CLI sudah berakhir` | `/github login` lagi |
147
+ | `Akses ditolak` pada repository privat | Pastikan GitHub App diinstal ke akun/organisasi dan repository itu dipilih |
148
+ | `Rate limit` | Tunggu reset; cek `/github test` |
149
+ | `confirmDestructive=false` | `/github config set confirmDestructive true` |
150
+
151
+ Dokumentasi lengkap: [`../../docs/github.md`](../../docs/github.md).