gemini-reverse 1.0.7 → 1.0.9
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/CHANGELOG-EN.md +75 -0
- package/CHANGELOG-IDN.md +75 -0
- package/README-IDN.md +800 -0
- package/README.md +2 -0
- package/client.js +1 -1
- package/package.json +1 -1
package/CHANGELOG-EN.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
> **Language / Bahasa:** [English](CHANGELOG-EN.md) · [Indonesia](CHANGELOG-IDN.md) | **README:** [EN](README.md) · [IDN](README-IDN.md)
|
|
4
|
+
|
|
5
|
+
All notable changes to this project will be documented in this file.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## [1.0.7]
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- **Extended Thinking** — `extended_thinking` parameter on `generateContent`, `generateContentStream`, `sendMessage`, and `sendMessageStream`. Enables deeper reasoning mode on supported models. Model header is extended at request time with the thinking flag and session ID.
|
|
13
|
+
- **`StreamingFrameParser`** — New stateful incremental frame parser class replacing the stateless `parseResponseByFrame`. Buffers partial frames efficiently across network chunks without rescanning already-processed bytes.
|
|
14
|
+
- **Quota & Usage Info** — `client.quotas`, `client.usageInfo`, and `client.abuseStatus` properties are populated automatically at initialization via `CHECK_GEMINI_QUOTA`, `CHECK_QUOTA`, `GET_USAGE_INFO`, and `GET_ABUSE_STATUS` RPCs.
|
|
15
|
+
- **Activity Watchdog** — Background timer (`_startActivityWatchdog`) sends periodic heartbeats every 60–300 seconds to keep the session alive without requiring explicit user requests.
|
|
16
|
+
- **`_checkAccountStatus()`** — Internal method that guards RPC calls from running on restricted accounts.
|
|
17
|
+
- **`_parseRpcResults()`** — Internal helper iterator for extracting typed bodies from batch RPC responses, including rejection code handling (code 7 → mark unauthenticated).
|
|
18
|
+
- **`_sessionid`** — Per-session UUID generated at constructor and refreshed on each `init()`. Used as a field in the model header for each generation request.
|
|
19
|
+
- **`source_path` in `_batchExecute`** — Optional parameter (default `/app`, `/usage` for `_fetchUsageInfo`).
|
|
20
|
+
- **`model_number` in `AvailableModel`** — New field mirrored from model header into request payload (`inner[79]`).
|
|
21
|
+
- **`buildModelIdNumberMapping()`** — Static method on `AvailableModel` returning a `modelId → modelNumber` mapping.
|
|
22
|
+
- **New models** — `BASIC_LITE` (`gemini-3-lite`), `PLUS_LITE` (`gemini-3-lite-plus`), `ADVANCED_LITE` (`gemini-3-lite-advanced`).
|
|
23
|
+
- **New GRPC keys** — Added from `pr`: `GET_CONVERSATION_TURN`, `UPDATE_CONVERSATION`, `MARK_LAST_CONVERSATION_TURN`, `GENERATE_HEADLINE`, `GET_GEM`, `DELETE_GEM_AND_CONVERSATIONS`, `CREATE_TASK`, `GET_TASK`, `GET_ALL_TASKS`, `GET_TASKS_IN_CONVERSATION`, `GET_CANDIDATES`, `LIST_DISCOVERY_CARDS`, `GET_DISCOVERY_CARD`, `LIST_DISCOVERY_BANNERS`, `LIST_GEMINI_APP_ARTIFACTS`, `DELETE_GEMINI_APP_ARTIFACTS`, `LIST_MEMORIES`, `CREATE_MEMORY`, `UPDATE_MEMORY`, `DELETE_MEMORY`, `DELETE_ALL_MEMORIES`, `CHECK_GEMINI_QUOTA`, `CHECK_QUOTA`, `GET_ABUSE_STATUS`, `UPDATE_USER_PREFERENCES`, `READ_USER_PREFERENCES`, `CONTINUE_SHARED_CONVERSATION`, `GET_USAGE_INFO`.
|
|
24
|
+
- **Auto-refresh jitter** — Cookie refresh interval now applies ±15 seconds of random jitter to prevent synchronized background requests.
|
|
25
|
+
- **`_fetchPreferences()` / `_syncActivity()`** — Replaced monolithic `_sendBardSettings` / `_sendBardActivity` with dedicated methods that cleanly separate preference sync from activity heartbeat.
|
|
26
|
+
- **Case-insensitive model resolution** — `_resolveModelByName` now matches model names and display names case-insensitively.
|
|
27
|
+
- **`_fetchRecentChats` account guard** — Skips fetching chat history if account status is not available.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
- **Model header format** — Updated from `[4]` to `[4,5,6,8]` with a `model_number` appended at the end. Header `x-goog-ext-73010990-jspb` changed from `[0]` to `[0,0,0]`.
|
|
31
|
+
- **`Headers.BATCH_EXEC`** — Updated to match the new model header format.
|
|
32
|
+
- **Inner request array** — Size increased from 69 to 81 elements. `inner[68]` changed from `2` to `1`. New slots `inner[79]` (model_number) and `inner[80]` (thinking mode: `2` = extended, `1` = standard).
|
|
33
|
+
- **`_initRpc`** — Now calls `_fetchPreferences`, `_syncActivity`, `_fetchRecentChats`, `_fetchQuota`, `_fetchExtraQuota`, `_fetchAbuseStatus`, `_fetchUsageInfo` in sequence.
|
|
34
|
+
- **`THINKING` models removed** — `BASIC_THINKING`, `PLUS_THINKING`, `ADVANCED_THINKING` replaced by the `LITE` model family.
|
|
35
|
+
- **Upload cookies** — `uploadFile` now forwards session cookies alongside the `Push-ID` and REFERER headers.
|
|
36
|
+
- **HTML entity decoding** — Extended to cover numeric entities (`{`, ``) and additional named entities.
|
|
37
|
+
- **Video download headers** — `_downloadFile` in `video.js` now sends `Origin` and `Referer` headers.
|
|
38
|
+
- **`fetchGems` language** — Uses `this.language` instead of hardcoded `'en'`.
|
|
39
|
+
- **Auto-init on first call** — `generateContent` and `generateContentStream` call `init()` automatically if the client is not running.
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
- **Upload failure** — Fixed missing `Push-ID` header, content-type, and REFERER headers in `uploadFile`.
|
|
43
|
+
- **Quota key format** — Null entries in quota ID list are now filtered before joining, producing clean numeric keys (e.g. `11`, `4`) instead of `-11`, `-4`.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## [1.0.8]
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
- Fixed quota key format — null entries in quota ID list are now filtered before joining, producing clean numeric keys (e.g. `11`, `4`) instead of `-11`, `-4`.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## [1.0.6]
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
- Fixed file upload — upload now correctly sends cookies and required headers.
|
|
58
|
+
- Fixed media download for generated video and audio.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## [1.0.5]
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
- Fixed image generation parsing — `GeneratedImage` now uses `client_ref` pattern instead of requiring direct cookie injection.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## [1.0.4]
|
|
70
|
+
|
|
71
|
+
### Added
|
|
72
|
+
- Initial public release.
|
|
73
|
+
- `GeminiClient` with cookie-based authentication.
|
|
74
|
+
- Chat sessions, streaming, image generation, deep research, gems.
|
|
75
|
+
- TypeScript declarations.
|
package/CHANGELOG-IDN.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
> **Language / Bahasa:** [English](CHANGELOG-EN.md) · [Indonesia](CHANGELOG-IDN.md) | **README:** [EN](README.md) · [IDN](README-IDN.md)
|
|
4
|
+
|
|
5
|
+
Semua perubahan penting pada proyek ini didokumentasikan di file ini.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## [1.0.7]
|
|
10
|
+
|
|
11
|
+
### Ditambahkan
|
|
12
|
+
- **Extended Thinking** — Parameter `extended_thinking` pada `generateContent`, `generateContentStream`, `sendMessage`, dan `sendMessageStream`. Mengaktifkan mode penalaran yang lebih dalam pada model yang mendukung. Model header dimodifikasi saat request dengan menambahkan flag thinking dan session ID.
|
|
13
|
+
- **`StreamingFrameParser`** — Class parser frame stateful incremental yang menggantikan `parseResponseByFrame` yang stateless. Buffer frame parsial secara efisien lintas chunk jaringan tanpa perlu memindai ulang byte yang sudah diproses.
|
|
14
|
+
- **Quota & Info Penggunaan** — Property `client.quotas`, `client.usageInfo`, dan `client.abuseStatus` diisi otomatis saat inisialisasi via RPC `CHECK_GEMINI_QUOTA`, `CHECK_QUOTA`, `GET_USAGE_INFO`, dan `GET_ABUSE_STATUS`.
|
|
15
|
+
- **Activity Watchdog** — Timer background (`_startActivityWatchdog`) yang mengirim heartbeat berkala setiap 60–300 detik untuk menjaga sesi tetap aktif tanpa perlu request eksplisit dari pengguna.
|
|
16
|
+
- **`_checkAccountStatus()`** — Method internal untuk memastikan RPC tidak dijalankan pada akun yang dibatasi.
|
|
17
|
+
- **`_parseRpcResults()`** — Helper iterator internal untuk mengekstrak body dari respons batch RPC, termasuk penanganan rejection code (code 7 → tandai sebagai unauthenticated).
|
|
18
|
+
- **`_sessionid`** — UUID per-sesi yang dibuat di constructor dan diperbarui setiap `init()`. Digunakan sebagai field di model header untuk setiap request generasi.
|
|
19
|
+
- **`source_path` di `_batchExecute`** — Parameter opsional (default `/app`, `/usage` untuk `_fetchUsageInfo`).
|
|
20
|
+
- **`model_number` di `AvailableModel`** — Field baru yang dicerminkan dari model header ke payload request (`inner[79]`).
|
|
21
|
+
- **`buildModelIdNumberMapping()`** — Method static pada `AvailableModel` yang mengembalikan mapping `modelId → modelNumber`.
|
|
22
|
+
- **Model baru** — `BASIC_LITE` (`gemini-3-lite`), `PLUS_LITE` (`gemini-3-lite-plus`), `ADVANCED_LITE` (`gemini-3-lite-advanced`).
|
|
23
|
+
- **GRPC key baru** — Ditambahkan dari `pr`: `GET_CONVERSATION_TURN`, `UPDATE_CONVERSATION`, `MARK_LAST_CONVERSATION_TURN`, `GENERATE_HEADLINE`, `GET_GEM`, `DELETE_GEM_AND_CONVERSATIONS`, `CREATE_TASK`, `GET_TASK`, `GET_ALL_TASKS`, `GET_TASKS_IN_CONVERSATION`, `GET_CANDIDATES`, `LIST_DISCOVERY_CARDS`, `GET_DISCOVERY_CARD`, `LIST_DISCOVERY_BANNERS`, `LIST_GEMINI_APP_ARTIFACTS`, `DELETE_GEMINI_APP_ARTIFACTS`, `LIST_MEMORIES`, `CREATE_MEMORY`, `UPDATE_MEMORY`, `DELETE_MEMORY`, `DELETE_ALL_MEMORIES`, `CHECK_GEMINI_QUOTA`, `CHECK_QUOTA`, `GET_ABUSE_STATUS`, `UPDATE_USER_PREFERENCES`, `READ_USER_PREFERENCES`, `CONTINUE_SHARED_CONVERSATION`, `GET_USAGE_INFO`.
|
|
24
|
+
- **Jitter auto-refresh** — Interval refresh cookie kini menerapkan jitter acak ±15 detik untuk mencegah request background yang tersinkronisasi.
|
|
25
|
+
- **`_fetchPreferences()` / `_syncActivity()`** — Menggantikan `_sendBardSettings` / `_sendBardActivity` yang monolitik dengan method khusus yang memisahkan sinkronisasi preferensi dari heartbeat aktivitas.
|
|
26
|
+
- **Resolusi model case-insensitive** — `_resolveModelByName` kini mencocokkan nama model dan display name tanpa memperhatikan huruf besar/kecil.
|
|
27
|
+
- **Guard akun di `_fetchRecentChats`** — Melewati pengambilan riwayat chat jika status akun tidak tersedia.
|
|
28
|
+
|
|
29
|
+
### Diubah
|
|
30
|
+
- **Format model header** — Diperbarui dari `[4]` menjadi `[4,5,6,8]` dengan `model_number` ditambahkan di akhir. Header `x-goog-ext-73010990-jspb` berubah dari `[0]` menjadi `[0,0,0]`.
|
|
31
|
+
- **`Headers.BATCH_EXEC`** — Diperbarui mengikuti format model header baru.
|
|
32
|
+
- **Array request inner** — Ukuran bertambah dari 69 menjadi 81 elemen. `inner[68]` berubah dari `2` menjadi `1`. Slot baru `inner[79]` (model_number) dan `inner[80]` (mode thinking: `2` = extended, `1` = standar).
|
|
33
|
+
- **`_initRpc`** — Sekarang memanggil `_fetchPreferences`, `_syncActivity`, `_fetchRecentChats`, `_fetchQuota`, `_fetchExtraQuota`, `_fetchAbuseStatus`, `_fetchUsageInfo` secara berurutan.
|
|
34
|
+
- **Model THINKING dihapus** — `BASIC_THINKING`, `PLUS_THINKING`, `ADVANCED_THINKING` digantikan oleh keluarga model LITE.
|
|
35
|
+
- **Cookie upload** — `uploadFile` kini meneruskan cookie sesi bersama header `Push-ID` dan REFERER.
|
|
36
|
+
- **Decode HTML entity** — Diperluas untuk mencakup entity numerik (`{`, ``) dan entity bernama tambahan.
|
|
37
|
+
- **Header download video** — `_downloadFile` di `video.js` kini mengirim header `Origin` dan `Referer`.
|
|
38
|
+
- **Bahasa `fetchGems`** — Menggunakan `this.language` alih-alih hardcode `'en'`.
|
|
39
|
+
- **Auto-init saat panggilan pertama** — `generateContent` dan `generateContentStream` memanggil `init()` otomatis jika client belum berjalan.
|
|
40
|
+
|
|
41
|
+
### Diperbaiki
|
|
42
|
+
- **Kegagalan upload** — Memperbaiki header `Push-ID`, content-type, dan REFERER yang hilang di `uploadFile`.
|
|
43
|
+
- **Format kunci quota** — Entry null pada daftar ID quota kini difilter sebelum digabung, menghasilkan kunci numerik yang bersih (mis. `11`, `4`) alih-alih `-11`, `-4`.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## [1.0.8]
|
|
48
|
+
|
|
49
|
+
### Diperbaiki
|
|
50
|
+
- Memperbaiki format kunci quota — entry null pada daftar ID quota kini difilter sebelum digabung, menghasilkan kunci numerik yang bersih (mis. `11`, `4`) alih-alih `-11`, `-4`.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## [1.0.6]
|
|
55
|
+
|
|
56
|
+
### Diperbaiki
|
|
57
|
+
- Memperbaiki upload file — upload kini mengirim cookie dan header yang diperlukan dengan benar.
|
|
58
|
+
- Memperbaiki unduhan media untuk video dan audio yang dihasilkan.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## [1.0.5]
|
|
63
|
+
|
|
64
|
+
### Diperbaiki
|
|
65
|
+
- Memperbaiki parsing image generation — `GeneratedImage` kini menggunakan pola `client_ref` alih-alih membutuhkan injeksi cookie langsung.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## [1.0.4]
|
|
70
|
+
|
|
71
|
+
### Ditambahkan
|
|
72
|
+
- Rilis publik pertama.
|
|
73
|
+
- `GeminiClient` dengan autentikasi berbasis cookie.
|
|
74
|
+
- Chat session, streaming, image generation, deep research, gems.
|
|
75
|
+
- Deklarasi TypeScript.
|
package/README-IDN.md
ADDED
|
@@ -0,0 +1,800 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
# Gemini-Reverse
|
|
4
|
+
|
|
5
|
+
Client Node.js tidak resmi untuk [Google Gemini](https://gemini.google.com), terinspirasi dari [Gemini-API](https://github.com/HanaokaYuzu/Gemini-API) — proyek reverse engineering Python oleh [@HanaokaYuzu](https://github.com/HanaokaYuzu).
|
|
6
|
+
|
|
7
|
+
> **Language / Bahasa:** [English](README.md) · [Indonesia](README-IDN.md) | **Changelog:** [EN](CHANGELOG-EN.md) · [IDN](CHANGELOG-IDN.md)
|
|
8
|
+
|
|
9
|
+
## Fitur
|
|
10
|
+
|
|
11
|
+
- **Cookie Persisten** — Secara otomatis memperbarui cookie di latar belakang dengan jitter acak untuk mencegah request yang tersinkronisasi. Dioptimalkan untuk layanan yang selalu aktif.
|
|
12
|
+
- **Pembuatan Gambar** — Mendukung pembuatan dan pengeditan gambar secara native dengan bahasa natural.
|
|
13
|
+
- **Pembuatan Video & Audio** — Mendukung pembuatan video dan konten audio/musik secara native.
|
|
14
|
+
- **Deep Research** — Alur kerja penelitian mendalam lengkap dengan pembuatan rencana, polling status, dan pengambilan hasil.
|
|
15
|
+
- **Extended Thinking** — Mengaktifkan mode penalaran yang lebih dalam pada model yang mendukung.
|
|
16
|
+
- **System Prompt** — Mendukung kustomisasi system prompt model dengan [Gemini Gems](https://gemini.google.com/gems/view).
|
|
17
|
+
- **Dukungan Ekstensi** — Mendukung pembuatan konten dengan ekstensi Gemini seperti YouTube dan Gmail.
|
|
18
|
+
- **Output Terklasifikasi** — Mengkategorikan teks, pikiran, gambar, video, dan audio dalam respons.
|
|
19
|
+
- **Mode Streaming** — Mendukung streaming dengan parser frame stateful incremental, menghasilkan output parsial saat dibuat.
|
|
20
|
+
- **Penemuan Model Dinamis** — Menemukan model yang tersedia secara otomatis dari akun Anda saat inisialisasi.
|
|
21
|
+
- **Quota & Info Penggunaan** — Mengekspos batas quota akun, penggunaan komputasi, dan status abuse setelah inisialisasi.
|
|
22
|
+
- **Activity Watchdog** — Task heartbeat background yang menjaga sesi tetap aktif secara otomatis.
|
|
23
|
+
- **Dukungan TypeScript** — Deklarasi tipe TypeScript lengkap sudah tersedia.
|
|
24
|
+
|
|
25
|
+
## Daftar Isi
|
|
26
|
+
|
|
27
|
+
- [Fitur](#fitur)
|
|
28
|
+
- [Daftar Isi](#daftar-isi)
|
|
29
|
+
- [Instalasi](#instalasi)
|
|
30
|
+
- [Autentikasi](#autentikasi)
|
|
31
|
+
- [Penggunaan](#penggunaan)
|
|
32
|
+
- [Inisialisasi](#inisialisasi)
|
|
33
|
+
- [Generate Konten](#generate-konten)
|
|
34
|
+
- [Generate Konten dengan File](#generate-konten-dengan-file)
|
|
35
|
+
- [Percakapan Multi-Giliran](#percakapan-multi-giliran)
|
|
36
|
+
- [Lanjutkan Percakapan Sebelumnya](#lanjutkan-percakapan-sebelumnya)
|
|
37
|
+
- [Baca Riwayat Percakapan](#baca-riwayat-percakapan)
|
|
38
|
+
- [Daftar Chat Terbaru](#daftar-chat-terbaru)
|
|
39
|
+
- [Hapus Percakapan](#hapus-percakapan)
|
|
40
|
+
- [Mode Sementara](#mode-sementara)
|
|
41
|
+
- [Mode Streaming](#mode-streaming)
|
|
42
|
+
- [Extended Thinking](#extended-thinking)
|
|
43
|
+
- [Pilih Model Bahasa](#pilih-model-bahasa)
|
|
44
|
+
- [Daftar Model Tersedia](#daftar-model-tersedia)
|
|
45
|
+
- [Terapkan System Prompt dengan Gemini Gems](#terapkan-system-prompt-dengan-gemini-gems)
|
|
46
|
+
- [Kelola Custom Gems](#kelola-custom-gems)
|
|
47
|
+
- [Buat Custom Gem](#buat-custom-gem)
|
|
48
|
+
- [Perbarui Gem yang Ada](#perbarui-gem-yang-ada)
|
|
49
|
+
- [Hapus Custom Gem](#hapus-custom-gem)
|
|
50
|
+
- [Ambil Proses Berpikir Model](#ambil-proses-berpikir-model)
|
|
51
|
+
- [Ambil Gambar dalam Respons](#ambil-gambar-dalam-respons)
|
|
52
|
+
- [Generate dan Edit Gambar](#generate-dan-edit-gambar)
|
|
53
|
+
- [Ambil Video dan Audio](#ambil-video-dan-audio)
|
|
54
|
+
- [Generate Konten dengan Ekstensi Gemini](#generate-konten-dengan-ekstensi-gemini)
|
|
55
|
+
- [Periksa dan Ganti Kandidat Balasan](#periksa-dan-ganti-kandidat-balasan)
|
|
56
|
+
- [Deep Research](#deep-research)
|
|
57
|
+
- [Status Akun](#status-akun)
|
|
58
|
+
- [Quota dan Info Penggunaan](#quota-dan-info-penggunaan)
|
|
59
|
+
- [Penanganan Error](#penanganan-error)
|
|
60
|
+
- [Persistensi Cookie](#persistensi-cookie)
|
|
61
|
+
- [TypeScript](#typescript)
|
|
62
|
+
- [Struktur Proyek](#struktur-proyek)
|
|
63
|
+
- [Referensi](#referensi)
|
|
64
|
+
|
|
65
|
+
## Instalasi
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm install gemini-reverse
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Autentikasi
|
|
72
|
+
|
|
73
|
+
- Buka [gemini.google.com](https://gemini.google.com) dan masuk dengan akun Google Anda
|
|
74
|
+
- Tekan F12 untuk membuka DevTools, buka tab `Application` → `Cookies` → `https://gemini.google.com`
|
|
75
|
+
- Salin nilai `__Secure-1PSID` (dan opsional `__Secure-1PSIDTS`)
|
|
76
|
+
|
|
77
|
+
> `__Secure-1PSIDTS` bersifat opsional — client akan mencoba memperbarui dan menyimpan cache-nya secara otomatis setelah inisialisasi pertama yang berhasil.
|
|
78
|
+
|
|
79
|
+
## Penggunaan
|
|
80
|
+
|
|
81
|
+
### Inisialisasi
|
|
82
|
+
|
|
83
|
+
Import package dan inisialisasi client dengan cookie Anda. Setelah inisialisasi berhasil, client akan memperbarui `__Secure-1PSIDTS` secara otomatis di latar belakang dengan jitter acak, dan memulai watchdog heartbeat untuk menjaga sesi tetap aktif.
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
const { GeminiClient } = require('gemini-reverse');
|
|
87
|
+
|
|
88
|
+
const client = new GeminiClient({
|
|
89
|
+
secure_1psid: 'SECURE_1PSID_ANDA',
|
|
90
|
+
secure_1psidts: 'SECURE_1PSIDTS_ANDA', // opsional
|
|
91
|
+
proxy: null, // opsional, mis. 'http://host:port'
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
await client.init({
|
|
95
|
+
timeout: 300000, // timeout request dalam ms, default 300000
|
|
96
|
+
autoClose: false, // tutup client otomatis setelah tidak aktif
|
|
97
|
+
closeDelay: 300000, // delay sebelum menutup dalam ms
|
|
98
|
+
autoRefresh: true, // perbarui cookie + mulai activity watchdog
|
|
99
|
+
refreshInterval: 540000 // interval refresh cookie dalam ms
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
> `autoClose` dan `closeDelay` adalah argumen opsional untuk menutup client secara otomatis setelah tidak aktif dalam jangka waktu tertentu. Pada layanan yang selalu aktif seperti chatbot, disarankan untuk mengatur `autoClose` ke `true` dengan nilai `closeDelay` yang wajar untuk manajemen resource yang lebih baik.
|
|
104
|
+
|
|
105
|
+
### Generate Konten
|
|
106
|
+
|
|
107
|
+
Ajukan pertanyaan satu-giliran dengan memanggil `generateContent`, yang mengembalikan objek `ModelOutput` berisi teks yang dihasilkan, gambar, pikiran, dan metadata percakapan.
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
const response = await client.generateContent({ prompt: 'Halo Dunia!' });
|
|
111
|
+
console.log(response.text);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Generate Konten dengan File
|
|
115
|
+
|
|
116
|
+
Gemini mendukung input file, termasuk gambar dan dokumen. Kirimkan array path file atau objek `Buffer` bersama prompt teks Anda.
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
const response = await client.generateContent({
|
|
120
|
+
prompt: 'Deskripsikan isi file-file ini.',
|
|
121
|
+
files: ['./dokumen.pdf', './foto.png'],
|
|
122
|
+
});
|
|
123
|
+
console.log(response.text);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Percakapan Multi-Giliran
|
|
127
|
+
|
|
128
|
+
Gunakan `startChat` untuk membuat objek `ChatSession` dan kirim pesan melaluinya. Riwayat percakapan ditangani secara otomatis dan diperbarui setiap giliran.
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
const chat = client.startChat();
|
|
132
|
+
|
|
133
|
+
const res1 = await chat.sendMessage({ prompt: 'Nama saya Alice.' });
|
|
134
|
+
console.log(res1.text);
|
|
135
|
+
|
|
136
|
+
const res2 = await chat.sendMessage({ prompt: 'Siapa nama saya?' });
|
|
137
|
+
console.log(res2.text); // mengingat konteks
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Lanjutkan Percakapan Sebelumnya
|
|
141
|
+
|
|
142
|
+
Kirimkan metadata `ChatSession` sebelumnya ke `startChat` untuk melanjutkan percakapan. Anda dapat menyimpan metadata ke file atau database untuk memulihkannya setelah proses di-restart.
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
const chat = client.startChat();
|
|
146
|
+
await chat.sendMessage({ prompt: 'Cuaca hari ini cerah.' });
|
|
147
|
+
|
|
148
|
+
// Simpan metadata sesi
|
|
149
|
+
const savedMetadata = chat.metadata;
|
|
150
|
+
const savedCid = chat.cid;
|
|
151
|
+
|
|
152
|
+
// Lanjutkan di sesi baru
|
|
153
|
+
const previousChat = client.startChat({ metadata: savedMetadata });
|
|
154
|
+
const response = await previousChat.sendMessage({ prompt: 'Apa pesan saya sebelumnya?' });
|
|
155
|
+
console.log(response.text);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Baca Riwayat Percakapan
|
|
159
|
+
|
|
160
|
+
Ambil riwayat percakapan lengkap dengan memanggil `readChat` menggunakan ID chat. Mengembalikan objek `ChatHistory` berisi daftar objek `ChatTurn` dari terbaru ke terlama.
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
const chat = client.startChat();
|
|
164
|
+
await chat.sendMessage({ prompt: 'Apa ibu kota Prancis?' });
|
|
165
|
+
|
|
166
|
+
const history = await client.readChat(chat.cid);
|
|
167
|
+
if (history) {
|
|
168
|
+
for (const turn of history.turns) {
|
|
169
|
+
console.log(`[${turn.role.toUpperCase()}] ${turn.text}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Anda juga bisa membaca riwayat langsung dari sesi:
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
const history = await chat.readHistory(10); // ambil 10 giliran terakhir
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Daftar Chat Terbaru
|
|
181
|
+
|
|
182
|
+
Gunakan `listChats` untuk mendapatkan daftar sesi chat terbaru yang di-cache saat inisialisasi.
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
const chats = client.listChats();
|
|
186
|
+
if (chats) {
|
|
187
|
+
for (const info of chats) {
|
|
188
|
+
console.log(`${info.cid}: ${info.title} (disematkan: ${info.is_pinned})`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Hapus Percakapan
|
|
194
|
+
|
|
195
|
+
Hapus chat tertentu dari riwayat Gemini di server dengan memanggil `deleteChat` menggunakan ID chat.
|
|
196
|
+
|
|
197
|
+
```js
|
|
198
|
+
const chat = client.startChat();
|
|
199
|
+
await chat.sendMessage({ prompt: 'Ini percakapan sementara.' });
|
|
200
|
+
|
|
201
|
+
await client.deleteChat(chat.cid);
|
|
202
|
+
console.log(`Chat dihapus: ${chat.cid}`);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Mode Sementara
|
|
206
|
+
|
|
207
|
+
Kirimkan `temporary: true` ke `generateContent` atau `sendMessage` agar percakapan tidak tersimpan ke riwayat Gemini.
|
|
208
|
+
|
|
209
|
+
```js
|
|
210
|
+
const response = await client.generateContent({
|
|
211
|
+
prompt: 'Halo Dunia!',
|
|
212
|
+
temporary: true,
|
|
213
|
+
});
|
|
214
|
+
console.log(response.text);
|
|
215
|
+
|
|
216
|
+
// Juga berfungsi dalam sesi chat
|
|
217
|
+
const chat = client.startChat();
|
|
218
|
+
await chat.sendMessage({ prompt: 'Cuaca hari ini cerah.', temporary: false });
|
|
219
|
+
const res2 = await chat.sendMessage({ prompt: 'Apa pesan terakhir saya?', temporary: true });
|
|
220
|
+
console.log(res2.text);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Mode Streaming
|
|
224
|
+
|
|
225
|
+
Untuk respons yang panjang, gunakan mode streaming untuk menerima output parsial saat dihasilkan. Respons menggunakan `StreamingFrameParser` stateful secara internal sehingga frame parsial di-buffer secara efisien. Atribut `text_delta` hanya berisi **karakter baru** sejak yield terakhir.
|
|
226
|
+
|
|
227
|
+
```js
|
|
228
|
+
for await (const chunk of client.generateContentStream({
|
|
229
|
+
prompt: 'Apa perbedaan antara promise dan async/await?',
|
|
230
|
+
})) {
|
|
231
|
+
process.stdout.write(chunk.text_delta);
|
|
232
|
+
}
|
|
233
|
+
console.log();
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Streaming juga berfungsi dalam sesi chat:
|
|
237
|
+
|
|
238
|
+
```js
|
|
239
|
+
const chat = client.startChat();
|
|
240
|
+
for await (const chunk of chat.sendMessageStream({ prompt: 'Ceritakan sebuah kisah panjang.' })) {
|
|
241
|
+
process.stdout.write(chunk.text_delta);
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Extended Thinking
|
|
246
|
+
|
|
247
|
+
Kirimkan `extended_thinking: true` untuk mengaktifkan mode penalaran yang lebih dalam. Model akan meluangkan lebih banyak waktu untuk merencanakan sebelum merespons. Didukung pada model tier Pro dan Advanced.
|
|
248
|
+
|
|
249
|
+
```js
|
|
250
|
+
const { Model } = require('gemini-reverse');
|
|
251
|
+
|
|
252
|
+
const response = await client.generateContent({
|
|
253
|
+
prompt: 'Selesaikan langkah demi langkah: Jika sebuah kereta melaju 120 km/jam dan harus menempuh 450 km, berapa lama waktu yang dibutuhkan?',
|
|
254
|
+
model: Model.ADVANCED_PRO,
|
|
255
|
+
extended_thinking: true,
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
if (response.thoughts) {
|
|
259
|
+
console.log('Proses berpikir:', response.thoughts);
|
|
260
|
+
}
|
|
261
|
+
console.log('Jawaban:', response.text);
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Juga berfungsi dalam streaming dan chat:
|
|
265
|
+
|
|
266
|
+
```js
|
|
267
|
+
const chat = client.startChat({ model: Model.ADVANCED_FLASH });
|
|
268
|
+
const res = await chat.sendMessage({
|
|
269
|
+
prompt: 'Jelaskan masalah P vs NP.',
|
|
270
|
+
extended_thinking: true,
|
|
271
|
+
});
|
|
272
|
+
console.log(res.text);
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Pilih Model Bahasa
|
|
276
|
+
|
|
277
|
+
Tentukan model bahasa yang digunakan dengan mengoper argumen `model`. Model tersedia ditemukan secara dinamis saat inisialisasi berdasarkan tier akun Anda.
|
|
278
|
+
|
|
279
|
+
```js
|
|
280
|
+
const { Model } = require('gemini-reverse');
|
|
281
|
+
|
|
282
|
+
// Menggunakan konstanta bawaan
|
|
283
|
+
const response1 = await client.generateContent({
|
|
284
|
+
prompt: 'Apa versi model Anda?',
|
|
285
|
+
model: Model.BASIC_FLASH,
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// Menggunakan string nama model (case-insensitive)
|
|
289
|
+
const chat = client.startChat({ model: 'gemini-3-pro' });
|
|
290
|
+
|
|
291
|
+
// Menggunakan dict model header kustom
|
|
292
|
+
const chat2 = client.startChat({
|
|
293
|
+
model: {
|
|
294
|
+
model_name: 'kustom',
|
|
295
|
+
model_header: {
|
|
296
|
+
'x-goog-ext-525001261-jspb': '[1,null,null,null,"MODEL_ID",null,null,0,[4,5,6,8],null,null,1,null,null,1]',
|
|
297
|
+
'x-goog-ext-73010989-jspb': '[0]',
|
|
298
|
+
'x-goog-ext-73010990-jspb': '[0,0,0]',
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**Konstanta model bawaan:**
|
|
305
|
+
|
|
306
|
+
| Konstanta | `model_name` | Catatan |
|
|
307
|
+
|---|---|---|
|
|
308
|
+
| `Model.UNSPECIFIED` | `unspecified` | Default, Gemini memilih sendiri |
|
|
309
|
+
| `Model.BASIC_PRO` | `gemini-3-pro` | Tier gratis |
|
|
310
|
+
| `Model.BASIC_FLASH` | `gemini-3-flash` | Tier gratis, tercepat |
|
|
311
|
+
| `Model.BASIC_LITE` | `gemini-3-lite` | Tier gratis, ringan |
|
|
312
|
+
| `Model.PLUS_PRO` | `gemini-3-pro-plus` | Tier Plus |
|
|
313
|
+
| `Model.PLUS_FLASH` | `gemini-3-flash-plus` | Tier Plus |
|
|
314
|
+
| `Model.PLUS_LITE` | `gemini-3-lite-plus` | Tier Plus |
|
|
315
|
+
| `Model.ADVANCED_PRO` | `gemini-3-pro-advanced` | Tier Advanced |
|
|
316
|
+
| `Model.ADVANCED_FLASH` | `gemini-3-flash-advanced` | Tier Advanced |
|
|
317
|
+
| `Model.ADVANCED_LITE` | `gemini-3-lite-advanced` | Tier Advanced |
|
|
318
|
+
|
|
319
|
+
### Daftar Model Tersedia
|
|
320
|
+
|
|
321
|
+
Client menemukan model mana yang dapat diakses akun Anda secara dinamis saat inisialisasi. Gunakan `listModels` untuk memeriksanya.
|
|
322
|
+
|
|
323
|
+
```js
|
|
324
|
+
await client.init();
|
|
325
|
+
|
|
326
|
+
const models = client.listModels();
|
|
327
|
+
if (models) {
|
|
328
|
+
for (const model of models) {
|
|
329
|
+
console.log(`${model.model_id} → ${model.model_name || model.display_name}`);
|
|
330
|
+
console.log(` capacity: ${model.capacity}, model_number: ${model.model_number}, advanced_only: ${model.advanced_only}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Terapkan System Prompt dengan Gemini Gems
|
|
336
|
+
|
|
337
|
+
System prompt dapat diterapkan pada percakapan melalui [Gemini Gems](https://gemini.google.com/gems/view). Kirimkan argumen `gem` ke `generateContent` atau `startChat` — bisa berupa objek `Gem` atau string ID gem.
|
|
338
|
+
|
|
339
|
+
```js
|
|
340
|
+
// Ambil semua gems untuk akun
|
|
341
|
+
await client.fetchGems();
|
|
342
|
+
const gems = client.gems;
|
|
343
|
+
|
|
344
|
+
// Dapatkan gem tertentu
|
|
345
|
+
const codingPartner = gems.get({ name: 'Coding partner' });
|
|
346
|
+
|
|
347
|
+
const response = await client.generateContent({
|
|
348
|
+
prompt: 'Apa system prompt Anda?',
|
|
349
|
+
gem: codingPartner,
|
|
350
|
+
});
|
|
351
|
+
console.log(response.text);
|
|
352
|
+
|
|
353
|
+
// Gunakan gem dalam chat multi-giliran
|
|
354
|
+
const chat = client.startChat({ gem: codingPartner });
|
|
355
|
+
const res2 = await chat.sendMessage({ prompt: 'Bantu saya menulis binary search.' });
|
|
356
|
+
console.log(res2.text);
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
> Ada beberapa gems sistem bawaan yang tersembunyi secara default. Gunakan `fetchGems({ includeHidden: true })` untuk menyertakannya.
|
|
360
|
+
|
|
361
|
+
### Kelola Custom Gems
|
|
362
|
+
|
|
363
|
+
Anda dapat membuat, memperbarui, dan menghapus custom gems secara programatik. Gems sistem bawaan tidak dapat dimodifikasi.
|
|
364
|
+
|
|
365
|
+
#### Buat Custom Gem
|
|
366
|
+
|
|
367
|
+
```js
|
|
368
|
+
const newGem = await client.createGem({
|
|
369
|
+
name: 'Tutor Python',
|
|
370
|
+
prompt: 'Anda adalah tutor pemrograman Python yang membantu. Selalu berikan contoh kode yang dapat dijalankan.',
|
|
371
|
+
description: 'Gem khusus untuk pemrograman Python',
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
console.log(`Dibuat: ${newGem.id}`);
|
|
375
|
+
|
|
376
|
+
// Gunakan gem baru segera
|
|
377
|
+
const response = await client.generateContent({
|
|
378
|
+
prompt: 'Jelaskan list comprehension.',
|
|
379
|
+
gem: newGem,
|
|
380
|
+
});
|
|
381
|
+
console.log(response.text);
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
#### Perbarui Gem yang Ada
|
|
385
|
+
|
|
386
|
+
> Saat memperbarui gem, semua parameter (`name`, `prompt`, `description`) harus disediakan meskipun hanya satu yang berubah.
|
|
387
|
+
|
|
388
|
+
```js
|
|
389
|
+
await client.fetchGems();
|
|
390
|
+
const pythonTutor = client.gems.get({ name: 'Tutor Python' });
|
|
391
|
+
|
|
392
|
+
const updatedGem = await client.updateGem({
|
|
393
|
+
gem: pythonTutor,
|
|
394
|
+
name: 'Tutor Python Lanjutan',
|
|
395
|
+
prompt: 'Anda adalah tutor pemrograman Python ahli. Fokus pada performa dan praktik terbaik.',
|
|
396
|
+
description: 'Asisten pemrograman Python tingkat lanjut',
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
console.log(`Diperbarui: ${updatedGem.id}`);
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
#### Hapus Custom Gem
|
|
403
|
+
|
|
404
|
+
```js
|
|
405
|
+
await client.fetchGems();
|
|
406
|
+
const gemToDelete = client.gems.get({ name: 'Tutor Python Lanjutan' });
|
|
407
|
+
|
|
408
|
+
await client.deleteGem(gemToDelete); // bisa juga kirim string ID gem
|
|
409
|
+
console.log(`Dihapus: ${gemToDelete.name}`);
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Ambil Proses Berpikir Model
|
|
413
|
+
|
|
414
|
+
Saat menggunakan model yang mendukung kemampuan berpikir, proses penalaran internal model diekspos melalui `response.thoughts`.
|
|
415
|
+
|
|
416
|
+
```js
|
|
417
|
+
const response = await client.generateContent({
|
|
418
|
+
prompt: 'Berapa 17 × 23?',
|
|
419
|
+
model: Model.BASIC_FLASH,
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
if (response.thoughts) {
|
|
423
|
+
console.log('Pemikiran:', response.thoughts);
|
|
424
|
+
}
|
|
425
|
+
console.log('Jawaban:', response.text);
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Ambil Gambar dalam Respons
|
|
429
|
+
|
|
430
|
+
Gambar dalam respons disimpan sebagai daftar objek `Image` yang dapat diakses melalui `response.images`. Setiap gambar memiliki `url`, `title`, dan deskripsi `alt`.
|
|
431
|
+
|
|
432
|
+
```js
|
|
433
|
+
const response = await client.generateContent({ prompt: 'Kirimkan beberapa foto kucing.' });
|
|
434
|
+
|
|
435
|
+
for (const image of response.images) {
|
|
436
|
+
console.log(`${image.title}: ${image.url}`);
|
|
437
|
+
console.log(`Alt: ${image.alt}`);
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Generate dan Edit Gambar
|
|
442
|
+
|
|
443
|
+
Minta Gemini untuk menghasilkan atau mengedit gambar menggunakan bahasa natural. Gambar yang dihasilkan dikembalikan sebagai objek `GeneratedImage` dan dapat disimpan ke disk.
|
|
444
|
+
|
|
445
|
+
> Google memiliki batasan ketersediaan pembuatan gambar yang bervariasi menurut wilayah dan jenis akun. Pengguna di bawah 18 tahun tidak dapat menggunakan fitur ini.
|
|
446
|
+
|
|
447
|
+
```js
|
|
448
|
+
const response = await client.generateContent({
|
|
449
|
+
prompt: 'Buat gambar realistis kucing berpakaian astronot.',
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
for (let i = 0; i < response.images.length; i++) {
|
|
453
|
+
const image = response.images[i];
|
|
454
|
+
const savedPath = await image.save({
|
|
455
|
+
path: './temp',
|
|
456
|
+
filename: `kucing_angkasa_${i}.png`,
|
|
457
|
+
verbose: true,
|
|
458
|
+
});
|
|
459
|
+
console.log(`Disimpan ke: ${savedPath}`);
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
> Saat meminta Gemini "mengirim" gambar, ia mengembalikan gambar web (`WebImage`). Saat meminta "menghasilkan" gambar, ia mengembalikan gambar yang dihasilkan AI (`GeneratedImage`). Keduanya dikategorikan otomatis di `response.images`.
|
|
464
|
+
|
|
465
|
+
### Ambil Video dan Audio
|
|
466
|
+
|
|
467
|
+
Gemini dapat menghasilkan video pendek dan audio/musik. Dikembalikan sebagai objek `GeneratedVideo` dan `GeneratedMedia` di `response.videos` dan `response.media`.
|
|
468
|
+
|
|
469
|
+
> Anda mungkin memerlukan langganan Gemini aktif untuk mengakses pembuatan video dan audio.
|
|
470
|
+
|
|
471
|
+
```js
|
|
472
|
+
// Generate video
|
|
473
|
+
const videoResponse = await client.generateContent({
|
|
474
|
+
prompt: 'Buat video pendek ombak di pantai.',
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
for (const video of videoResponse.videos) {
|
|
478
|
+
const result = await video.save({ savePath: './temp', verbose: true });
|
|
479
|
+
console.log('Video:', result.video);
|
|
480
|
+
console.log('Thumbnail:', result.video_thumbnail);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// Generate audio/musik
|
|
484
|
+
const mediaResponse = await client.generateContent({
|
|
485
|
+
prompt: 'Buat melodi piano yang menenangkan.',
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
for (const media of mediaResponse.media) {
|
|
489
|
+
// downloadType: 'audio' | 'video' | 'both' (default)
|
|
490
|
+
const result = await media.save({ savePath: './temp', downloadType: 'both', verbose: true });
|
|
491
|
+
console.log('MP3:', result.audio);
|
|
492
|
+
console.log('MP4:', result.video);
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
> `GeneratedMedia.save()` menerima parameter `downloadType`: `"audio"`, `"video"`, atau `"both"` (default). Metode save akan polling otomatis jika konten masih dalam proses generate (HTTP 206).
|
|
497
|
+
|
|
498
|
+
### Generate Konten dengan Ekstensi Gemini
|
|
499
|
+
|
|
500
|
+
Untuk menggunakan ekstensi Gemini (Gmail, YouTube, dll.), Anda harus mengaktifkannya terlebih dahulu di [situs Gemini](https://gemini.google.com/extensions). Referensikan dalam prompt dengan awalan `@` atau dalam bahasa natural.
|
|
501
|
+
|
|
502
|
+
> Anda harus mengaktifkan Gemini Apps Activity di akun untuk menggunakan ekstensi.
|
|
503
|
+
|
|
504
|
+
```js
|
|
505
|
+
const gmailResponse = await client.generateContent({
|
|
506
|
+
prompt: '@Gmail Apa pesan terbaru di kotak masuk saya?',
|
|
507
|
+
});
|
|
508
|
+
console.log(gmailResponse.text);
|
|
509
|
+
|
|
510
|
+
const youtubeResponse = await client.generateContent({
|
|
511
|
+
prompt: '@YouTube Apa video terbaru dari channel Fireship?',
|
|
512
|
+
});
|
|
513
|
+
console.log(youtubeResponse.text);
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### Periksa dan Ganti Kandidat Balasan
|
|
517
|
+
|
|
518
|
+
Respons Gemini terkadang berisi beberapa kandidat balasan dengan konten yang berbeda. Anda dapat memeriksa semua kandidat dan memilih satu untuk melanjutkan alur percakapan.
|
|
519
|
+
|
|
520
|
+
```js
|
|
521
|
+
const chat = client.startChat();
|
|
522
|
+
const response = await chat.sendMessage({ prompt: 'Rekomendasikan buku fiksi ilmiah.' });
|
|
523
|
+
|
|
524
|
+
// Daftar semua kandidat
|
|
525
|
+
response.candidates.forEach((candidate, i) => {
|
|
526
|
+
console.log(`[${i}] ${candidate.text.slice(0, 80)}...`);
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
if (response.candidates.length > 1) {
|
|
530
|
+
// Pilih kandidat kedua untuk dilanjutkan
|
|
531
|
+
chat.chooseCandidate(1);
|
|
532
|
+
|
|
533
|
+
const followup = await chat.sendMessage({ prompt: 'Ceritakan lebih lanjut tentangnya.' });
|
|
534
|
+
console.log(followup.text);
|
|
535
|
+
} else {
|
|
536
|
+
console.log('Hanya ada satu kandidat.');
|
|
537
|
+
}
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### Deep Research
|
|
541
|
+
|
|
542
|
+
Fitur deep research Gemini adalah agen otonom yang menjelajahi web, menganalisis sumber, dan menghasilkan laporan komprehensif.
|
|
543
|
+
|
|
544
|
+
> Anda mungkin memerlukan langganan Gemini aktif untuk mengakses deep research.
|
|
545
|
+
|
|
546
|
+
**Metode satu panggilan cepat:**
|
|
547
|
+
|
|
548
|
+
```js
|
|
549
|
+
const result = await client.deepResearch(
|
|
550
|
+
'Bandingkan 3 penyedia cloud teratas dan penawaran AI mereka',
|
|
551
|
+
10000, // interval polling dalam ms
|
|
552
|
+
600000, // timeout dalam ms
|
|
553
|
+
(status) => console.log(`Status: ${status.state} — ${status.notes.slice(0, 1).join(', ')}`),
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
console.log(`Selesai: ${result.done}`);
|
|
557
|
+
console.log(result.text);
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
**Alur kerja langkah demi langkah** untuk kontrol lebih:
|
|
561
|
+
|
|
562
|
+
```js
|
|
563
|
+
// Langkah 1: Buat rencana penelitian
|
|
564
|
+
const plan = await client.createDeepResearchPlan(
|
|
565
|
+
'Apa kemajuan terbaru dalam komputasi kuantum?'
|
|
566
|
+
);
|
|
567
|
+
|
|
568
|
+
console.log(`Judul: ${plan.title}`);
|
|
569
|
+
console.log(`ETA: ${plan.eta_text}`);
|
|
570
|
+
for (const step of plan.steps) {
|
|
571
|
+
console.log(` - ${step}`);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Langkah 2: Mulai penelitian
|
|
575
|
+
const startOutput = await client.startDeepResearch(plan);
|
|
576
|
+
console.log('Penelitian dimulai:', startOutput.text.slice(0, 100));
|
|
577
|
+
|
|
578
|
+
// Langkah 3: Poll hingga selesai
|
|
579
|
+
const result = await client.waitForDeepResearch(
|
|
580
|
+
plan,
|
|
581
|
+
10000, // interval polling dalam ms
|
|
582
|
+
600000, // timeout dalam ms
|
|
583
|
+
(status) => console.log(`[${status.state}] ${status.notes[0] || ''}`),
|
|
584
|
+
);
|
|
585
|
+
|
|
586
|
+
console.log(result.text);
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
### Status Akun
|
|
590
|
+
|
|
591
|
+
Client mendeteksi tier kemampuan akun Anda saat inisialisasi dan mengeksposnya melalui `client.accountStatus`.
|
|
592
|
+
|
|
593
|
+
```js
|
|
594
|
+
const { AccountStatus } = require('gemini-reverse');
|
|
595
|
+
|
|
596
|
+
await client.init();
|
|
597
|
+
|
|
598
|
+
if (client.accountStatus === AccountStatus.AVAILABLE) {
|
|
599
|
+
console.log('Akun terotorisasi penuh.');
|
|
600
|
+
} else if (client.accountStatus === AccountStatus.UNAUTHENTICATED) {
|
|
601
|
+
console.error('Cookie kedaluwarsa atau tidak valid.');
|
|
602
|
+
} else if (client.accountStatus === AccountStatus.LOCATION_REJECTED) {
|
|
603
|
+
console.error('Gemini tidak tersedia di wilayah Anda.');
|
|
604
|
+
} else {
|
|
605
|
+
console.warn(`Status akun: ${client.accountStatus.name} — ${client.accountStatus.description}`);
|
|
606
|
+
}
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
**Semua nilai status akun:**
|
|
610
|
+
|
|
611
|
+
| Konstanta | Kode | Deskripsi |
|
|
612
|
+
|---|---|---|
|
|
613
|
+
| `AccountStatus.AVAILABLE` | 1000 | Akun terotorisasi dan memiliki akses normal |
|
|
614
|
+
| `AccountStatus.ACCESS_TEMPORARILY_UNAVAILABLE` | 1014 | Akses dibatasi, mungkin wilayah/sementara |
|
|
615
|
+
| `AccountStatus.UNAUTHENTICATED` | 1016 | Cookie kedaluwarsa atau tidak valid |
|
|
616
|
+
| `AccountStatus.ACCOUNT_REJECTED` | 1021 | Akses akun ditolak |
|
|
617
|
+
| `AccountStatus.ACCOUNT_UNTRUSTED` | 1033 | Tidak lulus pemeriksaan keamanan/kepercayaan |
|
|
618
|
+
| `AccountStatus.TOS_PENDING` | 1040 | Harus menerima Syarat Layanan terbaru |
|
|
619
|
+
| `AccountStatus.TOS_OUT_OF_DATE` | 1042 | Syarat Layanan sudah usang |
|
|
620
|
+
| `AccountStatus.ACCOUNT_REJECTED_BY_GUARDIAN` | 1054 | Diblokir oleh orang tua atau wali |
|
|
621
|
+
| `AccountStatus.GUARDIAN_APPROVAL_REQUIRED` | 1057 | Memerlukan persetujuan orang tua |
|
|
622
|
+
| `AccountStatus.LOCATION_REJECTED` | 1060 | Tidak tersedia di negara/wilayah Anda |
|
|
623
|
+
|
|
624
|
+
### Quota dan Info Penggunaan
|
|
625
|
+
|
|
626
|
+
Setelah inisialisasi, client mengambil batas quota akun dan metrik penggunaan komputasi secara otomatis. Akses melalui `client.quotas`, `client.usageInfo`, dan `client.abuseStatus`.
|
|
627
|
+
|
|
628
|
+
```js
|
|
629
|
+
await client.init();
|
|
630
|
+
|
|
631
|
+
// Batas quota (Flash, Pro, fitur ekstra)
|
|
632
|
+
const quotas = client.quotas;
|
|
633
|
+
for (const [id, q] of Object.entries(quotas)) {
|
|
634
|
+
if (q.label) {
|
|
635
|
+
const remaining = q.remaining !== null ? `${q.remaining}/${q.total}` : 'tak terbatas';
|
|
636
|
+
console.log(`${q.label}: ${remaining} kredit (${q.usage_percentage?.toFixed(1) ?? '?'}% terpakai)`);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// Penggunaan komputasi (jendela 5 jam dan mingguan)
|
|
641
|
+
const usage = client.usageInfo;
|
|
642
|
+
if (usage.tier) {
|
|
643
|
+
console.log(`Tier akun: ${usage.tier.label}`);
|
|
644
|
+
}
|
|
645
|
+
if (usage.current_5h) {
|
|
646
|
+
console.log(`Jendela 5 jam: ${usage.current_5h.remaining_credits} kredit tersisa (${usage.current_5h.usage_percentage}% terpakai)`);
|
|
647
|
+
}
|
|
648
|
+
if (usage.weekly) {
|
|
649
|
+
console.log(`Mingguan: ${usage.weekly.remaining_credits} kredit tersisa`);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// Status abuse
|
|
653
|
+
const abuse = client.abuseStatus;
|
|
654
|
+
if (abuse) {
|
|
655
|
+
console.log(`Akun bersih: ${abuse.is_clean}`);
|
|
656
|
+
}
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
## Penanganan Error
|
|
660
|
+
|
|
661
|
+
```js
|
|
662
|
+
const {
|
|
663
|
+
AuthError,
|
|
664
|
+
APIError,
|
|
665
|
+
GeminiError,
|
|
666
|
+
TimeoutError,
|
|
667
|
+
UsageLimitExceeded,
|
|
668
|
+
ModelInvalid,
|
|
669
|
+
TemporarilyBlocked,
|
|
670
|
+
} = require('gemini-reverse');
|
|
671
|
+
|
|
672
|
+
try {
|
|
673
|
+
const response = await chat.sendMessage({ prompt: 'Halo!' });
|
|
674
|
+
console.log(response.text);
|
|
675
|
+
} catch (e) {
|
|
676
|
+
if (e instanceof AuthError) {
|
|
677
|
+
console.error('Cookie kedaluwarsa atau tidak valid. Perbarui cookie Anda.');
|
|
678
|
+
} else if (e instanceof UsageLimitExceeded) {
|
|
679
|
+
console.error('Batas penggunaan tercapai. Coba lagi nanti atau ganti model.');
|
|
680
|
+
} else if (e instanceof TemporarilyBlocked) {
|
|
681
|
+
console.error('IP diblokir sementara oleh Google. Coba gunakan proxy atau tunggu.');
|
|
682
|
+
} else if (e instanceof TimeoutError) {
|
|
683
|
+
console.error('Request timeout. Coba tingkatkan nilai timeout di init().');
|
|
684
|
+
} else if (e instanceof ModelInvalid) {
|
|
685
|
+
console.error('Model tidak valid atau tidak tersedia. Coba model lain.');
|
|
686
|
+
} else if (e instanceof APIError) {
|
|
687
|
+
console.error('API error:', e.message);
|
|
688
|
+
} else {
|
|
689
|
+
throw e;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
## Persistensi Cookie
|
|
695
|
+
|
|
696
|
+
Jika aplikasi Anda berjalan di lingkungan container (mis. Docker), Anda dapat menyimpan cache cookie yang diperbarui otomatis ke volume dengan mengatur variabel environment `GEMINI_COOKIE_PATH` ke path yang dapat ditulis.
|
|
697
|
+
|
|
698
|
+
```yaml
|
|
699
|
+
# docker-compose.yml
|
|
700
|
+
services:
|
|
701
|
+
app:
|
|
702
|
+
environment:
|
|
703
|
+
GEMINI_COOKIE_PATH: /tmp/gemini_cache
|
|
704
|
+
volumes:
|
|
705
|
+
- ./gemini_cookies:/tmp/gemini_cache
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
Secara default, cache disimpan di `utils/temp/` relatif terhadap direktori package.
|
|
709
|
+
|
|
710
|
+
## TypeScript
|
|
711
|
+
|
|
712
|
+
Package ini menyertakan deklarasi TypeScript lengkap.
|
|
713
|
+
|
|
714
|
+
```ts
|
|
715
|
+
import {
|
|
716
|
+
GeminiClient,
|
|
717
|
+
ChatSession,
|
|
718
|
+
ModelOutput,
|
|
719
|
+
ChatHistory,
|
|
720
|
+
ChatTurn,
|
|
721
|
+
ChatInfo,
|
|
722
|
+
Gem,
|
|
723
|
+
AvailableModel,
|
|
724
|
+
Model,
|
|
725
|
+
AccountStatus,
|
|
726
|
+
DeepResearchPlan,
|
|
727
|
+
DeepResearchResult,
|
|
728
|
+
StreamingFrameParser,
|
|
729
|
+
} from 'gemini-reverse';
|
|
730
|
+
|
|
731
|
+
const client = new GeminiClient({ secure_1psid: '...' });
|
|
732
|
+
await client.init();
|
|
733
|
+
|
|
734
|
+
const chat: ChatSession = client.startChat({ model: 'gemini-3-flash' });
|
|
735
|
+
const response: ModelOutput = await chat.sendMessage({
|
|
736
|
+
prompt: 'Halo!',
|
|
737
|
+
extended_thinking: false,
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
console.log(response.text);
|
|
741
|
+
|
|
742
|
+
const history: ChatHistory | null = await chat.readHistory();
|
|
743
|
+
if (history) {
|
|
744
|
+
history.turns.forEach((turn: ChatTurn) => console.log(turn.role, turn.text));
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
const models: AvailableModel[] | null = client.listModels();
|
|
748
|
+
|
|
749
|
+
// Akses quota dan usage setelah init
|
|
750
|
+
console.log(client.quotas);
|
|
751
|
+
console.log(client.usageInfo);
|
|
752
|
+
console.log(client.abuseStatus);
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
## Struktur Proyek
|
|
756
|
+
|
|
757
|
+
```
|
|
758
|
+
gemini-reverse/
|
|
759
|
+
├── index.js # entry point & ekspor
|
|
760
|
+
├── index.d.ts # deklarasi TypeScript
|
|
761
|
+
├── client.js # GeminiClient + ChatSession
|
|
762
|
+
├── constants.js # Endpoint, GRPC, Headers, Model, AccountStatus, ErrorCode
|
|
763
|
+
├── exceptions.js # kelas error kustom
|
|
764
|
+
├── types/
|
|
765
|
+
│ ├── availablemodel.js # AvailableModel (model dinamis dari API)
|
|
766
|
+
│ ├── candidate.js # Candidate
|
|
767
|
+
│ ├── chathistory.js # ChatTurn, ChatHistory
|
|
768
|
+
│ ├── chatinfo.js # ChatInfo
|
|
769
|
+
│ ├── gem.js # Gem, GemJar
|
|
770
|
+
│ ├── grpc.js # RPCData
|
|
771
|
+
│ ├── image.js # Image, WebImage, GeneratedImage
|
|
772
|
+
│ ├── modeloutput.js # ModelOutput
|
|
773
|
+
│ ├── research.js # DeepResearchPlan, DeepResearchStatus
|
|
774
|
+
│ ├── researchresult.js # DeepResearchResult
|
|
775
|
+
│ └── video.js # Video, GeneratedVideo, GeneratedMedia
|
|
776
|
+
├── utils/
|
|
777
|
+
│ ├── accessToken.js # penanganan cookie & request init
|
|
778
|
+
│ ├── parsing.js # utilitas parsing respons + StreamingFrameParser
|
|
779
|
+
│ ├── research.js # ekstraktor payload deep research
|
|
780
|
+
│ ├── rotate.js # rotasi cookie
|
|
781
|
+
│ └── upload.js # helper upload file
|
|
782
|
+
└── components/
|
|
783
|
+
├── chatMixin.js # metode riwayat chat
|
|
784
|
+
├── gemMixin.js # metode manajemen gem
|
|
785
|
+
└── researchMixin.js # metode deep research
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
## Referensi
|
|
789
|
+
|
|
790
|
+
[Google AI Studio](https://ai.google.dev/tutorials/ai-studio_quickstart)
|
|
791
|
+
|
|
792
|
+
[Gemini-API (Python)](https://github.com/HanaokaYuzu/Gemini-API) oleh [@HanaokaYuzu](https://github.com/HanaokaYuzu)
|
|
793
|
+
|
|
794
|
+
[acheong08/Bard](https://github.com/acheong08/Bard)
|
|
795
|
+
|
|
796
|
+
---
|
|
797
|
+
|
|
798
|
+
**Peringatan:** Ini adalah package tidak resmi dan tidak berafiliasi dengan atau didukung oleh Google. Autentikasi berbasis cookie mungkin tidak berfungsi jika Google mengubah API internalnya. Gunakan dengan risiko Anda sendiri.
|
|
799
|
+
|
|
800
|
+
**Lisensi:** MIT
|
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
An unofficial Node.js client for [Google Gemini](https://gemini.google.com), inspired by [Gemini-API](https://github.com/HanaokaYuzu/Gemini-API) — a Python reverse engineering project by [@HanaokaYuzu](https://github.com/HanaokaYuzu).
|
|
6
6
|
|
|
7
|
+
> **Language / Bahasa:** [English](README.md) · [Indonesia](README-IDN.md) | **Changelog:** [EN](CHANGELOG-EN.md) · [IDN](CHANGELOG-IDN.md)
|
|
8
|
+
|
|
7
9
|
## Features
|
|
8
10
|
|
|
9
11
|
- **Persistent Cookies** — Automatically refreshes cookies in the background with jitter to prevent synchronized requests. Optimized for always-on services.
|
package/client.js
CHANGED
|
@@ -317,7 +317,7 @@ class GeminiClient {
|
|
|
317
317
|
const resetTs = getNestedValue(item, [3, 0]);
|
|
318
318
|
const total = getNestedValue(item, [4]);
|
|
319
319
|
const remaining = getNestedValue(item, [5]);
|
|
320
|
-
const quotaId = quotaIdList.join('-');
|
|
320
|
+
const quotaId = quotaIdList.filter(x => x != null).join('-') || String(actionId);
|
|
321
321
|
const label = actionLabels[actionId] || `Gemini ${key}`;
|
|
322
322
|
this._quotas[quotaId] = { usage_percentage: usageLevel, reset_time: resetTs, total, remaining, action_id: actionId, label: `${label} [${quotaId}]` };
|
|
323
323
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gemini-reverse",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "Unofficial Node.js client for gemini.google.com — inspired by Gemini-API (Python). Supports streaming, chat sessions, gems, file uploads, and TypeScript.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|