anywhere-ai 0.0.35 → 0.0.37
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/cli.js +15 -6
- package/dist/server.js +57 -15
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -17,11 +17,11 @@ var STATUS_PATH = path.join(ANYWHERE_DIR, "status.json");
|
|
|
17
17
|
var args = process.argv.slice(2);
|
|
18
18
|
var command = args.find((a) => !a.startsWith("-"));
|
|
19
19
|
if (args.includes("--version") || args.includes("-v")) {
|
|
20
|
-
console.log(`anywhere-ai v${"0.0.
|
|
20
|
+
console.log(`anywhere-ai v${"0.0.37"}`);
|
|
21
21
|
process.exit(0);
|
|
22
22
|
}
|
|
23
23
|
if (args.includes("--help") || args.includes("-h") || command === "help") {
|
|
24
|
-
console.log(`anywhere-ai v${"0.0.
|
|
24
|
+
console.log(`anywhere-ai v${"0.0.37"} \u2014 Mobile coding agent
|
|
25
25
|
|
|
26
26
|
Usage: npx anywhere-ai [command] [options]
|
|
27
27
|
|
|
@@ -124,16 +124,25 @@ if (command === "regenerate-token") {
|
|
|
124
124
|
var isDaemon = !args.includes("--foreground");
|
|
125
125
|
var existingPid = getDaemonPid();
|
|
126
126
|
if (existingPid) {
|
|
127
|
-
console.log(`
|
|
128
|
-
process.
|
|
127
|
+
console.log(`Stopping existing server (PID ${existingPid})...`);
|
|
128
|
+
process.kill(existingPid, "SIGTERM");
|
|
129
|
+
try {
|
|
130
|
+
unlinkSync(PID_PATH);
|
|
131
|
+
} catch {
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
unlinkSync(STATUS_PATH);
|
|
135
|
+
} catch {
|
|
136
|
+
}
|
|
137
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
129
138
|
}
|
|
130
139
|
async function checkForUpdate() {
|
|
131
140
|
try {
|
|
132
141
|
const res = await fetch("https://registry.npmjs.org/anywhere-ai/latest", { signal: AbortSignal.timeout(3e3) });
|
|
133
142
|
const data = await res.json();
|
|
134
|
-
if (data.version && data.version !== "0.0.
|
|
143
|
+
if (data.version && data.version !== "0.0.37") {
|
|
135
144
|
console.log(`
|
|
136
|
-
Update available: v${"0.0.
|
|
145
|
+
Update available: v${"0.0.37"} \u2192 v${data.version}`);
|
|
137
146
|
console.log(` Run: npx anywhere-ai@latest
|
|
138
147
|
`);
|
|
139
148
|
}
|
package/dist/server.js
CHANGED
|
@@ -186,6 +186,15 @@ var sendMessage = async ({
|
|
|
186
186
|
}) => {
|
|
187
187
|
await session.send(prompt);
|
|
188
188
|
};
|
|
189
|
+
var abortSession = (sessionId) => {
|
|
190
|
+
const session = sessions.get(sessionId);
|
|
191
|
+
if (!session) return false;
|
|
192
|
+
session.close();
|
|
193
|
+
sessions.delete(sessionId);
|
|
194
|
+
activeSessions.delete(sessionId);
|
|
195
|
+
setPermissionCallback(sessionId, null);
|
|
196
|
+
return true;
|
|
197
|
+
};
|
|
189
198
|
var getSession = async ({
|
|
190
199
|
sessionId,
|
|
191
200
|
model,
|
|
@@ -478,10 +487,16 @@ chats.post("/new", async (c) => {
|
|
|
478
487
|
});
|
|
479
488
|
}
|
|
480
489
|
} catch (err) {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
490
|
+
const aborted = err?.message?.includes("aborted by user");
|
|
491
|
+
if (aborted) {
|
|
492
|
+
console.log(`[stream] session aborted by user: ${finalSessionId}`);
|
|
493
|
+
await stream.writeSSE({ data: JSON.stringify({ aborted: true }) });
|
|
494
|
+
} else {
|
|
495
|
+
console.error(err);
|
|
496
|
+
await stream.writeSSE({
|
|
497
|
+
data: JSON.stringify({ error: "Stream error" })
|
|
498
|
+
});
|
|
499
|
+
}
|
|
485
500
|
} finally {
|
|
486
501
|
setPermissionCallback(tempId, null);
|
|
487
502
|
if (finalSessionId) {
|
|
@@ -553,12 +568,18 @@ chats.post("/:id/message", async (c) => {
|
|
|
553
568
|
});
|
|
554
569
|
}
|
|
555
570
|
} catch (err) {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
571
|
+
const aborted = err?.message?.includes("aborted by user");
|
|
572
|
+
if (aborted) {
|
|
573
|
+
console.log(`[stream] session aborted by user: ${sessionId}`);
|
|
574
|
+
await stream.writeSSE({ data: JSON.stringify({ aborted: true }) });
|
|
575
|
+
} else {
|
|
576
|
+
console.error(err);
|
|
577
|
+
await stream.writeSSE({
|
|
578
|
+
data: JSON.stringify({ error: "Stream error" })
|
|
579
|
+
});
|
|
580
|
+
generateChatName(prompt, sessionId).catch(() => {
|
|
581
|
+
});
|
|
582
|
+
}
|
|
562
583
|
} finally {
|
|
563
584
|
sseStream = null;
|
|
564
585
|
setPermissionCallback(sessionId, null);
|
|
@@ -587,6 +608,19 @@ chats.post("/:id/permission", async (c) => {
|
|
|
587
608
|
}
|
|
588
609
|
return c.json({ ok: true });
|
|
589
610
|
});
|
|
611
|
+
chats.post("/:id/abort", async (c) => {
|
|
612
|
+
const sessionId = c.req.param("id");
|
|
613
|
+
if (!sessionId || /[\/\\]/.test(sessionId))
|
|
614
|
+
return c.json({ error: "Invalid session ID" }, 400);
|
|
615
|
+
if (!activeSessions.has(sessionId)) {
|
|
616
|
+
return c.json({ error: "Session is not currently streaming" }, 404);
|
|
617
|
+
}
|
|
618
|
+
const aborted = abortSession(sessionId);
|
|
619
|
+
if (!aborted) {
|
|
620
|
+
return c.json({ error: "Session not found" }, 404);
|
|
621
|
+
}
|
|
622
|
+
return c.json({ ok: true });
|
|
623
|
+
});
|
|
590
624
|
var listEntryCache = /* @__PURE__ */ new Map();
|
|
591
625
|
function parseListEntry(content, sessionId, fileMtimeIso, chatName) {
|
|
592
626
|
const lines = content.split("\n").filter(Boolean);
|
|
@@ -693,7 +727,7 @@ chats.get("/", async (c) => {
|
|
|
693
727
|
return c.json({ result: allChats });
|
|
694
728
|
} catch (error) {
|
|
695
729
|
console.error("[GET /chats] error:", error);
|
|
696
|
-
return c.json({
|
|
730
|
+
return c.json({ error: "Failed to list chats" }, 500);
|
|
697
731
|
}
|
|
698
732
|
});
|
|
699
733
|
chats.get("/:id", async (c) => {
|
|
@@ -721,7 +755,13 @@ chats.get("/:id", async (c) => {
|
|
|
721
755
|
} else {
|
|
722
756
|
const content = await readFile2(file, "utf-8");
|
|
723
757
|
const lines = content.split("\n").filter(Boolean);
|
|
724
|
-
const parsed = lines.
|
|
758
|
+
const parsed = lines.flatMap((line) => {
|
|
759
|
+
try {
|
|
760
|
+
return [JSON.parse(line)];
|
|
761
|
+
} catch {
|
|
762
|
+
return [];
|
|
763
|
+
}
|
|
764
|
+
});
|
|
725
765
|
for (const obj of parsed) {
|
|
726
766
|
if (obj.type === "user" && obj.cwd && !cwd) cwd = obj.cwd;
|
|
727
767
|
}
|
|
@@ -815,7 +855,7 @@ git.get("/status", async (c) => {
|
|
|
815
855
|
try {
|
|
816
856
|
const cwd = c.req.query("cwd");
|
|
817
857
|
const root = await getRepoRoot(cwd);
|
|
818
|
-
if (!root) return c.json({
|
|
858
|
+
if (!root) return c.json({ error: "Not a git repository" }, 400);
|
|
819
859
|
const { stdout: statusOut } = await execAsync("git status --porcelain", {
|
|
820
860
|
cwd: root
|
|
821
861
|
});
|
|
@@ -882,7 +922,7 @@ git.get("/status", async (c) => {
|
|
|
882
922
|
return c.json({ files });
|
|
883
923
|
} catch (error) {
|
|
884
924
|
console.error("git status error:", error);
|
|
885
|
-
return c.json({
|
|
925
|
+
return c.json({ error: "Failed to get git status" }, 500);
|
|
886
926
|
}
|
|
887
927
|
});
|
|
888
928
|
git.get("/diff", async (c) => {
|
|
@@ -974,7 +1014,7 @@ gh.get("/repos", async (c) => {
|
|
|
974
1014
|
);
|
|
975
1015
|
return c.json({ username, repos: all });
|
|
976
1016
|
} catch (error) {
|
|
977
|
-
return c.json(
|
|
1017
|
+
return c.json({ error: "Failed to list repos" }, 500);
|
|
978
1018
|
}
|
|
979
1019
|
});
|
|
980
1020
|
gh.get("/pr", async (c) => {
|
|
@@ -1028,6 +1068,8 @@ app.use("/v1/*", bearerAuth({ token }));
|
|
|
1028
1068
|
app.route("/v1/chats", chats);
|
|
1029
1069
|
app.route("/v1/git", git);
|
|
1030
1070
|
app.route("/v1/gh", gh);
|
|
1071
|
+
app.notFound((c) => c.json({ error: "Not found" }, 404));
|
|
1072
|
+
app.onError((err, c) => c.json({ error: err.message || "Internal server error" }, 500));
|
|
1031
1073
|
serve(
|
|
1032
1074
|
{
|
|
1033
1075
|
fetch: app.fetch,
|