amai 0.0.5 → 0.0.7
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.cjs +512 -374
- package/dist/cli.js +507 -369
- package/dist/lib/daemon-entry.cjs +424 -286
- package/dist/lib/daemon-entry.js +421 -283
- package/dist/server.cjs +406 -266
- package/dist/server.d.cts +1 -3
- package/dist/server.d.ts +1 -3
- package/dist/server.js +402 -261
- package/package.json +2 -2
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var WebSocket = require('ws');
|
|
5
|
-
var events = require('events');
|
|
6
5
|
var zod = require('zod');
|
|
7
6
|
var promises = require('fs/promises');
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
var
|
|
7
|
+
var path11 = require('path');
|
|
8
|
+
var fs4 = require('fs');
|
|
9
|
+
var os3 = require('os');
|
|
11
10
|
var crypto = require('crypto');
|
|
12
11
|
var child_process = require('child_process');
|
|
13
12
|
var util = require('util');
|
|
@@ -19,18 +18,18 @@ var cors = require('hono/cors');
|
|
|
19
18
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
20
19
|
|
|
21
20
|
var WebSocket__default = /*#__PURE__*/_interopDefault(WebSocket);
|
|
22
|
-
var
|
|
23
|
-
var
|
|
24
|
-
var
|
|
21
|
+
var path11__default = /*#__PURE__*/_interopDefault(path11);
|
|
22
|
+
var fs4__default = /*#__PURE__*/_interopDefault(fs4);
|
|
23
|
+
var os3__default = /*#__PURE__*/_interopDefault(os3);
|
|
25
24
|
var pc2__default = /*#__PURE__*/_interopDefault(pc2);
|
|
26
25
|
|
|
27
26
|
var DEFAULT_SERVER_URL = "wss://ama-production-a628.up.railway.app";
|
|
28
|
-
var AMA_DIR =
|
|
29
|
-
var CODE_DIR =
|
|
30
|
-
var STORAGE_DIR =
|
|
27
|
+
var AMA_DIR = path11__default.default.join(os3__default.default.homedir(), ".amai");
|
|
28
|
+
var CODE_DIR = path11__default.default.join(AMA_DIR, "code");
|
|
29
|
+
var STORAGE_DIR = path11__default.default.join(AMA_DIR, "storage");
|
|
31
30
|
|
|
32
31
|
// src/lib/project-registry.ts
|
|
33
|
-
var REGISTRY_FILE =
|
|
32
|
+
var REGISTRY_FILE = path11__default.default.join(AMA_DIR, "projects.json");
|
|
34
33
|
var ProjectRegistry = class {
|
|
35
34
|
projects = /* @__PURE__ */ new Map();
|
|
36
35
|
constructor() {
|
|
@@ -38,14 +37,14 @@ var ProjectRegistry = class {
|
|
|
38
37
|
}
|
|
39
38
|
load() {
|
|
40
39
|
try {
|
|
41
|
-
if (
|
|
42
|
-
const data =
|
|
40
|
+
if (fs4__default.default.existsSync(REGISTRY_FILE)) {
|
|
41
|
+
const data = fs4__default.default.readFileSync(REGISTRY_FILE, "utf8");
|
|
43
42
|
const parsed = JSON.parse(data);
|
|
44
43
|
if (!Array.isArray(parsed)) {
|
|
45
44
|
console.error("Invalid project registry format: expected array, got", typeof parsed);
|
|
46
45
|
const backupFile = REGISTRY_FILE + ".backup." + Date.now();
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
fs4__default.default.copyFileSync(REGISTRY_FILE, backupFile);
|
|
47
|
+
fs4__default.default.unlinkSync(REGISTRY_FILE);
|
|
49
48
|
return;
|
|
50
49
|
}
|
|
51
50
|
const projects = parsed;
|
|
@@ -58,11 +57,11 @@ var ProjectRegistry = class {
|
|
|
58
57
|
}
|
|
59
58
|
} catch (error) {
|
|
60
59
|
console.error("Failed to load project registry:", error);
|
|
61
|
-
if (
|
|
60
|
+
if (fs4__default.default.existsSync(REGISTRY_FILE)) {
|
|
62
61
|
try {
|
|
63
62
|
const backupFile = REGISTRY_FILE + ".backup." + Date.now();
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
fs4__default.default.copyFileSync(REGISTRY_FILE, backupFile);
|
|
64
|
+
fs4__default.default.unlinkSync(REGISTRY_FILE);
|
|
66
65
|
console.log("Corrupted registry file backed up and removed. Starting fresh.");
|
|
67
66
|
} catch (backupError) {
|
|
68
67
|
}
|
|
@@ -71,21 +70,21 @@ var ProjectRegistry = class {
|
|
|
71
70
|
}
|
|
72
71
|
save() {
|
|
73
72
|
try {
|
|
74
|
-
if (!
|
|
75
|
-
|
|
73
|
+
if (!fs4__default.default.existsSync(AMA_DIR)) {
|
|
74
|
+
fs4__default.default.mkdirSync(AMA_DIR, { recursive: true });
|
|
76
75
|
}
|
|
77
76
|
const projects = Array.from(this.projects.values());
|
|
78
|
-
|
|
77
|
+
fs4__default.default.writeFileSync(REGISTRY_FILE, JSON.stringify(projects, null, 2), "utf8");
|
|
79
78
|
} catch (error) {
|
|
80
79
|
console.error("Failed to save project registry:", error);
|
|
81
80
|
}
|
|
82
81
|
}
|
|
83
82
|
register(projectId, cwd, name) {
|
|
84
|
-
const normalizedCwd =
|
|
83
|
+
const normalizedCwd = path11__default.default.normalize(path11__default.default.resolve(cwd));
|
|
85
84
|
this.projects.set(projectId, {
|
|
86
85
|
id: projectId,
|
|
87
86
|
cwd: normalizedCwd,
|
|
88
|
-
name: name ||
|
|
87
|
+
name: name || path11__default.default.basename(normalizedCwd),
|
|
89
88
|
active: true
|
|
90
89
|
});
|
|
91
90
|
this.save();
|
|
@@ -115,9 +114,9 @@ var ProjectRegistry = class {
|
|
|
115
114
|
var projectRegistry = new ProjectRegistry();
|
|
116
115
|
function isPathWithinProject(filePath, projectCwd) {
|
|
117
116
|
try {
|
|
118
|
-
const resolved =
|
|
119
|
-
const normalized =
|
|
120
|
-
const normalizedCwd =
|
|
117
|
+
const resolved = path11__default.default.resolve(projectCwd, filePath);
|
|
118
|
+
const normalized = path11__default.default.normalize(resolved);
|
|
119
|
+
const normalizedCwd = path11__default.default.normalize(projectCwd);
|
|
121
120
|
return normalized.startsWith(normalizedCwd);
|
|
122
121
|
} catch {
|
|
123
122
|
return false;
|
|
@@ -133,7 +132,7 @@ function validatePath(filePath, projectCwd) {
|
|
|
133
132
|
};
|
|
134
133
|
}
|
|
135
134
|
try {
|
|
136
|
-
const resolvedPath =
|
|
135
|
+
const resolvedPath = path11__default.default.resolve(projectCwd, filePath);
|
|
137
136
|
if (!isPathWithinProject(filePath, projectCwd)) {
|
|
138
137
|
return {
|
|
139
138
|
valid: false,
|
|
@@ -152,7 +151,7 @@ function validatePath(filePath, projectCwd) {
|
|
|
152
151
|
}
|
|
153
152
|
}
|
|
154
153
|
function resolveProjectPath(filePath, projectCwd) {
|
|
155
|
-
return
|
|
154
|
+
return path11__default.default.resolve(projectCwd, filePath);
|
|
156
155
|
}
|
|
157
156
|
|
|
158
157
|
// src/tools/read-file.ts
|
|
@@ -274,7 +273,7 @@ var read_file = async function(input, projectCwd) {
|
|
|
274
273
|
};
|
|
275
274
|
}
|
|
276
275
|
} else {
|
|
277
|
-
const absolute_file_path =
|
|
276
|
+
const absolute_file_path = path11__default.default.resolve(relative_file_path);
|
|
278
277
|
try {
|
|
279
278
|
const fileStats = await promises.stat(absolute_file_path);
|
|
280
279
|
if (!fileStats.isFile()) {
|
|
@@ -868,20 +867,20 @@ var editFiles = async function(input, projectCwd) {
|
|
|
868
867
|
}
|
|
869
868
|
const basePath = projectCwd || process.cwd();
|
|
870
869
|
const filePath = resolveProjectPath(target_file, basePath);
|
|
871
|
-
const dirPath =
|
|
870
|
+
const dirPath = path11__default.default.dirname(filePath);
|
|
872
871
|
await promises.mkdir(dirPath, { recursive: true });
|
|
873
872
|
let isNewFile = providedNewFile;
|
|
874
873
|
let existingContent = "";
|
|
875
874
|
if (isNewFile === void 0) {
|
|
876
875
|
try {
|
|
877
|
-
existingContent = await
|
|
876
|
+
existingContent = await fs4__default.default.promises.readFile(filePath, "utf-8");
|
|
878
877
|
isNewFile = false;
|
|
879
878
|
} catch (error) {
|
|
880
879
|
isNewFile = true;
|
|
881
880
|
}
|
|
882
881
|
} else if (!isNewFile) {
|
|
883
882
|
try {
|
|
884
|
-
existingContent = await
|
|
883
|
+
existingContent = await fs4__default.default.promises.readFile(filePath, "utf-8");
|
|
885
884
|
} catch (error) {
|
|
886
885
|
isNewFile = true;
|
|
887
886
|
}
|
|
@@ -894,7 +893,7 @@ var editFiles = async function(input, projectCwd) {
|
|
|
894
893
|
content
|
|
895
894
|
);
|
|
896
895
|
try {
|
|
897
|
-
await
|
|
896
|
+
await fs4__default.default.promises.writeFile(filePath, content);
|
|
898
897
|
} catch (writeError) {
|
|
899
898
|
checkpointStore.removeCheckpoint(checkpointId);
|
|
900
899
|
throw writeError;
|
|
@@ -1018,7 +1017,7 @@ var grepTool = async function(input, projectCwd) {
|
|
|
1018
1017
|
try {
|
|
1019
1018
|
const { includePattern, excludePattern: excludePattern2, caseSensitive } = options || {};
|
|
1020
1019
|
const searchDir = projectCwd || process.cwd();
|
|
1021
|
-
if (projectCwd && !
|
|
1020
|
+
if (projectCwd && !path11__default.default.isAbsolute(projectCwd)) {
|
|
1022
1021
|
return {
|
|
1023
1022
|
success: false,
|
|
1024
1023
|
message: "Invalid project directory",
|
|
@@ -1210,8 +1209,8 @@ var list = async function(input, projectCwd) {
|
|
|
1210
1209
|
const walk = async (currentDir, depth) => {
|
|
1211
1210
|
const entries = await promises.readdir(currentDir, { withFileTypes: true });
|
|
1212
1211
|
for (const entry of entries) {
|
|
1213
|
-
const entryAbsolutePath =
|
|
1214
|
-
const entryRelativePath =
|
|
1212
|
+
const entryAbsolutePath = path11__default.default.join(currentDir, entry.name);
|
|
1213
|
+
const entryRelativePath = path11__default.default.relative(absolutePath, entryAbsolutePath) || ".";
|
|
1215
1214
|
if (entry.isDirectory()) {
|
|
1216
1215
|
const isExcluded = entry.name.match(excludePattern);
|
|
1217
1216
|
if (includeDirectoriesNormalized && matchPattern(entry.name) && !isExcluded) {
|
|
@@ -1261,213 +1260,9 @@ var list = async function(input, projectCwd) {
|
|
|
1261
1260
|
};
|
|
1262
1261
|
}
|
|
1263
1262
|
};
|
|
1264
|
-
var
|
|
1265
|
-
var getContext = (dir, base = dir, allFiles = []) => {
|
|
1266
|
-
const filePath = fs3.readdirSync(dir, { withFileTypes: true });
|
|
1267
|
-
for (const file of filePath) {
|
|
1268
|
-
if (ignoreFiles.includes(file.name)) continue;
|
|
1269
|
-
const fullPath = path9__default.default.join(dir, file.name);
|
|
1270
|
-
if (file.isDirectory()) {
|
|
1271
|
-
getContext(fullPath, base, allFiles);
|
|
1272
|
-
} else {
|
|
1273
|
-
allFiles.push(path9__default.default.relative(base, fullPath));
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1276
|
-
return allFiles;
|
|
1277
|
-
};
|
|
1278
|
-
var HOME = os2__default.default.homedir();
|
|
1279
|
-
var IDE_PROJECTS_PATHS = {
|
|
1280
|
-
vscode: path9__default.default.join(HOME, ".vscode", "projects"),
|
|
1281
|
-
cursor: path9__default.default.join(HOME, ".cursor", "projects"),
|
|
1282
|
-
claude: path9__default.default.join(HOME, ".claude", "projects")
|
|
1283
|
-
};
|
|
1284
|
-
function getWorkspaceStoragePath(ide) {
|
|
1285
|
-
const platform = os2__default.default.platform();
|
|
1286
|
-
const appName = "Cursor" ;
|
|
1287
|
-
if (platform === "darwin") {
|
|
1288
|
-
return path9__default.default.join(HOME, "Library", "Application Support", appName, "User", "workspaceStorage");
|
|
1289
|
-
} else if (platform === "win32") {
|
|
1290
|
-
return path9__default.default.join(process.env.APPDATA || "", appName, "User", "workspaceStorage");
|
|
1291
|
-
} else {
|
|
1292
|
-
return path9__default.default.join(HOME, ".config", appName, "User", "workspaceStorage");
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
function scanWorkspaceStorage(ide) {
|
|
1296
|
-
const projects = [];
|
|
1297
|
-
const storagePath = getWorkspaceStoragePath();
|
|
1298
|
-
if (!fs3__default.default.existsSync(storagePath)) {
|
|
1299
|
-
return projects;
|
|
1300
|
-
}
|
|
1301
|
-
try {
|
|
1302
|
-
const workspaces = fs3__default.default.readdirSync(storagePath);
|
|
1303
|
-
for (const workspace of workspaces) {
|
|
1304
|
-
const workspaceJsonPath = path9__default.default.join(storagePath, workspace, "workspace.json");
|
|
1305
|
-
if (fs3__default.default.existsSync(workspaceJsonPath)) {
|
|
1306
|
-
try {
|
|
1307
|
-
const content = fs3__default.default.readFileSync(workspaceJsonPath, "utf-8");
|
|
1308
|
-
const data = JSON.parse(content);
|
|
1309
|
-
if (data.folder && typeof data.folder === "string") {
|
|
1310
|
-
let projectPath = data.folder;
|
|
1311
|
-
if (projectPath.startsWith("file://")) {
|
|
1312
|
-
projectPath = projectPath.replace("file://", "");
|
|
1313
|
-
projectPath = decodeURIComponent(projectPath);
|
|
1314
|
-
}
|
|
1315
|
-
if (fs3__default.default.existsSync(projectPath) && fs3__default.default.statSync(projectPath).isDirectory()) {
|
|
1316
|
-
projects.push({
|
|
1317
|
-
name: path9__default.default.basename(projectPath),
|
|
1318
|
-
path: projectPath,
|
|
1319
|
-
type: ide
|
|
1320
|
-
});
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
} catch (err) {
|
|
1324
|
-
console.debug(`Error reading workspace.json at ${workspaceJsonPath}: ${err}`);
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
}
|
|
1328
|
-
} catch (err) {
|
|
1329
|
-
console.debug(`Error scanning workspaceStorage for ${ide}: ${err}`);
|
|
1330
|
-
}
|
|
1331
|
-
return projects;
|
|
1332
|
-
}
|
|
1333
|
-
var scanIdeProjects = async () => {
|
|
1334
|
-
try {
|
|
1335
|
-
const allProjects = [];
|
|
1336
|
-
const seenPaths = /* @__PURE__ */ new Set();
|
|
1337
|
-
const addProject = (projectPath, ide) => {
|
|
1338
|
-
try {
|
|
1339
|
-
const resolvedPath = fs3__default.default.realpathSync(projectPath);
|
|
1340
|
-
if (fs3__default.default.existsSync(resolvedPath) && fs3__default.default.statSync(resolvedPath).isDirectory() && !seenPaths.has(resolvedPath)) {
|
|
1341
|
-
const isIdeProjectsDir = Object.values(IDE_PROJECTS_PATHS).some((ideDir) => {
|
|
1342
|
-
try {
|
|
1343
|
-
return fs3__default.default.realpathSync(ideDir) === resolvedPath;
|
|
1344
|
-
} catch {
|
|
1345
|
-
return false;
|
|
1346
|
-
}
|
|
1347
|
-
});
|
|
1348
|
-
if (!isIdeProjectsDir) {
|
|
1349
|
-
seenPaths.add(resolvedPath);
|
|
1350
|
-
allProjects.push({
|
|
1351
|
-
name: path9__default.default.basename(resolvedPath),
|
|
1352
|
-
path: resolvedPath,
|
|
1353
|
-
type: ide
|
|
1354
|
-
});
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
} catch {
|
|
1358
|
-
}
|
|
1359
|
-
};
|
|
1360
|
-
const cursorProjects = scanWorkspaceStorage("cursor");
|
|
1361
|
-
for (const project of cursorProjects) {
|
|
1362
|
-
addProject(project.path, "cursor");
|
|
1363
|
-
}
|
|
1364
|
-
for (const [ide, dirPath] of Object.entries(IDE_PROJECTS_PATHS)) {
|
|
1365
|
-
if (ide === "cursor") continue;
|
|
1366
|
-
if (fs3__default.default.existsSync(dirPath)) {
|
|
1367
|
-
const projects = fs3__default.default.readdirSync(dirPath);
|
|
1368
|
-
projects.forEach((project) => {
|
|
1369
|
-
const projectPath = path9__default.default.join(dirPath, project);
|
|
1370
|
-
try {
|
|
1371
|
-
const stats = fs3__default.default.lstatSync(projectPath);
|
|
1372
|
-
let actualPath = null;
|
|
1373
|
-
if (stats.isSymbolicLink()) {
|
|
1374
|
-
actualPath = fs3__default.default.realpathSync(projectPath);
|
|
1375
|
-
} else if (stats.isFile()) {
|
|
1376
|
-
try {
|
|
1377
|
-
let content = fs3__default.default.readFileSync(projectPath, "utf-8").trim();
|
|
1378
|
-
if (content.startsWith("~/") || content === "~") {
|
|
1379
|
-
content = content.replace(/^~/, HOME);
|
|
1380
|
-
}
|
|
1381
|
-
const resolvedContent = path9__default.default.isAbsolute(content) ? content : path9__default.default.resolve(path9__default.default.dirname(projectPath), content);
|
|
1382
|
-
if (fs3__default.default.existsSync(resolvedContent) && fs3__default.default.statSync(resolvedContent).isDirectory()) {
|
|
1383
|
-
actualPath = fs3__default.default.realpathSync(resolvedContent);
|
|
1384
|
-
}
|
|
1385
|
-
} catch {
|
|
1386
|
-
return;
|
|
1387
|
-
}
|
|
1388
|
-
} else if (stats.isDirectory()) {
|
|
1389
|
-
actualPath = fs3__default.default.realpathSync(projectPath);
|
|
1390
|
-
}
|
|
1391
|
-
if (actualPath) {
|
|
1392
|
-
addProject(actualPath, ide);
|
|
1393
|
-
}
|
|
1394
|
-
} catch {
|
|
1395
|
-
}
|
|
1396
|
-
});
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
return allProjects;
|
|
1400
|
-
} catch (error) {
|
|
1401
|
-
console.debug(`Error scanning IDE projects: ${error}`);
|
|
1402
|
-
return [];
|
|
1403
|
-
}
|
|
1404
|
-
};
|
|
1405
|
-
var wsConnection = null;
|
|
1406
|
-
var startHttpServer = (connection) => {
|
|
1407
|
-
if (connection) {
|
|
1408
|
-
wsConnection = connection;
|
|
1409
|
-
}
|
|
1263
|
+
var startHttpServer = () => {
|
|
1410
1264
|
const app = new hono.Hono();
|
|
1411
1265
|
app.use(cors.cors());
|
|
1412
|
-
app.post("/daemon/status", (c) => {
|
|
1413
|
-
const status = wsConnection ? getConnectionStatus(wsConnection) : "closed";
|
|
1414
|
-
return c.json({ connected: status === "open" });
|
|
1415
|
-
});
|
|
1416
|
-
app.get("/daemon/status/stream", (c) => {
|
|
1417
|
-
const encoder = new TextEncoder();
|
|
1418
|
-
const stream = new ReadableStream({
|
|
1419
|
-
start(controller) {
|
|
1420
|
-
const initialStatus = wsConnection ? getConnectionStatus(wsConnection) : "closed";
|
|
1421
|
-
controller.enqueue(encoder.encode(`data: ${JSON.stringify({ connected: initialStatus === "open" })}
|
|
1422
|
-
|
|
1423
|
-
`));
|
|
1424
|
-
const statusHandler = (data) => {
|
|
1425
|
-
try {
|
|
1426
|
-
controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}
|
|
1427
|
-
|
|
1428
|
-
`));
|
|
1429
|
-
} catch {
|
|
1430
|
-
}
|
|
1431
|
-
};
|
|
1432
|
-
statusEmitter.on("status", statusHandler);
|
|
1433
|
-
const heartbeatInterval = setInterval(() => {
|
|
1434
|
-
try {
|
|
1435
|
-
const currentStatus = wsConnection ? getConnectionStatus(wsConnection) : "closed";
|
|
1436
|
-
controller.enqueue(encoder.encode(`data: ${JSON.stringify({ connected: currentStatus === "open" })}
|
|
1437
|
-
|
|
1438
|
-
`));
|
|
1439
|
-
} catch {
|
|
1440
|
-
}
|
|
1441
|
-
}, 15e3);
|
|
1442
|
-
c.req.raw.signal.addEventListener("abort", () => {
|
|
1443
|
-
statusEmitter.off("status", statusHandler);
|
|
1444
|
-
clearInterval(heartbeatInterval);
|
|
1445
|
-
});
|
|
1446
|
-
}
|
|
1447
|
-
});
|
|
1448
|
-
return new Response(stream, {
|
|
1449
|
-
headers: {
|
|
1450
|
-
"Content-Type": "text/event-stream",
|
|
1451
|
-
"Cache-Control": "no-cache",
|
|
1452
|
-
"Connection": "keep-alive"
|
|
1453
|
-
}
|
|
1454
|
-
});
|
|
1455
|
-
});
|
|
1456
|
-
app.get("context", async (c) => {
|
|
1457
|
-
const context = getContext(process.cwd());
|
|
1458
|
-
return c.body(JSON.stringify(context));
|
|
1459
|
-
});
|
|
1460
|
-
app.get("/ide-projects", async (c) => {
|
|
1461
|
-
try {
|
|
1462
|
-
const projects = await scanIdeProjects();
|
|
1463
|
-
if (!projects) {
|
|
1464
|
-
return c.json({ error: "No projects found" }, 500);
|
|
1465
|
-
}
|
|
1466
|
-
return c.json({ projects });
|
|
1467
|
-
} catch (error) {
|
|
1468
|
-
return c.json({ error: "Failed to scan IDE projects" }, 500);
|
|
1469
|
-
}
|
|
1470
|
-
});
|
|
1471
1266
|
app.post("/projects/register", async (c) => {
|
|
1472
1267
|
try {
|
|
1473
1268
|
const { projectId, cwd, name } = await c.req.json();
|
|
@@ -1496,14 +1291,14 @@ var startHttpServer = (connection) => {
|
|
|
1496
1291
|
}
|
|
1497
1292
|
let resolved;
|
|
1498
1293
|
if (projectCwd) {
|
|
1499
|
-
resolved =
|
|
1500
|
-
const normalizedResolved =
|
|
1501
|
-
const normalizedCwd =
|
|
1294
|
+
resolved = path11__default.default.isAbsolute(filePath) ? filePath : path11__default.default.resolve(projectCwd, filePath);
|
|
1295
|
+
const normalizedResolved = path11__default.default.normalize(resolved);
|
|
1296
|
+
const normalizedCwd = path11__default.default.normalize(projectCwd);
|
|
1502
1297
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
1503
1298
|
return c.json({ error: "Path is outside project directory" }, 403);
|
|
1504
1299
|
}
|
|
1505
1300
|
} else {
|
|
1506
|
-
resolved =
|
|
1301
|
+
resolved = path11__default.default.isAbsolute(filePath) ? filePath : path11__default.default.join(process.cwd(), filePath);
|
|
1507
1302
|
}
|
|
1508
1303
|
let currentContent;
|
|
1509
1304
|
try {
|
|
@@ -1590,9 +1385,9 @@ var startHttpServer = (connection) => {
|
|
|
1590
1385
|
}
|
|
1591
1386
|
let resolved;
|
|
1592
1387
|
if (projectCwd) {
|
|
1593
|
-
resolved =
|
|
1594
|
-
const normalizedResolved =
|
|
1595
|
-
const normalizedCwd =
|
|
1388
|
+
resolved = path11__default.default.isAbsolute(filePath || checkpoint.filePath) ? filePath || checkpoint.filePath : path11__default.default.resolve(projectCwd, filePath || checkpoint.filePath);
|
|
1389
|
+
const normalizedResolved = path11__default.default.normalize(resolved);
|
|
1390
|
+
const normalizedCwd = path11__default.default.normalize(projectCwd);
|
|
1596
1391
|
if (!normalizedResolved.startsWith(normalizedCwd)) {
|
|
1597
1392
|
return c.json({ error: "Path is outside project directory" }, 403);
|
|
1598
1393
|
}
|
|
@@ -1654,16 +1449,30 @@ var startHttpServer = (connection) => {
|
|
|
1654
1449
|
});
|
|
1655
1450
|
nodeServer.serve({ fetch: app.fetch, port: 3456 });
|
|
1656
1451
|
};
|
|
1657
|
-
var CREDENTIALS_DIR =
|
|
1658
|
-
var CREDENTIALS_PATH =
|
|
1452
|
+
var CREDENTIALS_DIR = path11__default.default.join(os3__default.default.homedir(), ".amai");
|
|
1453
|
+
var CREDENTIALS_PATH = path11__default.default.join(CREDENTIALS_DIR, "credentials.json");
|
|
1659
1454
|
function getTokens() {
|
|
1660
|
-
if (!
|
|
1455
|
+
if (!fs4__default.default.existsSync(CREDENTIALS_PATH)) {
|
|
1661
1456
|
return null;
|
|
1662
1457
|
}
|
|
1663
|
-
const raw =
|
|
1458
|
+
const raw = fs4__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
|
|
1664
1459
|
const data = JSON.parse(raw);
|
|
1665
1460
|
return data;
|
|
1666
1461
|
}
|
|
1462
|
+
var getUserId = () => {
|
|
1463
|
+
try {
|
|
1464
|
+
if (!fs4__default.default.existsSync(CREDENTIALS_PATH)) {
|
|
1465
|
+
return;
|
|
1466
|
+
}
|
|
1467
|
+
const raw = fs4__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
|
|
1468
|
+
const data = JSON.parse(raw);
|
|
1469
|
+
return {
|
|
1470
|
+
userId: data.user.id
|
|
1471
|
+
};
|
|
1472
|
+
} catch {
|
|
1473
|
+
throw new Error("Error while getting userId");
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1667
1476
|
var ExplanationSchema = zod.z.object({
|
|
1668
1477
|
explanation: zod.z.string().describe("One sentence explanation as to why this tool is being used")
|
|
1669
1478
|
});
|
|
@@ -1751,9 +1560,343 @@ var runTerminalCommand = async (input, projectCwd) => {
|
|
|
1751
1560
|
};
|
|
1752
1561
|
}
|
|
1753
1562
|
};
|
|
1563
|
+
var ignoreFiles = ["node_modules", ".git", ".next", ".env", ".env.local", ".env.development.local", ".env.test.local", ".env.production.local"];
|
|
1564
|
+
var getContext = (dir, base = dir, allFiles = []) => {
|
|
1565
|
+
const filePath = fs4.readdirSync(dir, { withFileTypes: true });
|
|
1566
|
+
for (const file of filePath) {
|
|
1567
|
+
if (ignoreFiles.includes(file.name)) continue;
|
|
1568
|
+
const fullPath = path11__default.default.join(dir, file.name);
|
|
1569
|
+
if (file.isDirectory()) {
|
|
1570
|
+
getContext(fullPath, base, allFiles);
|
|
1571
|
+
} else {
|
|
1572
|
+
allFiles.push(path11__default.default.relative(base, fullPath));
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
return allFiles;
|
|
1576
|
+
};
|
|
1577
|
+
var HOME = os3__default.default.homedir();
|
|
1578
|
+
var IDE_PROJECTS_PATHS = {
|
|
1579
|
+
vscode: path11__default.default.join(HOME, ".vscode", "projects"),
|
|
1580
|
+
cursor: path11__default.default.join(HOME, ".cursor", "projects"),
|
|
1581
|
+
claude: path11__default.default.join(HOME, ".claude", "projects")
|
|
1582
|
+
};
|
|
1583
|
+
function getWorkspaceStoragePath(ide) {
|
|
1584
|
+
const platform = os3__default.default.platform();
|
|
1585
|
+
const appName = "Cursor" ;
|
|
1586
|
+
if (platform === "darwin") {
|
|
1587
|
+
return path11__default.default.join(HOME, "Library", "Application Support", appName, "User", "workspaceStorage");
|
|
1588
|
+
} else if (platform === "win32") {
|
|
1589
|
+
return path11__default.default.join(process.env.APPDATA || "", appName, "User", "workspaceStorage");
|
|
1590
|
+
} else {
|
|
1591
|
+
return path11__default.default.join(HOME, ".config", appName, "User", "workspaceStorage");
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
function scanWorkspaceStorage(ide) {
|
|
1595
|
+
const projects = [];
|
|
1596
|
+
const storagePath = getWorkspaceStoragePath();
|
|
1597
|
+
if (!fs4__default.default.existsSync(storagePath)) {
|
|
1598
|
+
return projects;
|
|
1599
|
+
}
|
|
1600
|
+
try {
|
|
1601
|
+
const workspaces = fs4__default.default.readdirSync(storagePath);
|
|
1602
|
+
for (const workspace of workspaces) {
|
|
1603
|
+
const workspaceJsonPath = path11__default.default.join(storagePath, workspace, "workspace.json");
|
|
1604
|
+
if (fs4__default.default.existsSync(workspaceJsonPath)) {
|
|
1605
|
+
try {
|
|
1606
|
+
const content = fs4__default.default.readFileSync(workspaceJsonPath, "utf-8");
|
|
1607
|
+
const data = JSON.parse(content);
|
|
1608
|
+
if (data.folder && typeof data.folder === "string") {
|
|
1609
|
+
let projectPath = data.folder;
|
|
1610
|
+
if (projectPath.startsWith("file://")) {
|
|
1611
|
+
projectPath = projectPath.replace("file://", "");
|
|
1612
|
+
projectPath = decodeURIComponent(projectPath);
|
|
1613
|
+
}
|
|
1614
|
+
if (fs4__default.default.existsSync(projectPath) && fs4__default.default.statSync(projectPath).isDirectory()) {
|
|
1615
|
+
projects.push({
|
|
1616
|
+
name: path11__default.default.basename(projectPath),
|
|
1617
|
+
path: projectPath,
|
|
1618
|
+
type: ide
|
|
1619
|
+
});
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
} catch (err) {
|
|
1623
|
+
console.debug(`Error reading workspace.json at ${workspaceJsonPath}: ${err}`);
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
} catch (err) {
|
|
1628
|
+
console.debug(`Error scanning workspaceStorage for ${ide}: ${err}`);
|
|
1629
|
+
}
|
|
1630
|
+
return projects;
|
|
1631
|
+
}
|
|
1632
|
+
var scanIdeProjects = async () => {
|
|
1633
|
+
try {
|
|
1634
|
+
const allProjects = [];
|
|
1635
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
1636
|
+
const addProject = (projectPath, ide) => {
|
|
1637
|
+
try {
|
|
1638
|
+
const resolvedPath = fs4__default.default.realpathSync(projectPath);
|
|
1639
|
+
if (fs4__default.default.existsSync(resolvedPath) && fs4__default.default.statSync(resolvedPath).isDirectory() && !seenPaths.has(resolvedPath)) {
|
|
1640
|
+
const isIdeProjectsDir = Object.values(IDE_PROJECTS_PATHS).some((ideDir) => {
|
|
1641
|
+
try {
|
|
1642
|
+
return fs4__default.default.realpathSync(ideDir) === resolvedPath;
|
|
1643
|
+
} catch {
|
|
1644
|
+
return false;
|
|
1645
|
+
}
|
|
1646
|
+
});
|
|
1647
|
+
if (!isIdeProjectsDir) {
|
|
1648
|
+
seenPaths.add(resolvedPath);
|
|
1649
|
+
allProjects.push({
|
|
1650
|
+
name: path11__default.default.basename(resolvedPath),
|
|
1651
|
+
path: resolvedPath,
|
|
1652
|
+
type: ide
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
} catch {
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
const cursorProjects = scanWorkspaceStorage("cursor");
|
|
1660
|
+
for (const project of cursorProjects) {
|
|
1661
|
+
addProject(project.path, "cursor");
|
|
1662
|
+
}
|
|
1663
|
+
for (const [ide, dirPath] of Object.entries(IDE_PROJECTS_PATHS)) {
|
|
1664
|
+
if (ide === "cursor") continue;
|
|
1665
|
+
if (fs4__default.default.existsSync(dirPath)) {
|
|
1666
|
+
const projects = fs4__default.default.readdirSync(dirPath);
|
|
1667
|
+
projects.forEach((project) => {
|
|
1668
|
+
const projectPath = path11__default.default.join(dirPath, project);
|
|
1669
|
+
try {
|
|
1670
|
+
const stats = fs4__default.default.lstatSync(projectPath);
|
|
1671
|
+
let actualPath = null;
|
|
1672
|
+
if (stats.isSymbolicLink()) {
|
|
1673
|
+
actualPath = fs4__default.default.realpathSync(projectPath);
|
|
1674
|
+
} else if (stats.isFile()) {
|
|
1675
|
+
try {
|
|
1676
|
+
let content = fs4__default.default.readFileSync(projectPath, "utf-8").trim();
|
|
1677
|
+
if (content.startsWith("~/") || content === "~") {
|
|
1678
|
+
content = content.replace(/^~/, HOME);
|
|
1679
|
+
}
|
|
1680
|
+
const resolvedContent = path11__default.default.isAbsolute(content) ? content : path11__default.default.resolve(path11__default.default.dirname(projectPath), content);
|
|
1681
|
+
if (fs4__default.default.existsSync(resolvedContent) && fs4__default.default.statSync(resolvedContent).isDirectory()) {
|
|
1682
|
+
actualPath = fs4__default.default.realpathSync(resolvedContent);
|
|
1683
|
+
}
|
|
1684
|
+
} catch {
|
|
1685
|
+
return;
|
|
1686
|
+
}
|
|
1687
|
+
} else if (stats.isDirectory()) {
|
|
1688
|
+
actualPath = fs4__default.default.realpathSync(projectPath);
|
|
1689
|
+
}
|
|
1690
|
+
if (actualPath) {
|
|
1691
|
+
addProject(actualPath, ide);
|
|
1692
|
+
}
|
|
1693
|
+
} catch {
|
|
1694
|
+
}
|
|
1695
|
+
});
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
return allProjects;
|
|
1699
|
+
} catch (error) {
|
|
1700
|
+
console.debug(`Error scanning IDE projects: ${error}`);
|
|
1701
|
+
return [];
|
|
1702
|
+
}
|
|
1703
|
+
};
|
|
1704
|
+
|
|
1705
|
+
// src/lib/rpc-handlers.ts
|
|
1706
|
+
var rpcHandlers = {
|
|
1707
|
+
"daemon:get_workspace_folders": async () => {
|
|
1708
|
+
const projects = projectRegistry.list();
|
|
1709
|
+
return {
|
|
1710
|
+
folders: projects.map((p) => ({
|
|
1711
|
+
id: p.id,
|
|
1712
|
+
cwd: p.cwd,
|
|
1713
|
+
name: p.name,
|
|
1714
|
+
active: p.active
|
|
1715
|
+
}))
|
|
1716
|
+
};
|
|
1717
|
+
},
|
|
1718
|
+
"daemon:get_environment": async ({ gitRepositoryUrl }) => {
|
|
1719
|
+
const projects = projectRegistry.list();
|
|
1720
|
+
if (projects.length === 0) {
|
|
1721
|
+
const error = {
|
|
1722
|
+
_tag: "ProjectUnlinkedError",
|
|
1723
|
+
message: `Getting a local project by git repository URL "${gitRepositoryUrl}" returned an unlinked project. Please link it by running \`amai link <project name> <path to project directory>\``
|
|
1724
|
+
};
|
|
1725
|
+
throw error;
|
|
1726
|
+
}
|
|
1727
|
+
return {
|
|
1728
|
+
project: projects[0],
|
|
1729
|
+
env: {
|
|
1730
|
+
platform: process.platform,
|
|
1731
|
+
arch: process.arch,
|
|
1732
|
+
nodeVersion: process.version
|
|
1733
|
+
}
|
|
1734
|
+
};
|
|
1735
|
+
},
|
|
1736
|
+
"daemon:get_context": async ({ cwd }) => {
|
|
1737
|
+
try {
|
|
1738
|
+
const files = getContext(cwd);
|
|
1739
|
+
return { files, cwd };
|
|
1740
|
+
} catch (error) {
|
|
1741
|
+
const rpcError = {
|
|
1742
|
+
_tag: "ContextError",
|
|
1743
|
+
message: error.message || "Failed to get context"
|
|
1744
|
+
};
|
|
1745
|
+
throw rpcError;
|
|
1746
|
+
}
|
|
1747
|
+
},
|
|
1748
|
+
"daemon:get_ide_projects": async () => {
|
|
1749
|
+
const projects = await scanIdeProjects();
|
|
1750
|
+
return { projects };
|
|
1751
|
+
},
|
|
1752
|
+
"daemon:register_project": async ({ projectId, cwd, name }) => {
|
|
1753
|
+
if (!projectId || !cwd) {
|
|
1754
|
+
const error = {
|
|
1755
|
+
_tag: "ValidationError",
|
|
1756
|
+
message: "projectId and cwd are required"
|
|
1757
|
+
};
|
|
1758
|
+
throw error;
|
|
1759
|
+
}
|
|
1760
|
+
projectRegistry.register(projectId, cwd, name);
|
|
1761
|
+
return { success: true, projectId, cwd };
|
|
1762
|
+
},
|
|
1763
|
+
"daemon:unregister_project": async ({ projectId }) => {
|
|
1764
|
+
if (!projectId) {
|
|
1765
|
+
const error = {
|
|
1766
|
+
_tag: "ValidationError",
|
|
1767
|
+
message: "projectId is required"
|
|
1768
|
+
};
|
|
1769
|
+
throw error;
|
|
1770
|
+
}
|
|
1771
|
+
projectRegistry.unregister(projectId);
|
|
1772
|
+
return { success: true, projectId };
|
|
1773
|
+
},
|
|
1774
|
+
"daemon:get_project": async ({ projectId }) => {
|
|
1775
|
+
const project = projectRegistry.getProject(projectId);
|
|
1776
|
+
if (!project) {
|
|
1777
|
+
const error = {
|
|
1778
|
+
_tag: "ProjectNotFoundError",
|
|
1779
|
+
message: `Project not found: ${projectId}`
|
|
1780
|
+
};
|
|
1781
|
+
throw error;
|
|
1782
|
+
}
|
|
1783
|
+
return { project };
|
|
1784
|
+
},
|
|
1785
|
+
"daemon:list_projects": async () => {
|
|
1786
|
+
const projects = projectRegistry.list();
|
|
1787
|
+
return { projects };
|
|
1788
|
+
},
|
|
1789
|
+
"daemon:status": async () => {
|
|
1790
|
+
return {
|
|
1791
|
+
connected: true,
|
|
1792
|
+
timestamp: Date.now(),
|
|
1793
|
+
platform: process.platform,
|
|
1794
|
+
arch: process.arch
|
|
1795
|
+
};
|
|
1796
|
+
}
|
|
1797
|
+
};
|
|
1798
|
+
var reconnectTimeout = null;
|
|
1799
|
+
var connectToUserStreams = async (serverUrl) => {
|
|
1800
|
+
const userId = getUserId();
|
|
1801
|
+
if (!userId?.userId) {
|
|
1802
|
+
throw new Error("User ID not found");
|
|
1803
|
+
}
|
|
1804
|
+
const params = new URLSearchParams({
|
|
1805
|
+
userId: userId.userId,
|
|
1806
|
+
type: "cli"
|
|
1807
|
+
});
|
|
1808
|
+
const tokens = getTokens();
|
|
1809
|
+
if (!tokens) {
|
|
1810
|
+
throw new Error("No tokens found");
|
|
1811
|
+
}
|
|
1812
|
+
const wsUrl = `${serverUrl}/api/v1/user-streams?${params.toString()}`;
|
|
1813
|
+
const ws = new WebSocket__default.default(wsUrl, {
|
|
1814
|
+
headers: {
|
|
1815
|
+
Authorization: `Bearer ${tokens.access_token}`
|
|
1816
|
+
}
|
|
1817
|
+
});
|
|
1818
|
+
ws.on("open", () => {
|
|
1819
|
+
console.log(pc2__default.default.green("CLI connected to user-streams"));
|
|
1820
|
+
if (reconnectTimeout) {
|
|
1821
|
+
clearTimeout(reconnectTimeout);
|
|
1822
|
+
reconnectTimeout = null;
|
|
1823
|
+
}
|
|
1824
|
+
});
|
|
1825
|
+
ws.on("message", async (event) => {
|
|
1826
|
+
try {
|
|
1827
|
+
const message = JSON.parse(event.toString());
|
|
1828
|
+
if (message._tag === "rpc_call") {
|
|
1829
|
+
const { requestId, method, input } = message;
|
|
1830
|
+
console.log(pc2__default.default.gray(`RPC call: ${method}`));
|
|
1831
|
+
const handler = rpcHandlers[method];
|
|
1832
|
+
if (!handler) {
|
|
1833
|
+
ws.send(JSON.stringify({
|
|
1834
|
+
_tag: "rpc_result",
|
|
1835
|
+
requestId,
|
|
1836
|
+
data: {
|
|
1837
|
+
_tag: "UnknownMethodError",
|
|
1838
|
+
message: `Unknown RPC method: ${method}`
|
|
1839
|
+
}
|
|
1840
|
+
}));
|
|
1841
|
+
console.log(pc2__default.default.yellow(`Unknown RPC method: ${method}`));
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1844
|
+
try {
|
|
1845
|
+
const result = await handler(input || {});
|
|
1846
|
+
ws.send(JSON.stringify({
|
|
1847
|
+
_tag: "rpc_result",
|
|
1848
|
+
requestId,
|
|
1849
|
+
data: result
|
|
1850
|
+
}));
|
|
1851
|
+
console.log(pc2__default.default.green(`RPC completed: ${method}`));
|
|
1852
|
+
} catch (error) {
|
|
1853
|
+
const rpcError = error._tag ? error : {
|
|
1854
|
+
_tag: "RpcError",
|
|
1855
|
+
message: error.message || String(error)
|
|
1856
|
+
};
|
|
1857
|
+
ws.send(JSON.stringify({
|
|
1858
|
+
_tag: "rpc_result",
|
|
1859
|
+
requestId,
|
|
1860
|
+
data: rpcError
|
|
1861
|
+
}));
|
|
1862
|
+
console.log(pc2__default.default.red(`RPC failed: ${method} - ${rpcError.message}`));
|
|
1863
|
+
}
|
|
1864
|
+
return;
|
|
1865
|
+
}
|
|
1866
|
+
if (message.type === "presence_request") {
|
|
1867
|
+
if (message.status === "connected") {
|
|
1868
|
+
ws.send(JSON.stringify({
|
|
1869
|
+
type: "presence_request",
|
|
1870
|
+
status: "connected"
|
|
1871
|
+
}));
|
|
1872
|
+
}
|
|
1873
|
+
if (message.status === "disconnected") {
|
|
1874
|
+
ws.send(JSON.stringify({
|
|
1875
|
+
type: "presence_request",
|
|
1876
|
+
status: "disconnected"
|
|
1877
|
+
}));
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
} catch (parseError) {
|
|
1881
|
+
console.error(pc2__default.default.red(`Failed to parse message: ${parseError}`));
|
|
1882
|
+
}
|
|
1883
|
+
});
|
|
1884
|
+
ws.on("close", (code, reason) => {
|
|
1885
|
+
console.log(pc2__default.default.yellow(`CLI disconnected from user-streams (code: ${code})`));
|
|
1886
|
+
console.log(pc2__default.default.gray("Reconnecting in 5 seconds..."));
|
|
1887
|
+
reconnectTimeout = setTimeout(() => {
|
|
1888
|
+
connectToUserStreams(serverUrl).catch((err) => {
|
|
1889
|
+
console.error(pc2__default.default.red(`Reconnection failed: ${err.message}`));
|
|
1890
|
+
});
|
|
1891
|
+
}, 5e3);
|
|
1892
|
+
});
|
|
1893
|
+
ws.on("error", (error) => {
|
|
1894
|
+
console.error(pc2__default.default.red(`User streams WebSocket error: ${error.message}`));
|
|
1895
|
+
});
|
|
1896
|
+
return ws;
|
|
1897
|
+
};
|
|
1754
1898
|
|
|
1755
1899
|
// src/server.ts
|
|
1756
|
-
var statusEmitter = new events.EventEmitter();
|
|
1757
1900
|
var toolExecutors = {
|
|
1758
1901
|
editFile: editFiles,
|
|
1759
1902
|
deleteFile,
|
|
@@ -1764,10 +1907,7 @@ var toolExecutors = {
|
|
|
1764
1907
|
stringReplace: apply_patch,
|
|
1765
1908
|
runTerminalCommand
|
|
1766
1909
|
};
|
|
1767
|
-
function
|
|
1768
|
-
return ws.readyState === WebSocket__default.default.CONNECTING ? "connecting" : ws.readyState === WebSocket__default.default.OPEN ? "open" : ws.readyState === WebSocket__default.default.CLOSING ? "closing" : "closed";
|
|
1769
|
-
}
|
|
1770
|
-
function connectToServer2(serverUrl = DEFAULT_SERVER_URL) {
|
|
1910
|
+
function connectToServer(serverUrl = DEFAULT_SERVER_URL) {
|
|
1771
1911
|
const tokens = getTokens();
|
|
1772
1912
|
if (!tokens) {
|
|
1773
1913
|
throw new Error("No tokens found");
|
|
@@ -1780,7 +1920,6 @@ function connectToServer2(serverUrl = DEFAULT_SERVER_URL) {
|
|
|
1780
1920
|
});
|
|
1781
1921
|
ws.on("open", () => {
|
|
1782
1922
|
console.log(pc2__default.default.green("Connected to server agent streams"));
|
|
1783
|
-
statusEmitter.emit("status", { connected: true });
|
|
1784
1923
|
});
|
|
1785
1924
|
ws.on("message", async (data) => {
|
|
1786
1925
|
const message = JSON.parse(data.toString());
|
|
@@ -1810,12 +1949,10 @@ function connectToServer2(serverUrl = DEFAULT_SERVER_URL) {
|
|
|
1810
1949
|
});
|
|
1811
1950
|
ws.on("close", () => {
|
|
1812
1951
|
console.log(pc2__default.default.red("Disconnected from server. Reconnecting in 5s..."));
|
|
1813
|
-
|
|
1814
|
-
setTimeout(() => connectToServer2(serverUrl), 5e3);
|
|
1952
|
+
setTimeout(() => connectToServer(serverUrl), 5e3);
|
|
1815
1953
|
});
|
|
1816
1954
|
ws.on("error", (error) => {
|
|
1817
1955
|
console.error(pc2__default.default.red(`WebSocket error: ${error.message}`));
|
|
1818
|
-
statusEmitter.emit("status", { connected: false });
|
|
1819
1956
|
});
|
|
1820
1957
|
return ws;
|
|
1821
1958
|
}
|
|
@@ -1823,8 +1960,9 @@ async function main() {
|
|
|
1823
1960
|
const serverUrl = DEFAULT_SERVER_URL;
|
|
1824
1961
|
console.log(pc2__default.default.green("Starting local amai..."));
|
|
1825
1962
|
console.log(pc2__default.default.gray(`Connecting to server at ${serverUrl}`));
|
|
1826
|
-
|
|
1827
|
-
|
|
1963
|
+
connectToServer(serverUrl);
|
|
1964
|
+
await connectToUserStreams(serverUrl);
|
|
1965
|
+
startHttpServer();
|
|
1828
1966
|
}
|
|
1829
1967
|
var execAsync2 = util.promisify(child_process.exec);
|
|
1830
1968
|
var CODE_SERVER_VERSION = "4.96.4";
|
|
@@ -1853,27 +1991,27 @@ function getDownloadUrl() {
|
|
|
1853
1991
|
}
|
|
1854
1992
|
function getCodeServerDir() {
|
|
1855
1993
|
const { platform, arch } = getPlatformInfo();
|
|
1856
|
-
return
|
|
1994
|
+
return path11__default.default.join(CODE_DIR, `code-server-${CODE_SERVER_VERSION}-${platform}-${arch}`);
|
|
1857
1995
|
}
|
|
1858
1996
|
function getCodeServerBin() {
|
|
1859
|
-
return
|
|
1997
|
+
return path11__default.default.join(getCodeServerDir(), "bin", "code-server");
|
|
1860
1998
|
}
|
|
1861
1999
|
function isCodeServerInstalled() {
|
|
1862
2000
|
const binPath = getCodeServerBin();
|
|
1863
|
-
return
|
|
2001
|
+
return fs4__default.default.existsSync(binPath);
|
|
1864
2002
|
}
|
|
1865
2003
|
async function installCodeServer() {
|
|
1866
2004
|
const { ext } = getPlatformInfo();
|
|
1867
2005
|
const downloadUrl = getDownloadUrl();
|
|
1868
|
-
const tarballPath =
|
|
1869
|
-
if (!
|
|
1870
|
-
|
|
2006
|
+
const tarballPath = path11__default.default.join(AMA_DIR, `code-server.${ext}`);
|
|
2007
|
+
if (!fs4__default.default.existsSync(AMA_DIR)) {
|
|
2008
|
+
fs4__default.default.mkdirSync(AMA_DIR, { recursive: true });
|
|
1871
2009
|
}
|
|
1872
|
-
if (!
|
|
1873
|
-
|
|
2010
|
+
if (!fs4__default.default.existsSync(CODE_DIR)) {
|
|
2011
|
+
fs4__default.default.mkdirSync(CODE_DIR, { recursive: true });
|
|
1874
2012
|
}
|
|
1875
|
-
if (!
|
|
1876
|
-
|
|
2013
|
+
if (!fs4__default.default.existsSync(STORAGE_DIR)) {
|
|
2014
|
+
fs4__default.default.mkdirSync(STORAGE_DIR, { recursive: true });
|
|
1877
2015
|
}
|
|
1878
2016
|
console.log(pc2__default.default.cyan(`Downloading code-server v${CODE_SERVER_VERSION}...`));
|
|
1879
2017
|
console.log(pc2__default.default.gray(downloadUrl));
|
|
@@ -1882,13 +2020,13 @@ async function installCodeServer() {
|
|
|
1882
2020
|
throw new Error(`Failed to download code-server: ${response.statusText}`);
|
|
1883
2021
|
}
|
|
1884
2022
|
const buffer = await response.arrayBuffer();
|
|
1885
|
-
await
|
|
2023
|
+
await fs4__default.default.promises.writeFile(tarballPath, Buffer.from(buffer));
|
|
1886
2024
|
console.log(pc2__default.default.cyan("Extracting code-server..."));
|
|
1887
2025
|
await execAsync2(`tar -xzf ${tarballPath} -C ${CODE_DIR}`);
|
|
1888
|
-
await
|
|
2026
|
+
await fs4__default.default.promises.unlink(tarballPath);
|
|
1889
2027
|
const binPath = getCodeServerBin();
|
|
1890
|
-
if (
|
|
1891
|
-
await
|
|
2028
|
+
if (fs4__default.default.existsSync(binPath)) {
|
|
2029
|
+
await fs4__default.default.promises.chmod(binPath, 493);
|
|
1892
2030
|
}
|
|
1893
2031
|
console.log(pc2__default.default.green("\u2713 code-server installed successfully"));
|
|
1894
2032
|
}
|
|
@@ -1913,19 +2051,19 @@ async function killExistingCodeServer() {
|
|
|
1913
2051
|
async function startCodeServer(cwd) {
|
|
1914
2052
|
const binPath = getCodeServerBin();
|
|
1915
2053
|
const workDir = cwd || process.cwd();
|
|
1916
|
-
if (!
|
|
2054
|
+
if (!fs4__default.default.existsSync(binPath)) {
|
|
1917
2055
|
throw new Error("code-server is not installed. Run installCodeServer() first.");
|
|
1918
2056
|
}
|
|
1919
2057
|
await killExistingCodeServer();
|
|
1920
|
-
const workspaceStoragePath =
|
|
1921
|
-
|
|
2058
|
+
const workspaceStoragePath = path11__default.default.join(STORAGE_DIR, "User", "workspaceStorage");
|
|
2059
|
+
path11__default.default.join(STORAGE_DIR, "User", "globalStorage");
|
|
1922
2060
|
try {
|
|
1923
|
-
if (
|
|
1924
|
-
await
|
|
2061
|
+
if (fs4__default.default.existsSync(workspaceStoragePath)) {
|
|
2062
|
+
await fs4__default.default.promises.rm(workspaceStoragePath, { recursive: true, force: true });
|
|
1925
2063
|
}
|
|
1926
|
-
const stateDbPath =
|
|
1927
|
-
if (
|
|
1928
|
-
await
|
|
2064
|
+
const stateDbPath = path11__default.default.join(STORAGE_DIR, "User", "globalStorage", "state.vscdb");
|
|
2065
|
+
if (fs4__default.default.existsSync(stateDbPath)) {
|
|
2066
|
+
await fs4__default.default.promises.unlink(stateDbPath);
|
|
1929
2067
|
}
|
|
1930
2068
|
} catch {
|
|
1931
2069
|
}
|
|
@@ -1965,7 +2103,7 @@ if (process.env.AMA_DAEMON === "1") {
|
|
|
1965
2103
|
}
|
|
1966
2104
|
if (isCodeServerInstalled()) {
|
|
1967
2105
|
try {
|
|
1968
|
-
const projectDir = process.cwd() ||
|
|
2106
|
+
const projectDir = process.cwd() || os3__default.default.homedir();
|
|
1969
2107
|
await startCodeServer(projectDir);
|
|
1970
2108
|
} catch (error) {
|
|
1971
2109
|
console.error(pc2__default.default.red(`Failed to start code-server: ${error.message}`));
|