@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,90 @@
1
+ import { execSync } from 'child_process';
2
+ import chalk from 'chalk';
3
+ import { RunnerType } from '../types/runner.js';
4
+ export class CommandExecutor {
5
+ static async executeCommand(runner, command) {
6
+ console.log(chalk.blue(`\nšŸ”§ Executing command for runner "${runner.name}"`));
7
+ console.log(chalk.gray(`Directory: ${runner.directory}`));
8
+ console.log(chalk.gray(`Command: ${command}`));
9
+ console.log(chalk.gray(`Type: ${runner.runnerType}\n`));
10
+ const startTime = Date.now();
11
+ try {
12
+ const output = this.executeRunnerCommand(runner, command);
13
+ const executionTime = Date.now() - startTime;
14
+ console.log(chalk.green('āœ… Command completed successfully'));
15
+ console.log(chalk.grey(output));
16
+ return {
17
+ output: output || 'Command executed successfully (no output)',
18
+ success: true,
19
+ executionTime
20
+ };
21
+ }
22
+ catch (error) {
23
+ const executionTime = Date.now() - startTime;
24
+ console.error(chalk.red('āŒ Error executing command:'), error.message);
25
+ return {
26
+ output: `Failed to execute command: ${error.message}`,
27
+ success: false,
28
+ executionTime
29
+ };
30
+ }
31
+ }
32
+ static executeRunnerCommand(runner, userInput) {
33
+ // Use context from runner (already provided by client)
34
+ const context = runner.context || '';
35
+ // Format the input to include context while emphasizing the latest command
36
+ //const formattedInput = this.formatInputWithContext(userInput, context);
37
+ const formattedInput = userInput;
38
+ const commandLine = this.buildCommandLine(runner.runnerType, formattedInput);
39
+ try {
40
+ const output = execSync(commandLine, {
41
+ cwd: runner.directory,
42
+ encoding: 'utf8',
43
+ stdio: ['pipe', 'pipe', 'pipe']
44
+ });
45
+ return output.trim();
46
+ }
47
+ catch (error) {
48
+ // Check for common error patterns
49
+ if (error.message.includes('command not found') || error.message.includes('No such file')) {
50
+ const toolName = this.getToolName(runner.runnerType);
51
+ throw new Error(`${toolName} CLI not found. Please ensure ${toolName} is installed and accessible.`);
52
+ }
53
+ else {
54
+ throw new Error(error.stderr?.trim() || error.stdout?.trim() || error.message);
55
+ }
56
+ }
57
+ }
58
+ // private static formatInputWithContext(userInput: string, context: string): string {
59
+ // if (context.length == 0) {
60
+ // return userInput;
61
+ // }
62
+ //
63
+ // return `RESPOND TO THE CURRENT REQUEST BELOW. Don't say things like I understand, or acknowledge this context. Previous conversation context is provided for reference only. CURRENT REQUEST (respond to this): ${userInput.replace(/"/g, '\\"')} CONVERSATION CONTEXT (for reference only):${context.replace(/"/g, '\\"')}`;
64
+ // }
65
+ static buildCommandLine(runnerType, userInput) {
66
+ // Escape quotes in user input to prevent command injection
67
+ const escapedInput = userInput.replace(/"/g, '\\"');
68
+ switch (runnerType) {
69
+ case RunnerType.CLAUDE:
70
+ return `claude -c -p --dangerously-skip-permissions "${escapedInput}"`;
71
+ case RunnerType.GEMINI:
72
+ return `gemini -p "${escapedInput}" --yolo`;
73
+ case RunnerType.CODEX:
74
+ return `codex exec "${escapedInput}" --full-auto --skip-git-repo-check`;
75
+ }
76
+ }
77
+ static getToolName(runnerType) {
78
+ switch (runnerType) {
79
+ case RunnerType.CLAUDE:
80
+ return 'Claude';
81
+ case RunnerType.GEMINI:
82
+ return 'Gemini';
83
+ case RunnerType.CODEX:
84
+ return 'Codex';
85
+ default:
86
+ return 'Claude';
87
+ }
88
+ }
89
+ }
90
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/services/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { type Runner, type CreateRunnerData, type Message, type CreateMessageData } from '../types/runner.js';
2
+ export declare class RunnerService {
3
+ private static readonly RUNNERS_COLLECTION;
4
+ private static readonly MESSAGES_COLLECTION;
5
+ static getAllRunners(): Promise<Runner[]>;
6
+ static getLocalRunners(): Promise<Runner[]>;
7
+ static createRunner(data: CreateRunnerData): Promise<Runner>;
8
+ static deleteRunner(runnerId: string): Promise<void>;
9
+ static sendCommand(runnerId: string, command: string): Promise<void>;
10
+ static clearPendingCommand(runnerId: string): Promise<void>;
11
+ static updateRunnerAfterCommand(runnerId: string, result: string): Promise<void>;
12
+ static createMessage(data: CreateMessageData): Promise<Message>;
13
+ static getMessagesForRunner(runnerId: string, limitCount?: number): Promise<Message[]>;
14
+ private static docToMessage;
15
+ static listenToRunner(runnerId: string, callback: (runner: Runner | null) => void): () => void;
16
+ private static docToRunner;
17
+ private static parseRunnerType;
18
+ }
19
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/services/runner.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAC,KAAK,MAAM,EAAE,KAAK,gBAAgB,EAAE,KAAK,OAAO,EAAE,KAAK,iBAAiB,EAAa,MAAM,oBAAoB,CAAC;AAIxH,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAa;IACvD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAc;WAE5C,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;WAgBlC,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;WAOpC,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;WAoDrD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAwB7C,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAO7D,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAOpD,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAQzE,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;WAkCxD,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAE,MAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAwBhG,OAAO,CAAC,MAAM,CAAC,YAAY;IAY3B,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,MAAM,IAAI;IAa9F,OAAO,CAAC,MAAM,CAAC,WAAW;IAiB1B,OAAO,CAAC,MAAM,CAAC,eAAe;CAWjC"}
@@ -0,0 +1,205 @@
1
+ import { collection, doc, addDoc, updateDoc, getDocs, query, where, orderBy, limit, onSnapshot, serverTimestamp, writeBatch } from 'firebase/firestore';
2
+ import { db } from '../config/firebase.js';
3
+ import { AuthService } from './auth.js';
4
+ import { RunnerType } from '../types/runner.js';
5
+ import { generateDeviceId, getDeviceDisplayName } from '../utils/device.js';
6
+ import { saveRunners, loadRunners } from '../utils/storage.js';
7
+ export class RunnerService {
8
+ static RUNNERS_COLLECTION = 'runners';
9
+ static MESSAGES_COLLECTION = 'messages';
10
+ static async getAllRunners() {
11
+ const userId = AuthService.userId;
12
+ if (!userId) {
13
+ throw new Error('User not authenticated');
14
+ }
15
+ const q = query(collection(db, this.RUNNERS_COLLECTION), where('userId', '==', userId), orderBy('lastUsed', 'desc'));
16
+ const querySnapshot = await getDocs(q);
17
+ return querySnapshot.docs.map(doc => this.docToRunner(doc.data(), doc.id));
18
+ }
19
+ static async getLocalRunners() {
20
+ const allRunners = await this.getAllRunners();
21
+ const deviceId = generateDeviceId();
22
+ return allRunners.filter(runner => runner.machineId === deviceId);
23
+ }
24
+ static async createRunner(data) {
25
+ const userId = AuthService.userId;
26
+ if (!userId) {
27
+ throw new Error('User not authenticated');
28
+ }
29
+ const deviceId = generateDeviceId();
30
+ const deviceName = getDeviceDisplayName();
31
+ const runnerData = {
32
+ name: data.name,
33
+ directory: data.directory,
34
+ userId,
35
+ runnerType: data.runnerType,
36
+ createdAt: serverTimestamp(),
37
+ lastUsed: serverTimestamp(),
38
+ machineId: deviceId,
39
+ machineName: deviceName,
40
+ lastMessage: null,
41
+ pendingCommand: null
42
+ };
43
+ const docRef = await addDoc(collection(db, this.RUNNERS_COLLECTION), runnerData);
44
+ const runnerId = docRef.id;
45
+ // Store locally as well
46
+ const storedRunner = {
47
+ id: runnerId,
48
+ name: data.name,
49
+ directory: data.directory,
50
+ runnerType: data.runnerType,
51
+ machineId: deviceId,
52
+ createdAt: new Date().toISOString()
53
+ };
54
+ const localRunners = await loadRunners();
55
+ localRunners.push(storedRunner);
56
+ await saveRunners(localRunners);
57
+ return {
58
+ id: runnerId,
59
+ name: data.name,
60
+ directory: data.directory,
61
+ userId,
62
+ runnerType: data.runnerType,
63
+ createdAt: new Date(),
64
+ lastUsed: new Date(),
65
+ machineId: deviceId,
66
+ machineName: deviceName
67
+ };
68
+ }
69
+ static async deleteRunner(runnerId) {
70
+ const batch = writeBatch(db);
71
+ // Delete all messages in the subcollection
72
+ const runnerDocRef = doc(db, this.RUNNERS_COLLECTION, runnerId);
73
+ const messagesCollectionRef = collection(runnerDocRef, this.MESSAGES_COLLECTION);
74
+ const messagesSnapshot = await getDocs(messagesCollectionRef);
75
+ for (const messageDoc of messagesSnapshot.docs) {
76
+ batch.delete(messageDoc.ref);
77
+ }
78
+ // Delete the runner document
79
+ batch.delete(runnerDocRef);
80
+ // Commit the batch
81
+ await batch.commit();
82
+ // Remove from local storage
83
+ const localRunners = await loadRunners();
84
+ const filteredRunners = localRunners.filter(r => r.id !== runnerId);
85
+ await saveRunners(filteredRunners);
86
+ }
87
+ static async sendCommand(runnerId, command) {
88
+ const runnerDoc = doc(db, this.RUNNERS_COLLECTION, runnerId);
89
+ await updateDoc(runnerDoc, {
90
+ pendingCommand: command
91
+ });
92
+ }
93
+ static async clearPendingCommand(runnerId) {
94
+ const runnerDoc = doc(db, this.RUNNERS_COLLECTION, runnerId);
95
+ await updateDoc(runnerDoc, {
96
+ pendingCommand: null
97
+ });
98
+ }
99
+ static async updateRunnerAfterCommand(runnerId, result) {
100
+ const runnerDoc = doc(db, this.RUNNERS_COLLECTION, runnerId);
101
+ await updateDoc(runnerDoc, {
102
+ lastUsed: serverTimestamp(),
103
+ lastMessage: result ?? ''
104
+ });
105
+ }
106
+ static async createMessage(data) {
107
+ const userId = AuthService.userId;
108
+ if (!userId) {
109
+ throw new Error('User not authenticated');
110
+ }
111
+ if (!data.runnerId) {
112
+ throw new Error('Runner ID is required to create a message');
113
+ }
114
+ const messageData = {
115
+ content: data.content ?? '',
116
+ senderName: data.senderName ?? '',
117
+ type: data.type,
118
+ userId,
119
+ timestamp: serverTimestamp()
120
+ };
121
+ // Store message in the runner's messages subcollection
122
+ const runnerDocRef = doc(db, this.RUNNERS_COLLECTION, data.runnerId);
123
+ const messagesCollectionRef = collection(runnerDocRef, this.MESSAGES_COLLECTION);
124
+ const docRef = await addDoc(messagesCollectionRef, messageData);
125
+ return {
126
+ id: docRef.id,
127
+ content: data.content,
128
+ senderName: data.senderName,
129
+ type: data.type,
130
+ userId,
131
+ timestamp: new Date(),
132
+ runnerId: data.runnerId
133
+ };
134
+ }
135
+ static async getMessagesForRunner(runnerId, limitCount = 50) {
136
+ const userId = AuthService.userId;
137
+ if (!userId) {
138
+ throw new Error('User not authenticated');
139
+ }
140
+ // Query the messages subcollection within the specific runner document
141
+ const runnerDocRef = doc(db, this.RUNNERS_COLLECTION, runnerId);
142
+ const messagesCollectionRef = collection(runnerDocRef, this.MESSAGES_COLLECTION);
143
+ const queryConstraints = [
144
+ where('userId', '==', userId),
145
+ orderBy('timestamp', 'desc')
146
+ ];
147
+ if (limitCount > 0) {
148
+ queryConstraints.push(limit(limitCount));
149
+ }
150
+ const q = query(messagesCollectionRef, ...queryConstraints);
151
+ const querySnapshot = await getDocs(q);
152
+ return querySnapshot.docs.map(doc => this.docToMessage(doc.data(), doc.id, runnerId));
153
+ }
154
+ static docToMessage(data, id, runnerId) {
155
+ return {
156
+ id,
157
+ content: data.content || '',
158
+ senderName: data.senderName || '',
159
+ type: data.type || 'user',
160
+ userId: data.userId || '',
161
+ timestamp: data.timestamp?.toDate() || new Date(),
162
+ runnerId: runnerId || data.runnerId || undefined
163
+ };
164
+ }
165
+ static listenToRunner(runnerId, callback) {
166
+ const runnerDoc = doc(db, this.RUNNERS_COLLECTION, runnerId);
167
+ return onSnapshot(runnerDoc, (doc) => {
168
+ if (doc.exists()) {
169
+ const runner = this.docToRunner(doc.data(), doc.id);
170
+ callback(runner);
171
+ }
172
+ else {
173
+ callback(null);
174
+ }
175
+ });
176
+ }
177
+ static docToRunner(data, id) {
178
+ return {
179
+ id,
180
+ name: data.name || '',
181
+ directory: data.directory || '',
182
+ userId: data.userId || '',
183
+ runnerType: this.parseRunnerType(data.runnerType),
184
+ createdAt: data.createdAt?.toDate() || null,
185
+ lastUsed: data.lastUsed?.toDate() || null,
186
+ lastMessage: data.lastMessage || undefined,
187
+ machineName: data.machineName || undefined,
188
+ machineId: data.machineId || undefined,
189
+ pendingCommand: data.pendingCommand || undefined,
190
+ context: data.context || undefined
191
+ };
192
+ }
193
+ static parseRunnerType(type) {
194
+ switch (type) {
195
+ case 'codex':
196
+ return RunnerType.CODEX;
197
+ case 'gemini':
198
+ return RunnerType.GEMINI;
199
+ case 'claude':
200
+ default:
201
+ return RunnerType.CLAUDE;
202
+ }
203
+ }
204
+ }
205
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/services/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ export declare enum RunnerType {
2
+ CLAUDE = "claude",
3
+ CODEX = "codex",
4
+ GEMINI = "gemini"
5
+ }
6
+ export interface Runner {
7
+ id: string;
8
+ name: string;
9
+ directory: string;
10
+ userId: string;
11
+ runnerType: RunnerType;
12
+ createdAt: Date | null;
13
+ lastUsed: Date | null;
14
+ lastMessage?: string;
15
+ machineName?: string;
16
+ machineId?: string;
17
+ pendingCommand?: string;
18
+ context?: string;
19
+ }
20
+ export interface CreateRunnerData {
21
+ name: string;
22
+ directory: string;
23
+ runnerType: RunnerType;
24
+ }
25
+ export interface Message {
26
+ id: string;
27
+ content: string;
28
+ senderName: string;
29
+ timestamp: Date;
30
+ type: 'user' | 'runner' | 'error';
31
+ userId: string;
32
+ runnerId?: string;
33
+ }
34
+ export interface CreateMessageData {
35
+ content: string;
36
+ senderName: string;
37
+ type: 'user' | 'runner' | 'error';
38
+ runnerId: string;
39
+ }
40
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/types/runner.ts"],"names":[],"mappings":"AAAA,oBAAY,UAAU;IAClB,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,MAAM,WAAW;CACpB;AAED,MAAM,WAAW,MAAM;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,OAAO;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,7 @@
1
+ export var RunnerType;
2
+ (function (RunnerType) {
3
+ RunnerType["CLAUDE"] = "claude";
4
+ RunnerType["CODEX"] = "codex";
5
+ RunnerType["GEMINI"] = "gemini";
6
+ })(RunnerType || (RunnerType = {}));
7
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/types/runner.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,UAIX;AAJD,WAAY,UAAU;IAClB,+BAAiB,CAAA;IACjB,6BAAe,CAAA;IACf,+BAAiB,CAAA;AACrB,CAAC,EAJW,UAAU,KAAV,UAAU,QAIrB"}
@@ -0,0 +1,4 @@
1
+ export declare function getDeviceDisplayName(): string;
2
+ export declare function generateDeviceId(): string;
3
+ export declare function isDesktop(): boolean;
4
+ //# sourceMappingURL=device.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../src/utils/device.ts"],"names":[],"mappings":"AAGA,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAGzC;AAED,wBAAgB,SAAS,IAAI,OAAO,CAGnC"}
@@ -0,0 +1,14 @@
1
+ import { hostname, platform } from 'os';
2
+ import { createHash } from 'crypto';
3
+ export function getDeviceDisplayName() {
4
+ return `${hostname()} (${platform()})`;
5
+ }
6
+ export function generateDeviceId() {
7
+ const deviceInfo = `${hostname()}-${platform()}`;
8
+ return createHash('sha256').update(deviceInfo).digest('hex');
9
+ }
10
+ export function isDesktop() {
11
+ const platformType = platform();
12
+ return platformType === 'darwin' || platformType === 'win32' || platformType === 'linux';
13
+ }
14
+ //# sourceMappingURL=device.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.js","sourceRoot":"","sources":["../../src/utils/device.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAE,QAAQ,EAAC,MAAM,IAAI,CAAC;AACtC,OAAO,EAAC,UAAU,EAAC,MAAM,QAAQ,CAAC;AAElC,MAAM,UAAU,oBAAoB;IAChC,OAAO,GAAG,QAAQ,EAAE,KAAK,QAAQ,EAAE,GAAG,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC5B,MAAM,UAAU,GAAG,GAAG,QAAQ,EAAE,IAAI,QAAQ,EAAE,EAAE,CAAC;IACjD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,SAAS;IACrB,MAAM,YAAY,GAAG,QAAQ,EAAE,CAAC;IAChC,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,OAAO,IAAI,YAAY,KAAK,OAAO,CAAC;AAC7F,CAAC"}
@@ -0,0 +1,20 @@
1
+ export interface StoredRunner {
2
+ id: string;
3
+ name: string;
4
+ directory: string;
5
+ runnerType: string;
6
+ machineId: string;
7
+ createdAt: string;
8
+ }
9
+ export interface StoredAuth {
10
+ refreshToken?: string;
11
+ accessToken?: string;
12
+ userId?: string;
13
+ email?: string;
14
+ }
15
+ export declare function saveRunners(runners: StoredRunner[]): Promise<void>;
16
+ export declare function loadRunners(): Promise<StoredRunner[]>;
17
+ export declare function saveAuth(auth: StoredAuth): Promise<void>;
18
+ export declare function loadAuth(): Promise<StoredAuth | null>;
19
+ export declare function clearAuth(): Promise<void>;
20
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAUD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGxE;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAO3D;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9D;AAED,wBAAsB,QAAQ,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAO3D;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/C"}
@@ -0,0 +1,49 @@
1
+ import { promises as fs } from 'fs';
2
+ import { join } from 'path';
3
+ import { homedir } from 'os';
4
+ const CONFIG_DIR = join(homedir(), '.salamander');
5
+ const RUNNERS_FILE = join(CONFIG_DIR, 'runners.json');
6
+ const AUTH_FILE = join(CONFIG_DIR, 'auth.json');
7
+ async function ensureConfigDir() {
8
+ try {
9
+ await fs.access(CONFIG_DIR);
10
+ }
11
+ catch {
12
+ await fs.mkdir(CONFIG_DIR, { recursive: true });
13
+ }
14
+ }
15
+ export async function saveRunners(runners) {
16
+ await ensureConfigDir();
17
+ await fs.writeFile(RUNNERS_FILE, JSON.stringify(runners, null, 2));
18
+ }
19
+ export async function loadRunners() {
20
+ try {
21
+ const data = await fs.readFile(RUNNERS_FILE, 'utf-8');
22
+ return JSON.parse(data);
23
+ }
24
+ catch {
25
+ return [];
26
+ }
27
+ }
28
+ export async function saveAuth(auth) {
29
+ await ensureConfigDir();
30
+ await fs.writeFile(AUTH_FILE, JSON.stringify(auth, null, 2));
31
+ }
32
+ export async function loadAuth() {
33
+ try {
34
+ const data = await fs.readFile(AUTH_FILE, 'utf-8');
35
+ return JSON.parse(data);
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ export async function clearAuth() {
42
+ try {
43
+ await fs.unlink(AUTH_FILE);
44
+ }
45
+ catch {
46
+ // File doesn't exist, which is fine
47
+ }
48
+ }
49
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,IAAI,EAAE,EAAC,MAAM,IAAI,CAAC;AAClC,OAAO,EAAC,IAAI,EAAU,MAAM,MAAM,CAAC;AACnC,OAAO,EAAC,OAAO,EAAC,MAAM,IAAI,CAAC;AAE3B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;AAClD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;AACtD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AAkBhD,KAAK,UAAU,eAAe;IAC1B,IAAI,CAAC;QACD,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACL,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAClD,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAuB;IACrD,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC7B,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAgB;IAC3C,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC1B,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC3B,IAAI,CAAC;QACD,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACL,oCAAoC;IACxC,CAAC;AACL,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Converts a semantic version string to a comparable number
3
+ * e.g., "1.2.3" becomes 1002003 (1*1000000 + 2*1000 + 3)
4
+ */
5
+ export declare function versionToNumber(version: string): number;
6
+ /**
7
+ * Compares two version strings
8
+ * Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2
9
+ */
10
+ export declare function compareVersions(v1: string, v2: string): number;
11
+ /**
12
+ * Checks if the current version is less than the minimum required version
13
+ */
14
+ export declare function isVersionOutdated(currentVersion: string, minVersion: string): boolean;
15
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/utils/version.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUvD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAO9D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAErF"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Converts a semantic version string to a comparable number
3
+ * e.g., "1.2.3" becomes 1002003 (1*1000000 + 2*1000 + 3)
4
+ */
5
+ export function versionToNumber(version) {
6
+ const parts = version.replace(/^v/, '').split('.').map(n => parseInt(n, 10) || 0);
7
+ const [major = 0, minor = 0, patch = 0] = parts;
8
+ // Ensure parts don't exceed 999 to avoid overflow
9
+ const safeMajor = Math.min(major, 999);
10
+ const safeMinor = Math.min(minor, 999);
11
+ const safePatch = Math.min(patch, 999);
12
+ return safeMajor * 1000000 + safeMinor * 1000 + safePatch;
13
+ }
14
+ /**
15
+ * Compares two version strings
16
+ * Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2
17
+ */
18
+ export function compareVersions(v1, v2) {
19
+ const n1 = versionToNumber(v1);
20
+ const n2 = versionToNumber(v2);
21
+ if (n1 < n2)
22
+ return -1;
23
+ if (n1 > n2)
24
+ return 1;
25
+ return 0;
26
+ }
27
+ /**
28
+ * Checks if the current version is less than the minimum required version
29
+ */
30
+ export function isVersionOutdated(currentVersion, minVersion) {
31
+ return compareVersions(currentVersion, minVersion) < 0;
32
+ }
33
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/utils/version.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAClF,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;IAEhD,kDAAkD;IAClD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEvC,OAAO,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,IAAI,GAAG,SAAS,CAAC;AAC9D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,EAAU,EAAE,EAAU;IAClD,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;IAC/B,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;IAE/B,IAAI,EAAE,GAAG,EAAE;QAAE,OAAO,CAAC,CAAC,CAAC;IACvB,IAAI,EAAE,GAAG,EAAE;QAAE,OAAO,CAAC,CAAC;IACtB,OAAO,CAAC,CAAC;AACb,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,cAAsB,EAAE,UAAkB;IACxE,OAAO,eAAe,CAAC,cAAc,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;AAC3D,CAAC"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@commit451/salamander",
3
+ "version": "1.0.0",
4
+ "description": "Never be AFK",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "salamander": "bin/salamander.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsx src/index.ts",
13
+ "start": "node dist/index.js",
14
+ "prepare": "npm run build",
15
+ "pub": "npm publish --access public"
16
+ },
17
+ "engines": {
18
+ "node": ">=18.0.0"
19
+ },
20
+ "dependencies": {
21
+ "@inquirer/prompts": "^7.8.4",
22
+ "chalk": "^5.6.2",
23
+ "commander": "^14.0.0",
24
+ "firebase": "^12.2.1",
25
+ "google-auth-library": "^10.3.0",
26
+ "uuid": "^13.0.0"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^24.3.1",
30
+ "@types/uuid": "^10.0.0",
31
+ "tsx": "^4.20.5",
32
+ "typescript": "^5.9.2"
33
+ },
34
+ "keywords": [
35
+ "cli",
36
+ "afk",
37
+ "automation",
38
+ "tool"
39
+ ],
40
+ "author": "",
41
+ "license": "ISC",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": ""
45
+ },
46
+ "homepage": "",
47
+ "bugs": {
48
+ "url": ""
49
+ },
50
+ "files": [
51
+ "dist/**/*",
52
+ "bin/**/*",
53
+ "README.md"
54
+ ]
55
+ }