anywhere-ai 0.0.28 → 0.0.30
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 +148 -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,168 @@
|
|
|
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.30"}`);
|
|
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.30"} \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 isDaemon = args.includes("--daemon") || args.includes("-d");
|
|
125
|
+
if (isDaemon && !args.includes("--_daemonized")) {
|
|
126
|
+
await fs.mkdir(ANYWHERE_DIR, { recursive: true });
|
|
127
|
+
const existingPid2 = getDaemonPid();
|
|
128
|
+
if (existingPid2) {
|
|
129
|
+
console.log(`Server already running (PID ${existingPid2}). Use 'anywhere-ai stop' first.`);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
const logFd = openSync(LOG_PATH, "a");
|
|
133
|
+
const daemonArgs = args.filter((a) => a !== "--daemon" && a !== "-d");
|
|
134
|
+
daemonArgs.push("--_daemonized");
|
|
135
|
+
const child = spawn(process.execPath, [new URL(import.meta.url).pathname, ...daemonArgs], {
|
|
136
|
+
detached: true,
|
|
137
|
+
stdio: ["ignore", logFd, logFd],
|
|
138
|
+
env: { ...process.env }
|
|
139
|
+
});
|
|
140
|
+
child.unref();
|
|
141
|
+
writeFileSync(PID_PATH, String(child.pid));
|
|
142
|
+
console.log(`Starting server in background (PID ${child.pid})...`);
|
|
143
|
+
console.log(` Logs: ${LOG_PATH}`);
|
|
144
|
+
console.log(` Status: anywhere-ai status`);
|
|
145
|
+
console.log(` Stop: anywhere-ai stop`);
|
|
146
|
+
process.exit(0);
|
|
147
|
+
}
|
|
148
|
+
var existingPid = getDaemonPid();
|
|
149
|
+
if (existingPid && !args.includes("--_daemonized")) {
|
|
150
|
+
console.log(`Server already running (PID ${existingPid}). Use 'anywhere-ai stop' first.`);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
async function checkForUpdate() {
|
|
154
|
+
try {
|
|
155
|
+
const res = await fetch("https://registry.npmjs.org/anywhere-ai/latest", { signal: AbortSignal.timeout(3e3) });
|
|
156
|
+
const data = await res.json();
|
|
157
|
+
if (data.version && data.version !== "0.0.30") {
|
|
158
|
+
console.log(`
|
|
159
|
+
Update available: v${"0.0.30"} \u2192 v${data.version}`);
|
|
160
|
+
console.log(` Run: npx anywhere-ai@latest
|
|
161
|
+
`);
|
|
162
|
+
}
|
|
163
|
+
} catch {
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
checkForUpdate();
|
|
46
167
|
function ask(question, preserveCase = false) {
|
|
47
168
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
48
169
|
return new Promise((resolve) => {
|
|
@@ -52,8 +173,6 @@ function ask(question, preserveCase = false) {
|
|
|
52
173
|
});
|
|
53
174
|
});
|
|
54
175
|
}
|
|
55
|
-
var ANYWHERE_DIR = path.join(os.homedir(), ".anywhere");
|
|
56
|
-
var CONFIG_PATH = path.join(ANYWHERE_DIR, "config.json");
|
|
57
176
|
async function createConfigFile() {
|
|
58
177
|
try {
|
|
59
178
|
await fs.access(CONFIG_PATH);
|
|
@@ -319,7 +438,18 @@ if (!args.includes("--no-tunnel")) {
|
|
|
319
438
|
}
|
|
320
439
|
var localURL = isVPS ? "http://" + publicIP + ":" + port : "http://" + (localIP || "localhost") + ":" + port;
|
|
321
440
|
var serverURL = tunnelURL || localURL;
|
|
322
|
-
|
|
441
|
+
var isDaemonized = args.includes("--_daemonized");
|
|
442
|
+
if (!isDaemonized) {
|
|
443
|
+
await printBanner(serverURL, localURL);
|
|
444
|
+
}
|
|
445
|
+
writeFileSync(PID_PATH, String(process.pid));
|
|
446
|
+
writeFileSync(STATUS_PATH, JSON.stringify({
|
|
447
|
+
serverURL,
|
|
448
|
+
localURL,
|
|
449
|
+
authToken: config.authToken,
|
|
450
|
+
startedAt: Date.now(),
|
|
451
|
+
pid: process.pid
|
|
452
|
+
}, null, 2));
|
|
323
453
|
function cleanup() {
|
|
324
454
|
intentionalShutdown = true;
|
|
325
455
|
if (serverProcess) {
|
|
@@ -330,6 +460,14 @@ function cleanup() {
|
|
|
330
460
|
tunnelProcess.kill();
|
|
331
461
|
tunnelProcess = null;
|
|
332
462
|
}
|
|
463
|
+
try {
|
|
464
|
+
unlinkSync(PID_PATH);
|
|
465
|
+
} catch {
|
|
466
|
+
}
|
|
467
|
+
try {
|
|
468
|
+
unlinkSync(STATUS_PATH);
|
|
469
|
+
} catch {
|
|
470
|
+
}
|
|
333
471
|
process.exit();
|
|
334
472
|
}
|
|
335
473
|
process.on("SIGINT", cleanup);
|