anywhere-ai 0.0.28 → 0.0.29
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/chunk-PDX44BCA.js +11 -0
- package/dist/cli.js +158 -10
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
__require
|
|
11
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -2,47 +2,144 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import fs from "fs/promises";
|
|
5
|
-
import { readFileSync } from "fs";
|
|
5
|
+
import { readFileSync, existsSync, writeFileSync, unlinkSync, openSync } from "fs";
|
|
6
6
|
import os from "os";
|
|
7
7
|
import path from "path";
|
|
8
8
|
import crypto from "crypto";
|
|
9
9
|
import { spawn, spawnSync, execSync } from "child_process";
|
|
10
10
|
import readline from "readline";
|
|
11
11
|
import qrcode from "qrcode";
|
|
12
|
+
var ANYWHERE_DIR = path.join(os.homedir(), ".anywhere");
|
|
13
|
+
var CONFIG_PATH = path.join(ANYWHERE_DIR, "config.json");
|
|
14
|
+
var PID_PATH = path.join(ANYWHERE_DIR, "server.pid");
|
|
15
|
+
var LOG_PATH = path.join(ANYWHERE_DIR, "server.log");
|
|
16
|
+
var STATUS_PATH = path.join(ANYWHERE_DIR, "status.json");
|
|
12
17
|
var args = process.argv.slice(2);
|
|
13
18
|
var command = args.find((a) => !a.startsWith("-"));
|
|
14
19
|
if (args.includes("--version") || args.includes("-v")) {
|
|
15
|
-
console.log(`anywhere-ai v${"0.0.
|
|
20
|
+
console.log(`anywhere-ai v${"0.0.29"}`);
|
|
16
21
|
process.exit(0);
|
|
17
22
|
}
|
|
18
23
|
if (args.includes("--help") || args.includes("-h") || command === "help") {
|
|
19
|
-
console.log(`anywhere-ai v${"0.0.
|
|
24
|
+
console.log(`anywhere-ai v${"0.0.29"} \u2014 Mobile coding agent
|
|
20
25
|
|
|
21
26
|
Usage: anywhere-ai [command] [options]
|
|
22
27
|
|
|
23
28
|
Commands:
|
|
29
|
+
status Show server status and connection info
|
|
30
|
+
stop Stop the background server
|
|
31
|
+
logs Tail server logs
|
|
24
32
|
regenerate-token Generate a new auth token
|
|
25
33
|
|
|
26
34
|
Options:
|
|
27
35
|
--help, -h Show this help message
|
|
28
36
|
--version, -v Show version
|
|
37
|
+
--daemon, -d Run server in background
|
|
29
38
|
--no-tunnel Skip Cloudflare tunnel`);
|
|
30
39
|
process.exit(0);
|
|
31
40
|
}
|
|
41
|
+
function getDaemonPid() {
|
|
42
|
+
try {
|
|
43
|
+
const pid = parseInt(readFileSync(PID_PATH, "utf-8").trim(), 10);
|
|
44
|
+
process.kill(pid, 0);
|
|
45
|
+
return pid;
|
|
46
|
+
} catch {
|
|
47
|
+
try {
|
|
48
|
+
unlinkSync(PID_PATH);
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (command === "stop" || args.includes("--stop")) {
|
|
55
|
+
const pid = getDaemonPid();
|
|
56
|
+
if (!pid) {
|
|
57
|
+
console.log("No server running.");
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
process.kill(pid, "SIGTERM");
|
|
61
|
+
try {
|
|
62
|
+
unlinkSync(PID_PATH);
|
|
63
|
+
} catch {
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
unlinkSync(STATUS_PATH);
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
69
|
+
console.log(`Server stopped (PID ${pid}).`);
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
if (command === "status") {
|
|
73
|
+
const pid = getDaemonPid();
|
|
74
|
+
if (!pid) {
|
|
75
|
+
console.log("No server running.");
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const status = JSON.parse(readFileSync(STATUS_PATH, "utf-8"));
|
|
80
|
+
const uptimeMs = Date.now() - status.startedAt;
|
|
81
|
+
const hours = Math.floor(uptimeMs / 36e5);
|
|
82
|
+
const mins = Math.floor(uptimeMs % 36e5 / 6e4);
|
|
83
|
+
console.log(`Anywhere server running (PID ${pid})`);
|
|
84
|
+
console.log(` Tunnel: ${status.serverURL}`);
|
|
85
|
+
if (status.localURL && status.localURL !== status.serverURL) {
|
|
86
|
+
console.log(` Direct: ${status.localURL}`);
|
|
87
|
+
}
|
|
88
|
+
console.log(` Token: ${status.authToken}`);
|
|
89
|
+
console.log(` Uptime: ${hours}h ${mins}m`);
|
|
90
|
+
console.log(` Logs: ${LOG_PATH}`);
|
|
91
|
+
} catch {
|
|
92
|
+
console.log(`Server running (PID ${pid}) but no status info available.`);
|
|
93
|
+
console.log(` Logs: ${LOG_PATH}`);
|
|
94
|
+
}
|
|
95
|
+
process.exit(0);
|
|
96
|
+
}
|
|
97
|
+
if (command === "logs") {
|
|
98
|
+
if (!existsSync(LOG_PATH)) {
|
|
99
|
+
console.log("No log file found. Start the server first.");
|
|
100
|
+
process.exit(0);
|
|
101
|
+
}
|
|
102
|
+
const tail = spawn("tail", ["-f", "-n", "50", LOG_PATH], { stdio: "inherit" });
|
|
103
|
+
tail.on("exit", () => process.exit(0));
|
|
104
|
+
process.on("SIGINT", () => {
|
|
105
|
+
tail.kill();
|
|
106
|
+
process.exit(0);
|
|
107
|
+
});
|
|
108
|
+
await new Promise(() => {
|
|
109
|
+
});
|
|
110
|
+
}
|
|
32
111
|
if (command === "regenerate-token") {
|
|
33
|
-
const configPath = path.join(os.homedir(), ".anywhere", "config.json");
|
|
34
112
|
try {
|
|
35
|
-
await fs.access(
|
|
113
|
+
await fs.access(CONFIG_PATH);
|
|
36
114
|
} catch {
|
|
37
115
|
console.error("No config found. Run `anywhere-ai` first to set up.");
|
|
38
116
|
process.exit(1);
|
|
39
117
|
}
|
|
40
|
-
const config2 = JSON.parse(await fs.readFile(
|
|
118
|
+
const config2 = JSON.parse(await fs.readFile(CONFIG_PATH, "utf-8"));
|
|
41
119
|
config2.authToken = crypto.randomBytes(16).toString("hex");
|
|
42
|
-
await fs.writeFile(
|
|
120
|
+
await fs.writeFile(CONFIG_PATH, JSON.stringify(config2, null, 2));
|
|
43
121
|
console.log("New auth token: " + config2.authToken);
|
|
44
122
|
process.exit(0);
|
|
45
123
|
}
|
|
124
|
+
var existingPid = getDaemonPid();
|
|
125
|
+
if (existingPid) {
|
|
126
|
+
console.log(`Server already running (PID ${existingPid}). Use 'anywhere-ai stop' first.`);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
async function checkForUpdate() {
|
|
130
|
+
try {
|
|
131
|
+
const res = await fetch("https://registry.npmjs.org/anywhere-ai/latest", { signal: AbortSignal.timeout(3e3) });
|
|
132
|
+
const data = await res.json();
|
|
133
|
+
if (data.version && data.version !== "0.0.29") {
|
|
134
|
+
console.log(`
|
|
135
|
+
Update available: v${"0.0.29"} \u2192 v${data.version}`);
|
|
136
|
+
console.log(` Run: npx anywhere-ai@latest
|
|
137
|
+
`);
|
|
138
|
+
}
|
|
139
|
+
} catch {
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
checkForUpdate();
|
|
46
143
|
function ask(question, preserveCase = false) {
|
|
47
144
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
48
145
|
return new Promise((resolve) => {
|
|
@@ -52,8 +149,6 @@ function ask(question, preserveCase = false) {
|
|
|
52
149
|
});
|
|
53
150
|
});
|
|
54
151
|
}
|
|
55
|
-
var ANYWHERE_DIR = path.join(os.homedir(), ".anywhere");
|
|
56
|
-
var CONFIG_PATH = path.join(ANYWHERE_DIR, "config.json");
|
|
57
152
|
async function createConfigFile() {
|
|
58
153
|
try {
|
|
59
154
|
await fs.access(CONFIG_PATH);
|
|
@@ -319,7 +414,52 @@ if (!args.includes("--no-tunnel")) {
|
|
|
319
414
|
}
|
|
320
415
|
var localURL = isVPS ? "http://" + publicIP + ":" + port : "http://" + (localIP || "localhost") + ":" + port;
|
|
321
416
|
var serverURL = tunnelURL || localURL;
|
|
322
|
-
|
|
417
|
+
var isDaemonized = args.includes("--_daemonized");
|
|
418
|
+
if (!isDaemonized) {
|
|
419
|
+
await printBanner(serverURL, localURL);
|
|
420
|
+
}
|
|
421
|
+
writeFileSync(PID_PATH, String(process.pid));
|
|
422
|
+
writeFileSync(STATUS_PATH, JSON.stringify({
|
|
423
|
+
serverURL,
|
|
424
|
+
localURL,
|
|
425
|
+
authToken: config.authToken,
|
|
426
|
+
startedAt: Date.now(),
|
|
427
|
+
pid: process.pid
|
|
428
|
+
}, null, 2));
|
|
429
|
+
var isDaemon = args.includes("--daemon") || args.includes("-d");
|
|
430
|
+
if (isDaemon) {
|
|
431
|
+
const logFd = openSync(LOG_PATH, "a");
|
|
432
|
+
const child = spawn(process.execPath, [new URL(import.meta.url).pathname, ...args.filter((a) => a !== "--daemon" && a !== "-d"), "--_daemonized"], {
|
|
433
|
+
detached: true,
|
|
434
|
+
stdio: ["ignore", logFd, logFd],
|
|
435
|
+
env: { ...process.env }
|
|
436
|
+
});
|
|
437
|
+
child.unref();
|
|
438
|
+
writeFileSync(PID_PATH, String(child.pid));
|
|
439
|
+
writeFileSync(STATUS_PATH, JSON.stringify({
|
|
440
|
+
serverURL,
|
|
441
|
+
localURL,
|
|
442
|
+
authToken: config.authToken,
|
|
443
|
+
startedAt: Date.now(),
|
|
444
|
+
pid: child.pid
|
|
445
|
+
}, null, 2));
|
|
446
|
+
console.log(`
|
|
447
|
+
Running in background (PID ${child.pid})`);
|
|
448
|
+
console.log(` Logs: ${LOG_PATH}`);
|
|
449
|
+
console.log(` Status: anywhere-ai status`);
|
|
450
|
+
console.log(` Stop: anywhere-ai stop
|
|
451
|
+
`);
|
|
452
|
+
intentionalShutdown = true;
|
|
453
|
+
if (serverProcess) {
|
|
454
|
+
serverProcess.kill();
|
|
455
|
+
serverProcess = null;
|
|
456
|
+
}
|
|
457
|
+
if (tunnelProcess) {
|
|
458
|
+
tunnelProcess.kill();
|
|
459
|
+
tunnelProcess = null;
|
|
460
|
+
}
|
|
461
|
+
process.exit(0);
|
|
462
|
+
}
|
|
323
463
|
function cleanup() {
|
|
324
464
|
intentionalShutdown = true;
|
|
325
465
|
if (serverProcess) {
|
|
@@ -330,6 +470,14 @@ function cleanup() {
|
|
|
330
470
|
tunnelProcess.kill();
|
|
331
471
|
tunnelProcess = null;
|
|
332
472
|
}
|
|
473
|
+
try {
|
|
474
|
+
unlinkSync(PID_PATH);
|
|
475
|
+
} catch {
|
|
476
|
+
}
|
|
477
|
+
try {
|
|
478
|
+
unlinkSync(STATUS_PATH);
|
|
479
|
+
} catch {
|
|
480
|
+
}
|
|
333
481
|
process.exit();
|
|
334
482
|
}
|
|
335
483
|
process.on("SIGINT", cleanup);
|