@sarkar-ai/deskmate 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +49 -0
- package/LICENSE +21 -0
- package/README.md +360 -0
- package/dist/cli/init.js +387 -0
- package/dist/cli.js +184 -0
- package/dist/clients/telegram.js +148 -0
- package/dist/core/agent/factory.js +67 -0
- package/dist/core/agent/index.js +32 -0
- package/dist/core/agent/providers/claude-code.js +158 -0
- package/dist/core/agent/types.js +9 -0
- package/dist/core/approval.js +192 -0
- package/dist/core/executor.js +237 -0
- package/dist/core/logger.js +76 -0
- package/dist/core/platform.js +130 -0
- package/dist/gateway/gateway.js +435 -0
- package/dist/gateway/index.js +9 -0
- package/dist/gateway/security.js +35 -0
- package/dist/gateway/session.js +195 -0
- package/dist/gateway/types.js +8 -0
- package/dist/index.js +130 -0
- package/dist/mcp/server.js +156 -0
- package/dist/telegram/bot.js +333 -0
- package/install.sh +817 -0
- package/package.json +73 -0
- package/uninstall.sh +121 -0
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Interactive Setup Wizard
|
|
4
|
+
*
|
|
5
|
+
* Self-contained setup: writes .env, optionally installs a background service
|
|
6
|
+
* (launchd on macOS, systemd on Linux), and guides through macOS permissions.
|
|
7
|
+
*
|
|
8
|
+
* For an alternative shell-based installer, see ./install.sh.
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.runInitWizard = runInitWizard;
|
|
45
|
+
const readline = __importStar(require("readline"));
|
|
46
|
+
const fs = __importStar(require("fs/promises"));
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
const os = __importStar(require("os"));
|
|
49
|
+
const child_process_1 = require("child_process");
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Helpers
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
function createPrompt() {
|
|
54
|
+
return readline.createInterface({
|
|
55
|
+
input: process.stdin,
|
|
56
|
+
output: process.stdout,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function ask(rl, question) {
|
|
60
|
+
return new Promise((resolve) => {
|
|
61
|
+
rl.question(question, (answer) => resolve(answer.trim()));
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async function askYesNo(rl, question, defaultYes = true) {
|
|
65
|
+
const hint = defaultYes ? "[Y/n]" : "[y/N]";
|
|
66
|
+
const answer = await ask(rl, `${question} ${hint}: `);
|
|
67
|
+
if (answer === "")
|
|
68
|
+
return defaultYes;
|
|
69
|
+
return answer.toLowerCase() === "y";
|
|
70
|
+
}
|
|
71
|
+
async function checkClaudeCLI() {
|
|
72
|
+
try {
|
|
73
|
+
(0, child_process_1.execSync)("which claude", { stdio: "ignore" });
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function detectPlatform() {
|
|
81
|
+
switch (process.platform) {
|
|
82
|
+
case "darwin":
|
|
83
|
+
return "macos";
|
|
84
|
+
case "linux":
|
|
85
|
+
return "linux";
|
|
86
|
+
case "win32":
|
|
87
|
+
return "windows";
|
|
88
|
+
default:
|
|
89
|
+
return "unsupported";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// Service installation helpers
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
const PLIST_NAME = "com.deskmate.service";
|
|
96
|
+
function plistPath() {
|
|
97
|
+
return path.join(os.homedir(), "Library", "LaunchAgents", `${PLIST_NAME}.plist`);
|
|
98
|
+
}
|
|
99
|
+
function systemdDir() {
|
|
100
|
+
return path.join(os.homedir(), ".config", "systemd", "user");
|
|
101
|
+
}
|
|
102
|
+
function systemdPath() {
|
|
103
|
+
return path.join(systemdDir(), "deskmate.service");
|
|
104
|
+
}
|
|
105
|
+
function buildPlist(nodePath, projectDir, logsDir, runMode) {
|
|
106
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
107
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
108
|
+
<plist version="1.0">
|
|
109
|
+
<dict>
|
|
110
|
+
<key>Label</key>
|
|
111
|
+
<string>${PLIST_NAME}</string>
|
|
112
|
+
|
|
113
|
+
<key>ProgramArguments</key>
|
|
114
|
+
<array>
|
|
115
|
+
<string>${nodePath}</string>
|
|
116
|
+
<string>${projectDir}/dist/index.js</string>
|
|
117
|
+
<string>${runMode}</string>
|
|
118
|
+
</array>
|
|
119
|
+
|
|
120
|
+
<key>WorkingDirectory</key>
|
|
121
|
+
<string>${projectDir}</string>
|
|
122
|
+
|
|
123
|
+
<key>EnvironmentVariables</key>
|
|
124
|
+
<dict>
|
|
125
|
+
<key>PATH</key>
|
|
126
|
+
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:${os.homedir()}/.local/bin</string>
|
|
127
|
+
</dict>
|
|
128
|
+
|
|
129
|
+
<key>RunAtLoad</key>
|
|
130
|
+
<true/>
|
|
131
|
+
|
|
132
|
+
<key>KeepAlive</key>
|
|
133
|
+
<true/>
|
|
134
|
+
|
|
135
|
+
<key>StandardOutPath</key>
|
|
136
|
+
<string>${logsDir}/stdout.log</string>
|
|
137
|
+
|
|
138
|
+
<key>StandardErrorPath</key>
|
|
139
|
+
<string>${logsDir}/stderr.log</string>
|
|
140
|
+
</dict>
|
|
141
|
+
</plist>`;
|
|
142
|
+
}
|
|
143
|
+
function buildSystemdUnit(nodePath, projectDir, logsDir, runMode) {
|
|
144
|
+
return `[Unit]
|
|
145
|
+
Description=Deskmate - Local Machine Assistant
|
|
146
|
+
After=network-online.target
|
|
147
|
+
Wants=network-online.target
|
|
148
|
+
|
|
149
|
+
[Service]
|
|
150
|
+
Type=simple
|
|
151
|
+
ExecStart=${nodePath} ${projectDir}/dist/index.js ${runMode}
|
|
152
|
+
WorkingDirectory=${projectDir}
|
|
153
|
+
Environment=PATH=/usr/local/bin:/usr/bin:/bin:${os.homedir()}/.local/bin
|
|
154
|
+
Restart=always
|
|
155
|
+
RestartSec=5
|
|
156
|
+
|
|
157
|
+
InhibitDelayMaxSec=5
|
|
158
|
+
|
|
159
|
+
StandardOutput=append:${logsDir}/stdout.log
|
|
160
|
+
StandardError=append:${logsDir}/stderr.log
|
|
161
|
+
|
|
162
|
+
[Install]
|
|
163
|
+
WantedBy=default.target`;
|
|
164
|
+
}
|
|
165
|
+
async function installMacosService(projectDir, logsDir, runMode) {
|
|
166
|
+
const nodePath = process.execPath;
|
|
167
|
+
const dest = plistPath();
|
|
168
|
+
// Unload existing
|
|
169
|
+
try {
|
|
170
|
+
(0, child_process_1.execSync)(`launchctl list 2>/dev/null | grep -q "${PLIST_NAME}" && launchctl unload "${dest}"`, {
|
|
171
|
+
stdio: "ignore",
|
|
172
|
+
shell: "/bin/bash",
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// not loaded — fine
|
|
177
|
+
}
|
|
178
|
+
await fs.mkdir(path.dirname(dest), { recursive: true });
|
|
179
|
+
await fs.mkdir(logsDir, { recursive: true });
|
|
180
|
+
await fs.writeFile(dest, buildPlist(nodePath, projectDir, logsDir, runMode), "utf-8");
|
|
181
|
+
(0, child_process_1.execSync)(`launchctl load "${dest}"`);
|
|
182
|
+
console.log("\n Service installed and started via launchd.");
|
|
183
|
+
console.log(` Plist: ${dest}`);
|
|
184
|
+
}
|
|
185
|
+
async function installLinuxService(projectDir, logsDir, runMode) {
|
|
186
|
+
const nodePath = process.execPath;
|
|
187
|
+
const dest = systemdPath();
|
|
188
|
+
// Stop existing
|
|
189
|
+
try {
|
|
190
|
+
(0, child_process_1.execSync)("systemctl --user stop deskmate.service", { stdio: "ignore" });
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// not running — fine
|
|
194
|
+
}
|
|
195
|
+
await fs.mkdir(systemdDir(), { recursive: true });
|
|
196
|
+
await fs.mkdir(logsDir, { recursive: true });
|
|
197
|
+
await fs.writeFile(dest, buildSystemdUnit(nodePath, projectDir, logsDir, runMode), "utf-8");
|
|
198
|
+
(0, child_process_1.execSync)("systemctl --user daemon-reload");
|
|
199
|
+
(0, child_process_1.execSync)("systemctl --user enable deskmate.service");
|
|
200
|
+
(0, child_process_1.execSync)("systemctl --user start deskmate.service");
|
|
201
|
+
// Enable lingering so the service survives logout
|
|
202
|
+
try {
|
|
203
|
+
(0, child_process_1.execSync)(`loginctl enable-linger "$(whoami)"`, { stdio: "ignore", shell: "/bin/bash" });
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// loginctl may not be available
|
|
207
|
+
}
|
|
208
|
+
console.log("\n Service installed and started via systemd.");
|
|
209
|
+
console.log(` Unit file: ${dest}`);
|
|
210
|
+
}
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
// macOS permissions helper
|
|
213
|
+
// ---------------------------------------------------------------------------
|
|
214
|
+
async function offerMacosPermissions(rl) {
|
|
215
|
+
console.log("\n--- macOS Permissions ---\n");
|
|
216
|
+
console.log(" Deskmate works best with the following permissions:");
|
|
217
|
+
console.log(" - Screen Recording (screenshots)");
|
|
218
|
+
console.log(" - Accessibility (system control)");
|
|
219
|
+
console.log(" - Full Disk Access (read/write anywhere)");
|
|
220
|
+
console.log(" - Automation (AppleScript)");
|
|
221
|
+
console.log("");
|
|
222
|
+
if (await askYesNo(rl, "Trigger Screen Recording permission dialog?")) {
|
|
223
|
+
try {
|
|
224
|
+
(0, child_process_1.execSync)("screencapture -x /tmp/deskmate-test-screenshot.png", { stdio: "ignore" });
|
|
225
|
+
(0, child_process_1.execSync)("rm -f /tmp/deskmate-test-screenshot.png", { stdio: "ignore" });
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
// permission dialog may have appeared
|
|
229
|
+
}
|
|
230
|
+
console.log(" If a dialog appeared, click Allow.\n");
|
|
231
|
+
}
|
|
232
|
+
if (await askYesNo(rl, "Open Accessibility settings?")) {
|
|
233
|
+
(0, child_process_1.execSync)('open "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"');
|
|
234
|
+
await ask(rl, " Press Enter when done...");
|
|
235
|
+
}
|
|
236
|
+
if (await askYesNo(rl, "Open Full Disk Access settings?")) {
|
|
237
|
+
(0, child_process_1.execSync)('open "x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles"');
|
|
238
|
+
await ask(rl, " Press Enter when done...");
|
|
239
|
+
}
|
|
240
|
+
if (await askYesNo(rl, "Open Automation settings?")) {
|
|
241
|
+
(0, child_process_1.execSync)('open "x-apple.systempreferences:com.apple.preference.security?Privacy_Automation"');
|
|
242
|
+
await ask(rl, " Press Enter when done...");
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// ---------------------------------------------------------------------------
|
|
246
|
+
// Management commands summary
|
|
247
|
+
// ---------------------------------------------------------------------------
|
|
248
|
+
function printManagementCommands(platform, logsDir) {
|
|
249
|
+
console.log("\nManagement commands:\n");
|
|
250
|
+
console.log(` View logs: tail -f ${logsDir}/stdout.log`);
|
|
251
|
+
if (platform === "macos") {
|
|
252
|
+
const dest = plistPath();
|
|
253
|
+
console.log(` Stop service: launchctl unload "${dest}"`);
|
|
254
|
+
console.log(` Start service: launchctl load "${dest}"`);
|
|
255
|
+
console.log(` Check status: launchctl list | grep deskmate`);
|
|
256
|
+
}
|
|
257
|
+
else if (platform === "linux") {
|
|
258
|
+
console.log(" Stop service: systemctl --user stop deskmate.service");
|
|
259
|
+
console.log(" Start service: systemctl --user start deskmate.service");
|
|
260
|
+
console.log(" Restart service: systemctl --user restart deskmate.service");
|
|
261
|
+
console.log(" Check status: systemctl --user status deskmate.service");
|
|
262
|
+
}
|
|
263
|
+
else if (platform === "windows") {
|
|
264
|
+
console.log(" On Windows (WSL2), manage the service from inside your WSL2 terminal.");
|
|
265
|
+
console.log(" Stop service: systemctl --user stop deskmate.service");
|
|
266
|
+
console.log(" Start service: systemctl --user start deskmate.service");
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// ---------------------------------------------------------------------------
|
|
270
|
+
// Main wizard
|
|
271
|
+
// ---------------------------------------------------------------------------
|
|
272
|
+
async function runInitWizard() {
|
|
273
|
+
const rl = createPrompt();
|
|
274
|
+
console.log("\n========================================");
|
|
275
|
+
console.log(" Deskmate Setup Wizard");
|
|
276
|
+
console.log("========================================\n");
|
|
277
|
+
const platform = detectPlatform();
|
|
278
|
+
console.log(`Detected platform: ${platform}\n`);
|
|
279
|
+
if (platform === "windows") {
|
|
280
|
+
console.log("Native Windows is not directly supported.");
|
|
281
|
+
console.log("Please run this wizard inside a WSL2 terminal.\n");
|
|
282
|
+
}
|
|
283
|
+
const hasClaude = await checkClaudeCLI();
|
|
284
|
+
if (!hasClaude) {
|
|
285
|
+
console.log("WARNING: 'claude' CLI not found in PATH.");
|
|
286
|
+
console.log("Install it from: https://docs.anthropic.com/en/docs/claude-code");
|
|
287
|
+
console.log("");
|
|
288
|
+
}
|
|
289
|
+
// ----- Step 1: .env wizard -----
|
|
290
|
+
const env = {};
|
|
291
|
+
env.AGENT_PROVIDER = "claude-code";
|
|
292
|
+
const apiKey = await ask(rl, "Anthropic API Key (for Claude Code): ");
|
|
293
|
+
if (apiKey)
|
|
294
|
+
env.ANTHROPIC_API_KEY = apiKey;
|
|
295
|
+
console.log("\n--- Telegram Configuration ---\n");
|
|
296
|
+
console.log(" Bot token → message @BotFather on Telegram, send /newbot");
|
|
297
|
+
console.log(" User ID → message @userinfobot on Telegram, copy the number");
|
|
298
|
+
console.log("");
|
|
299
|
+
const token = await ask(rl, "Telegram Bot Token (from @BotFather): ");
|
|
300
|
+
if (token)
|
|
301
|
+
env.TELEGRAM_BOT_TOKEN = token;
|
|
302
|
+
const userId = await ask(rl, "Your Telegram User ID (from @userinfobot): ");
|
|
303
|
+
if (userId) {
|
|
304
|
+
env.ALLOWED_USER_ID = userId;
|
|
305
|
+
env.ALLOWED_USERS = `telegram:${userId}`;
|
|
306
|
+
}
|
|
307
|
+
console.log("\n--- General Configuration ---\n");
|
|
308
|
+
const workingDir = await ask(rl, `Working directory (default: ${os.homedir()}): `);
|
|
309
|
+
if (workingDir)
|
|
310
|
+
env.WORKING_DIR = workingDir;
|
|
311
|
+
const botName = await ask(rl, "Bot name (default: Deskmate): ");
|
|
312
|
+
if (botName)
|
|
313
|
+
env.BOT_NAME = botName;
|
|
314
|
+
// ----- Step 2: Write .env -----
|
|
315
|
+
const envPath = path.join(process.cwd(), ".env");
|
|
316
|
+
let envContent = "# Deskmate Configuration (generated by deskmate init)\n\n";
|
|
317
|
+
for (const [key, value] of Object.entries(env)) {
|
|
318
|
+
envContent += `${key}=${value}\n`;
|
|
319
|
+
}
|
|
320
|
+
if (!env.LOG_LEVEL)
|
|
321
|
+
envContent += "LOG_LEVEL=info\n";
|
|
322
|
+
if (!env.REQUIRE_APPROVAL_FOR_ALL)
|
|
323
|
+
envContent += "REQUIRE_APPROVAL_FOR_ALL=false\n";
|
|
324
|
+
try {
|
|
325
|
+
let envExists = false;
|
|
326
|
+
try {
|
|
327
|
+
await fs.access(envPath);
|
|
328
|
+
envExists = true;
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
// does not exist
|
|
332
|
+
}
|
|
333
|
+
if (envExists) {
|
|
334
|
+
console.log(`\nWARNING: .env file already exists at ${envPath}`);
|
|
335
|
+
const newPath = envPath + ".new";
|
|
336
|
+
await fs.writeFile(newPath, envContent, "utf-8");
|
|
337
|
+
console.log(`Configuration saved to ${newPath}`);
|
|
338
|
+
console.log("Review and rename it to .env when ready.");
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
await fs.writeFile(envPath, envContent, "utf-8");
|
|
342
|
+
console.log(`\nConfiguration saved to ${envPath}`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
console.error(`\nFailed to write config: ${error.message}`);
|
|
347
|
+
console.log("\nHere is your configuration:\n");
|
|
348
|
+
console.log(envContent);
|
|
349
|
+
}
|
|
350
|
+
// ----- Step 3: Service installation -----
|
|
351
|
+
if (platform === "macos" || platform === "linux") {
|
|
352
|
+
console.log("");
|
|
353
|
+
const installService = await askYesNo(rl, "Install as background service?");
|
|
354
|
+
if (installService) {
|
|
355
|
+
// Determine project root (where package.json lives)
|
|
356
|
+
const projectDir = path.resolve(__dirname, "..");
|
|
357
|
+
const logsDir = path.join(projectDir, "logs");
|
|
358
|
+
const runMode = "gateway";
|
|
359
|
+
try {
|
|
360
|
+
if (platform === "macos") {
|
|
361
|
+
await installMacosService(projectDir, logsDir, runMode);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
await installLinuxService(projectDir, logsDir, runMode);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
catch (err) {
|
|
368
|
+
console.error(`\n Failed to install service: ${err.message}`);
|
|
369
|
+
console.log(" You can install manually with ./install.sh");
|
|
370
|
+
}
|
|
371
|
+
// macOS permissions
|
|
372
|
+
if (platform === "macos") {
|
|
373
|
+
const setupPerms = await askYesNo(rl, "\nConfigure macOS permissions?");
|
|
374
|
+
if (setupPerms) {
|
|
375
|
+
await offerMacosPermissions(rl);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
printManagementCommands(platform, logsDir);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
else if (platform === "windows") {
|
|
382
|
+
console.log("\nTo run as a service on Windows, open a WSL2 terminal and run: deskmate init");
|
|
383
|
+
}
|
|
384
|
+
rl.close();
|
|
385
|
+
console.log("\nSetup complete! Your bot is ready.");
|
|
386
|
+
console.log("");
|
|
387
|
+
}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.buildAllowedUsers = buildAllowedUsers;
|
|
38
|
+
require("dotenv/config");
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf-8"));
|
|
42
|
+
const VERSION = pkg.version;
|
|
43
|
+
const BOT_NAME = process.env.BOT_NAME || "Deskmate";
|
|
44
|
+
function printHelp() {
|
|
45
|
+
console.log(`
|
|
46
|
+
${BOT_NAME} - Control your machine from anywhere using natural language
|
|
47
|
+
|
|
48
|
+
Usage:
|
|
49
|
+
deskmate <command> [options]
|
|
50
|
+
|
|
51
|
+
Commands:
|
|
52
|
+
telegram Start the Telegram bot (default)
|
|
53
|
+
mcp Start the MCP server
|
|
54
|
+
both Start both Telegram bot and MCP server
|
|
55
|
+
gateway Start the multi-client gateway
|
|
56
|
+
init Interactive setup wizard
|
|
57
|
+
|
|
58
|
+
Options:
|
|
59
|
+
-h, --help Show this help message
|
|
60
|
+
-v, --version Show version number
|
|
61
|
+
|
|
62
|
+
Examples:
|
|
63
|
+
deskmate Start in Telegram mode
|
|
64
|
+
deskmate telegram Start the Telegram bot
|
|
65
|
+
deskmate mcp Start the MCP server
|
|
66
|
+
deskmate gateway Start multi-client gateway
|
|
67
|
+
deskmate init Run the setup wizard
|
|
68
|
+
deskmate --version Print version
|
|
69
|
+
|
|
70
|
+
Environment:
|
|
71
|
+
AGENT_PROVIDER Agent provider (default: claude-code)
|
|
72
|
+
TELEGRAM_BOT_TOKEN Telegram bot token
|
|
73
|
+
ANTHROPIC_API_KEY Anthropic API key
|
|
74
|
+
ALLOWED_USERS Multi-client allowlist (e.g. telegram:123,discord:456)
|
|
75
|
+
`);
|
|
76
|
+
}
|
|
77
|
+
function buildAllowedUsers() {
|
|
78
|
+
const users = [];
|
|
79
|
+
const multiClient = process.env.ALLOWED_USERS;
|
|
80
|
+
if (multiClient) {
|
|
81
|
+
for (const entry of multiClient.split(",").map((s) => s.trim()).filter(Boolean)) {
|
|
82
|
+
const colonIdx = entry.indexOf(":");
|
|
83
|
+
if (colonIdx > 0) {
|
|
84
|
+
users.push({
|
|
85
|
+
clientType: entry.slice(0, colonIdx),
|
|
86
|
+
platformUserId: entry.slice(colonIdx + 1),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const legacyId = process.env.ALLOWED_USER_ID;
|
|
92
|
+
if (legacyId && legacyId !== "0") {
|
|
93
|
+
const alreadyHas = users.some((u) => u.clientType === "telegram" && u.platformUserId === legacyId);
|
|
94
|
+
if (!alreadyHas) {
|
|
95
|
+
users.push({ clientType: "telegram", platformUserId: legacyId });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return users;
|
|
99
|
+
}
|
|
100
|
+
async function main() {
|
|
101
|
+
const args = process.argv.slice(2);
|
|
102
|
+
const command = args.find((a) => !a.startsWith("-")) || "telegram";
|
|
103
|
+
const flags = new Set(args.filter((a) => a.startsWith("-")));
|
|
104
|
+
if (flags.has("--help") || flags.has("-h")) {
|
|
105
|
+
printHelp();
|
|
106
|
+
process.exit(0);
|
|
107
|
+
}
|
|
108
|
+
if (flags.has("--version") || flags.has("-v")) {
|
|
109
|
+
console.log(VERSION);
|
|
110
|
+
process.exit(0);
|
|
111
|
+
}
|
|
112
|
+
// If no explicit command and no .env found, suggest running init
|
|
113
|
+
if (!args.find((a) => !a.startsWith("-")) &&
|
|
114
|
+
!fs.existsSync(path.join(process.cwd(), ".env"))) {
|
|
115
|
+
console.log(`No .env file found. Run "deskmate init" to get started.\n`);
|
|
116
|
+
}
|
|
117
|
+
switch (command) {
|
|
118
|
+
case "telegram": {
|
|
119
|
+
console.log(`Starting ${BOT_NAME} in telegram mode...`);
|
|
120
|
+
const { startTelegramBot } = await Promise.resolve().then(() => __importStar(require("./telegram/bot")));
|
|
121
|
+
await startTelegramBot();
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
case "mcp": {
|
|
125
|
+
console.log(`Starting ${BOT_NAME} in mcp mode...`);
|
|
126
|
+
const { startMcpServer } = await Promise.resolve().then(() => __importStar(require("./mcp/server")));
|
|
127
|
+
await startMcpServer();
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
case "both": {
|
|
131
|
+
console.log(`Starting ${BOT_NAME} in both mode...`);
|
|
132
|
+
const [{ startTelegramBot: startBot }, { startMcpServer: startMcp }] = await Promise.all([
|
|
133
|
+
Promise.resolve().then(() => __importStar(require("./telegram/bot"))),
|
|
134
|
+
Promise.resolve().then(() => __importStar(require("./mcp/server"))),
|
|
135
|
+
]);
|
|
136
|
+
startBot().catch(console.error);
|
|
137
|
+
await startMcp();
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
case "gateway": {
|
|
141
|
+
console.log(`Starting ${BOT_NAME} in gateway mode...`);
|
|
142
|
+
const { Gateway } = await Promise.resolve().then(() => __importStar(require("./gateway")));
|
|
143
|
+
const { TelegramClient } = await Promise.resolve().then(() => __importStar(require("./clients/telegram")));
|
|
144
|
+
const allowedUsers = buildAllowedUsers();
|
|
145
|
+
if (allowedUsers.length === 0) {
|
|
146
|
+
console.error("No allowed users configured. Set ALLOWED_USERS or ALLOWED_USER_ID in your .env");
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
const gateway = new Gateway({
|
|
150
|
+
botName: BOT_NAME,
|
|
151
|
+
workingDir: process.env.WORKING_DIR || process.env.HOME || "/",
|
|
152
|
+
allowedUsers,
|
|
153
|
+
maxTurns: 10,
|
|
154
|
+
});
|
|
155
|
+
if (process.env.TELEGRAM_BOT_TOKEN) {
|
|
156
|
+
gateway.registerClient(new TelegramClient(process.env.TELEGRAM_BOT_TOKEN));
|
|
157
|
+
}
|
|
158
|
+
await gateway.start();
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
case "setup":
|
|
162
|
+
case "init": {
|
|
163
|
+
const { runInitWizard } = await Promise.resolve().then(() => __importStar(require("./cli/init")));
|
|
164
|
+
await runInitWizard();
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
default:
|
|
168
|
+
console.error(`Unknown command: ${command}`);
|
|
169
|
+
console.error('Run "deskmate --help" for usage information.');
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
main().catch((error) => {
|
|
174
|
+
console.error("Fatal error:", error);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
});
|
|
177
|
+
process.on("SIGINT", () => {
|
|
178
|
+
console.log("\nShutting down...");
|
|
179
|
+
process.exit(0);
|
|
180
|
+
});
|
|
181
|
+
process.on("SIGTERM", () => {
|
|
182
|
+
console.log("\nShutting down...");
|
|
183
|
+
process.exit(0);
|
|
184
|
+
});
|