anycodex 0.0.15 → 0.0.17
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/bin.js +120 -115
- 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-
|
|
25
|
+
// ../server/dist/chunk-55FJSWGH.js
|
|
26
26
|
import http from "http";
|
|
27
27
|
import { fileURLToPath } from "url";
|
|
28
28
|
import path3 from "path";
|
|
@@ -459,29 +459,29 @@ 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
|
-
var PROVIDER = "";
|
|
464
|
-
var MODEL = "";
|
|
465
|
-
var API_KEY = "";
|
|
466
|
-
var BASE_URL = "";
|
|
467
|
-
var PORT = 3210;
|
|
468
|
-
var PREVIEW_PORT = 3211;
|
|
469
462
|
function loadConfig() {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
463
|
+
let userSettings = {};
|
|
464
|
+
try {
|
|
465
|
+
userSettings = JSON.parse(fs4.readFileSync(path3.join(ANYCODE_DIR, "settings.json"), "utf-8"));
|
|
466
|
+
} catch {
|
|
467
|
+
}
|
|
468
|
+
const provider = process.env.PROVIDER ?? userSettings.PROVIDER ?? "anthropic";
|
|
469
|
+
const model = process.env.MODEL ?? userSettings.MODEL ?? "claude-sonnet-4-20250514";
|
|
470
|
+
const apiKey = process.env.API_KEY ?? userSettings.API_KEY ?? "";
|
|
471
|
+
const baseUrl = process.env.BASE_URL ?? userSettings.BASE_URL ?? "";
|
|
472
|
+
const port = parseInt(process.env.PORT ?? "3210", 10);
|
|
473
|
+
const previewPort = parseInt(process.env.PREVIEW_PORT ?? String(port + 1), 10);
|
|
474
|
+
if (!provider || !model || !baseUrl) {
|
|
477
475
|
console.error("\u274C Missing PROVIDER, MODEL, BASE_URL");
|
|
478
476
|
process.exit(1);
|
|
479
477
|
}
|
|
480
|
-
if (!
|
|
478
|
+
if (!apiKey) {
|
|
481
479
|
console.error("\u274C Missing API_KEY");
|
|
482
480
|
console.error("Run 'anycode start' to configure, or set API_KEY env var.");
|
|
483
481
|
process.exit(1);
|
|
484
482
|
}
|
|
483
|
+
const appDist = resolveAppDist();
|
|
484
|
+
return { provider, model, apiKey, baseUrl, port, previewPort, appDist, userSettings };
|
|
485
485
|
}
|
|
486
486
|
function makePaths() {
|
|
487
487
|
const dataPath = path3.join(ANYCODE_DIR, "data");
|
|
@@ -546,10 +546,9 @@ var NodeGitProvider = class {
|
|
|
546
546
|
}
|
|
547
547
|
};
|
|
548
548
|
var sessions = /* @__PURE__ */ new Map();
|
|
549
|
-
var PROVIDER_ID = PROVIDER;
|
|
550
549
|
var sharedStorage;
|
|
551
550
|
var db;
|
|
552
|
-
function createAgentConfig(directory, sessionId, terminal, preview) {
|
|
551
|
+
function createAgentConfig(cfg, directory, sessionId, terminal, preview) {
|
|
553
552
|
return {
|
|
554
553
|
directory,
|
|
555
554
|
fs: new NodeFS(),
|
|
@@ -562,28 +561,26 @@ function createAgentConfig(directory, sessionId, terminal, preview) {
|
|
|
562
561
|
...terminal ? { terminal } : {},
|
|
563
562
|
...preview ? { preview } : {},
|
|
564
563
|
provider: {
|
|
565
|
-
id:
|
|
566
|
-
apiKey:
|
|
567
|
-
model:
|
|
568
|
-
...
|
|
564
|
+
id: cfg.provider,
|
|
565
|
+
apiKey: cfg.apiKey,
|
|
566
|
+
model: cfg.model,
|
|
567
|
+
...cfg.baseUrl ? { baseUrl: cfg.baseUrl } : {}
|
|
569
568
|
},
|
|
570
|
-
settings: userSettings,
|
|
569
|
+
settings: cfg.userSettings,
|
|
571
570
|
config: {
|
|
572
|
-
model: `${
|
|
573
|
-
small_model: `${
|
|
571
|
+
model: `${cfg.provider}/${cfg.model}`,
|
|
572
|
+
small_model: `${cfg.provider}/${cfg.model}`,
|
|
574
573
|
provider: {
|
|
575
|
-
[
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
npm: /claude/i.test(MODEL) ? "@ai-sdk/anthropic" : "@ai-sdk/openai-compatible",
|
|
579
|
-
...BASE_URL ? { api: BASE_URL } : {},
|
|
574
|
+
[cfg.provider]: {
|
|
575
|
+
npm: /claude/i.test(cfg.model) ? "@ai-sdk/anthropic" : "@ai-sdk/openai-compatible",
|
|
576
|
+
...cfg.baseUrl ? { api: cfg.baseUrl } : {},
|
|
580
577
|
options: {
|
|
581
|
-
apiKey:
|
|
582
|
-
...
|
|
578
|
+
apiKey: cfg.apiKey,
|
|
579
|
+
...cfg.baseUrl ? { baseURL: cfg.baseUrl } : {}
|
|
583
580
|
},
|
|
584
581
|
models: {
|
|
585
|
-
[
|
|
586
|
-
name:
|
|
582
|
+
[cfg.model]: {
|
|
583
|
+
name: cfg.model,
|
|
587
584
|
attachment: true,
|
|
588
585
|
tool_call: true,
|
|
589
586
|
temperature: true,
|
|
@@ -597,7 +594,7 @@ function createAgentConfig(directory, sessionId, terminal, preview) {
|
|
|
597
594
|
}
|
|
598
595
|
};
|
|
599
596
|
}
|
|
600
|
-
function registerSession(id, agent, directory, createdAt) {
|
|
597
|
+
function registerSession(cfg, id, agent, directory, createdAt) {
|
|
601
598
|
const entry = { id, agent, directory, createdAt };
|
|
602
599
|
sessions.set(id, entry);
|
|
603
600
|
agent.on("directory.set", (data) => {
|
|
@@ -609,36 +606,36 @@ function registerSession(id, agent, directory, createdAt) {
|
|
|
609
606
|
}
|
|
610
607
|
db.update("user_session", { op: "eq", field: "session_id", value: id }, { directory: dir });
|
|
611
608
|
console.log(`\u{1F4C2} Session ${id} directory set to: ${dir}`);
|
|
612
|
-
pushState(id);
|
|
613
|
-
watchDirectory(id, dir);
|
|
609
|
+
pushState(cfg, id);
|
|
610
|
+
watchDirectory(cfg, id, dir);
|
|
614
611
|
});
|
|
615
612
|
return entry;
|
|
616
613
|
}
|
|
617
|
-
async function resumeSession(row) {
|
|
614
|
+
async function resumeSession(cfg, row) {
|
|
618
615
|
const sessionId = row.session_id;
|
|
619
616
|
const cached = sessions.get(sessionId);
|
|
620
617
|
if (cached) return cached;
|
|
621
618
|
const dir = row.directory || "";
|
|
622
619
|
const tp = getOrCreateTerminalProvider(sessionId);
|
|
623
|
-
const pp = getOrCreatePreviewProvider(sessionId);
|
|
624
|
-
const agent = new CodeAgent(createAgentConfig(dir, sessionId, tp, pp));
|
|
620
|
+
const pp = getOrCreatePreviewProvider(cfg, sessionId);
|
|
621
|
+
const agent = new CodeAgent(createAgentConfig(cfg, dir, sessionId, tp, pp));
|
|
625
622
|
await agent.init();
|
|
626
|
-
const entry = registerSession(sessionId, agent, dir, row.time_created);
|
|
623
|
+
const entry = registerSession(cfg, sessionId, agent, dir, row.time_created);
|
|
627
624
|
if (dir) {
|
|
628
625
|
try {
|
|
629
626
|
agent.setWorkingDirectory(dir);
|
|
630
627
|
} catch {
|
|
631
628
|
}
|
|
632
|
-
watchDirectory(sessionId, dir);
|
|
629
|
+
watchDirectory(cfg, sessionId, dir);
|
|
633
630
|
}
|
|
634
631
|
console.log(`\u267B\uFE0F Session ${sessionId} resumed`);
|
|
635
632
|
return entry;
|
|
636
633
|
}
|
|
637
|
-
async function createNewWindow(userId, isDefault = false) {
|
|
634
|
+
async function createNewWindow(cfg, userId, isDefault = false) {
|
|
638
635
|
const tempId = `temp-${Date.now()}`;
|
|
639
636
|
const tp = getOrCreateTerminalProvider(tempId);
|
|
640
|
-
const pp = getOrCreatePreviewProvider(tempId);
|
|
641
|
-
const agent = new CodeAgent(createAgentConfig("", void 0, tp, pp));
|
|
637
|
+
const pp = getOrCreatePreviewProvider(cfg, tempId);
|
|
638
|
+
const agent = new CodeAgent(createAgentConfig(cfg, "", void 0, tp, pp));
|
|
642
639
|
await agent.init();
|
|
643
640
|
const sessionId = agent.sessionId;
|
|
644
641
|
const now = Date.now();
|
|
@@ -648,7 +645,7 @@ async function createNewWindow(userId, isDefault = false) {
|
|
|
648
645
|
previewProviders.set(sessionId, pp);
|
|
649
646
|
tp.sessionId = sessionId;
|
|
650
647
|
pp.sessionId = sessionId;
|
|
651
|
-
const entry = registerSession(sessionId, agent, "", now);
|
|
648
|
+
const entry = registerSession(cfg, sessionId, agent, "", now);
|
|
652
649
|
db.insert("user_session", {
|
|
653
650
|
user_id: userId,
|
|
654
651
|
session_id: sessionId,
|
|
@@ -659,22 +656,22 @@ async function createNewWindow(userId, isDefault = false) {
|
|
|
659
656
|
console.log(`\u2705 Window ${sessionId} created for user ${userId}${isDefault ? " (default)" : ""}`);
|
|
660
657
|
return entry;
|
|
661
658
|
}
|
|
662
|
-
async function getOrCreateSession(userId) {
|
|
659
|
+
async function getOrCreateSession(cfg, userId) {
|
|
663
660
|
const rows = db.findMany("user_session", { filter: { op: "eq", field: "user_id", value: userId } });
|
|
664
661
|
const defaultRow = rows.find((r) => r.is_default === 1) || rows[0];
|
|
665
662
|
if (defaultRow) {
|
|
666
663
|
if (defaultRow.is_default !== 1) {
|
|
667
664
|
db.update("user_session", { op: "eq", field: "session_id", value: defaultRow.session_id }, { is_default: 1 });
|
|
668
665
|
}
|
|
669
|
-
return resumeSession(defaultRow);
|
|
666
|
+
return resumeSession(cfg, defaultRow);
|
|
670
667
|
}
|
|
671
|
-
return createNewWindow(userId, true);
|
|
668
|
+
return createNewWindow(cfg, userId, true);
|
|
672
669
|
}
|
|
673
|
-
async function getAllWindows(userId) {
|
|
670
|
+
async function getAllWindows(cfg, userId) {
|
|
674
671
|
const rows = db.findMany("user_session", { filter: { op: "eq", field: "user_id", value: userId } });
|
|
675
672
|
const entries = [];
|
|
676
673
|
for (const row of rows) {
|
|
677
|
-
entries.push(await resumeSession(row));
|
|
674
|
+
entries.push(await resumeSession(cfg, row));
|
|
678
675
|
}
|
|
679
676
|
return entries;
|
|
680
677
|
}
|
|
@@ -737,12 +734,12 @@ var sessionClients = /* @__PURE__ */ new Map();
|
|
|
737
734
|
var sessionChatAbort = /* @__PURE__ */ new Map();
|
|
738
735
|
var lastStateJson = /* @__PURE__ */ new Map();
|
|
739
736
|
var statePushTimers = /* @__PURE__ */ new Map();
|
|
740
|
-
function scheduleStatePush(sessionId, delayMs = 300) {
|
|
737
|
+
function scheduleStatePush(cfg, sessionId, delayMs = 300) {
|
|
741
738
|
const existing = statePushTimers.get(sessionId);
|
|
742
739
|
if (existing) clearTimeout(existing);
|
|
743
740
|
const timer = setTimeout(() => {
|
|
744
741
|
statePushTimers.delete(sessionId);
|
|
745
|
-
void pushState(sessionId);
|
|
742
|
+
void pushState(cfg, sessionId);
|
|
746
743
|
}, delayMs);
|
|
747
744
|
statePushTimers.set(sessionId, timer);
|
|
748
745
|
}
|
|
@@ -901,11 +898,11 @@ ${message}` : message;
|
|
|
901
898
|
}
|
|
902
899
|
}
|
|
903
900
|
var watchers = /* @__PURE__ */ new Map();
|
|
904
|
-
function watchDirectory(sessionId, dir) {
|
|
901
|
+
function watchDirectory(cfg, sessionId, dir) {
|
|
905
902
|
const existing = watchers.get(sessionId);
|
|
906
903
|
if (existing) existing.close();
|
|
907
904
|
const debouncedPush = () => {
|
|
908
|
-
scheduleStatePush(sessionId, 500);
|
|
905
|
+
scheduleStatePush(cfg, sessionId, 500);
|
|
909
906
|
};
|
|
910
907
|
try {
|
|
911
908
|
const watcher = fs4.watch(dir, { recursive: true }, (eventType, filename) => {
|
|
@@ -918,7 +915,7 @@ function watchDirectory(sessionId, dir) {
|
|
|
918
915
|
console.error(`\u274C fs.watch failed for ${dir}:`, err);
|
|
919
916
|
}
|
|
920
917
|
}
|
|
921
|
-
async function buildState(sessionId) {
|
|
918
|
+
async function buildState(cfg, sessionId) {
|
|
922
919
|
const session = getSession(sessionId);
|
|
923
920
|
if (!session) return null;
|
|
924
921
|
const dir = session.directory;
|
|
@@ -929,12 +926,12 @@ async function buildState(sessionId) {
|
|
|
929
926
|
directory: dir,
|
|
930
927
|
changes,
|
|
931
928
|
topLevel,
|
|
932
|
-
previewPort: previewSessionId === sessionId && previewTarget ?
|
|
929
|
+
previewPort: previewSessionId === sessionId && previewTarget ? cfg.previewPort : null
|
|
933
930
|
};
|
|
934
931
|
}
|
|
935
|
-
async function pushState(sessionId) {
|
|
932
|
+
async function pushState(cfg, sessionId) {
|
|
936
933
|
try {
|
|
937
|
-
const payload = await buildState(sessionId);
|
|
934
|
+
const payload = await buildState(cfg, sessionId);
|
|
938
935
|
if (!payload) return;
|
|
939
936
|
const json = JSON.stringify(payload);
|
|
940
937
|
const prev = lastStateJson.get(sessionId);
|
|
@@ -951,11 +948,11 @@ async function pushState(sessionId) {
|
|
|
951
948
|
console.error(`\u274C pushState error:`, err);
|
|
952
949
|
}
|
|
953
950
|
}
|
|
954
|
-
async function sendStateTo(sessionId, client) {
|
|
951
|
+
async function sendStateTo(cfg, sessionId, client) {
|
|
955
952
|
try {
|
|
956
953
|
let json = lastStateJson.get(sessionId);
|
|
957
954
|
if (!json) {
|
|
958
|
-
const payload = await buildState(sessionId);
|
|
955
|
+
const payload = await buildState(cfg, sessionId);
|
|
959
956
|
if (!payload) return;
|
|
960
957
|
json = JSON.stringify(payload);
|
|
961
958
|
lastStateJson.set(sessionId, json);
|
|
@@ -1158,31 +1155,32 @@ var previewTarget = null;
|
|
|
1158
1155
|
var previewSessionId = null;
|
|
1159
1156
|
var NodePreviewProvider = class {
|
|
1160
1157
|
sessionId;
|
|
1161
|
-
|
|
1158
|
+
cfg;
|
|
1159
|
+
constructor(cfg, sessionId) {
|
|
1160
|
+
this.cfg = cfg;
|
|
1162
1161
|
this.sessionId = sessionId;
|
|
1163
1162
|
}
|
|
1164
1163
|
setPreviewTarget(forwardedLocalUrl) {
|
|
1165
1164
|
previewTarget = forwardedLocalUrl.replace(/\/+$/, "");
|
|
1166
1165
|
previewSessionId = this.sessionId;
|
|
1167
|
-
console.log(`\u{1F517} Preview proxy: :${
|
|
1166
|
+
console.log(`\u{1F517} Preview proxy: :${this.cfg.previewPort} \u2192 ${previewTarget} (session ${this.sessionId})`);
|
|
1168
1167
|
broadcast(this.sessionId, {
|
|
1169
1168
|
type: "preview",
|
|
1170
|
-
port:
|
|
1169
|
+
port: this.cfg.previewPort
|
|
1171
1170
|
});
|
|
1172
1171
|
}
|
|
1173
1172
|
};
|
|
1174
1173
|
var previewProviders = /* @__PURE__ */ new Map();
|
|
1175
|
-
function getOrCreatePreviewProvider(sessionId) {
|
|
1174
|
+
function getOrCreatePreviewProvider(cfg, sessionId) {
|
|
1176
1175
|
let pp = previewProviders.get(sessionId);
|
|
1177
1176
|
if (!pp) {
|
|
1178
|
-
pp = new NodePreviewProvider(sessionId);
|
|
1177
|
+
pp = new NodePreviewProvider(cfg, sessionId);
|
|
1179
1178
|
previewProviders.set(sessionId, pp);
|
|
1180
1179
|
}
|
|
1181
1180
|
return pp;
|
|
1182
1181
|
}
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
previewServer = http.createServer((req, res) => {
|
|
1182
|
+
function createPreviewServer(cfg) {
|
|
1183
|
+
const previewServer = http.createServer((req, res) => {
|
|
1186
1184
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
1187
1185
|
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
1188
1186
|
res.setHeader("Access-Control-Allow-Headers", "*");
|
|
@@ -1252,8 +1250,9 @@ function createPreviewServer() {
|
|
|
1252
1250
|
socket.destroy();
|
|
1253
1251
|
}
|
|
1254
1252
|
});
|
|
1253
|
+
return previewServer;
|
|
1255
1254
|
}
|
|
1256
|
-
function adminHTML() {
|
|
1255
|
+
function adminHTML(cfg) {
|
|
1257
1256
|
return (
|
|
1258
1257
|
/* html */
|
|
1259
1258
|
`<!DOCTYPE html>
|
|
@@ -1304,9 +1303,9 @@ function adminHTML() {
|
|
|
1304
1303
|
<h1><span class="dot"></span> AnyCode Server</h1>
|
|
1305
1304
|
<div class="card">
|
|
1306
1305
|
<h2>\u2699 Configuration</h2>
|
|
1307
|
-
<div class="row"><span class="label">Provider</span><span class="value">${
|
|
1308
|
-
<div class="row"><span class="label">Model</span><span class="value">${
|
|
1309
|
-
<div class="row"><span class="label">Port</span><span class="value">${
|
|
1306
|
+
<div class="row"><span class="label">Provider</span><span class="value">${cfg.provider}</span></div>
|
|
1307
|
+
<div class="row"><span class="label">Model</span><span class="value">${cfg.model}</span></div>
|
|
1308
|
+
<div class="row"><span class="label">Port</span><span class="value">${cfg.port}</span></div>
|
|
1310
1309
|
<div class="row"><span class="label">Sessions</span><span class="value" id="session-count">0</span></div>
|
|
1311
1310
|
</div>
|
|
1312
1311
|
<div class="card">
|
|
@@ -1373,10 +1372,9 @@ function resolveAppDist() {
|
|
|
1373
1372
|
}
|
|
1374
1373
|
return bundled;
|
|
1375
1374
|
}
|
|
1376
|
-
|
|
1377
|
-
function serveStatic(req, res) {
|
|
1375
|
+
function serveStatic(cfg, req, res) {
|
|
1378
1376
|
const url = req.url || "/";
|
|
1379
|
-
const filePath = path3.join(
|
|
1377
|
+
const filePath = path3.join(cfg.appDist, url);
|
|
1380
1378
|
if (fs4.existsSync(filePath) && fs4.statSync(filePath).isFile()) {
|
|
1381
1379
|
const ext = path3.extname(filePath);
|
|
1382
1380
|
res.writeHead(200, { "Content-Type": MIME_TYPES[ext] || "application/octet-stream" });
|
|
@@ -1385,10 +1383,10 @@ function serveStatic(req, res) {
|
|
|
1385
1383
|
}
|
|
1386
1384
|
return false;
|
|
1387
1385
|
}
|
|
1388
|
-
function serveAppIndex(res) {
|
|
1389
|
-
const indexPath = path3.join(
|
|
1386
|
+
function serveAppIndex(cfg, res) {
|
|
1387
|
+
const indexPath = path3.join(cfg.appDist, "index.html");
|
|
1390
1388
|
if (fs4.existsSync(indexPath)) {
|
|
1391
|
-
const webSocket = userSettings.webSocket === true;
|
|
1389
|
+
const webSocket = cfg.userSettings.webSocket === true;
|
|
1392
1390
|
const configScript = `<script>window.__ANYCODE_CONFIG__=${JSON.stringify({ webSocket })}</script>`;
|
|
1393
1391
|
let html = fs4.readFileSync(indexPath, "utf-8");
|
|
1394
1392
|
html = html.replace("</head>", `${configScript}</head>`);
|
|
@@ -1398,9 +1396,8 @@ function serveAppIndex(res) {
|
|
|
1398
1396
|
}
|
|
1399
1397
|
return false;
|
|
1400
1398
|
}
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
server = http.createServer(async (req, res) => {
|
|
1399
|
+
function createMainServer(cfg) {
|
|
1400
|
+
const server = http.createServer(async (req, res) => {
|
|
1404
1401
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
1405
1402
|
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
1406
1403
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
@@ -1424,13 +1421,13 @@ function createMainServer() {
|
|
|
1424
1421
|
pollingClients.set(channelId, client);
|
|
1425
1422
|
getSessionClients(sessionId).add(client);
|
|
1426
1423
|
console.log(`\u{1F50C} Poll client connected to session ${sessionId} (channel=${channelId})`);
|
|
1427
|
-
sendStateTo(sessionId, client);
|
|
1424
|
+
sendStateTo(cfg, sessionId, client);
|
|
1428
1425
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1429
1426
|
res.end(JSON.stringify({ channelId }));
|
|
1430
1427
|
return;
|
|
1431
1428
|
}
|
|
1432
1429
|
if (req.method === "GET" && req.url?.startsWith("/api/poll?")) {
|
|
1433
|
-
const url = new URL(req.url, `http://localhost:${
|
|
1430
|
+
const url = new URL(req.url, `http://localhost:${cfg.port}`);
|
|
1434
1431
|
const channelId = url.searchParams.get("channelId");
|
|
1435
1432
|
const client = channelId ? pollingClients.get(channelId) : void 0;
|
|
1436
1433
|
if (!client || client.readyState !== 1) {
|
|
@@ -1483,7 +1480,7 @@ function createMainServer() {
|
|
|
1483
1480
|
res.end(JSON.stringify({ error: "userId is required" }));
|
|
1484
1481
|
return;
|
|
1485
1482
|
}
|
|
1486
|
-
getOrCreateSession(userId).then((entry) => {
|
|
1483
|
+
getOrCreateSession(cfg, userId).then((entry) => {
|
|
1487
1484
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1488
1485
|
res.end(JSON.stringify({ id: entry.id, directory: entry.directory }));
|
|
1489
1486
|
}).catch((err) => {
|
|
@@ -1504,14 +1501,14 @@ function createMainServer() {
|
|
|
1504
1501
|
return;
|
|
1505
1502
|
}
|
|
1506
1503
|
if (req.method === "GET" && req.url?.startsWith("/api/windows")) {
|
|
1507
|
-
const url = new URL(req.url, `http://localhost:${
|
|
1504
|
+
const url = new URL(req.url, `http://localhost:${cfg.port}`);
|
|
1508
1505
|
const userId = url.searchParams.get("userId");
|
|
1509
1506
|
if (!userId) {
|
|
1510
1507
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1511
1508
|
res.end(JSON.stringify({ error: "userId is required" }));
|
|
1512
1509
|
return;
|
|
1513
1510
|
}
|
|
1514
|
-
getAllWindows(userId).then((entries) => {
|
|
1511
|
+
getAllWindows(cfg, userId).then((entries) => {
|
|
1515
1512
|
const rows = db.findMany("user_session", { filter: { op: "eq", field: "user_id", value: userId } });
|
|
1516
1513
|
const defaultMap = new Map(rows.map((r) => [r.session_id, r.is_default === 1]));
|
|
1517
1514
|
const list = entries.map((e) => ({
|
|
@@ -1538,7 +1535,7 @@ function createMainServer() {
|
|
|
1538
1535
|
res.end(JSON.stringify({ error: "userId is required" }));
|
|
1539
1536
|
return;
|
|
1540
1537
|
}
|
|
1541
|
-
createNewWindow(userId, false).then((entry) => {
|
|
1538
|
+
createNewWindow(cfg, userId, false).then((entry) => {
|
|
1542
1539
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1543
1540
|
res.end(JSON.stringify({ id: entry.id, directory: entry.directory, isDefault: false }));
|
|
1544
1541
|
}).catch((err) => {
|
|
@@ -1569,7 +1566,7 @@ function createMainServer() {
|
|
|
1569
1566
|
return;
|
|
1570
1567
|
}
|
|
1571
1568
|
const sub = sessionMatch[2];
|
|
1572
|
-
const url = new URL(req.url, `http://localhost:${
|
|
1569
|
+
const url = new URL(req.url, `http://localhost:${cfg.port}`);
|
|
1573
1570
|
if (sub === "state") {
|
|
1574
1571
|
const dir = session.directory;
|
|
1575
1572
|
const [topLevel, changes] = await Promise.all([
|
|
@@ -1578,7 +1575,7 @@ function createMainServer() {
|
|
|
1578
1575
|
]);
|
|
1579
1576
|
const hasPreview = previewSessionId === session.id && previewTarget;
|
|
1580
1577
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1581
|
-
res.end(JSON.stringify({ directory: dir, topLevel, changes, previewPort: hasPreview ?
|
|
1578
|
+
res.end(JSON.stringify({ directory: dir, topLevel, changes, previewPort: hasPreview ? cfg.previewPort : null }));
|
|
1582
1579
|
return;
|
|
1583
1580
|
}
|
|
1584
1581
|
if (sub === "ls") {
|
|
@@ -1695,7 +1692,7 @@ function createMainServer() {
|
|
|
1695
1692
|
return;
|
|
1696
1693
|
}
|
|
1697
1694
|
if (req.method === "GET" && req.url?.startsWith("/api/messages")) {
|
|
1698
|
-
const url = new URL(req.url, `http://localhost:${
|
|
1695
|
+
const url = new URL(req.url, `http://localhost:${cfg.port}`);
|
|
1699
1696
|
const sessionId = url.searchParams.get("sessionId");
|
|
1700
1697
|
const session = sessionId ? getSession(sessionId) : void 0;
|
|
1701
1698
|
if (!session) {
|
|
@@ -1714,32 +1711,28 @@ function createMainServer() {
|
|
|
1714
1711
|
}
|
|
1715
1712
|
if (req.method === "GET" && req.url === "/admin") {
|
|
1716
1713
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
1717
|
-
res.end(adminHTML());
|
|
1714
|
+
res.end(adminHTML(cfg));
|
|
1718
1715
|
return;
|
|
1719
1716
|
}
|
|
1720
1717
|
if (req.method === "GET") {
|
|
1721
|
-
if (serveStatic(req, res)) return;
|
|
1722
|
-
if (serveAppIndex(res)) return;
|
|
1718
|
+
if (serveStatic(cfg, req, res)) return;
|
|
1719
|
+
if (serveAppIndex(cfg, res)) return;
|
|
1723
1720
|
}
|
|
1724
1721
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1725
1722
|
res.end(JSON.stringify({ error: "Not found" }));
|
|
1726
1723
|
});
|
|
1724
|
+
return server;
|
|
1727
1725
|
}
|
|
1728
1726
|
async function startServer() {
|
|
1729
|
-
|
|
1730
|
-
userSettings = JSON.parse(fs4.readFileSync(path3.join(ANYCODE_DIR, "settings.json"), "utf-8"));
|
|
1731
|
-
} catch {
|
|
1732
|
-
}
|
|
1733
|
-
loadConfig();
|
|
1727
|
+
const cfg = loadConfig();
|
|
1734
1728
|
process.on("uncaughtException", (err) => {
|
|
1735
1729
|
console.error("\u26A0 Uncaught exception:", err.message);
|
|
1736
1730
|
});
|
|
1737
1731
|
process.on("unhandledRejection", (reason) => {
|
|
1738
1732
|
console.error("\u26A0 Unhandled rejection:", reason instanceof Error ? reason.message : reason);
|
|
1739
1733
|
});
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
createMainServer();
|
|
1734
|
+
const previewServer = createPreviewServer(cfg);
|
|
1735
|
+
const server = createMainServer(cfg);
|
|
1743
1736
|
console.log("\u{1F680} Starting @any-code/server\u2026");
|
|
1744
1737
|
sharedStorage = new SqlJsStorage(DB_PATH);
|
|
1745
1738
|
const migrations = Database.getMigrations();
|
|
@@ -1780,7 +1773,7 @@ async function startServer() {
|
|
|
1780
1773
|
)
|
|
1781
1774
|
`);
|
|
1782
1775
|
}
|
|
1783
|
-
const appDistExists = fs4.existsSync(
|
|
1776
|
+
const appDistExists = fs4.existsSync(cfg.appDist);
|
|
1784
1777
|
setInterval(() => {
|
|
1785
1778
|
const now = Date.now();
|
|
1786
1779
|
for (const [id, client] of pollingClients) {
|
|
@@ -1794,7 +1787,7 @@ async function startServer() {
|
|
|
1794
1787
|
}, 3e4);
|
|
1795
1788
|
const wss = new WebSocketServer({ server });
|
|
1796
1789
|
wss.on("connection", (ws, req) => {
|
|
1797
|
-
const url = new URL(req.url || "/", `http://localhost:${
|
|
1790
|
+
const url = new URL(req.url || "/", `http://localhost:${cfg.port}`);
|
|
1798
1791
|
const sessionId = url.searchParams.get("sessionId");
|
|
1799
1792
|
if (!sessionId || !getSession(sessionId)) {
|
|
1800
1793
|
ws.close(4001, "Invalid session");
|
|
@@ -1807,7 +1800,7 @@ async function startServer() {
|
|
|
1807
1800
|
const clients = getSessionClients(sessionId);
|
|
1808
1801
|
clients.add(ws);
|
|
1809
1802
|
console.log(`\u{1F50C} WS client connected to session ${sessionId} (${clients.size} total)`);
|
|
1810
|
-
sendStateTo(sessionId, ws);
|
|
1803
|
+
sendStateTo(cfg, sessionId, ws);
|
|
1811
1804
|
ws.on("message", async (raw) => {
|
|
1812
1805
|
try {
|
|
1813
1806
|
const msg = JSON.parse(raw.toString());
|
|
@@ -1821,20 +1814,20 @@ async function startServer() {
|
|
|
1821
1814
|
});
|
|
1822
1815
|
});
|
|
1823
1816
|
const HOST = process.env.HOST ?? "0.0.0.0";
|
|
1824
|
-
previewServer.listen(
|
|
1825
|
-
console.log(`\u{1F441} Preview proxy: http://${HOST}:${
|
|
1817
|
+
previewServer.listen(cfg.previewPort, HOST, () => {
|
|
1818
|
+
console.log(`\u{1F441} Preview proxy: http://${HOST}:${cfg.previewPort}`);
|
|
1826
1819
|
});
|
|
1827
|
-
server.listen(
|
|
1828
|
-
console.log(`\u{1F310} http://${HOST}:${
|
|
1829
|
-
console.log(`\u{1F916} Provider: ${
|
|
1830
|
-
console.log(`\u{1F5A5} Admin: http://${HOST}:${
|
|
1820
|
+
server.listen(cfg.port, HOST, () => {
|
|
1821
|
+
console.log(`\u{1F310} http://${HOST}:${cfg.port}`);
|
|
1822
|
+
console.log(`\u{1F916} Provider: ${cfg.provider} / ${cfg.model}`);
|
|
1823
|
+
console.log(`\u{1F5A5} Admin: http://${HOST}:${cfg.port}/admin`);
|
|
1831
1824
|
if (appDistExists) {
|
|
1832
|
-
console.log(`\u{1F4F1} App: http://${HOST}:${
|
|
1825
|
+
console.log(`\u{1F4F1} App: http://${HOST}:${cfg.port}`);
|
|
1833
1826
|
} else {
|
|
1834
|
-
console.log(`\u26A0 App dist not found at ${
|
|
1827
|
+
console.log(`\u26A0 App dist not found at ${cfg.appDist} \u2014 run 'pnpm --filter @any-code/app build' first`);
|
|
1835
1828
|
}
|
|
1836
1829
|
console.log(`\u{1F4CB} Sessions: POST /api/sessions to create`);
|
|
1837
|
-
console.log(`\u{1F50C} WebSocket: ws://${HOST}:${
|
|
1830
|
+
console.log(`\u{1F50C} WebSocket: ws://${HOST}:${cfg.port}?sessionId=xxx`);
|
|
1838
1831
|
});
|
|
1839
1832
|
}
|
|
1840
1833
|
|
|
@@ -1922,12 +1915,24 @@ function prompt(question) {
|
|
|
1922
1915
|
async function ensureSettings() {
|
|
1923
1916
|
const settings = loadSettings();
|
|
1924
1917
|
let changed = false;
|
|
1925
|
-
if (!settings.
|
|
1918
|
+
if (!settings.PROVIDER) {
|
|
1926
1919
|
blank();
|
|
1927
1920
|
console.log(` ${c.bold}${c.white}Welcome! Let's configure your LLM provider.${c.reset}`);
|
|
1928
1921
|
blank();
|
|
1929
1922
|
divider();
|
|
1930
1923
|
blank();
|
|
1924
|
+
const val = await prompt(` ${c.cyan}?${c.reset} ${c.bold}Provider${c.reset} ${c.gray}(anthropic, openai)${c.reset}: `);
|
|
1925
|
+
settings.PROVIDER = val || "anthropic";
|
|
1926
|
+
changed = true;
|
|
1927
|
+
}
|
|
1928
|
+
if (!settings.API_KEY) {
|
|
1929
|
+
if (!changed) {
|
|
1930
|
+
blank();
|
|
1931
|
+
console.log(` ${c.bold}${c.white}Welcome! Let's configure your LLM provider.${c.reset}`);
|
|
1932
|
+
blank();
|
|
1933
|
+
divider();
|
|
1934
|
+
blank();
|
|
1935
|
+
}
|
|
1931
1936
|
settings.API_KEY = await prompt(` ${c.cyan}?${c.reset} ${c.bold}API Key${c.reset} ${c.gray}(required)${c.reset}: `);
|
|
1932
1937
|
if (!settings.API_KEY) {
|
|
1933
1938
|
fail("API Key is required to continue.");
|