anycodex 0.0.14 → 0.0.15

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 (2) hide show
  1. package/dist/bin.js +387 -371
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -22,7 +22,7 @@ import fs5 from "fs";
22
22
  import readline from "readline";
23
23
  import { fileURLToPath as fileURLToPath2 } from "url";
24
24
 
25
- // ../server/dist/chunk-W3A4E2Q5.js
25
+ // ../server/dist/chunk-AQFLUXUT.js
26
26
  import http from "http";
27
27
  import { fileURLToPath } from "url";
28
28
  import path3 from "path";
@@ -459,34 +459,30 @@ function simpleGlobMatch(filename, pattern) {
459
459
  }
460
460
  var ANYCODE_DIR = path3.join(os.homedir(), ".anycode");
461
461
  var DB_PATH = path3.join(ANYCODE_DIR, "data.db");
462
- var userSettings = (() => {
463
- try {
464
- return JSON.parse(fs4.readFileSync(path3.join(ANYCODE_DIR, "settings.json"), "utf-8"));
465
- } catch {
466
- return {};
462
+ var userSettings = {};
463
+ var PROVIDER = "";
464
+ var MODEL = "";
465
+ var API_KEY = "";
466
+ var BASE_URL = "";
467
+ var PORT = 3210;
468
+ var PREVIEW_PORT = 3211;
469
+ function loadConfig() {
470
+ PROVIDER = process.env.PROVIDER ?? "";
471
+ MODEL = process.env.MODEL ?? userSettings.MODEL ?? "claude-sonnet-4-20250514";
472
+ API_KEY = process.env.API_KEY ?? userSettings.API_KEY ?? "";
473
+ BASE_URL = process.env.BASE_URL ?? userSettings.BASE_URL ?? "";
474
+ PORT = parseInt(process.env.PORT ?? "3210", 10);
475
+ PREVIEW_PORT = parseInt(process.env.PREVIEW_PORT ?? String(PORT + 1), 10);
476
+ if (!PROVIDER || !MODEL || !BASE_URL) {
477
+ console.error("\u274C Missing PROVIDER, MODEL, BASE_URL");
478
+ process.exit(1);
479
+ }
480
+ if (!API_KEY) {
481
+ console.error("\u274C Missing API_KEY");
482
+ console.error("Run 'anycode start' to configure, or set API_KEY env var.");
483
+ process.exit(1);
467
484
  }
468
- })();
469
- var PROVIDER = process.env.PROVIDER ?? "";
470
- var MODEL = process.env.MODEL ?? userSettings.MODEL ?? "claude-sonnet-4-20250514";
471
- var API_KEY = process.env.API_KEY ?? userSettings.API_KEY;
472
- var BASE_URL = process.env.BASE_URL ?? userSettings.BASE_URL;
473
- var PORT = parseInt(process.env.PORT ?? "3210", 10);
474
- var PREVIEW_PORT = parseInt(process.env.PREVIEW_PORT ?? String(PORT + 1), 10);
475
- if (!PROVIDER || !MODEL || !BASE_URL) {
476
- console.error("\u274C Missing PROVIDER, MODEL, BASE_URL");
477
- process.exit();
478
- }
479
- if (!API_KEY) {
480
- console.error("\u274C Missing API_KEY");
481
- console.error("Run 'anycode start' to configure, or set API_KEY env var.");
482
- process.exit(1);
483
- }
484
- process.on("uncaughtException", (err) => {
485
- console.error("\u26A0 Uncaught exception:", err.message);
486
- });
487
- process.on("unhandledRejection", (reason) => {
488
- console.error("\u26A0 Unhandled rejection:", reason instanceof Error ? reason.message : reason);
489
- });
485
+ }
490
486
  function makePaths() {
491
487
  const dataPath = path3.join(ANYCODE_DIR, "data");
492
488
  fs4.mkdirSync(dataPath, { recursive: true });
@@ -1184,76 +1180,79 @@ function getOrCreatePreviewProvider(sessionId) {
1184
1180
  }
1185
1181
  return pp;
1186
1182
  }
1187
- var previewServer = http.createServer((req, res) => {
1188
- res.setHeader("Access-Control-Allow-Origin", "*");
1189
- res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
1190
- res.setHeader("Access-Control-Allow-Headers", "*");
1191
- if (req.method === "OPTIONS") {
1192
- res.writeHead(204);
1193
- res.end();
1194
- return;
1195
- }
1196
- if (!previewTarget) {
1197
- res.writeHead(502, { "Content-Type": "text/plain" });
1198
- res.end("No preview target configured");
1199
- return;
1200
- }
1201
- try {
1202
- const targetUrl = previewTarget + (req.url || "/");
1203
- const parsed = new URL(targetUrl);
1204
- const options = {
1205
- hostname: parsed.hostname,
1206
- port: parsed.port,
1207
- path: parsed.pathname + parsed.search,
1208
- method: req.method,
1209
- headers: { ...req.headers, host: parsed.host }
1210
- };
1211
- const proxyReq = http.request(options, (proxyRes) => {
1212
- res.writeHead(proxyRes.statusCode || 502, proxyRes.headers);
1213
- proxyRes.pipe(res);
1214
- });
1215
- proxyReq.on("error", (err) => {
1216
- if (!res.headersSent) res.writeHead(502, { "Content-Type": "text/plain" });
1217
- res.end(`Preview proxy error: ${err.message}`);
1218
- });
1219
- req.pipe(proxyReq);
1220
- } catch (err) {
1221
- res.writeHead(502, { "Content-Type": "text/plain" });
1222
- res.end(`Invalid proxy target: ${err.message}`);
1223
- }
1224
- });
1225
- previewServer.on("upgrade", (req, socket, head) => {
1226
- if (!previewTarget) {
1227
- socket.destroy();
1228
- return;
1229
- }
1230
- try {
1231
- const parsed = new URL(previewTarget);
1232
- const targetWs = `ws://${parsed.hostname}:${parsed.port}${req.url || "/"}`;
1233
- const wsTarget = new URL(targetWs);
1234
- const options = {
1235
- hostname: wsTarget.hostname,
1236
- port: wsTarget.port,
1237
- path: wsTarget.pathname + wsTarget.search,
1238
- method: "GET",
1239
- headers: { ...req.headers, host: wsTarget.host }
1240
- };
1241
- const proxyReq = http.request(options);
1242
- proxyReq.on("upgrade", (_proxyRes, proxySocket, proxyHead) => {
1243
- socket.write(
1244
- "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\n" + Object.entries(_proxyRes.headers).filter(([k]) => !["upgrade", "connection"].includes(k.toLowerCase())).map(([k, v]) => `${k}: ${v}`).join("\r\n") + "\r\n\r\n"
1245
- );
1246
- if (proxyHead.length > 0) socket.write(proxyHead);
1247
- proxySocket.pipe(socket);
1248
- socket.pipe(proxySocket);
1249
- });
1250
- proxyReq.on("error", () => socket.destroy());
1251
- socket.on("error", () => proxyReq.destroy());
1252
- proxyReq.end();
1253
- } catch {
1254
- socket.destroy();
1255
- }
1256
- });
1183
+ var previewServer;
1184
+ function createPreviewServer() {
1185
+ previewServer = http.createServer((req, res) => {
1186
+ res.setHeader("Access-Control-Allow-Origin", "*");
1187
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
1188
+ res.setHeader("Access-Control-Allow-Headers", "*");
1189
+ if (req.method === "OPTIONS") {
1190
+ res.writeHead(204);
1191
+ res.end();
1192
+ return;
1193
+ }
1194
+ if (!previewTarget) {
1195
+ res.writeHead(502, { "Content-Type": "text/plain" });
1196
+ res.end("No preview target configured");
1197
+ return;
1198
+ }
1199
+ try {
1200
+ const targetUrl = previewTarget + (req.url || "/");
1201
+ const parsed = new URL(targetUrl);
1202
+ const options = {
1203
+ hostname: parsed.hostname,
1204
+ port: parsed.port,
1205
+ path: parsed.pathname + parsed.search,
1206
+ method: req.method,
1207
+ headers: { ...req.headers, host: parsed.host }
1208
+ };
1209
+ const proxyReq = http.request(options, (proxyRes) => {
1210
+ res.writeHead(proxyRes.statusCode || 502, proxyRes.headers);
1211
+ proxyRes.pipe(res);
1212
+ });
1213
+ proxyReq.on("error", (err) => {
1214
+ if (!res.headersSent) res.writeHead(502, { "Content-Type": "text/plain" });
1215
+ res.end(`Preview proxy error: ${err.message}`);
1216
+ });
1217
+ req.pipe(proxyReq);
1218
+ } catch (err) {
1219
+ res.writeHead(502, { "Content-Type": "text/plain" });
1220
+ res.end(`Invalid proxy target: ${err.message}`);
1221
+ }
1222
+ });
1223
+ previewServer.on("upgrade", (req, socket, head) => {
1224
+ if (!previewTarget) {
1225
+ socket.destroy();
1226
+ return;
1227
+ }
1228
+ try {
1229
+ const parsed = new URL(previewTarget);
1230
+ const targetWs = `ws://${parsed.hostname}:${parsed.port}${req.url || "/"}`;
1231
+ const wsTarget = new URL(targetWs);
1232
+ const options = {
1233
+ hostname: wsTarget.hostname,
1234
+ port: wsTarget.port,
1235
+ path: wsTarget.pathname + wsTarget.search,
1236
+ method: "GET",
1237
+ headers: { ...req.headers, host: wsTarget.host }
1238
+ };
1239
+ const proxyReq = http.request(options);
1240
+ proxyReq.on("upgrade", (_proxyRes, proxySocket, proxyHead) => {
1241
+ socket.write(
1242
+ "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\n" + Object.entries(_proxyRes.headers).filter(([k]) => !["upgrade", "connection"].includes(k.toLowerCase())).map(([k, v]) => `${k}: ${v}`).join("\r\n") + "\r\n\r\n"
1243
+ );
1244
+ if (proxyHead.length > 0) socket.write(proxyHead);
1245
+ proxySocket.pipe(socket);
1246
+ socket.pipe(proxySocket);
1247
+ });
1248
+ proxyReq.on("error", () => socket.destroy());
1249
+ socket.on("error", () => proxyReq.destroy());
1250
+ proxyReq.end();
1251
+ } catch {
1252
+ socket.destroy();
1253
+ }
1254
+ });
1255
+ }
1257
1256
  function adminHTML() {
1258
1257
  return (
1259
1258
  /* html */
@@ -1374,7 +1373,7 @@ function resolveAppDist() {
1374
1373
  }
1375
1374
  return bundled;
1376
1375
  }
1377
- var APP_DIST = resolveAppDist();
1376
+ var APP_DIST = "";
1378
1377
  function serveStatic(req, res) {
1379
1378
  const url = req.url || "/";
1380
1379
  const filePath = path3.join(APP_DIST, url);
@@ -1399,331 +1398,348 @@ function serveAppIndex(res) {
1399
1398
  }
1400
1399
  return false;
1401
1400
  }
1402
- var server = http.createServer(async (req, res) => {
1403
- res.setHeader("Access-Control-Allow-Origin", "*");
1404
- res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
1405
- res.setHeader("Access-Control-Allow-Headers", "Content-Type");
1406
- if (req.method === "OPTIONS") {
1407
- res.writeHead(204);
1408
- res.end();
1409
- return;
1410
- }
1411
- if (req.method === "POST" && req.url === "/api/poll/connect") {
1412
- let body = "";
1413
- for await (const chunk of req) body += chunk;
1414
- const { sessionId } = body ? JSON.parse(body) : {};
1415
- const session = sessionId ? getSession(sessionId) : void 0;
1416
- if (!session) {
1417
- res.writeHead(404, { "Content-Type": "application/json" });
1418
- res.end(JSON.stringify({ error: "Session not found" }));
1401
+ var server;
1402
+ function createMainServer() {
1403
+ server = http.createServer(async (req, res) => {
1404
+ res.setHeader("Access-Control-Allow-Origin", "*");
1405
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
1406
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
1407
+ if (req.method === "OPTIONS") {
1408
+ res.writeHead(204);
1409
+ res.end();
1419
1410
  return;
1420
1411
  }
1421
- const channelId = Math.random().toString(36).slice(2) + Date.now().toString(36);
1422
- const client = new PollingClient(channelId, sessionId);
1423
- pollingClients.set(channelId, client);
1424
- getSessionClients(sessionId).add(client);
1425
- console.log(`\u{1F50C} Poll client connected to session ${sessionId} (channel=${channelId})`);
1426
- sendStateTo(sessionId, client);
1427
- res.writeHead(200, { "Content-Type": "application/json" });
1428
- res.end(JSON.stringify({ channelId }));
1429
- return;
1430
- }
1431
- if (req.method === "GET" && req.url?.startsWith("/api/poll?")) {
1432
- const url = new URL(req.url, `http://localhost:${PORT}`);
1433
- const channelId = url.searchParams.get("channelId");
1434
- const client = channelId ? pollingClients.get(channelId) : void 0;
1435
- if (!client || client.readyState !== 1) {
1436
- res.writeHead(404, { "Content-Type": "application/json" });
1437
- res.end(JSON.stringify({ error: "Channel not found" }));
1412
+ if (req.method === "POST" && req.url === "/api/poll/connect") {
1413
+ let body = "";
1414
+ for await (const chunk of req) body += chunk;
1415
+ const { sessionId } = body ? JSON.parse(body) : {};
1416
+ const session = sessionId ? getSession(sessionId) : void 0;
1417
+ if (!session) {
1418
+ res.writeHead(404, { "Content-Type": "application/json" });
1419
+ res.end(JSON.stringify({ error: "Session not found" }));
1420
+ return;
1421
+ }
1422
+ const channelId = Math.random().toString(36).slice(2) + Date.now().toString(36);
1423
+ const client = new PollingClient(channelId, sessionId);
1424
+ pollingClients.set(channelId, client);
1425
+ getSessionClients(sessionId).add(client);
1426
+ console.log(`\u{1F50C} Poll client connected to session ${sessionId} (channel=${channelId})`);
1427
+ sendStateTo(sessionId, client);
1428
+ res.writeHead(200, { "Content-Type": "application/json" });
1429
+ res.end(JSON.stringify({ channelId }));
1438
1430
  return;
1439
1431
  }
1440
- client.hold(res);
1441
- return;
1442
- }
1443
- if (req.method === "POST" && req.url === "/api/poll/send") {
1444
- let body = "";
1445
- for await (const chunk of req) body += chunk;
1446
- const { channelId, data } = body ? JSON.parse(body) : {};
1447
- const client = channelId ? pollingClients.get(channelId) : void 0;
1448
- if (!client || client.readyState !== 1) {
1449
- res.writeHead(404, { "Content-Type": "application/json" });
1450
- res.end(JSON.stringify({ error: "Channel not found" }));
1432
+ if (req.method === "GET" && req.url?.startsWith("/api/poll?")) {
1433
+ const url = new URL(req.url, `http://localhost:${PORT}`);
1434
+ const channelId = url.searchParams.get("channelId");
1435
+ const client = channelId ? pollingClients.get(channelId) : void 0;
1436
+ if (!client || client.readyState !== 1) {
1437
+ res.writeHead(404, { "Content-Type": "application/json" });
1438
+ res.end(JSON.stringify({ error: "Channel not found" }));
1439
+ return;
1440
+ }
1441
+ client.hold(res);
1451
1442
  return;
1452
1443
  }
1453
- client.lastActivity = Date.now();
1454
- handleClientMessage(client.sessionId, client, data).catch(() => {
1455
- });
1456
- res.writeHead(200, { "Content-Type": "application/json" });
1457
- res.end(JSON.stringify({ ok: true }));
1458
- return;
1459
- }
1460
- if (req.method === "POST" && req.url === "/api/poll/close") {
1461
- let body = "";
1462
- for await (const chunk of req) body += chunk;
1463
- const { channelId } = body ? JSON.parse(body) : {};
1464
- const client = channelId ? pollingClients.get(channelId) : void 0;
1465
- if (client) {
1466
- client.close();
1467
- removeClient(client.sessionId, client);
1468
- pollingClients.delete(channelId);
1469
- console.log(`\u{1F50C} Poll client disconnected (channel=${channelId})`);
1470
- }
1471
- res.writeHead(200, { "Content-Type": "application/json" });
1472
- res.end(JSON.stringify({ ok: true }));
1473
- return;
1474
- }
1475
- if (req.method === "POST" && req.url === "/api/sessions") {
1476
- (async () => {
1444
+ if (req.method === "POST" && req.url === "/api/poll/send") {
1477
1445
  let body = "";
1478
1446
  for await (const chunk of req) body += chunk;
1479
- const { userId } = body ? JSON.parse(body) : {};
1480
- if (!userId) {
1481
- res.writeHead(400, { "Content-Type": "application/json" });
1482
- res.end(JSON.stringify({ error: "userId is required" }));
1447
+ const { channelId, data } = body ? JSON.parse(body) : {};
1448
+ const client = channelId ? pollingClients.get(channelId) : void 0;
1449
+ if (!client || client.readyState !== 1) {
1450
+ res.writeHead(404, { "Content-Type": "application/json" });
1451
+ res.end(JSON.stringify({ error: "Channel not found" }));
1483
1452
  return;
1484
1453
  }
1485
- getOrCreateSession(userId).then((entry) => {
1486
- res.writeHead(200, { "Content-Type": "application/json" });
1487
- res.end(JSON.stringify({ id: entry.id, directory: entry.directory }));
1488
- }).catch((err) => {
1489
- res.writeHead(500, { "Content-Type": "application/json" });
1490
- res.end(JSON.stringify({ error: err.message }));
1454
+ client.lastActivity = Date.now();
1455
+ handleClientMessage(client.sessionId, client, data).catch(() => {
1491
1456
  });
1492
- })();
1493
- return;
1494
- }
1495
- if (req.method === "GET" && req.url === "/api/sessions") {
1496
- const list = Array.from(sessions.values()).map((s) => ({
1497
- id: s.id,
1498
- directory: s.directory,
1499
- createdAt: s.createdAt
1500
- }));
1501
- res.writeHead(200, { "Content-Type": "application/json" });
1502
- res.end(JSON.stringify(list));
1503
- return;
1504
- }
1505
- if (req.method === "GET" && req.url?.startsWith("/api/windows")) {
1506
- const url = new URL(req.url, `http://localhost:${PORT}`);
1507
- const userId = url.searchParams.get("userId");
1508
- if (!userId) {
1509
- res.writeHead(400, { "Content-Type": "application/json" });
1510
- res.end(JSON.stringify({ error: "userId is required" }));
1457
+ res.writeHead(200, { "Content-Type": "application/json" });
1458
+ res.end(JSON.stringify({ ok: true }));
1459
+ return;
1460
+ }
1461
+ if (req.method === "POST" && req.url === "/api/poll/close") {
1462
+ let body = "";
1463
+ for await (const chunk of req) body += chunk;
1464
+ const { channelId } = body ? JSON.parse(body) : {};
1465
+ const client = channelId ? pollingClients.get(channelId) : void 0;
1466
+ if (client) {
1467
+ client.close();
1468
+ removeClient(client.sessionId, client);
1469
+ pollingClients.delete(channelId);
1470
+ console.log(`\u{1F50C} Poll client disconnected (channel=${channelId})`);
1471
+ }
1472
+ res.writeHead(200, { "Content-Type": "application/json" });
1473
+ res.end(JSON.stringify({ ok: true }));
1474
+ return;
1475
+ }
1476
+ if (req.method === "POST" && req.url === "/api/sessions") {
1477
+ (async () => {
1478
+ let body = "";
1479
+ for await (const chunk of req) body += chunk;
1480
+ const { userId } = body ? JSON.parse(body) : {};
1481
+ if (!userId) {
1482
+ res.writeHead(400, { "Content-Type": "application/json" });
1483
+ res.end(JSON.stringify({ error: "userId is required" }));
1484
+ return;
1485
+ }
1486
+ getOrCreateSession(userId).then((entry) => {
1487
+ res.writeHead(200, { "Content-Type": "application/json" });
1488
+ res.end(JSON.stringify({ id: entry.id, directory: entry.directory }));
1489
+ }).catch((err) => {
1490
+ res.writeHead(500, { "Content-Type": "application/json" });
1491
+ res.end(JSON.stringify({ error: err.message }));
1492
+ });
1493
+ })();
1511
1494
  return;
1512
1495
  }
1513
- getAllWindows(userId).then((entries) => {
1514
- const rows = db.findMany("user_session", { filter: { op: "eq", field: "user_id", value: userId } });
1515
- const defaultMap = new Map(rows.map((r) => [r.session_id, r.is_default === 1]));
1516
- const list = entries.map((e) => ({
1517
- id: e.id,
1518
- directory: e.directory,
1519
- createdAt: e.createdAt,
1520
- isDefault: defaultMap.get(e.id) ?? false
1496
+ if (req.method === "GET" && req.url === "/api/sessions") {
1497
+ const list = Array.from(sessions.values()).map((s) => ({
1498
+ id: s.id,
1499
+ directory: s.directory,
1500
+ createdAt: s.createdAt
1521
1501
  }));
1522
1502
  res.writeHead(200, { "Content-Type": "application/json" });
1523
1503
  res.end(JSON.stringify(list));
1524
- }).catch((err) => {
1525
- res.writeHead(500, { "Content-Type": "application/json" });
1526
- res.end(JSON.stringify({ error: err.message }));
1527
- });
1528
- return;
1529
- }
1530
- if (req.method === "POST" && req.url === "/api/windows") {
1531
- (async () => {
1532
- let body = "";
1533
- for await (const chunk of req) body += chunk;
1534
- const { userId } = body ? JSON.parse(body) : {};
1504
+ return;
1505
+ }
1506
+ if (req.method === "GET" && req.url?.startsWith("/api/windows")) {
1507
+ const url = new URL(req.url, `http://localhost:${PORT}`);
1508
+ const userId = url.searchParams.get("userId");
1535
1509
  if (!userId) {
1536
1510
  res.writeHead(400, { "Content-Type": "application/json" });
1537
1511
  res.end(JSON.stringify({ error: "userId is required" }));
1538
1512
  return;
1539
1513
  }
1540
- createNewWindow(userId, false).then((entry) => {
1514
+ getAllWindows(userId).then((entries) => {
1515
+ const rows = db.findMany("user_session", { filter: { op: "eq", field: "user_id", value: userId } });
1516
+ const defaultMap = new Map(rows.map((r) => [r.session_id, r.is_default === 1]));
1517
+ const list = entries.map((e) => ({
1518
+ id: e.id,
1519
+ directory: e.directory,
1520
+ createdAt: e.createdAt,
1521
+ isDefault: defaultMap.get(e.id) ?? false
1522
+ }));
1541
1523
  res.writeHead(200, { "Content-Type": "application/json" });
1542
- res.end(JSON.stringify({ id: entry.id, directory: entry.directory, isDefault: false }));
1524
+ res.end(JSON.stringify(list));
1543
1525
  }).catch((err) => {
1544
1526
  res.writeHead(500, { "Content-Type": "application/json" });
1545
1527
  res.end(JSON.stringify({ error: err.message }));
1546
1528
  });
1547
- })();
1548
- return;
1549
- }
1550
- const windowDeleteMatch = req.url?.match(/^\/api\/windows\/([^/?]+)$/);
1551
- if (req.method === "DELETE" && windowDeleteMatch) {
1552
- const ok = deleteWindow(windowDeleteMatch[1]);
1553
- if (ok) {
1554
- res.writeHead(200, { "Content-Type": "application/json" });
1555
- res.end(JSON.stringify({ ok: true }));
1556
- } else {
1557
- res.writeHead(400, { "Content-Type": "application/json" });
1558
- res.end(JSON.stringify({ error: "Cannot delete default window or window not found" }));
1559
- }
1560
- return;
1561
- }
1562
- const sessionMatch = req.url?.match(/^\/api\/sessions\/([^/?]+)(?:\/([a-z]+))?/);
1563
- if (req.method === "GET" && sessionMatch) {
1564
- const session = getSession(sessionMatch[1]);
1565
- if (!session) {
1566
- res.writeHead(404, { "Content-Type": "application/json" });
1567
- res.end(JSON.stringify({ error: "Session not found" }));
1568
1529
  return;
1569
1530
  }
1570
- const sub = sessionMatch[2];
1571
- const url = new URL(req.url, `http://localhost:${PORT}`);
1572
- if (sub === "state") {
1573
- const dir = session.directory;
1574
- const [topLevel, changes] = await Promise.all([
1575
- dir ? listDir(dir) : Promise.resolve([]),
1576
- dir ? getGitChanges(dir) : Promise.resolve([])
1577
- ]);
1578
- const hasPreview = previewSessionId === session.id && previewTarget;
1579
- res.writeHead(200, { "Content-Type": "application/json" });
1580
- res.end(JSON.stringify({ directory: dir, topLevel, changes, previewPort: hasPreview ? PREVIEW_PORT : null }));
1531
+ if (req.method === "POST" && req.url === "/api/windows") {
1532
+ (async () => {
1533
+ let body = "";
1534
+ for await (const chunk of req) body += chunk;
1535
+ const { userId } = body ? JSON.parse(body) : {};
1536
+ if (!userId) {
1537
+ res.writeHead(400, { "Content-Type": "application/json" });
1538
+ res.end(JSON.stringify({ error: "userId is required" }));
1539
+ return;
1540
+ }
1541
+ createNewWindow(userId, false).then((entry) => {
1542
+ res.writeHead(200, { "Content-Type": "application/json" });
1543
+ res.end(JSON.stringify({ id: entry.id, directory: entry.directory, isDefault: false }));
1544
+ }).catch((err) => {
1545
+ res.writeHead(500, { "Content-Type": "application/json" });
1546
+ res.end(JSON.stringify({ error: err.message }));
1547
+ });
1548
+ })();
1581
1549
  return;
1582
1550
  }
1583
- if (sub === "ls") {
1584
- const subPath = url.searchParams.get("path") || "";
1585
- const dir = session.directory;
1586
- if (!dir) {
1551
+ const windowDeleteMatch = req.url?.match(/^\/api\/windows\/([^/?]+)$/);
1552
+ if (req.method === "DELETE" && windowDeleteMatch) {
1553
+ const ok = deleteWindow(windowDeleteMatch[1]);
1554
+ if (ok) {
1587
1555
  res.writeHead(200, { "Content-Type": "application/json" });
1588
- res.end(JSON.stringify({ entries: [] }));
1589
- return;
1590
- }
1591
- const target = path3.resolve(dir, subPath);
1592
- if (!target.startsWith(path3.resolve(dir))) {
1593
- res.writeHead(403, { "Content-Type": "application/json" });
1594
- res.end(JSON.stringify({ error: "Forbidden" }));
1595
- return;
1556
+ res.end(JSON.stringify({ ok: true }));
1557
+ } else {
1558
+ res.writeHead(400, { "Content-Type": "application/json" });
1559
+ res.end(JSON.stringify({ error: "Cannot delete default window or window not found" }));
1596
1560
  }
1597
- const entries = await listDir(target);
1598
- res.writeHead(200, { "Content-Type": "application/json" });
1599
- res.end(JSON.stringify({ entries }));
1600
1561
  return;
1601
1562
  }
1602
- if (sub === "file") {
1603
- const filePath = url.searchParams.get("path") || "";
1604
- const dir = session.directory;
1605
- if (!dir) {
1606
- res.writeHead(200, { "Content-Type": "application/json" });
1607
- res.end(JSON.stringify({ content: null, error: "No directory" }));
1563
+ const sessionMatch = req.url?.match(/^\/api\/sessions\/([^/?]+)(?:\/([a-z]+))?/);
1564
+ if (req.method === "GET" && sessionMatch) {
1565
+ const session = getSession(sessionMatch[1]);
1566
+ if (!session) {
1567
+ res.writeHead(404, { "Content-Type": "application/json" });
1568
+ res.end(JSON.stringify({ error: "Session not found" }));
1608
1569
  return;
1609
1570
  }
1610
- const target = path3.resolve(dir, filePath);
1611
- if (!target.startsWith(path3.resolve(dir))) {
1612
- res.writeHead(403, { "Content-Type": "application/json" });
1613
- res.end(JSON.stringify({ error: "Forbidden" }));
1571
+ const sub = sessionMatch[2];
1572
+ const url = new URL(req.url, `http://localhost:${PORT}`);
1573
+ if (sub === "state") {
1574
+ const dir = session.directory;
1575
+ const [topLevel, changes] = await Promise.all([
1576
+ dir ? listDir(dir) : Promise.resolve([]),
1577
+ dir ? getGitChanges(dir) : Promise.resolve([])
1578
+ ]);
1579
+ const hasPreview = previewSessionId === session.id && previewTarget;
1580
+ res.writeHead(200, { "Content-Type": "application/json" });
1581
+ res.end(JSON.stringify({ directory: dir, topLevel, changes, previewPort: hasPreview ? PREVIEW_PORT : null }));
1614
1582
  return;
1615
1583
  }
1616
- try {
1617
- const content = await fsPromises.readFile(target, "utf-8");
1618
- res.writeHead(200, { "Content-Type": "application/json" });
1619
- res.end(JSON.stringify({ content }));
1620
- } catch {
1584
+ if (sub === "ls") {
1585
+ const subPath = url.searchParams.get("path") || "";
1586
+ const dir = session.directory;
1587
+ if (!dir) {
1588
+ res.writeHead(200, { "Content-Type": "application/json" });
1589
+ res.end(JSON.stringify({ entries: [] }));
1590
+ return;
1591
+ }
1592
+ const target = path3.resolve(dir, subPath);
1593
+ if (!target.startsWith(path3.resolve(dir))) {
1594
+ res.writeHead(403, { "Content-Type": "application/json" });
1595
+ res.end(JSON.stringify({ error: "Forbidden" }));
1596
+ return;
1597
+ }
1598
+ const entries = await listDir(target);
1621
1599
  res.writeHead(200, { "Content-Type": "application/json" });
1622
- res.end(JSON.stringify({ content: null, error: "\u8BFB\u53D6\u5931\u8D25" }));
1600
+ res.end(JSON.stringify({ entries }));
1601
+ return;
1623
1602
  }
1624
- return;
1625
- }
1626
- if (sub === "diff") {
1627
- const filePath = url.searchParams.get("path") || "";
1628
- const dir = session.directory;
1629
- if (!dir) {
1630
- res.writeHead(200, { "Content-Type": "application/json" });
1631
- res.end(JSON.stringify({ added: [], removed: [] }));
1603
+ if (sub === "file") {
1604
+ const filePath = url.searchParams.get("path") || "";
1605
+ const dir = session.directory;
1606
+ if (!dir) {
1607
+ res.writeHead(200, { "Content-Type": "application/json" });
1608
+ res.end(JSON.stringify({ content: null, error: "No directory" }));
1609
+ return;
1610
+ }
1611
+ const target = path3.resolve(dir, filePath);
1612
+ if (!target.startsWith(path3.resolve(dir))) {
1613
+ res.writeHead(403, { "Content-Type": "application/json" });
1614
+ res.end(JSON.stringify({ error: "Forbidden" }));
1615
+ return;
1616
+ }
1617
+ try {
1618
+ const content = await fsPromises.readFile(target, "utf-8");
1619
+ res.writeHead(200, { "Content-Type": "application/json" });
1620
+ res.end(JSON.stringify({ content }));
1621
+ } catch {
1622
+ res.writeHead(200, { "Content-Type": "application/json" });
1623
+ res.end(JSON.stringify({ content: null, error: "\u8BFB\u53D6\u5931\u8D25" }));
1624
+ }
1632
1625
  return;
1633
1626
  }
1634
- try {
1635
- const added = [];
1636
- const removed = [];
1637
- let result = await gitProvider.run(
1638
- ["diff", "--unified=0", "--", filePath],
1639
- { cwd: dir }
1640
- );
1641
- if (result.exitCode !== 0 || !result.text().trim()) {
1642
- result = await gitProvider.run(
1643
- ["diff", "--unified=0", "--cached", "--", filePath],
1627
+ if (sub === "diff") {
1628
+ const filePath = url.searchParams.get("path") || "";
1629
+ const dir = session.directory;
1630
+ if (!dir) {
1631
+ res.writeHead(200, { "Content-Type": "application/json" });
1632
+ res.end(JSON.stringify({ added: [], removed: [] }));
1633
+ return;
1634
+ }
1635
+ try {
1636
+ const added = [];
1637
+ const removed = [];
1638
+ let result = await gitProvider.run(
1639
+ ["diff", "--unified=0", "--", filePath],
1644
1640
  { cwd: dir }
1645
1641
  );
1646
- }
1647
- const diffText = result.text();
1648
- const hunkRe = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/gm;
1649
- let m;
1650
- while (m = hunkRe.exec(diffText)) {
1651
- const oldStart = parseInt(m[1], 10);
1652
- const oldCount = parseInt(m[2] ?? "1", 10);
1653
- const newStart = parseInt(m[3], 10);
1654
- const newCount = parseInt(m[4] ?? "1", 10);
1655
- for (let i = 0; i < oldCount; i++) removed.push(oldStart + i);
1656
- for (let i = 0; i < newCount; i++) added.push(newStart + i);
1657
- }
1658
- if (!diffText.trim()) {
1659
- try {
1660
- const target = path3.resolve(dir, filePath);
1661
- if (target.startsWith(path3.resolve(dir))) {
1662
- const content = await fsPromises.readFile(target, "utf-8");
1663
- const lineCount = content.split("\n").length;
1664
- for (let i = 1; i <= lineCount; i++) added.push(i);
1642
+ if (result.exitCode !== 0 || !result.text().trim()) {
1643
+ result = await gitProvider.run(
1644
+ ["diff", "--unified=0", "--cached", "--", filePath],
1645
+ { cwd: dir }
1646
+ );
1647
+ }
1648
+ const diffText = result.text();
1649
+ const hunkRe = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/gm;
1650
+ let m;
1651
+ while (m = hunkRe.exec(diffText)) {
1652
+ const oldStart = parseInt(m[1], 10);
1653
+ const oldCount = parseInt(m[2] ?? "1", 10);
1654
+ const newStart = parseInt(m[3], 10);
1655
+ const newCount = parseInt(m[4] ?? "1", 10);
1656
+ for (let i = 0; i < oldCount; i++) removed.push(oldStart + i);
1657
+ for (let i = 0; i < newCount; i++) added.push(newStart + i);
1658
+ }
1659
+ if (!diffText.trim()) {
1660
+ try {
1661
+ const target = path3.resolve(dir, filePath);
1662
+ if (target.startsWith(path3.resolve(dir))) {
1663
+ const content = await fsPromises.readFile(target, "utf-8");
1664
+ const lineCount = content.split("\n").length;
1665
+ for (let i = 1; i <= lineCount; i++) added.push(i);
1666
+ }
1667
+ } catch {
1665
1668
  }
1666
- } catch {
1667
1669
  }
1670
+ res.writeHead(200, { "Content-Type": "application/json" });
1671
+ res.end(JSON.stringify({ added, removed }));
1672
+ } catch {
1673
+ res.writeHead(200, { "Content-Type": "application/json" });
1674
+ res.end(JSON.stringify({ added: [], removed: [] }));
1668
1675
  }
1669
- res.writeHead(200, { "Content-Type": "application/json" });
1670
- res.end(JSON.stringify({ added, removed }));
1671
- } catch {
1672
- res.writeHead(200, { "Content-Type": "application/json" });
1673
- res.end(JSON.stringify({ added: [], removed: [] }));
1676
+ return;
1674
1677
  }
1678
+ res.writeHead(200, { "Content-Type": "application/json" });
1679
+ res.end(JSON.stringify({
1680
+ id: session.id,
1681
+ directory: session.directory,
1682
+ createdAt: session.createdAt
1683
+ }));
1675
1684
  return;
1676
1685
  }
1677
- res.writeHead(200, { "Content-Type": "application/json" });
1678
- res.end(JSON.stringify({
1679
- id: session.id,
1680
- directory: session.directory,
1681
- createdAt: session.createdAt
1682
- }));
1683
- return;
1684
- }
1685
- if (req.method === "GET" && req.url === "/api/status") {
1686
- const list = Array.from(sessions.values()).map((s) => ({
1687
- id: s.id,
1688
- directory: s.directory,
1689
- stats: s.agent.getStats(),
1690
- sessionId: s.agent.sessionId
1691
- }));
1692
- res.writeHead(200, { "Content-Type": "application/json" });
1693
- res.end(JSON.stringify({ sessions: list }));
1694
- return;
1695
- }
1696
- if (req.method === "GET" && req.url?.startsWith("/api/messages")) {
1697
- const url = new URL(req.url, `http://localhost:${PORT}`);
1698
- const sessionId = url.searchParams.get("sessionId");
1699
- const session = sessionId ? getSession(sessionId) : void 0;
1700
- if (!session) {
1701
- res.writeHead(404, { "Content-Type": "application/json" });
1702
- res.end(JSON.stringify({ error: "Session not found" }));
1686
+ if (req.method === "GET" && req.url === "/api/status") {
1687
+ const list = Array.from(sessions.values()).map((s) => ({
1688
+ id: s.id,
1689
+ directory: s.directory,
1690
+ stats: s.agent.getStats(),
1691
+ sessionId: s.agent.sessionId
1692
+ }));
1693
+ res.writeHead(200, { "Content-Type": "application/json" });
1694
+ res.end(JSON.stringify({ sessions: list }));
1703
1695
  return;
1704
1696
  }
1705
- session.agent.getSessionMessages({ limit: 30 }).then((messages) => {
1706
- res.writeHead(200, { "Content-Type": "application/json" });
1707
- res.end(JSON.stringify(messages));
1708
- }).catch((err) => {
1709
- res.writeHead(500, { "Content-Type": "application/json" });
1710
- res.end(JSON.stringify({ error: err.message }));
1711
- });
1712
- return;
1713
- }
1714
- if (req.method === "GET" && req.url === "/admin") {
1715
- res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
1716
- res.end(adminHTML());
1717
- return;
1718
- }
1719
- if (req.method === "GET") {
1720
- if (serveStatic(req, res)) return;
1721
- if (serveAppIndex(res)) return;
1722
- }
1723
- res.writeHead(404, { "Content-Type": "application/json" });
1724
- res.end(JSON.stringify({ error: "Not found" }));
1725
- });
1697
+ if (req.method === "GET" && req.url?.startsWith("/api/messages")) {
1698
+ const url = new URL(req.url, `http://localhost:${PORT}`);
1699
+ const sessionId = url.searchParams.get("sessionId");
1700
+ const session = sessionId ? getSession(sessionId) : void 0;
1701
+ if (!session) {
1702
+ res.writeHead(404, { "Content-Type": "application/json" });
1703
+ res.end(JSON.stringify({ error: "Session not found" }));
1704
+ return;
1705
+ }
1706
+ session.agent.getSessionMessages({ limit: 30 }).then((messages) => {
1707
+ res.writeHead(200, { "Content-Type": "application/json" });
1708
+ res.end(JSON.stringify(messages));
1709
+ }).catch((err) => {
1710
+ res.writeHead(500, { "Content-Type": "application/json" });
1711
+ res.end(JSON.stringify({ error: err.message }));
1712
+ });
1713
+ return;
1714
+ }
1715
+ if (req.method === "GET" && req.url === "/admin") {
1716
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
1717
+ res.end(adminHTML());
1718
+ return;
1719
+ }
1720
+ if (req.method === "GET") {
1721
+ if (serveStatic(req, res)) return;
1722
+ if (serveAppIndex(res)) return;
1723
+ }
1724
+ res.writeHead(404, { "Content-Type": "application/json" });
1725
+ res.end(JSON.stringify({ error: "Not found" }));
1726
+ });
1727
+ }
1726
1728
  async function startServer() {
1729
+ try {
1730
+ userSettings = JSON.parse(fs4.readFileSync(path3.join(ANYCODE_DIR, "settings.json"), "utf-8"));
1731
+ } catch {
1732
+ }
1733
+ loadConfig();
1734
+ process.on("uncaughtException", (err) => {
1735
+ console.error("\u26A0 Uncaught exception:", err.message);
1736
+ });
1737
+ process.on("unhandledRejection", (reason) => {
1738
+ console.error("\u26A0 Unhandled rejection:", reason instanceof Error ? reason.message : reason);
1739
+ });
1740
+ APP_DIST = resolveAppDist();
1741
+ createPreviewServer();
1742
+ createMainServer();
1727
1743
  console.log("\u{1F680} Starting @any-code/server\u2026");
1728
1744
  sharedStorage = new SqlJsStorage(DB_PATH);
1729
1745
  const migrations = Database.getMigrations();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anycodex",
3
- "version": "0.0.14",
3
+ "version": "0.0.15",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"