@google/gemini-cli-core 0.34.0-preview.2 → 0.34.0-preview.3

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 (32) hide show
  1. package/dist/google-gemini-cli-core-0.34.0-preview.2.tgz +0 -0
  2. package/dist/src/generated/git-commit.d.ts +2 -2
  3. package/dist/src/generated/git-commit.js +2 -2
  4. package/dist/src/mcp/oauth-token-storage.test.js +10 -6
  5. package/dist/src/mcp/oauth-token-storage.test.js.map +1 -1
  6. package/dist/src/mcp/token-storage/hybrid-token-storage.js +9 -21
  7. package/dist/src/mcp/token-storage/hybrid-token-storage.js.map +1 -1
  8. package/dist/src/mcp/token-storage/hybrid-token-storage.test.js +10 -59
  9. package/dist/src/mcp/token-storage/hybrid-token-storage.test.js.map +1 -1
  10. package/dist/src/mcp/token-storage/index.d.ts +1 -1
  11. package/dist/src/mcp/token-storage/index.js +1 -1
  12. package/dist/src/mcp/token-storage/index.js.map +1 -1
  13. package/dist/src/mcp/token-storage/keychain-token-storage.d.ts +1 -0
  14. package/dist/src/mcp/token-storage/keychain-token-storage.js +3 -0
  15. package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -1
  16. package/dist/src/services/fileKeychain.d.ts +24 -0
  17. package/dist/src/services/fileKeychain.js +123 -0
  18. package/dist/src/services/fileKeychain.js.map +1 -0
  19. package/dist/src/services/keychainService.d.ts +5 -0
  20. package/dist/src/services/keychainService.js +30 -13
  21. package/dist/src/services/keychainService.js.map +1 -1
  22. package/dist/src/services/keychainService.test.js +52 -22
  23. package/dist/src/services/keychainService.test.js.map +1 -1
  24. package/dist/tsconfig.tsbuildinfo +1 -1
  25. package/package.json +1 -1
  26. package/dist/google-gemini-cli-core-0.34.0-preview.1.tgz +0 -0
  27. package/dist/src/mcp/token-storage/file-token-storage.d.ts +0 -24
  28. package/dist/src/mcp/token-storage/file-token-storage.js +0 -152
  29. package/dist/src/mcp/token-storage/file-token-storage.js.map +0 -1
  30. package/dist/src/mcp/token-storage/file-token-storage.test.d.ts +0 -6
  31. package/dist/src/mcp/token-storage/file-token-storage.test.js +0 -276
  32. package/dist/src/mcp/token-storage/file-token-storage.test.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@google/gemini-cli-core",
3
- "version": "0.34.0-preview.2",
3
+ "version": "0.34.0-preview.3",
4
4
  "description": "Gemini CLI Core",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -1,24 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
- import { BaseTokenStorage } from './base-token-storage.js';
7
- import type { OAuthCredentials } from './types.js';
8
- export declare class FileTokenStorage extends BaseTokenStorage {
9
- private readonly tokenFilePath;
10
- private readonly encryptionKey;
11
- constructor(serviceName: string);
12
- private deriveEncryptionKey;
13
- private encrypt;
14
- private decrypt;
15
- private ensureDirectoryExists;
16
- private loadTokens;
17
- private saveTokens;
18
- getCredentials(serverName: string): Promise<OAuthCredentials | null>;
19
- setCredentials(credentials: OAuthCredentials): Promise<void>;
20
- deleteCredentials(serverName: string): Promise<void>;
21
- listServers(): Promise<string[]>;
22
- getAllCredentials(): Promise<Map<string, OAuthCredentials>>;
23
- clearAll(): Promise<void>;
24
- }
@@ -1,152 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
- import { promises as fs } from 'node:fs';
7
- import * as path from 'node:path';
8
- import * as os from 'node:os';
9
- import * as crypto from 'node:crypto';
10
- import { BaseTokenStorage } from './base-token-storage.js';
11
- import { GEMINI_DIR, homedir } from '../../utils/paths.js';
12
- export class FileTokenStorage extends BaseTokenStorage {
13
- tokenFilePath;
14
- encryptionKey;
15
- constructor(serviceName) {
16
- super(serviceName);
17
- const configDir = path.join(homedir(), GEMINI_DIR);
18
- this.tokenFilePath = path.join(configDir, 'mcp-oauth-tokens-v2.json');
19
- this.encryptionKey = this.deriveEncryptionKey();
20
- }
21
- deriveEncryptionKey() {
22
- const salt = `${os.hostname()}-${os.userInfo().username}-gemini-cli`;
23
- return crypto.scryptSync('gemini-cli-oauth', salt, 32);
24
- }
25
- encrypt(text) {
26
- const iv = crypto.randomBytes(16);
27
- const cipher = crypto.createCipheriv('aes-256-gcm', this.encryptionKey, iv);
28
- let encrypted = cipher.update(text, 'utf8', 'hex');
29
- encrypted += cipher.final('hex');
30
- const authTag = cipher.getAuthTag();
31
- return iv.toString('hex') + ':' + authTag.toString('hex') + ':' + encrypted;
32
- }
33
- decrypt(encryptedData) {
34
- const parts = encryptedData.split(':');
35
- if (parts.length !== 3) {
36
- throw new Error('Invalid encrypted data format');
37
- }
38
- const iv = Buffer.from(parts[0], 'hex');
39
- const authTag = Buffer.from(parts[1], 'hex');
40
- const encrypted = parts[2];
41
- const decipher = crypto.createDecipheriv('aes-256-gcm', this.encryptionKey, iv);
42
- decipher.setAuthTag(authTag);
43
- let decrypted = decipher.update(encrypted, 'hex', 'utf8');
44
- decrypted += decipher.final('utf8');
45
- return decrypted;
46
- }
47
- async ensureDirectoryExists() {
48
- const dir = path.dirname(this.tokenFilePath);
49
- await fs.mkdir(dir, { recursive: true, mode: 0o700 });
50
- }
51
- async loadTokens() {
52
- try {
53
- const data = await fs.readFile(this.tokenFilePath, 'utf-8');
54
- const decrypted = this.decrypt(data);
55
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
56
- const tokens = JSON.parse(decrypted);
57
- return new Map(Object.entries(tokens));
58
- }
59
- catch (error) {
60
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
61
- const err = error;
62
- if (err.code === 'ENOENT') {
63
- return new Map();
64
- }
65
- if (err.message?.includes('Invalid encrypted data format') ||
66
- err.message?.includes('Unsupported state or unable to authenticate data')) {
67
- // Decryption failed - this can happen when switching between auth types
68
- // or if the file is genuinely corrupted.
69
- throw new Error(`Corrupted token file detected at: ${this.tokenFilePath}\n` +
70
- `Please delete or rename this file to resolve the issue.`);
71
- }
72
- throw error;
73
- }
74
- }
75
- async saveTokens(tokens) {
76
- await this.ensureDirectoryExists();
77
- const data = Object.fromEntries(tokens);
78
- const json = JSON.stringify(data, null, 2);
79
- const encrypted = this.encrypt(json);
80
- await fs.writeFile(this.tokenFilePath, encrypted, { mode: 0o600 });
81
- }
82
- async getCredentials(serverName) {
83
- const tokens = await this.loadTokens();
84
- const credentials = tokens.get(serverName);
85
- if (!credentials) {
86
- return null;
87
- }
88
- if (this.isTokenExpired(credentials)) {
89
- return null;
90
- }
91
- return credentials;
92
- }
93
- async setCredentials(credentials) {
94
- this.validateCredentials(credentials);
95
- const tokens = await this.loadTokens();
96
- const updatedCredentials = {
97
- ...credentials,
98
- updatedAt: Date.now(),
99
- };
100
- tokens.set(credentials.serverName, updatedCredentials);
101
- await this.saveTokens(tokens);
102
- }
103
- async deleteCredentials(serverName) {
104
- const tokens = await this.loadTokens();
105
- if (!tokens.has(serverName)) {
106
- throw new Error(`No credentials found for ${serverName}`);
107
- }
108
- tokens.delete(serverName);
109
- if (tokens.size === 0) {
110
- try {
111
- await fs.unlink(this.tokenFilePath);
112
- }
113
- catch (error) {
114
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
115
- const err = error;
116
- if (err.code !== 'ENOENT') {
117
- throw error;
118
- }
119
- }
120
- }
121
- else {
122
- await this.saveTokens(tokens);
123
- }
124
- }
125
- async listServers() {
126
- const tokens = await this.loadTokens();
127
- return Array.from(tokens.keys());
128
- }
129
- async getAllCredentials() {
130
- const tokens = await this.loadTokens();
131
- const result = new Map();
132
- for (const [serverName, credentials] of tokens) {
133
- if (!this.isTokenExpired(credentials)) {
134
- result.set(serverName, credentials);
135
- }
136
- }
137
- return result;
138
- }
139
- async clearAll() {
140
- try {
141
- await fs.unlink(this.tokenFilePath);
142
- }
143
- catch (error) {
144
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
145
- const err = error;
146
- if (err.code !== 'ENOENT') {
147
- throw error;
148
- }
149
- }
150
- }
151
- }
152
- //# sourceMappingURL=file-token-storage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-token-storage.js","sourceRoot":"","sources":["../../../../src/mcp/token-storage/file-token-storage.ts"],"names":[],"mappings":"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"}
@@ -1,6 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
- export {};
@@ -1,276 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
7
- import { promises as fs } from 'node:fs';
8
- import * as path from 'node:path';
9
- import { FileTokenStorage } from './file-token-storage.js';
10
- import { GEMINI_DIR } from '../../utils/paths.js';
11
- vi.mock('node:fs', () => ({
12
- promises: {
13
- readFile: vi.fn(),
14
- writeFile: vi.fn(),
15
- unlink: vi.fn(),
16
- mkdir: vi.fn(),
17
- rename: vi.fn(),
18
- },
19
- }));
20
- vi.mock('node:os', () => ({
21
- default: {
22
- homedir: vi.fn(() => '/home/test'),
23
- hostname: vi.fn(() => 'test-host'),
24
- userInfo: vi.fn(() => ({ username: 'test-user' })),
25
- },
26
- homedir: vi.fn(() => '/home/test'),
27
- hostname: vi.fn(() => 'test-host'),
28
- userInfo: vi.fn(() => ({ username: 'test-user' })),
29
- }));
30
- describe('FileTokenStorage', () => {
31
- let storage;
32
- const mockFs = fs;
33
- const existingCredentials = {
34
- serverName: 'existing-server',
35
- token: {
36
- accessToken: 'existing-token',
37
- tokenType: 'Bearer',
38
- },
39
- updatedAt: Date.now() - 10000,
40
- };
41
- beforeEach(() => {
42
- vi.clearAllMocks();
43
- storage = new FileTokenStorage('test-storage');
44
- });
45
- afterEach(() => {
46
- vi.clearAllMocks();
47
- });
48
- describe('getCredentials', () => {
49
- it('should return null when file does not exist', async () => {
50
- mockFs.readFile.mockRejectedValue({ code: 'ENOENT' });
51
- const result = await storage.getCredentials('test-server');
52
- expect(result).toBeNull();
53
- });
54
- it('should return null for expired tokens', async () => {
55
- const credentials = {
56
- serverName: 'test-server',
57
- token: {
58
- accessToken: 'access-token',
59
- tokenType: 'Bearer',
60
- expiresAt: Date.now() - 3600000,
61
- },
62
- updatedAt: Date.now(),
63
- };
64
- const encryptedData = storage['encrypt'](JSON.stringify({ 'test-server': credentials }));
65
- mockFs.readFile.mockResolvedValue(encryptedData);
66
- const result = await storage.getCredentials('test-server');
67
- expect(result).toBeNull();
68
- });
69
- it('should return credentials for valid tokens', async () => {
70
- const credentials = {
71
- serverName: 'test-server',
72
- token: {
73
- accessToken: 'access-token',
74
- tokenType: 'Bearer',
75
- expiresAt: Date.now() + 3600000,
76
- },
77
- updatedAt: Date.now(),
78
- };
79
- const encryptedData = storage['encrypt'](JSON.stringify({ 'test-server': credentials }));
80
- mockFs.readFile.mockResolvedValue(encryptedData);
81
- const result = await storage.getCredentials('test-server');
82
- expect(result).toEqual(credentials);
83
- });
84
- it('should throw error with file path when file is corrupted', async () => {
85
- mockFs.readFile.mockResolvedValue('corrupted-data');
86
- try {
87
- await storage.getCredentials('test-server');
88
- expect.fail('Expected error to be thrown');
89
- }
90
- catch (error) {
91
- expect(error).toBeInstanceOf(Error);
92
- const err = error;
93
- expect(err.message).toContain('Corrupted token file detected at:');
94
- expect(err.message).toContain('mcp-oauth-tokens-v2.json');
95
- expect(err.message).toContain('delete or rename');
96
- }
97
- });
98
- });
99
- describe('auth type switching', () => {
100
- it('should throw error when trying to save credentials with corrupted file', async () => {
101
- // Simulate corrupted file on first read
102
- mockFs.readFile.mockResolvedValue('corrupted-data');
103
- // Try to save new credentials (simulating switch from OAuth to API key)
104
- const newCredentials = {
105
- serverName: 'new-auth-server',
106
- token: {
107
- accessToken: 'new-api-key',
108
- tokenType: 'ApiKey',
109
- },
110
- updatedAt: Date.now(),
111
- };
112
- // Should throw error with file path
113
- try {
114
- await storage.setCredentials(newCredentials);
115
- expect.fail('Expected error to be thrown');
116
- }
117
- catch (error) {
118
- expect(error).toBeInstanceOf(Error);
119
- const err = error;
120
- expect(err.message).toContain('Corrupted token file detected at:');
121
- expect(err.message).toContain('mcp-oauth-tokens-v2.json');
122
- expect(err.message).toContain('delete or rename');
123
- }
124
- });
125
- });
126
- describe('setCredentials', () => {
127
- it('should save credentials with encryption', async () => {
128
- const encryptedData = storage['encrypt'](JSON.stringify({ 'existing-server': existingCredentials }));
129
- mockFs.readFile.mockResolvedValue(encryptedData);
130
- mockFs.mkdir.mockResolvedValue(undefined);
131
- mockFs.writeFile.mockResolvedValue(undefined);
132
- const credentials = {
133
- serverName: 'test-server',
134
- token: {
135
- accessToken: 'access-token',
136
- tokenType: 'Bearer',
137
- },
138
- updatedAt: Date.now(),
139
- };
140
- await storage.setCredentials(credentials);
141
- expect(mockFs.mkdir).toHaveBeenCalledWith(path.join('/home/test', GEMINI_DIR), { recursive: true, mode: 0o700 });
142
- expect(mockFs.writeFile).toHaveBeenCalled();
143
- const writeCall = mockFs.writeFile.mock.calls[0];
144
- expect(writeCall[1]).toMatch(/^[0-9a-f]+:[0-9a-f]+:[0-9a-f]+$/);
145
- expect(writeCall[2]).toEqual({ mode: 0o600 });
146
- });
147
- it('should update existing credentials', async () => {
148
- const encryptedData = storage['encrypt'](JSON.stringify({ 'existing-server': existingCredentials }));
149
- mockFs.readFile.mockResolvedValue(encryptedData);
150
- mockFs.writeFile.mockResolvedValue(undefined);
151
- const newCredentials = {
152
- serverName: 'test-server',
153
- token: {
154
- accessToken: 'new-token',
155
- tokenType: 'Bearer',
156
- },
157
- updatedAt: Date.now(),
158
- };
159
- await storage.setCredentials(newCredentials);
160
- expect(mockFs.writeFile).toHaveBeenCalled();
161
- const writeCall = mockFs.writeFile.mock.calls[0];
162
- const decrypted = storage['decrypt'](writeCall[1]);
163
- const saved = JSON.parse(decrypted);
164
- expect(saved['existing-server']).toEqual(existingCredentials);
165
- expect(saved['test-server'].token.accessToken).toBe('new-token');
166
- });
167
- });
168
- describe('deleteCredentials', () => {
169
- it('should throw when credentials do not exist', async () => {
170
- mockFs.readFile.mockRejectedValue({ code: 'ENOENT' });
171
- await expect(storage.deleteCredentials('test-server')).rejects.toThrow('No credentials found for test-server');
172
- });
173
- it('should delete file when last credential is removed', async () => {
174
- const credentials = {
175
- serverName: 'test-server',
176
- token: {
177
- accessToken: 'access-token',
178
- tokenType: 'Bearer',
179
- },
180
- updatedAt: Date.now(),
181
- };
182
- const encryptedData = storage['encrypt'](JSON.stringify({ 'test-server': credentials }));
183
- mockFs.readFile.mockResolvedValue(encryptedData);
184
- mockFs.unlink.mockResolvedValue(undefined);
185
- await storage.deleteCredentials('test-server');
186
- expect(mockFs.unlink).toHaveBeenCalledWith(path.join('/home/test', GEMINI_DIR, 'mcp-oauth-tokens-v2.json'));
187
- });
188
- it('should update file when other credentials remain', async () => {
189
- const credentials1 = {
190
- serverName: 'server1',
191
- token: {
192
- accessToken: 'token1',
193
- tokenType: 'Bearer',
194
- },
195
- updatedAt: Date.now(),
196
- };
197
- const credentials2 = {
198
- serverName: 'server2',
199
- token: {
200
- accessToken: 'token2',
201
- tokenType: 'Bearer',
202
- },
203
- updatedAt: Date.now(),
204
- };
205
- const encryptedData = storage['encrypt'](JSON.stringify({ server1: credentials1, server2: credentials2 }));
206
- mockFs.readFile.mockResolvedValue(encryptedData);
207
- mockFs.writeFile.mockResolvedValue(undefined);
208
- await storage.deleteCredentials('server1');
209
- expect(mockFs.writeFile).toHaveBeenCalled();
210
- expect(mockFs.unlink).not.toHaveBeenCalled();
211
- const writeCall = mockFs.writeFile.mock.calls[0];
212
- const decrypted = storage['decrypt'](writeCall[1]);
213
- const saved = JSON.parse(decrypted);
214
- expect(saved['server1']).toBeUndefined();
215
- expect(saved['server2']).toEqual(credentials2);
216
- });
217
- });
218
- describe('listServers', () => {
219
- it('should return empty list when file does not exist', async () => {
220
- mockFs.readFile.mockRejectedValue({ code: 'ENOENT' });
221
- const result = await storage.listServers();
222
- expect(result).toEqual([]);
223
- });
224
- it('should return list of server names', async () => {
225
- const credentials = {
226
- server1: {
227
- serverName: 'server1',
228
- token: { accessToken: 'token1', tokenType: 'Bearer' },
229
- updatedAt: Date.now(),
230
- },
231
- server2: {
232
- serverName: 'server2',
233
- token: { accessToken: 'token2', tokenType: 'Bearer' },
234
- updatedAt: Date.now(),
235
- },
236
- };
237
- const encryptedData = storage['encrypt'](JSON.stringify(credentials));
238
- mockFs.readFile.mockResolvedValue(encryptedData);
239
- const result = await storage.listServers();
240
- expect(result).toEqual(['server1', 'server2']);
241
- });
242
- });
243
- describe('clearAll', () => {
244
- it('should delete the token file', async () => {
245
- mockFs.unlink.mockResolvedValue(undefined);
246
- await storage.clearAll();
247
- expect(mockFs.unlink).toHaveBeenCalledWith(path.join('/home/test', GEMINI_DIR, 'mcp-oauth-tokens-v2.json'));
248
- });
249
- it('should not throw when file does not exist', async () => {
250
- mockFs.unlink.mockRejectedValue({ code: 'ENOENT' });
251
- await expect(storage.clearAll()).resolves.not.toThrow();
252
- });
253
- });
254
- describe('encryption', () => {
255
- it('should encrypt and decrypt data correctly', () => {
256
- const original = 'test-data-123';
257
- const encrypted = storage['encrypt'](original);
258
- const decrypted = storage['decrypt'](encrypted);
259
- expect(decrypted).toBe(original);
260
- expect(encrypted).not.toBe(original);
261
- expect(encrypted).toMatch(/^[0-9a-f]+:[0-9a-f]+:[0-9a-f]+$/);
262
- });
263
- it('should produce different encrypted output each time', () => {
264
- const original = 'test-data';
265
- const encrypted1 = storage['encrypt'](original);
266
- const encrypted2 = storage['encrypt'](original);
267
- expect(encrypted1).not.toBe(encrypted2);
268
- expect(storage['decrypt'](encrypted1)).toBe(original);
269
- expect(storage['decrypt'](encrypted2)).toBe(original);
270
- });
271
- it('should throw on invalid encrypted data format', () => {
272
- expect(() => storage['decrypt']('invalid-data')).toThrow('Invalid encrypted data format');
273
- });
274
- });
275
- });
276
- //# sourceMappingURL=file-token-storage.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-token-storage.test.js","sourceRoot":"","sources":["../../../../src/mcp/token-storage/file-token-storage.test.ts"],"names":[],"mappings":"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"}