@quantiya/codevibe-gemini-plugin 1.0.6 → 1.0.8
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/dist/server.js +13 -1424
- package/package.json +5 -4
- package/dist/appsync-client.js +0 -819
- package/dist/auth-cli.js +0 -472
- package/dist/command-executor.js +0 -127
- package/dist/config.js +0 -106
- package/dist/crypto-service.js +0 -278
- package/dist/http-api.js +0 -582
- package/dist/key-manager.js +0 -287
- package/dist/logger.js +0 -18
- package/dist/prompt-responder.js +0 -132
- package/dist/token-storage.js +0 -169
- package/dist/transcript-watcher.js +0 -324
- package/dist/types.js +0 -16
package/dist/key-manager.js
DELETED
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
//
|
|
3
|
-
// key-manager.ts
|
|
4
|
-
// CodeVibe Gemini Plugin
|
|
5
|
-
//
|
|
6
|
-
// Manages device encryption keys and session keys for E2E encryption
|
|
7
|
-
//
|
|
8
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
-
if (k2 === undefined) k2 = k;
|
|
10
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
-
}
|
|
14
|
-
Object.defineProperty(o, k2, desc);
|
|
15
|
-
}) : (function(o, m, k, k2) {
|
|
16
|
-
if (k2 === undefined) k2 = k;
|
|
17
|
-
o[k2] = m[k];
|
|
18
|
-
}));
|
|
19
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
-
}) : function(o, v) {
|
|
22
|
-
o["default"] = v;
|
|
23
|
-
});
|
|
24
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
-
var ownKeys = function(o) {
|
|
26
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
-
var ar = [];
|
|
28
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
-
return ar;
|
|
30
|
-
};
|
|
31
|
-
return ownKeys(o);
|
|
32
|
-
};
|
|
33
|
-
return function (mod) {
|
|
34
|
-
if (mod && mod.__esModule) return mod;
|
|
35
|
-
var result = {};
|
|
36
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
-
__setModuleDefault(result, mod);
|
|
38
|
-
return result;
|
|
39
|
-
};
|
|
40
|
-
})();
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.keyManager = exports.KeyManager = exports.KeyManagerError = void 0;
|
|
43
|
-
const fs = __importStar(require("fs"));
|
|
44
|
-
const path = __importStar(require("path"));
|
|
45
|
-
const os = __importStar(require("os"));
|
|
46
|
-
const uuid_1 = require("uuid");
|
|
47
|
-
const crypto_service_1 = require("./crypto-service");
|
|
48
|
-
const logger_1 = require("./logger");
|
|
49
|
-
// Errors that can occur during key management
|
|
50
|
-
class KeyManagerError extends Error {
|
|
51
|
-
constructor(message) {
|
|
52
|
-
super(message);
|
|
53
|
-
this.name = 'KeyManagerError';
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
exports.KeyManagerError = KeyManagerError;
|
|
57
|
-
// Storage directory for keys
|
|
58
|
-
const CONFIG_DIR = path.join(os.homedir(), '.codevibe-gemini');
|
|
59
|
-
const DEVICE_KEY_FILE = 'device-key.json';
|
|
60
|
-
/**
|
|
61
|
-
* Manages device and session encryption keys
|
|
62
|
-
*/
|
|
63
|
-
class KeyManager {
|
|
64
|
-
constructor() {
|
|
65
|
-
this.deviceKey = null;
|
|
66
|
-
this.sessionKeyCache = new Map(); // sessionId -> base64 session key
|
|
67
|
-
this.isRegistered = false;
|
|
68
|
-
this.ensureConfigDir();
|
|
69
|
-
this.loadDeviceKey();
|
|
70
|
-
}
|
|
71
|
-
static getInstance() {
|
|
72
|
-
if (!KeyManager.instance) {
|
|
73
|
-
KeyManager.instance = new KeyManager();
|
|
74
|
-
}
|
|
75
|
-
return KeyManager.instance;
|
|
76
|
-
}
|
|
77
|
-
// MARK: - Device Key Management
|
|
78
|
-
/**
|
|
79
|
-
* Get or generate the device ID
|
|
80
|
-
*/
|
|
81
|
-
getDeviceId() {
|
|
82
|
-
if (this.deviceKey) {
|
|
83
|
-
return this.deviceKey.deviceId;
|
|
84
|
-
}
|
|
85
|
-
// Generate and store new device key if none exists
|
|
86
|
-
this.generateAndStoreDeviceKey();
|
|
87
|
-
return this.deviceKey.deviceId;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Get the current device's key pair, generating if needed
|
|
91
|
-
*/
|
|
92
|
-
getOrCreateDeviceKeyPair() {
|
|
93
|
-
if (!this.deviceKey) {
|
|
94
|
-
this.generateAndStoreDeviceKey();
|
|
95
|
-
}
|
|
96
|
-
return {
|
|
97
|
-
privateKey: this.deviceKey.privateKey,
|
|
98
|
-
publicKey: this.deviceKey.publicKey,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Get the device's public key (base64)
|
|
103
|
-
*/
|
|
104
|
-
getDevicePublicKey() {
|
|
105
|
-
const keyPair = this.getOrCreateDeviceKeyPair();
|
|
106
|
-
return keyPair.publicKey;
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Check if we have a device key
|
|
110
|
-
*/
|
|
111
|
-
hasDeviceKey() {
|
|
112
|
-
return this.deviceKey !== null;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Check if device key is registered with backend
|
|
116
|
-
*/
|
|
117
|
-
getIsRegistered() {
|
|
118
|
-
return this.isRegistered;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Set registration status
|
|
122
|
-
*/
|
|
123
|
-
setIsRegistered(registered) {
|
|
124
|
-
this.isRegistered = registered;
|
|
125
|
-
}
|
|
126
|
-
// MARK: - Session Key Management
|
|
127
|
-
/**
|
|
128
|
-
* Get session key for a session, decrypting from encryptedKeys if needed
|
|
129
|
-
*/
|
|
130
|
-
getSessionKey(sessionId, encryptedKeys) {
|
|
131
|
-
// Check cache first
|
|
132
|
-
const cachedKey = this.sessionKeyCache.get(sessionId);
|
|
133
|
-
if (cachedKey) {
|
|
134
|
-
return cachedKey;
|
|
135
|
-
}
|
|
136
|
-
// Try to decrypt from encrypted keys
|
|
137
|
-
if (!encryptedKeys || encryptedKeys.length === 0) {
|
|
138
|
-
return null;
|
|
139
|
-
}
|
|
140
|
-
const deviceId = this.getDeviceId();
|
|
141
|
-
const ourEncryptedKey = encryptedKeys.find((k) => k.deviceId === deviceId);
|
|
142
|
-
if (!ourEncryptedKey) {
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
// Load our private key
|
|
146
|
-
if (!this.deviceKey) {
|
|
147
|
-
throw new KeyManagerError('Device key not found');
|
|
148
|
-
}
|
|
149
|
-
// Decrypt session key
|
|
150
|
-
const sessionKey = crypto_service_1.cryptoService.decryptSessionKey(ourEncryptedKey, this.deviceKey.privateKey);
|
|
151
|
-
// Cache for future use
|
|
152
|
-
this.sessionKeyCache.set(sessionId, sessionKey);
|
|
153
|
-
return sessionKey;
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Generate and encrypt a new session key for all devices
|
|
157
|
-
*/
|
|
158
|
-
createSessionKey(devicePublicKeys) {
|
|
159
|
-
// Generate random session key
|
|
160
|
-
const sessionKey = crypto_service_1.cryptoService.generateSessionKey();
|
|
161
|
-
// Encrypt for each device
|
|
162
|
-
const encryptedKeys = devicePublicKeys.map((device) => {
|
|
163
|
-
const encrypted = crypto_service_1.cryptoService.encryptSessionKey(sessionKey, device.publicKey);
|
|
164
|
-
return {
|
|
165
|
-
deviceId: device.deviceId,
|
|
166
|
-
encryptedKey: encrypted.encryptedKey,
|
|
167
|
-
ephemeralPublicKey: encrypted.ephemeralPublicKey,
|
|
168
|
-
};
|
|
169
|
-
});
|
|
170
|
-
return { sessionKey, encryptedKeys };
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Cache a session key (after successfully decrypting or creating)
|
|
174
|
-
*/
|
|
175
|
-
cacheSessionKey(sessionId, sessionKey) {
|
|
176
|
-
this.sessionKeyCache.set(sessionId, sessionKey);
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Clear cached session key (on session end)
|
|
180
|
-
*/
|
|
181
|
-
clearSessionKey(sessionId) {
|
|
182
|
-
this.sessionKeyCache.delete(sessionId);
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Clear all cached session keys (on sign out)
|
|
186
|
-
*/
|
|
187
|
-
clearAllSessionKeys() {
|
|
188
|
-
this.sessionKeyCache.clear();
|
|
189
|
-
}
|
|
190
|
-
// MARK: - Key Storage
|
|
191
|
-
ensureConfigDir() {
|
|
192
|
-
if (!fs.existsSync(CONFIG_DIR)) {
|
|
193
|
-
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
getKeyFilePath() {
|
|
197
|
-
return path.join(CONFIG_DIR, DEVICE_KEY_FILE);
|
|
198
|
-
}
|
|
199
|
-
loadDeviceKey() {
|
|
200
|
-
const keyFilePath = this.getKeyFilePath();
|
|
201
|
-
if (!fs.existsSync(keyFilePath)) {
|
|
202
|
-
this.deviceKey = null;
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
try {
|
|
206
|
-
const data = fs.readFileSync(keyFilePath, 'utf8');
|
|
207
|
-
const stored = JSON.parse(data);
|
|
208
|
-
this.deviceKey = stored.device;
|
|
209
|
-
logger_1.logger.info(`[KeyManager] Loaded device key: ${this.deviceKey.deviceId}`);
|
|
210
|
-
}
|
|
211
|
-
catch (error) {
|
|
212
|
-
logger_1.logger.error(`[KeyManager] Failed to load device key: ${error}`);
|
|
213
|
-
this.deviceKey = null;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
saveDeviceKey() {
|
|
217
|
-
if (!this.deviceKey) {
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
const keyFilePath = this.getKeyFilePath();
|
|
221
|
-
const stored = {
|
|
222
|
-
device: this.deviceKey,
|
|
223
|
-
};
|
|
224
|
-
try {
|
|
225
|
-
fs.writeFileSync(keyFilePath, JSON.stringify(stored, null, 2), {
|
|
226
|
-
mode: 0o600, // Owner read/write only
|
|
227
|
-
});
|
|
228
|
-
logger_1.logger.info(`[KeyManager] Saved device key: ${this.deviceKey.deviceId}`);
|
|
229
|
-
}
|
|
230
|
-
catch (error) {
|
|
231
|
-
logger_1.logger.error(`[KeyManager] Failed to save device key: ${error}`);
|
|
232
|
-
throw new KeyManagerError(`Failed to save device key: ${error}`);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
generateAndStoreDeviceKey() {
|
|
236
|
-
const keyPair = crypto_service_1.cryptoService.generateKeyPair();
|
|
237
|
-
const deviceId = (0, uuid_1.v4)().toUpperCase();
|
|
238
|
-
this.deviceKey = {
|
|
239
|
-
deviceId,
|
|
240
|
-
privateKey: keyPair.privateKey,
|
|
241
|
-
publicKey: keyPair.publicKey,
|
|
242
|
-
createdAt: new Date().toISOString(),
|
|
243
|
-
};
|
|
244
|
-
this.saveDeviceKey();
|
|
245
|
-
logger_1.logger.info(`[KeyManager] Generated new device key: ${deviceId}`);
|
|
246
|
-
}
|
|
247
|
-
// MARK: - Helpers
|
|
248
|
-
/**
|
|
249
|
-
* Get device name for registration
|
|
250
|
-
*/
|
|
251
|
-
getDeviceName() {
|
|
252
|
-
return os.hostname() || 'CLI Client';
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Get platform for registration
|
|
256
|
-
*/
|
|
257
|
-
getDevicePlatform() {
|
|
258
|
-
const platform = os.platform();
|
|
259
|
-
if (platform === 'darwin') {
|
|
260
|
-
return 'MACOS';
|
|
261
|
-
}
|
|
262
|
-
else if (platform === 'linux') {
|
|
263
|
-
return 'LINUX';
|
|
264
|
-
}
|
|
265
|
-
else if (platform === 'win32') {
|
|
266
|
-
return 'WINDOWS';
|
|
267
|
-
}
|
|
268
|
-
return 'CLI';
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Clear all encryption data (on sign out)
|
|
272
|
-
*/
|
|
273
|
-
clearAllData() {
|
|
274
|
-
const keyFilePath = this.getKeyFilePath();
|
|
275
|
-
if (fs.existsSync(keyFilePath)) {
|
|
276
|
-
fs.unlinkSync(keyFilePath);
|
|
277
|
-
}
|
|
278
|
-
this.deviceKey = null;
|
|
279
|
-
this.sessionKeyCache.clear();
|
|
280
|
-
this.isRegistered = false;
|
|
281
|
-
logger_1.logger.info('[KeyManager] Cleared all encryption data');
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
exports.KeyManager = KeyManager;
|
|
285
|
-
// Export singleton instance
|
|
286
|
-
exports.keyManager = KeyManager.getInstance();
|
|
287
|
-
//# sourceMappingURL=key-manager.js.map
|
package/dist/logger.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.logger = void 0;
|
|
7
|
-
/**
|
|
8
|
-
* Plugin-specific logger for CodeVibe Gemini Plugin
|
|
9
|
-
*/
|
|
10
|
-
const os_1 = __importDefault(require("os"));
|
|
11
|
-
const path_1 = __importDefault(require("path"));
|
|
12
|
-
const codevibe_core_1 = require("@quantiya/codevibe-core");
|
|
13
|
-
exports.logger = (0, codevibe_core_1.createLogger)({
|
|
14
|
-
name: 'codevibe-gemini',
|
|
15
|
-
logFile: path_1.default.join(os_1.default.tmpdir(), 'codevibe-gemini-mcp.log'),
|
|
16
|
-
level: 'info',
|
|
17
|
-
});
|
|
18
|
-
//# sourceMappingURL=logger.js.map
|
package/dist/prompt-responder.js
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PromptResponder = void 0;
|
|
4
|
-
const child_process_1 = require("child_process");
|
|
5
|
-
const util_1 = require("util");
|
|
6
|
-
const logger_1 = require("./logger");
|
|
7
|
-
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
8
|
-
class PromptResponder {
|
|
9
|
-
/**
|
|
10
|
-
* Answer an interactive prompt by sending input to the waiting Gemini process
|
|
11
|
-
* Requires tmux session (set by codevibe-gemini wrapper)
|
|
12
|
-
*/
|
|
13
|
-
async answerInteractivePrompt(sessionId, response) {
|
|
14
|
-
logger_1.logger.info('Attempting to answer interactive prompt', {
|
|
15
|
-
sessionId,
|
|
16
|
-
response,
|
|
17
|
-
});
|
|
18
|
-
try {
|
|
19
|
-
// Check if running in tmux (set by codevibe-gemini wrapper)
|
|
20
|
-
const tmuxSession = process.env.CODEVIBE_GEMINI_TMUX_SESSION;
|
|
21
|
-
logger_1.logger.info('Checking tmux session environment', {
|
|
22
|
-
tmuxSession: tmuxSession || '(not set)',
|
|
23
|
-
allEnvKeys: Object.keys(process.env).filter(k => k.includes('CODEVIBE') || k.includes('TMUX')),
|
|
24
|
-
});
|
|
25
|
-
if (!tmuxSession) {
|
|
26
|
-
logger_1.logger.error('No tmux session found - codevibe-gemini wrapper is required', {
|
|
27
|
-
sessionId,
|
|
28
|
-
hint: 'Start Gemini CLI using the codevibe-gemini wrapper script',
|
|
29
|
-
});
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
// Use tmux send-keys (works even when screen is locked)
|
|
33
|
-
logger_1.logger.info('Using tmux send-keys', { tmuxSession });
|
|
34
|
-
await this.sendViaTmux(tmuxSession, response);
|
|
35
|
-
logger_1.logger.info('Successfully sent response to interactive prompt', {
|
|
36
|
-
sessionId,
|
|
37
|
-
response,
|
|
38
|
-
});
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
logger_1.logger.error('Failed to answer interactive prompt', {
|
|
43
|
-
sessionId,
|
|
44
|
-
error: error instanceof Error ? error.message : String(error),
|
|
45
|
-
});
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Send input via tmux send-keys
|
|
51
|
-
* Works even when screen is locked - this is the only supported method
|
|
52
|
-
*/
|
|
53
|
-
async sendViaTmux(sessionName, input) {
|
|
54
|
-
// Escape special characters for tmux
|
|
55
|
-
// tmux send-keys interprets certain sequences, so we need to escape them
|
|
56
|
-
const escaped = input
|
|
57
|
-
.replace(/\\/g, '\\\\') // Escape backslashes first
|
|
58
|
-
.replace(/"/g, '\\"') // Escape double quotes
|
|
59
|
-
.replace(/\$/g, '\\$') // Escape dollar signs
|
|
60
|
-
.replace(/`/g, '\\`'); // Escape backticks
|
|
61
|
-
logger_1.logger.info('Sending via tmux', { sessionName, inputLength: input.length });
|
|
62
|
-
try {
|
|
63
|
-
// Step 1: Send the input text (without Enter)
|
|
64
|
-
const textCmd = `tmux send-keys -t "${sessionName}" -l "${escaped}"`;
|
|
65
|
-
const textResult = await execAsync(textCmd);
|
|
66
|
-
logger_1.logger.info('tmux send-keys (text) completed', {
|
|
67
|
-
stdout: textResult.stdout || '(empty)',
|
|
68
|
-
stderr: textResult.stderr || '(empty)'
|
|
69
|
-
});
|
|
70
|
-
// Step 2: Wait for the text to be processed by the terminal
|
|
71
|
-
// Longer delay needed for Gemini CLI's interactive prompts
|
|
72
|
-
await this.delay(500);
|
|
73
|
-
// Step 3: Send Enter key separately
|
|
74
|
-
const enterCmd = `tmux send-keys -t "${sessionName}" Enter`;
|
|
75
|
-
const enterResult = await execAsync(enterCmd);
|
|
76
|
-
logger_1.logger.info('tmux send-keys (Enter) completed', {
|
|
77
|
-
stdout: enterResult.stdout || '(empty)',
|
|
78
|
-
stderr: enterResult.stderr || '(empty)'
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
catch (error) {
|
|
82
|
-
logger_1.logger.error('tmux send-keys failed', { sessionName, error });
|
|
83
|
-
throw error;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Simple delay helper
|
|
88
|
-
*/
|
|
89
|
-
delay(ms) {
|
|
90
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Check if a response looks like an answer to an interactive prompt
|
|
94
|
-
* Covers Y/N prompts, numbered choices, and other common responses
|
|
95
|
-
*/
|
|
96
|
-
isPromptResponse(content) {
|
|
97
|
-
const normalized = content.trim().toLowerCase();
|
|
98
|
-
// Y/N responses
|
|
99
|
-
if (normalized === 'y' ||
|
|
100
|
-
normalized === 'n' ||
|
|
101
|
-
normalized === 'yes' ||
|
|
102
|
-
normalized === 'no') {
|
|
103
|
-
return true;
|
|
104
|
-
}
|
|
105
|
-
// Numbered choices (1-9, or just digits)
|
|
106
|
-
if (/^[0-9]+$/.test(normalized)) {
|
|
107
|
-
return true;
|
|
108
|
-
}
|
|
109
|
-
// Single letter choices (a, b, c, etc.)
|
|
110
|
-
if (/^[a-z]$/.test(normalized)) {
|
|
111
|
-
return true;
|
|
112
|
-
}
|
|
113
|
-
// Common terminal control inputs
|
|
114
|
-
// These are typically responses to prompts, not new commands
|
|
115
|
-
const controlInputs = [
|
|
116
|
-
'exit',
|
|
117
|
-
'quit',
|
|
118
|
-
'q',
|
|
119
|
-
'continue',
|
|
120
|
-
'skip',
|
|
121
|
-
'abort',
|
|
122
|
-
'retry',
|
|
123
|
-
'cancel',
|
|
124
|
-
];
|
|
125
|
-
if (controlInputs.includes(normalized)) {
|
|
126
|
-
return true;
|
|
127
|
-
}
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
exports.PromptResponder = PromptResponder;
|
|
132
|
-
//# sourceMappingURL=prompt-responder.js.map
|
package/dist/token-storage.js
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.saveTokens = saveTokens;
|
|
37
|
-
exports.loadTokens = loadTokens;
|
|
38
|
-
exports.deleteTokens = deleteTokens;
|
|
39
|
-
exports.isTokenExpired = isTokenExpired;
|
|
40
|
-
exports.isAuthenticated = isAuthenticated;
|
|
41
|
-
exports.getTokenFilePath = getTokenFilePath;
|
|
42
|
-
exports.getTokenExpiration = getTokenExpiration;
|
|
43
|
-
const fs = __importStar(require("fs"));
|
|
44
|
-
const path = __importStar(require("path"));
|
|
45
|
-
const os = __importStar(require("os"));
|
|
46
|
-
const logger_1 = require("./logger");
|
|
47
|
-
// Token storage location - environment-specific
|
|
48
|
-
const TOKEN_DIR = path.join(os.homedir(), '.codevibe-gemini');
|
|
49
|
-
// Get environment-specific token file
|
|
50
|
-
function getTokenFile() {
|
|
51
|
-
const environment = process.env.ENVIRONMENT || 'production';
|
|
52
|
-
return path.join(TOKEN_DIR, `tokens-${environment}.json`);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Ensure the token directory exists with proper permissions
|
|
56
|
-
*/
|
|
57
|
-
function ensureTokenDir() {
|
|
58
|
-
if (!fs.existsSync(TOKEN_DIR)) {
|
|
59
|
-
fs.mkdirSync(TOKEN_DIR, { mode: 0o700 }); // rwx------
|
|
60
|
-
logger_1.logger.debug('Created token directory', { path: TOKEN_DIR });
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Save tokens to secure file storage
|
|
65
|
-
*/
|
|
66
|
-
function saveTokens(tokens) {
|
|
67
|
-
try {
|
|
68
|
-
ensureTokenDir();
|
|
69
|
-
const tokenFile = getTokenFile();
|
|
70
|
-
const content = JSON.stringify(tokens, null, 2);
|
|
71
|
-
fs.writeFileSync(tokenFile, content, { mode: 0o600 }); // rw-------
|
|
72
|
-
logger_1.logger.info('Tokens saved successfully', {
|
|
73
|
-
userId: tokens.userId,
|
|
74
|
-
email: tokens.email,
|
|
75
|
-
expiresAt: new Date(tokens.expiresAt).toISOString(),
|
|
76
|
-
environment: process.env.ENVIRONMENT || 'production',
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
catch (error) {
|
|
80
|
-
logger_1.logger.error('Failed to save tokens:', error);
|
|
81
|
-
throw new Error(`Failed to save tokens: ${error}`);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Load tokens from secure file storage
|
|
86
|
-
* Returns null if no tokens are stored or if they're invalid
|
|
87
|
-
*/
|
|
88
|
-
function loadTokens() {
|
|
89
|
-
try {
|
|
90
|
-
const tokenFile = getTokenFile();
|
|
91
|
-
if (!fs.existsSync(tokenFile)) {
|
|
92
|
-
logger_1.logger.debug('No tokens file found', { environment: process.env.ENVIRONMENT || 'production' });
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
|
-
const content = fs.readFileSync(tokenFile, 'utf-8');
|
|
96
|
-
const tokens = JSON.parse(content);
|
|
97
|
-
// Validate required fields
|
|
98
|
-
if (!tokens.accessToken || !tokens.refreshToken || !tokens.expiresAt) {
|
|
99
|
-
logger_1.logger.warn('Invalid tokens file - missing required fields');
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
logger_1.logger.debug('Tokens loaded', {
|
|
103
|
-
userId: tokens.userId,
|
|
104
|
-
email: tokens.email,
|
|
105
|
-
expiresAt: new Date(tokens.expiresAt).toISOString(),
|
|
106
|
-
isExpired: isTokenExpired(tokens),
|
|
107
|
-
});
|
|
108
|
-
return tokens;
|
|
109
|
-
}
|
|
110
|
-
catch (error) {
|
|
111
|
-
logger_1.logger.error('Failed to load tokens:', error);
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Delete stored tokens (logout)
|
|
117
|
-
*/
|
|
118
|
-
function deleteTokens() {
|
|
119
|
-
try {
|
|
120
|
-
const tokenFile = getTokenFile();
|
|
121
|
-
if (fs.existsSync(tokenFile)) {
|
|
122
|
-
fs.unlinkSync(tokenFile);
|
|
123
|
-
logger_1.logger.info('Tokens deleted successfully', { environment: process.env.ENVIRONMENT || 'production' });
|
|
124
|
-
return true;
|
|
125
|
-
}
|
|
126
|
-
logger_1.logger.debug('No tokens file to delete', { environment: process.env.ENVIRONMENT || 'production' });
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
catch (error) {
|
|
130
|
-
logger_1.logger.error('Failed to delete tokens:', error);
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Check if the access token is expired or about to expire
|
|
136
|
-
* Considers token expired if less than 5 minutes remaining
|
|
137
|
-
*/
|
|
138
|
-
function isTokenExpired(tokens) {
|
|
139
|
-
const bufferMs = 5 * 60 * 1000; // 5 minutes buffer
|
|
140
|
-
return Date.now() >= (tokens.expiresAt - bufferMs);
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Check if user is authenticated (has valid, non-expired tokens)
|
|
144
|
-
*/
|
|
145
|
-
function isAuthenticated() {
|
|
146
|
-
const tokens = loadTokens();
|
|
147
|
-
if (!tokens) {
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
// Even if access token is expired, we can refresh if we have a refresh token
|
|
151
|
-
return !!tokens.refreshToken;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Get the token file path (for display purposes)
|
|
155
|
-
*/
|
|
156
|
-
function getTokenFilePath() {
|
|
157
|
-
return getTokenFile();
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Get token expiration date
|
|
161
|
-
*/
|
|
162
|
-
function getTokenExpiration() {
|
|
163
|
-
const tokens = loadTokens();
|
|
164
|
-
if (!tokens) {
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
return new Date(tokens.expiresAt);
|
|
168
|
-
}
|
|
169
|
-
//# sourceMappingURL=token-storage.js.map
|