gemini-reverse 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/constants.js ADDED
@@ -0,0 +1,94 @@
1
+ 'use strict';
2
+
3
+ const TEMPORARY_CHAT_FLAG_INDEX = 45;
4
+
5
+ const Endpoint = {
6
+ GOOGLE: 'https://www.google.com',
7
+ INIT: 'https://gemini.google.com/app',
8
+ GENERATE: 'https://gemini.google.com/_/BardChatUi/data/assistant.lamda.BardFrontendService/StreamGenerate',
9
+ ROTATE_COOKIES: 'https://accounts.google.com/RotateCookies',
10
+ UPLOAD: 'https://content-push.googleapis.com/upload',
11
+ BATCH_EXEC: 'https://gemini.google.com/_/BardChatUi/data/batchexecute',
12
+ };
13
+
14
+ const GRPC = {
15
+ LIST_CHATS: 'MaZiqc',
16
+ READ_CHAT: 'hNvQHb',
17
+ DELETE_CHAT: 'GzXR5e',
18
+ LIST_GEMS: 'CNgdBe',
19
+ CREATE_GEM: 'oMH3Zd',
20
+ UPDATE_GEM: 'kHv0Vd',
21
+ DELETE_GEM: 'UXcSJb',
22
+ BARD_ACTIVITY: 'ESY5D',
23
+ };
24
+
25
+ const Headers = {
26
+ GEMINI: {
27
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
28
+ 'Host': 'gemini.google.com',
29
+ 'Origin': 'https://gemini.google.com',
30
+ 'Referer': 'https://gemini.google.com/',
31
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36',
32
+ 'X-Same-Domain': '1',
33
+ },
34
+ ROTATE_COOKIES: {
35
+ 'Content-Type': 'application/json',
36
+ },
37
+ UPLOAD: {
38
+ 'Push-ID': 'feeds/mcudyrk2a4khkz',
39
+ },
40
+ };
41
+
42
+ const Model = {
43
+ UNSPECIFIED: { model_name: 'unspecified', model_header: {}, advanced_only: false },
44
+ G_3_1_PRO: {
45
+ model_name: 'gemini-3.1-pro',
46
+ model_header: {
47
+ 'x-goog-ext-525001261-jspb': '[1,null,null,null,"e6fa609c3fa255c0",null,null,0,[4],null,null,2]',
48
+ 'x-goog-ext-73010989-jspb': '[0]',
49
+ 'x-goog-ext-73010990-jspb': '[0]',
50
+ },
51
+ advanced_only: false,
52
+ },
53
+ G_3_0_FLASH: {
54
+ model_name: 'gemini-3.0-flash',
55
+ model_header: {
56
+ 'x-goog-ext-525001261-jspb': '[1,null,null,null,"fbb127bbb056c959",null,null,0,[4],null,null,1]',
57
+ 'x-goog-ext-73010989-jspb': '[0]',
58
+ 'x-goog-ext-73010990-jspb': '[0]',
59
+ },
60
+ advanced_only: false,
61
+ },
62
+ G_3_0_FLASH_THINKING: {
63
+ model_name: 'gemini-3.0-flash-thinking',
64
+ model_header: {
65
+ 'x-goog-ext-525001261-jspb': '[1,null,null,null,"5bf011840784117a",null,null,0,[4],null,null,1]',
66
+ 'x-goog-ext-73010989-jspb': '[0]',
67
+ 'x-goog-ext-73010990-jspb': '[0]',
68
+ },
69
+ advanced_only: false,
70
+ },
71
+ fromName(name) {
72
+ const legacy = { 'gemini-3.0-pro': 'gemini-3.1-pro' };
73
+ const resolved = legacy[name] || name;
74
+ for (const k of ['UNSPECIFIED', 'G_3_1_PRO', 'G_3_0_FLASH', 'G_3_0_FLASH_THINKING']) {
75
+ if (Model[k].model_name === resolved) return Model[k];
76
+ }
77
+ throw new Error(`Unknown model name: ${name}. Available: ${['UNSPECIFIED', 'G_3_1_PRO', 'G_3_0_FLASH', 'G_3_0_FLASH_THINKING'].map(k => Model[k].model_name).join(', ')}`);
78
+ },
79
+ fromDict(d) {
80
+ if (!d.model_name || !d.model_header || typeof d.model_header !== 'object')
81
+ throw new Error('model_name and model_header (object) required');
82
+ return { model_name: d.model_name, model_header: d.model_header, advanced_only: false };
83
+ },
84
+ };
85
+
86
+ const ErrorCode = {
87
+ TEMPORARY_ERROR_1013: 1013,
88
+ USAGE_LIMIT_EXCEEDED: 1037,
89
+ MODEL_INCONSISTENT: 1050,
90
+ MODEL_HEADER_INVALID: 1052,
91
+ IP_TEMPORARILY_BLOCKED: 1060,
92
+ };
93
+
94
+ module.exports = { TEMPORARY_CHAT_FLAG_INDEX, Endpoint, GRPC, Headers, Model, ErrorCode };
package/exceptions.js ADDED
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ class AuthError extends Error {
4
+ constructor(m) { super(m); this.name = 'AuthError'; }
5
+ }
6
+
7
+ class APIError extends Error {
8
+ constructor(m) { super(m); this.name = 'APIError'; }
9
+ }
10
+
11
+ class ImageGenerationError extends APIError {
12
+ constructor(m) { super(m); this.name = 'ImageGenerationError'; }
13
+ }
14
+
15
+ class GeminiError extends Error {
16
+ constructor(m) { super(m); this.name = 'GeminiError'; }
17
+ }
18
+
19
+ class TimeoutError extends GeminiError {
20
+ constructor(m) { super(m); this.name = 'TimeoutError'; }
21
+ }
22
+
23
+ class UsageLimitExceeded extends GeminiError {
24
+ constructor(m) { super(m); this.name = 'UsageLimitExceeded'; }
25
+ }
26
+
27
+ class ModelInvalid extends GeminiError {
28
+ constructor(m) { super(m); this.name = 'ModelInvalid'; }
29
+ }
30
+
31
+ class TemporarilyBlocked extends GeminiError {
32
+ constructor(m) { super(m); this.name = 'TemporarilyBlocked'; }
33
+ }
34
+
35
+ module.exports = { AuthError, APIError, ImageGenerationError, GeminiError, TimeoutError, UsageLimitExceeded, ModelInvalid, TemporarilyBlocked };
package/index.d.ts ADDED
@@ -0,0 +1,329 @@
1
+ export interface ModelHeader {
2
+ 'x-goog-ext-525001261-jspb'?: string;
3
+ 'x-goog-ext-73010989-jspb'?: string;
4
+ 'x-goog-ext-73010990-jspb'?: string;
5
+ [key: string]: string | undefined;
6
+ }
7
+
8
+ export interface ModelDef {
9
+ model_name: string;
10
+ model_header: ModelHeader;
11
+ advanced_only: boolean;
12
+ }
13
+
14
+ export interface ModelDict {
15
+ model_name: string;
16
+ model_header: ModelHeader;
17
+ }
18
+
19
+ export type ModelInput = string | ModelDef | ModelDict | null;
20
+
21
+ export declare const Model: {
22
+ readonly UNSPECIFIED: ModelDef;
23
+ readonly G_3_1_PRO: ModelDef;
24
+ readonly G_3_0_FLASH: ModelDef;
25
+ readonly G_3_0_FLASH_THINKING: ModelDef;
26
+ fromName(name: string): ModelDef;
27
+ fromDict(d: ModelDict): ModelDef;
28
+ };
29
+
30
+ export declare const GRPC: {
31
+ readonly LIST_CHATS: string;
32
+ readonly READ_CHAT: string;
33
+ readonly DELETE_CHAT: string;
34
+ readonly LIST_GEMS: string;
35
+ readonly CREATE_GEM: string;
36
+ readonly UPDATE_GEM: string;
37
+ readonly DELETE_GEM: string;
38
+ readonly BARD_ACTIVITY: string;
39
+ };
40
+
41
+ export declare const Endpoint: {
42
+ readonly GOOGLE: string;
43
+ readonly INIT: string;
44
+ readonly GENERATE: string;
45
+ readonly ROTATE_COOKIES: string;
46
+ readonly UPLOAD: string;
47
+ readonly BATCH_EXEC: string;
48
+ };
49
+
50
+ export declare const Headers: {
51
+ readonly GEMINI: Record<string, string>;
52
+ readonly ROTATE_COOKIES: Record<string, string>;
53
+ readonly UPLOAD: Record<string, string>;
54
+ };
55
+
56
+ export declare const ErrorCode: {
57
+ readonly TEMPORARY_ERROR_1013: 1013;
58
+ readonly USAGE_LIMIT_EXCEEDED: 1037;
59
+ readonly MODEL_INCONSISTENT: 1050;
60
+ readonly MODEL_HEADER_INVALID: 1052;
61
+ readonly IP_TEMPORARILY_BLOCKED: 1060;
62
+ };
63
+
64
+ export declare const TEMPORARY_CHAT_FLAG_INDEX: number;
65
+
66
+ export declare class AuthError extends Error { name: 'AuthError'; }
67
+ export declare class APIError extends Error { name: 'APIError'; }
68
+ export declare class ImageGenerationError extends APIError { name: 'ImageGenerationError'; }
69
+ export declare class GeminiError extends Error { name: 'GeminiError'; }
70
+ export declare class TimeoutError extends GeminiError { name: 'TimeoutError'; }
71
+ export declare class UsageLimitExceeded extends GeminiError { name: 'UsageLimitExceeded'; }
72
+ export declare class ModelInvalid extends GeminiError { name: 'ModelInvalid'; }
73
+ export declare class TemporarilyBlocked extends GeminiError { name: 'TemporarilyBlocked'; }
74
+
75
+ export interface ImageSaveOptions {
76
+ path?: string;
77
+ filename?: string;
78
+ cookies?: Record<string, string> | null;
79
+ verbose?: boolean;
80
+ skipInvalidFilename?: boolean;
81
+ }
82
+
83
+ export declare class Image {
84
+ url: string;
85
+ title: string;
86
+ alt: string;
87
+ proxy: string | null;
88
+ constructor(opts: { url: string; title?: string; alt?: string; proxy?: string | null });
89
+ save(opts?: ImageSaveOptions): Promise<string | null>;
90
+ toString(): string;
91
+ }
92
+
93
+ export declare class WebImage extends Image {}
94
+
95
+ export interface GeneratedImageSaveOptions extends ImageSaveOptions {
96
+ fullSize?: boolean;
97
+ }
98
+
99
+ export declare class GeneratedImage extends Image {
100
+ cookies: Record<string, string>;
101
+ constructor(opts: { url: string; title?: string; alt?: string; proxy?: string | null; cookies: Record<string, string> });
102
+ save(opts?: GeneratedImageSaveOptions): Promise<string | null>;
103
+ }
104
+
105
+ export declare class Candidate {
106
+ rcid: string;
107
+ text: string;
108
+ text_delta: string | null;
109
+ thoughts: string | null;
110
+ thoughts_delta: string | null;
111
+ web_images: WebImage[];
112
+ generated_images: GeneratedImage[];
113
+ constructor(opts: {
114
+ rcid: string;
115
+ text: string;
116
+ text_delta?: string | null;
117
+ thoughts?: string | null;
118
+ thoughts_delta?: string | null;
119
+ web_images?: WebImage[];
120
+ generated_images?: GeneratedImage[];
121
+ });
122
+ get images(): (WebImage | GeneratedImage)[];
123
+ toString(): string;
124
+ repr(): string;
125
+ }
126
+
127
+ export declare class ModelOutput {
128
+ metadata: string[];
129
+ candidates: Candidate[];
130
+ chosen: number;
131
+ constructor(metadata: string[], candidates: Candidate[], chosen?: number);
132
+ get text(): string;
133
+ get text_delta(): string;
134
+ get thoughts(): string | null;
135
+ get thoughts_delta(): string;
136
+ get images(): (WebImage | GeneratedImage)[];
137
+ get rcid(): string;
138
+ toString(): string;
139
+ repr(): string;
140
+ }
141
+
142
+ export declare class ConversationTurn {
143
+ rid: string;
144
+ user_prompt: string;
145
+ assistant_response: string;
146
+ rcid: string;
147
+ thoughts: string | null;
148
+ timestamp: Date | null;
149
+ constructor(opts: {
150
+ rid: string;
151
+ user_prompt: string;
152
+ assistant_response: string;
153
+ rcid: string;
154
+ thoughts?: string | null;
155
+ timestamp?: Date | string | null;
156
+ });
157
+ toString(): string;
158
+ repr(): string;
159
+ }
160
+
161
+ export declare class Gem {
162
+ id: string;
163
+ name: string;
164
+ description: string | null;
165
+ prompt: string | null;
166
+ predefined: boolean;
167
+ constructor(opts: { id: string; name: string; description?: string | null; prompt?: string | null; predefined: boolean });
168
+ toString(): string;
169
+ }
170
+
171
+ export interface GemGetOptions {
172
+ id?: string | null;
173
+ name?: string | null;
174
+ defaultVal?: Gem | null;
175
+ }
176
+
177
+ export interface GemFilterOptions {
178
+ predefined?: boolean | null;
179
+ name?: string | null;
180
+ }
181
+
182
+ export declare class GemJar {
183
+ constructor(entries?: [string, Gem][]);
184
+ set(id: string, gem: Gem): void;
185
+ get(opts: GemGetOptions): Gem | null;
186
+ filter(opts?: GemFilterOptions): GemJar;
187
+ values(): Gem[];
188
+ keys(): string[];
189
+ entries(): [string, Gem][];
190
+ [Symbol.iterator](): Iterator<Gem>;
191
+ toObject(): Record<string, Gem>;
192
+ }
193
+
194
+ export declare class RPCData {
195
+ rpcid: string;
196
+ payload: string;
197
+ identifier: string;
198
+ constructor(opts: { rpcid: string; payload: string; identifier?: string });
199
+ serialize(): [string, string, null, string];
200
+ toString(): string;
201
+ }
202
+
203
+ export interface GeminiClientOptions {
204
+ secure_1psid?: string | null;
205
+ secure_1psidts?: string | null;
206
+ proxy?: string | null;
207
+ cookies?: Record<string, string>;
208
+ }
209
+
210
+ export interface InitOptions {
211
+ timeout?: number;
212
+ autoClose?: boolean;
213
+ closeDelay?: number;
214
+ autoRefresh?: boolean;
215
+ refreshInterval?: number;
216
+ verbose?: boolean;
217
+ watchdogTimeout?: number;
218
+ }
219
+
220
+ export interface GenerateOptions {
221
+ prompt: string;
222
+ files?: (string | Buffer)[] | null;
223
+ model?: ModelInput;
224
+ gem?: Gem | string | null;
225
+ chat?: ChatSession | null;
226
+ temporary?: boolean;
227
+ }
228
+
229
+ export interface StartChatOptions {
230
+ metadata?: string[] | null;
231
+ cid?: string | null;
232
+ rid?: string | null;
233
+ rcid?: string | null;
234
+ model?: ModelInput;
235
+ gem?: Gem | string | null;
236
+ }
237
+
238
+ export interface FetchGemsOptions {
239
+ includeHidden?: boolean;
240
+ language?: string;
241
+ }
242
+
243
+ export interface CreateGemOptions {
244
+ name: string;
245
+ prompt: string;
246
+ description?: string;
247
+ }
248
+
249
+ export interface UpdateGemOptions {
250
+ gem: Gem | string;
251
+ name: string;
252
+ prompt: string;
253
+ description?: string;
254
+ }
255
+
256
+ export declare class GeminiClient {
257
+ cookies: Record<string, string>;
258
+ proxy: string | null;
259
+ accessToken: string | null;
260
+ buildLabel: string | null;
261
+ sessionId: string | null;
262
+ timeout: number;
263
+ autoClose: boolean;
264
+ closeDelay: number;
265
+ autoRefresh: boolean;
266
+ refreshInterval: number;
267
+ verbose: boolean;
268
+ watchdogTimeout: number;
269
+
270
+ constructor(opts?: GeminiClientOptions);
271
+
272
+ init(opts?: InitOptions): Promise<void>;
273
+ close(delay?: number): Promise<void>;
274
+
275
+ generateContent(opts: GenerateOptions): Promise<ModelOutput>;
276
+ generateContentStream(opts: GenerateOptions): AsyncGenerator<ModelOutput>;
277
+
278
+ startChat(opts?: StartChatOptions): ChatSession;
279
+
280
+ fetchLatestChatResponse(cid: string): Promise<ModelOutput | null>;
281
+ readChat(cid: string, maxTurns?: number): Promise<ConversationTurn[]>;
282
+ deleteChat(cid: string): Promise<void>;
283
+
284
+ get gems(): GemJar;
285
+ fetchGems(opts?: FetchGemsOptions): Promise<GemJar>;
286
+ createGem(opts: CreateGemOptions): Promise<Gem>;
287
+ updateGem(opts: UpdateGemOptions): Promise<Gem>;
288
+ deleteGem(gem: Gem | string): Promise<void>;
289
+ }
290
+
291
+ export interface ChatSessionOptions {
292
+ geminiclient: GeminiClient;
293
+ metadata?: string[] | null;
294
+ cid?: string | null;
295
+ rid?: string | null;
296
+ rcid?: string | null;
297
+ model?: ModelInput;
298
+ gem?: Gem | string | null;
299
+ }
300
+
301
+ export interface SendMessageOptions {
302
+ prompt: string;
303
+ files?: (string | Buffer)[] | null;
304
+ temporary?: boolean;
305
+ }
306
+
307
+ export declare class ChatSession {
308
+ geminiclient: GeminiClient;
309
+ lastOutput: ModelOutput | null;
310
+ model: ModelDef;
311
+ gem: Gem | string | null;
312
+
313
+ constructor(opts: ChatSessionOptions);
314
+
315
+ get metadata(): string[];
316
+ set metadata(v: string[]);
317
+ get cid(): string;
318
+ set cid(v: string);
319
+ get rid(): string;
320
+ set rid(v: string);
321
+ get rcid(): string;
322
+ set rcid(v: string);
323
+
324
+ sendMessage(opts: SendMessageOptions): Promise<ModelOutput>;
325
+ sendMessageStream(opts: SendMessageOptions): AsyncGenerator<ModelOutput>;
326
+ chooseCandidate(index: number): ModelOutput;
327
+
328
+ toString(): string;
329
+ }
package/index.js ADDED
@@ -0,0 +1,34 @@
1
+ 'use strict';
2
+
3
+ const { GeminiClient, ChatSession } = require('./client');
4
+ const { Model, GRPC, Endpoint, Headers, ErrorCode, TEMPORARY_CHAT_FLAG_INDEX } = require('./constants');
5
+ const { AuthError, APIError, ImageGenerationError, GeminiError, TimeoutError, UsageLimitExceeded, ModelInvalid, TemporarilyBlocked } = require('./exceptions');
6
+ const { Candidate, ConversationTurn, Gem, GemJar, RPCData, Image, WebImage, GeneratedImage, ModelOutput } = require('./types');
7
+
8
+ module.exports = {
9
+ GeminiClient,
10
+ ChatSession,
11
+ Model,
12
+ GRPC,
13
+ Endpoint,
14
+ Headers,
15
+ ErrorCode,
16
+ TEMPORARY_CHAT_FLAG_INDEX,
17
+ AuthError,
18
+ APIError,
19
+ ImageGenerationError,
20
+ GeminiError,
21
+ TimeoutError,
22
+ UsageLimitExceeded,
23
+ ModelInvalid,
24
+ TemporarilyBlocked,
25
+ Candidate,
26
+ ConversationTurn,
27
+ Gem,
28
+ GemJar,
29
+ RPCData,
30
+ Image,
31
+ WebImage,
32
+ GeneratedImage,
33
+ ModelOutput,
34
+ };
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "gemini-reverse",
3
+ "version": "1.0.0",
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
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "license": "MIT",
8
+ "author": "rynn-k",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/rynn-k/gemini-core.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/rynn-k/gemini-core/issues"
15
+ },
16
+ "homepage": "https://github.com/rynn-k/gemini-core#readme",
17
+ "keywords": [
18
+ "gemini",
19
+ "google-gemini",
20
+ "gemini-api",
21
+ "nodejs",
22
+ "javascript",
23
+ "typescript",
24
+ "reverse-engineering",
25
+ "chatbot",
26
+ "ai",
27
+ "llm",
28
+ "unofficial"
29
+ ],
30
+ "dependencies": {
31
+ "axios": "^1.13.6",
32
+ "form-data": "^4.0.5",
33
+ "uuid": "^13.0.0"
34
+ }
35
+ }
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ const { WebImage, GeneratedImage } = require('./image');
4
+
5
+ class Candidate {
6
+ constructor({ rcid, text, text_delta = null, thoughts = null, thoughts_delta = null, web_images = [], generated_images = [] } = {}) {
7
+ this.rcid = rcid;
8
+ this.text = this._decodeHtml(text);
9
+ this.text_delta = text_delta;
10
+ this.thoughts = thoughts ? this._decodeHtml(thoughts) : null;
11
+ this.thoughts_delta = thoughts_delta;
12
+ this.web_images = web_images;
13
+ this.generated_images = generated_images;
14
+ }
15
+
16
+ _decodeHtml(str) {
17
+ if (!str) return str;
18
+ return str
19
+ .replace(/&amp;/g, '&')
20
+ .replace(/&lt;/g, '<')
21
+ .replace(/&gt;/g, '>')
22
+ .replace(/&quot;/g, '"')
23
+ .replace(/&#39;/g, '\'')
24
+ .replace(/&apos;/g, '\'');
25
+ }
26
+
27
+ get images() {
28
+ return [...this.web_images, ...this.generated_images];
29
+ }
30
+
31
+ toString() { return this.text; }
32
+
33
+ repr() {
34
+ const preview = this.text.length <= 20 ? this.text : this.text.slice(0, 20) + '...';
35
+ return `Candidate(rcid='${this.rcid}', text='${preview}', images=${this.images.length})`;
36
+ }
37
+ }
38
+
39
+ module.exports = { Candidate };
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ class ConversationTurn {
4
+ constructor({ rid, user_prompt, assistant_response, rcid, thoughts = null, timestamp = null } = {}) {
5
+ this.rid = rid;
6
+ this.user_prompt = this._decodeHtml(user_prompt);
7
+ this.assistant_response = this._decodeHtml(assistant_response);
8
+ this.rcid = rcid;
9
+ this.thoughts = thoughts ? this._decodeHtml(thoughts) : null;
10
+ this.timestamp = timestamp instanceof Date ? timestamp : timestamp ? new Date(timestamp) : null;
11
+ }
12
+
13
+ _decodeHtml(str) {
14
+ if (!str) return str;
15
+ return str
16
+ .replace(/&amp;/g, '&')
17
+ .replace(/&lt;/g, '<')
18
+ .replace(/&gt;/g, '>')
19
+ .replace(/&quot;/g, '"')
20
+ .replace(/&#39;/g, '\'')
21
+ .replace(/&apos;/g, '\'');
22
+ }
23
+
24
+ toString() { return this.assistant_response; }
25
+
26
+ repr() {
27
+ const preview = this.user_prompt.length > 30 ? this.user_prompt.slice(0, 30) + '...' : this.user_prompt;
28
+ return `ConversationTurn(rid='${this.rid}', prompt='${preview}')`;
29
+ }
30
+ }
31
+
32
+ module.exports = { ConversationTurn };
package/types/gem.js ADDED
@@ -0,0 +1,58 @@
1
+ 'use strict';
2
+
3
+ class Gem {
4
+ constructor({ id, name, description = null, prompt = null, predefined } = {}) {
5
+ this.id = id;
6
+ this.name = name;
7
+ this.description = description;
8
+ this.prompt = prompt;
9
+ this.predefined = predefined;
10
+ }
11
+
12
+ toString() {
13
+ return `Gem(id='${this.id}', name='${this.name}', description='${this.description}', prompt='${this.prompt}', predefined=${this.predefined})`;
14
+ }
15
+ }
16
+
17
+ class GemJar {
18
+ constructor(entries = []) {
19
+ this._store = {};
20
+ for (const [id, gem] of entries) this._store[id] = gem;
21
+ }
22
+
23
+ set(id, gem) { this._store[id] = gem; }
24
+
25
+ get({ id = null, name = null, defaultVal = null } = {}) {
26
+ if (id == null && name == null) throw new Error('At least one of gem id or name must be provided.');
27
+ if (id != null) {
28
+ const gem = this._store[id];
29
+ if (!gem) return defaultVal;
30
+ if (name != null) return gem.name === name ? gem : defaultVal;
31
+ return gem;
32
+ }
33
+ for (const gem of Object.values(this._store)) {
34
+ if (gem.name === name) return gem;
35
+ }
36
+ return defaultVal;
37
+ }
38
+
39
+ filter({ predefined = null, name = null } = {}) {
40
+ const result = new GemJar();
41
+ for (const [id, gem] of Object.entries(this._store)) {
42
+ if (predefined != null && gem.predefined !== predefined) continue;
43
+ if (name != null && gem.name !== name) continue;
44
+ result.set(id, gem);
45
+ }
46
+ return result;
47
+ }
48
+
49
+ values() { return Object.values(this._store); }
50
+ keys() { return Object.keys(this._store); }
51
+ entries() { return Object.entries(this._store); }
52
+
53
+ [Symbol.iterator]() { return this.values()[Symbol.iterator](); }
54
+
55
+ toObject() { return { ...this._store }; }
56
+ }
57
+
58
+ module.exports = { Gem, GemJar };
package/types/grpc.js ADDED
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ class RPCData {
4
+ constructor({ rpcid, payload, identifier = 'generic' } = {}) {
5
+ this.rpcid = rpcid;
6
+ this.payload = payload;
7
+ this.identifier = identifier;
8
+ }
9
+
10
+ serialize() {
11
+ return [this.rpcid, this.payload, null, this.identifier];
12
+ }
13
+
14
+ toString() {
15
+ return `RPCData(rpcid='${this.rpcid}', payload='${this.payload}', identifier='${this.identifier}')`;
16
+ }
17
+ }
18
+
19
+ module.exports = { RPCData };