@commit451/salamander 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.
Files changed (59) hide show
  1. package/README.md +50 -0
  2. package/bin/salamander.js +2 -0
  3. package/dist/commands/create-runner.d.ts +2 -0
  4. package/dist/commands/create-runner.d.ts.map +1 -0
  5. package/dist/commands/create-runner.js +57 -0
  6. package/dist/commands/create-runner.js.map +1 -0
  7. package/dist/commands/delete-runner.d.ts +2 -0
  8. package/dist/commands/delete-runner.d.ts.map +1 -0
  9. package/dist/commands/delete-runner.js +55 -0
  10. package/dist/commands/delete-runner.js.map +1 -0
  11. package/dist/commands/runner-selection.d.ts +2 -0
  12. package/dist/commands/runner-selection.d.ts.map +1 -0
  13. package/dist/commands/runner-selection.js +82 -0
  14. package/dist/commands/runner-selection.js.map +1 -0
  15. package/dist/config/firebase.d.ts +4 -0
  16. package/dist/config/firebase.d.ts.map +1 -0
  17. package/dist/config/firebase.js +17 -0
  18. package/dist/config/firebase.js.map +1 -0
  19. package/dist/index.d.ts +3 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +128 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/services/auth.d.ts +35 -0
  24. package/dist/services/auth.d.ts.map +1 -0
  25. package/dist/services/auth.js +393 -0
  26. package/dist/services/auth.js.map +1 -0
  27. package/dist/services/command-listener.d.ts +8 -0
  28. package/dist/services/command-listener.d.ts.map +1 -0
  29. package/dist/services/command-listener.js +84 -0
  30. package/dist/services/command-listener.js.map +1 -0
  31. package/dist/services/config.d.ts +12 -0
  32. package/dist/services/config.d.ts.map +1 -0
  33. package/dist/services/config.js +26 -0
  34. package/dist/services/config.js.map +1 -0
  35. package/dist/services/executor.d.ts +13 -0
  36. package/dist/services/executor.d.ts.map +1 -0
  37. package/dist/services/executor.js +90 -0
  38. package/dist/services/executor.js.map +1 -0
  39. package/dist/services/runner.d.ts +19 -0
  40. package/dist/services/runner.d.ts.map +1 -0
  41. package/dist/services/runner.js +205 -0
  42. package/dist/services/runner.js.map +1 -0
  43. package/dist/types/runner.d.ts +40 -0
  44. package/dist/types/runner.d.ts.map +1 -0
  45. package/dist/types/runner.js +7 -0
  46. package/dist/types/runner.js.map +1 -0
  47. package/dist/utils/device.d.ts +4 -0
  48. package/dist/utils/device.d.ts.map +1 -0
  49. package/dist/utils/device.js +14 -0
  50. package/dist/utils/device.js.map +1 -0
  51. package/dist/utils/storage.d.ts +20 -0
  52. package/dist/utils/storage.d.ts.map +1 -0
  53. package/dist/utils/storage.js +49 -0
  54. package/dist/utils/storage.js.map +1 -0
  55. package/dist/utils/version.d.ts +15 -0
  56. package/dist/utils/version.d.ts.map +1 -0
  57. package/dist/utils/version.js +33 -0
  58. package/dist/utils/version.js.map +1 -0
  59. package/package.json +55 -0
@@ -0,0 +1,393 @@
1
+ import { input } from '@inquirer/prompts';
2
+ import chalk from 'chalk';
3
+ import { createServer } from 'http';
4
+ import { URL } from 'url';
5
+ import { exec } from 'child_process';
6
+ import { promisify } from 'util';
7
+ import { randomBytes, createHash } from 'crypto';
8
+ import { OAuth2Client } from 'google-auth-library';
9
+ import { saveAuth, loadAuth, clearAuth } from '../utils/storage.js';
10
+ import { signInWithCredential, GoogleAuthProvider, getAuth, onAuthStateChanged } from 'firebase/auth';
11
+ import app from '../config/firebase.js';
12
+ const execAsync = promisify(exec);
13
+ const auth = getAuth(app);
14
+ export class AuthService {
15
+ static currentUser = null;
16
+ static customUserInfo = null;
17
+ static tokens = null;
18
+ static oauth2Client = null;
19
+ static authStateInitialized = false;
20
+ static config = {
21
+ clientId: '87955960620-mu7hdiu5nntb4al1ekk79dn73bu5otvu.apps.googleusercontent.com',
22
+ redirectUri: 'http://localhost:8080/oauth/callback',
23
+ scope: 'openid email profile'
24
+ };
25
+ static getOAuth2Client() {
26
+ if (!this.oauth2Client) {
27
+ this.oauth2Client = new OAuth2Client({
28
+ clientId: this.config.clientId,
29
+ redirectUri: this.config.redirectUri
30
+ });
31
+ }
32
+ return this.oauth2Client;
33
+ }
34
+ static generateCodeVerifier() {
35
+ return randomBytes(32).toString('base64url');
36
+ }
37
+ static generateCodeChallenge(verifier) {
38
+ return createHash('sha256').update(verifier).digest('base64url');
39
+ }
40
+ static async initialize() {
41
+ if (this.authStateInitialized)
42
+ return;
43
+ // First, try to restore from stored auth
44
+ const storedAuth = await loadAuth();
45
+ if (storedAuth?.accessToken) {
46
+ try {
47
+ // Try to validate the stored access token
48
+ this.customUserInfo = await this.fetchUserInfo(storedAuth.accessToken);
49
+ this.tokens = {
50
+ access_token: storedAuth.accessToken,
51
+ refresh_token: storedAuth.refreshToken,
52
+ expires_in: 3600,
53
+ token_type: 'Bearer'
54
+ };
55
+ // Sign in to Firebase using the stored token
56
+ if (this.tokens.access_token) {
57
+ try {
58
+ const credential = GoogleAuthProvider.credential(null, this.tokens.access_token);
59
+ const userCredential = await signInWithCredential(auth, credential);
60
+ this.currentUser = userCredential.user;
61
+ console.log(chalk.green('✅ Session restored from stored credentials'));
62
+ }
63
+ catch (firebaseError) {
64
+ // Firebase sign-in failed, but we have valid Google tokens
65
+ console.log(chalk.yellow('⚠️ Firebase auth failed but Google tokens are valid'));
66
+ }
67
+ }
68
+ }
69
+ catch (error) {
70
+ // Access token is invalid, try to refresh if we have a refresh token
71
+ if (storedAuth.refreshToken) {
72
+ try {
73
+ console.log(chalk.yellow('🔄 Access token expired, refreshing...'));
74
+ this.tokens = await this.refreshAccessToken(storedAuth.refreshToken);
75
+ this.customUserInfo = await this.fetchUserInfo(this.tokens.access_token);
76
+ // Save the new tokens
77
+ await saveAuth({
78
+ userId: storedAuth.userId,
79
+ email: storedAuth.email,
80
+ accessToken: this.tokens.access_token,
81
+ refreshToken: this.tokens.refresh_token
82
+ });
83
+ // Sign in to Firebase with refreshed token
84
+ try {
85
+ const credential = GoogleAuthProvider.credential(null, this.tokens.access_token);
86
+ const userCredential = await signInWithCredential(auth, credential);
87
+ this.currentUser = userCredential.user;
88
+ }
89
+ catch (firebaseError) {
90
+ console.log(chalk.yellow('⚠️ Firebase auth failed but Google tokens refreshed'));
91
+ }
92
+ console.log(chalk.green('✅ Tokens refreshed and session restored'));
93
+ }
94
+ catch (refreshError) {
95
+ // Refresh failed, clear stored auth
96
+ console.log(chalk.yellow('⚠️ Token refresh failed, will need to re-authenticate'));
97
+ await clearAuth();
98
+ this.customUserInfo = null;
99
+ this.tokens = null;
100
+ this.currentUser = null;
101
+ }
102
+ }
103
+ else {
104
+ // No refresh token, clear stored auth
105
+ console.log(chalk.yellow('⚠️ No valid tokens found, will need to authenticate'));
106
+ await clearAuth();
107
+ this.customUserInfo = null;
108
+ this.tokens = null;
109
+ this.currentUser = null;
110
+ }
111
+ }
112
+ }
113
+ // Set up Firebase Auth state observer for any future changes
114
+ onAuthStateChanged(auth, async (user) => {
115
+ if (!user && this.currentUser) {
116
+ // User signed out, clean up
117
+ this.currentUser = null;
118
+ this.customUserInfo = null;
119
+ this.tokens = null;
120
+ await clearAuth();
121
+ }
122
+ });
123
+ this.authStateInitialized = true;
124
+ }
125
+ static get isAuthenticated() {
126
+ return this.currentUser !== null;
127
+ }
128
+ static get user() {
129
+ return this.currentUser;
130
+ }
131
+ static get userInfo() {
132
+ return this.customUserInfo;
133
+ }
134
+ static get userId() {
135
+ return this.currentUser?.uid || null;
136
+ }
137
+ static get accessToken() {
138
+ return this.tokens?.access_token || null;
139
+ }
140
+ static async waitForAuthInit() {
141
+ if (!this.authStateInitialized) {
142
+ await this.initialize();
143
+ }
144
+ }
145
+ static async ensureValidToken() {
146
+ if (!this.tokens?.access_token) {
147
+ return null;
148
+ }
149
+ // Try to use current token
150
+ try {
151
+ await this.fetchUserInfo(this.tokens.access_token);
152
+ return this.tokens.access_token;
153
+ }
154
+ catch (error) {
155
+ // Token is invalid, try to refresh
156
+ if (this.tokens.refresh_token) {
157
+ try {
158
+ const storedAuth = await loadAuth();
159
+ this.tokens = await this.refreshAccessToken(this.tokens.refresh_token);
160
+ this.customUserInfo = await this.fetchUserInfo(this.tokens.access_token);
161
+ // Save the new tokens
162
+ await saveAuth({
163
+ userId: storedAuth?.userId || this.customUserInfo.id,
164
+ email: storedAuth?.email || this.customUserInfo.email,
165
+ accessToken: this.tokens.access_token,
166
+ refreshToken: this.tokens.refresh_token
167
+ });
168
+ return this.tokens.access_token;
169
+ }
170
+ catch (refreshError) {
171
+ // Refresh failed
172
+ this.tokens = null;
173
+ this.customUserInfo = null;
174
+ await clearAuth();
175
+ return null;
176
+ }
177
+ }
178
+ return null;
179
+ }
180
+ }
181
+ static async fetchUserInfo(accessToken) {
182
+ const response = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
183
+ headers: {
184
+ 'Authorization': `Bearer ${accessToken}`,
185
+ },
186
+ });
187
+ if (!response.ok) {
188
+ throw new Error(`Failed to fetch user info: ${response.statusText}`);
189
+ }
190
+ return await response.json();
191
+ }
192
+ static async exchangeCodeForTokens(code, codeVerifier) {
193
+ const params = new URLSearchParams({
194
+ client_id: this.config.clientId,
195
+ code,
196
+ code_verifier: codeVerifier,
197
+ grant_type: 'authorization_code',
198
+ redirect_uri: this.config.redirectUri,
199
+ });
200
+ console.log(chalk.dim('Debug - Token exchange params:'));
201
+ console.log(chalk.dim(` client_id: ${this.config.clientId}`));
202
+ console.log(chalk.dim(` grant_type: authorization_code`));
203
+ console.log(chalk.dim(` redirect_uri: ${this.config.redirectUri}`));
204
+ console.log(chalk.dim(` code_verifier: ${codeVerifier.substring(0, 10)}...`));
205
+ console.log(chalk.dim(` code: ${code.substring(0, 10)}...`));
206
+ const response = await fetch('https://oauth2.googleapis.com/token', {
207
+ method: 'POST',
208
+ headers: {
209
+ 'Content-Type': 'application/x-www-form-urlencoded',
210
+ },
211
+ body: params.toString(),
212
+ });
213
+ if (!response.ok) {
214
+ const error = await response.text();
215
+ console.log(chalk.red(`Debug - Full error response: ${error}`));
216
+ throw new Error(`Token exchange failed: ${error}`);
217
+ }
218
+ return await response.json();
219
+ }
220
+ static async refreshAccessToken(refreshToken) {
221
+ const client = this.getOAuth2Client();
222
+ client.setCredentials({
223
+ refresh_token: refreshToken
224
+ });
225
+ try {
226
+ const { credentials } = await client.refreshAccessToken();
227
+ return {
228
+ access_token: credentials.access_token,
229
+ refresh_token: credentials.refresh_token ?? refreshToken,
230
+ expires_in: credentials.expiry_date ? Math.floor((credentials.expiry_date - Date.now()) / 1000) : 3600,
231
+ token_type: 'Bearer'
232
+ };
233
+ }
234
+ catch (error) {
235
+ throw new Error(`Token refresh failed: ${error.message}`);
236
+ }
237
+ }
238
+ static async openBrowser(url) {
239
+ const platform = process.platform;
240
+ let command;
241
+ switch (platform) {
242
+ case 'darwin':
243
+ command = `open "${url}"`;
244
+ break;
245
+ case 'win32':
246
+ command = `start "${url}"`;
247
+ break;
248
+ default:
249
+ command = `xdg-open "${url}"`;
250
+ }
251
+ try {
252
+ await execAsync(command);
253
+ }
254
+ catch (error) {
255
+ console.log(chalk.yellow(`⚠️ Could not open browser automatically. Please visit: ${url}`));
256
+ }
257
+ }
258
+ static async startLocalServer() {
259
+ return new Promise((resolve, reject) => {
260
+ const server = createServer();
261
+ let authCodeResolve;
262
+ let authCodeReject;
263
+ const authCodePromise = new Promise((res, rej) => {
264
+ authCodeResolve = res;
265
+ authCodeReject = rej;
266
+ });
267
+ server.on('request', (req, res) => {
268
+ if (req.url) {
269
+ const url = new URL(req.url, 'http://localhost:8080');
270
+ if (url.pathname === '/oauth/callback') {
271
+ const code = url.searchParams.get('code');
272
+ const error = url.searchParams.get('error');
273
+ if (error) {
274
+ res.writeHead(400, { 'Content-Type': 'text/html' });
275
+ res.end('<h1>Authentication Failed</h1><p>You can close this window.</p>');
276
+ authCodeReject(new Error(`OAuth error: ${error}`));
277
+ return;
278
+ }
279
+ if (code) {
280
+ res.writeHead(200, { 'Content-Type': 'text/html' });
281
+ res.end('<h1>Authentication Successful!</h1><p>You can close this window and return to the CLI.</p>');
282
+ authCodeResolve(code);
283
+ }
284
+ else {
285
+ res.writeHead(400, { 'Content-Type': 'text/html' });
286
+ res.end('<h1>Authentication Failed</h1><p>No authorization code received.</p>');
287
+ authCodeReject(new Error('No authorization code received'));
288
+ }
289
+ }
290
+ }
291
+ });
292
+ server.listen(8080, 'localhost', () => {
293
+ resolve({ server, authCodePromise });
294
+ });
295
+ server.on('error', (error) => {
296
+ reject(error);
297
+ });
298
+ });
299
+ }
300
+ static async loginFlow() {
301
+ console.log(chalk.blue('\n🔐 Authentication Required'));
302
+ console.log('Please sign in with Google to continue.\n');
303
+ try {
304
+ // Check if we need OAuth credentials
305
+ if (this.config.clientId === 'YOUR_CLIENT_ID') {
306
+ console.log(chalk.red('❌ OAuth credentials not configured.'));
307
+ console.log(chalk.yellow('Please set up Google OAuth 2.0 credentials:'));
308
+ console.log('1. Go to https://console.cloud.google.com/apis/credentials');
309
+ console.log('2. Create OAuth 2.0 Client IDs (select "Desktop application")');
310
+ console.log('3. Add http://localhost:8080/oauth/callback as redirect URI');
311
+ console.log('4. Set GOOGLE_CLIENT_ID environment variable');
312
+ console.log(chalk.dim('Note: No client secret needed - this uses PKCE for security'));
313
+ return false;
314
+ }
315
+ // Ensure auth state is initialized
316
+ await this.initialize();
317
+ // Check if user is already authenticated
318
+ if (this.isAuthenticated) {
319
+ console.log(chalk.green('✅ Session restored successfully!'));
320
+ return true;
321
+ }
322
+ const proceed = await input({
323
+ message: 'Press Enter to open Google sign-in in your browser, or type "q" to quit:',
324
+ default: '',
325
+ });
326
+ if (proceed.toLowerCase() === 'q') {
327
+ return false;
328
+ }
329
+ console.log(chalk.yellow('🌐 Starting local server and opening browser...'));
330
+ // Start local server to receive callback
331
+ const { server, authCodePromise } = await this.startLocalServer();
332
+ try {
333
+ // Generate PKCE parameters manually
334
+ const client = this.getOAuth2Client();
335
+ const codeVerifier = this.generateCodeVerifier();
336
+ const codeChallenge = this.generateCodeChallenge(codeVerifier);
337
+ const authUrl = client.generateAuthUrl({
338
+ access_type: 'offline',
339
+ prompt: 'consent',
340
+ scope: this.config.scope.split(' ')
341
+ });
342
+ // Add PKCE parameters to the URL manually
343
+ const urlWithPKCE = new URL(authUrl);
344
+ urlWithPKCE.searchParams.set('code_challenge', codeChallenge);
345
+ urlWithPKCE.searchParams.set('code_challenge_method', 'S256');
346
+ // Open browser
347
+ await this.openBrowser(urlWithPKCE.toString());
348
+ console.log('Please complete the authentication in your browser...\n');
349
+ // Wait for callback
350
+ const authCode = await authCodePromise;
351
+ console.log(chalk.green('✅ Authorization code received!'));
352
+ // Exchange code for tokens
353
+ console.log('Exchanging authorization code for tokens...');
354
+ this.tokens = await this.exchangeCodeForTokens(authCode, codeVerifier);
355
+ // Get user info
356
+ this.customUserInfo = await this.fetchUserInfo(this.tokens.access_token);
357
+ // Sign in to Firebase Auth using the Google OAuth token
358
+ const credential = GoogleAuthProvider.credential(null, this.tokens.access_token);
359
+ const userCredential = await signInWithCredential(auth, credential);
360
+ this.currentUser = userCredential.user;
361
+ console.log(chalk.green(`✅ Welcome ${this.customUserInfo.name || this.customUserInfo.email}!`));
362
+ console.log(chalk.green('✅ Login successful!'));
363
+ // Store auth info
364
+ await saveAuth({
365
+ userId: this.customUserInfo.id,
366
+ email: this.customUserInfo.email,
367
+ accessToken: this.tokens.access_token,
368
+ refreshToken: this.tokens.refresh_token
369
+ });
370
+ return true;
371
+ }
372
+ finally {
373
+ server.close();
374
+ }
375
+ }
376
+ catch (error) {
377
+ console.error(chalk.red('❌ Authentication failed:'), error.message);
378
+ return false;
379
+ }
380
+ }
381
+ static async signOut() {
382
+ try {
383
+ await auth.signOut();
384
+ // Firebase auth state observer will handle clearing user state
385
+ console.log(chalk.green('✅ Signed out successfully'));
386
+ }
387
+ catch (error) {
388
+ console.error(chalk.red('❌ Error signing out:'), error.message);
389
+ throw error;
390
+ }
391
+ }
392
+ }
393
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/services/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { Runner } from '../types/runner.js';
2
+ export declare class CommandListener {
3
+ private activeListeners;
4
+ private isShuttingDown;
5
+ startListening(runner: Runner): Promise<void>;
6
+ stopListening(runnerId: string): void;
7
+ }
8
+ //# sourceMappingURL=command-listener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-listener.d.ts","sourceRoot":"","sources":["../../src/services/command-listener.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAC,MAAM,oBAAoB,CAAC;AAK1C,qBAAa,eAAe;IACxB,OAAO,CAAC,eAAe,CAAsC;IAC7D,OAAO,CAAC,cAAc,CAAS;IAEzB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkFnD,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;CAOxC"}
@@ -0,0 +1,84 @@
1
+ import chalk from 'chalk';
2
+ import { RunnerService } from './runner.js';
3
+ import { CommandExecutor } from './executor.js';
4
+ import { generateDeviceId } from '../utils/device.js';
5
+ export class CommandListener {
6
+ activeListeners = new Map();
7
+ isShuttingDown = false;
8
+ async startListening(runner) {
9
+ if (this.activeListeners.has(runner.id)) {
10
+ console.log(chalk.yellow(`Already listening to runner "${runner.name}"`));
11
+ return;
12
+ }
13
+ // Verify this is a local runner
14
+ const deviceId = generateDeviceId();
15
+ if (runner.machineId !== deviceId) {
16
+ throw new Error('Cannot listen to non-local runner');
17
+ }
18
+ console.log(chalk.blue(`👂 Started listening for commands on runner "${runner.name}"`));
19
+ console.log(chalk.gray(` Directory: ${runner.directory}`));
20
+ console.log(chalk.gray(` Type: ${runner.runnerType}`));
21
+ console.log(chalk.gray(` Press Ctrl+C to stop`));
22
+ console.log(chalk.gray(` Keep in mind, if your machine goes to sleep, it won't process commands`));
23
+ const unsubscribe = RunnerService.listenToRunner(runner.id, async (updatedRunner) => {
24
+ if (!updatedRunner || this.isShuttingDown)
25
+ return;
26
+ if (updatedRunner.pendingCommand) {
27
+ console.log(chalk.cyan(`📨 Received command: ${updatedRunner.pendingCommand}`));
28
+ try {
29
+ // Clear the pending command immediately
30
+ await RunnerService.clearPendingCommand(runner.id);
31
+ // Execute the command
32
+ const result = await CommandExecutor.executeCommand(updatedRunner, updatedRunner.pendingCommand);
33
+ // Create assistant message for the result
34
+ await RunnerService.createMessage({
35
+ content: result.output,
36
+ senderName: '',
37
+ type: 'runner',
38
+ runnerId: runner.id
39
+ });
40
+ // Update the runner with the result
41
+ await RunnerService.updateRunnerAfterCommand(runner.id, result.output);
42
+ console.log(chalk.blue(`💌 Message sent`));
43
+ console.log(chalk.gray('Waiting for next command...'));
44
+ }
45
+ catch (error) {
46
+ console.error(chalk.red(`❌ Error processing command: ${error.message}`));
47
+ const errorMessage = `Error executing command: ${error.message}`;
48
+ try {
49
+ // Create assistant message for the error
50
+ await RunnerService.createMessage({
51
+ content: errorMessage,
52
+ senderName: '',
53
+ type: 'runner',
54
+ runnerId: runner.id
55
+ });
56
+ await RunnerService.updateRunnerAfterCommand(runner.id, errorMessage);
57
+ }
58
+ catch (updateError) {
59
+ console.error(chalk.red('Failed to update runner with error result'));
60
+ }
61
+ console.log(chalk.gray('Waiting for next command...'));
62
+ }
63
+ }
64
+ });
65
+ this.activeListeners.set(runner.id, unsubscribe);
66
+ // Set up graceful shutdown
67
+ const cleanup = () => {
68
+ this.isShuttingDown = true;
69
+ this.stopListening(runner.id);
70
+ console.log(chalk.blue(`👋 Stopped listening to runner "${runner.name}"`));
71
+ process.exit(0);
72
+ };
73
+ process.on('SIGINT', cleanup);
74
+ process.on('SIGTERM', cleanup);
75
+ }
76
+ stopListening(runnerId) {
77
+ const unsubscribe = this.activeListeners.get(runnerId);
78
+ if (unsubscribe) {
79
+ unsubscribe();
80
+ this.activeListeners.delete(runnerId);
81
+ }
82
+ }
83
+ }
84
+ //# sourceMappingURL=command-listener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-listener.js","sourceRoot":"","sources":["../../src/services/command-listener.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ interface GlobalConfig {
2
+ appDisabled: boolean;
3
+ minBuildCLI: string;
4
+ }
5
+ export declare class ConfigService {
6
+ private static config;
7
+ static fetchConfig(): Promise<GlobalConfig>;
8
+ static isAppDisabled(): boolean;
9
+ static getMinBuildCLI(): string;
10
+ }
11
+ export {};
12
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/services/config.ts"],"names":[],"mappings":"AAGA,UAAU,YAAY;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAC,MAAM,CAA6B;WAErC,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC;IAgBjD,MAAM,CAAC,aAAa,IAAI,OAAO;IAI/B,MAAM,CAAC,cAAc,IAAI,MAAM;CAGlC"}
@@ -0,0 +1,26 @@
1
+ import { doc, getDoc } from 'firebase/firestore';
2
+ import { db } from '../config/firebase.js';
3
+ export class ConfigService {
4
+ static config = null;
5
+ static async fetchConfig() {
6
+ if (this.config) {
7
+ return this.config;
8
+ }
9
+ try {
10
+ const configDoc = doc(db, 'globals', 'config');
11
+ const docSnap = await getDoc(configDoc);
12
+ this.config = docSnap.data();
13
+ return this.config;
14
+ }
15
+ catch (error) {
16
+ throw new Error(`Failed to fetch global config from Firestore: ${error instanceof Error ? error.message : 'Unknown error'}`);
17
+ }
18
+ }
19
+ static isAppDisabled() {
20
+ return this.config?.appDisabled ?? false;
21
+ }
22
+ static getMinBuildCLI() {
23
+ return this.config?.minBuildCLI ?? "1.0.0";
24
+ }
25
+ }
26
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/services/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAE,MAAM,EAAC,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAC,EAAE,EAAC,MAAM,uBAAuB,CAAC;AAOzC,MAAM,OAAO,aAAa;IACd,MAAM,CAAC,MAAM,GAAwB,IAAI,CAAC;IAElD,MAAM,CAAC,KAAK,CAAC,WAAW;QACpB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,OAAO,IAAI,CAAC,MAAM,CAAC;QACvB,CAAC;QAED,IAAI,CAAC;YACD,MAAM,SAAS,GAAG,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;YAC/C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;YAExC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,EAAkB,CAAC;YAC7C,OAAO,IAAI,CAAC,MAAM,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,iDAAiD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QACjI,CAAC;IACL,CAAC;IAED,MAAM,CAAC,aAAa;QAChB,OAAO,IAAI,CAAC,MAAM,EAAE,WAAW,IAAI,KAAK,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,cAAc;QACjB,OAAO,IAAI,CAAC,MAAM,EAAE,WAAW,IAAI,OAAO,CAAC;IAC/C,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type Runner } from '../types/runner.js';
2
+ export interface CommandResult {
3
+ output: string;
4
+ success: boolean;
5
+ executionTime: number;
6
+ }
7
+ export declare class CommandExecutor {
8
+ static executeCommand(runner: Runner, command: string): Promise<CommandResult>;
9
+ private static executeRunnerCommand;
10
+ private static buildCommandLine;
11
+ private static getToolName;
12
+ }
13
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/services/executor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,KAAK,MAAM,EAAa,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,eAAe;WACX,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAiCpF,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAsCnC,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAgB/B,OAAO,CAAC,MAAM,CAAC,WAAW;CAY7B"}