amai 0.0.8 → 0.0.10
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 +361 -206
- package/dist/cli.js +359 -204
- package/dist/lib/daemon-entry.cjs +169 -90
- package/dist/lib/daemon-entry.js +166 -87
- package/dist/server.cjs +52 -24
- package/dist/server.js +51 -23
- package/package.json +2 -2
package/dist/lib/daemon-entry.js
CHANGED
|
@@ -3,11 +3,11 @@ import WebSocket from 'ws';
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import fs5, { readFile, writeFile, stat, access, readdir, glob, unlink, mkdir } from 'fs/promises';
|
|
5
5
|
import path10 from 'path';
|
|
6
|
-
import
|
|
6
|
+
import fs6, { readdirSync } from 'fs';
|
|
7
7
|
import os3 from 'os';
|
|
8
8
|
import { exec, spawn } from 'child_process';
|
|
9
9
|
import { promisify } from 'util';
|
|
10
|
-
import
|
|
10
|
+
import pc4 from 'picocolors';
|
|
11
11
|
import { Hono } from 'hono';
|
|
12
12
|
import { serve } from '@hono/node-server';
|
|
13
13
|
import { cors } from 'hono/cors';
|
|
@@ -26,14 +26,14 @@ var ProjectRegistry = class {
|
|
|
26
26
|
}
|
|
27
27
|
load() {
|
|
28
28
|
try {
|
|
29
|
-
if (
|
|
30
|
-
const data =
|
|
29
|
+
if (fs6.existsSync(REGISTRY_FILE)) {
|
|
30
|
+
const data = fs6.readFileSync(REGISTRY_FILE, "utf8");
|
|
31
31
|
const parsed = JSON.parse(data);
|
|
32
32
|
if (!Array.isArray(parsed)) {
|
|
33
33
|
console.error("Invalid project registry format: expected array, got", typeof parsed);
|
|
34
34
|
const backupFile = REGISTRY_FILE + ".backup." + Date.now();
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
fs6.copyFileSync(REGISTRY_FILE, backupFile);
|
|
36
|
+
fs6.unlinkSync(REGISTRY_FILE);
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
const projects = parsed;
|
|
@@ -46,11 +46,11 @@ var ProjectRegistry = class {
|
|
|
46
46
|
}
|
|
47
47
|
} catch (error) {
|
|
48
48
|
console.error("Failed to load project registry:", error);
|
|
49
|
-
if (
|
|
49
|
+
if (fs6.existsSync(REGISTRY_FILE)) {
|
|
50
50
|
try {
|
|
51
51
|
const backupFile = REGISTRY_FILE + ".backup." + Date.now();
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
fs6.copyFileSync(REGISTRY_FILE, backupFile);
|
|
53
|
+
fs6.unlinkSync(REGISTRY_FILE);
|
|
54
54
|
console.log("Corrupted registry file backed up and removed. Starting fresh.");
|
|
55
55
|
} catch (backupError) {
|
|
56
56
|
}
|
|
@@ -59,11 +59,11 @@ var ProjectRegistry = class {
|
|
|
59
59
|
}
|
|
60
60
|
save() {
|
|
61
61
|
try {
|
|
62
|
-
if (!
|
|
63
|
-
|
|
62
|
+
if (!fs6.existsSync(AMA_DIR)) {
|
|
63
|
+
fs6.mkdirSync(AMA_DIR, { recursive: true });
|
|
64
64
|
}
|
|
65
65
|
const projects = Array.from(this.projects.values());
|
|
66
|
-
|
|
66
|
+
fs6.writeFileSync(REGISTRY_FILE, JSON.stringify(projects, null, 2), "utf8");
|
|
67
67
|
} catch (error) {
|
|
68
68
|
console.error("Failed to save project registry:", error);
|
|
69
69
|
}
|
|
@@ -731,20 +731,20 @@ var editFiles = async function(input, projectCwd) {
|
|
|
731
731
|
let existingContent = "";
|
|
732
732
|
if (isNewFile === void 0) {
|
|
733
733
|
try {
|
|
734
|
-
existingContent = await
|
|
734
|
+
existingContent = await fs6.promises.readFile(filePath, "utf-8");
|
|
735
735
|
isNewFile = false;
|
|
736
736
|
} catch (error) {
|
|
737
737
|
isNewFile = true;
|
|
738
738
|
}
|
|
739
739
|
} else if (!isNewFile) {
|
|
740
740
|
try {
|
|
741
|
-
existingContent = await
|
|
741
|
+
existingContent = await fs6.promises.readFile(filePath, "utf-8");
|
|
742
742
|
} catch (error) {
|
|
743
743
|
isNewFile = true;
|
|
744
744
|
}
|
|
745
745
|
}
|
|
746
746
|
try {
|
|
747
|
-
await
|
|
747
|
+
await fs6.promises.writeFile(filePath, content);
|
|
748
748
|
} catch (writeError) {
|
|
749
749
|
throw writeError;
|
|
750
750
|
}
|
|
@@ -1123,24 +1123,27 @@ var list = async function(input, projectCwd) {
|
|
|
1123
1123
|
var startHttpServer = () => {
|
|
1124
1124
|
const app = new Hono();
|
|
1125
1125
|
app.use(cors());
|
|
1126
|
+
app.get("/", (c) => {
|
|
1127
|
+
return c.text("Hello World");
|
|
1128
|
+
});
|
|
1126
1129
|
serve({ fetch: app.fetch, port: 3456 });
|
|
1127
1130
|
};
|
|
1128
1131
|
var CREDENTIALS_DIR = path10.join(os3.homedir(), ".amai");
|
|
1129
1132
|
var CREDENTIALS_PATH = path10.join(CREDENTIALS_DIR, "credentials.json");
|
|
1130
1133
|
function getTokens() {
|
|
1131
|
-
if (!
|
|
1134
|
+
if (!fs6.existsSync(CREDENTIALS_PATH)) {
|
|
1132
1135
|
return null;
|
|
1133
1136
|
}
|
|
1134
|
-
const raw =
|
|
1137
|
+
const raw = fs6.readFileSync(CREDENTIALS_PATH, "utf8");
|
|
1135
1138
|
const data = JSON.parse(raw);
|
|
1136
1139
|
return data;
|
|
1137
1140
|
}
|
|
1138
1141
|
var getUserId = () => {
|
|
1139
1142
|
try {
|
|
1140
|
-
if (!
|
|
1143
|
+
if (!fs6.existsSync(CREDENTIALS_PATH)) {
|
|
1141
1144
|
return;
|
|
1142
1145
|
}
|
|
1143
|
-
const raw =
|
|
1146
|
+
const raw = fs6.readFileSync(CREDENTIALS_PATH, "utf8");
|
|
1144
1147
|
const data = JSON.parse(raw);
|
|
1145
1148
|
return {
|
|
1146
1149
|
userId: data.user.id
|
|
@@ -1319,16 +1322,16 @@ function getWorkspaceStoragePath(ide) {
|
|
|
1319
1322
|
function scanWorkspaceStorage(ide) {
|
|
1320
1323
|
const projects = [];
|
|
1321
1324
|
const storagePath = getWorkspaceStoragePath();
|
|
1322
|
-
if (!
|
|
1325
|
+
if (!fs6.existsSync(storagePath)) {
|
|
1323
1326
|
return projects;
|
|
1324
1327
|
}
|
|
1325
1328
|
try {
|
|
1326
|
-
const workspaces =
|
|
1329
|
+
const workspaces = fs6.readdirSync(storagePath);
|
|
1327
1330
|
for (const workspace of workspaces) {
|
|
1328
1331
|
const workspaceJsonPath = path10.join(storagePath, workspace, "workspace.json");
|
|
1329
|
-
if (
|
|
1332
|
+
if (fs6.existsSync(workspaceJsonPath)) {
|
|
1330
1333
|
try {
|
|
1331
|
-
const content =
|
|
1334
|
+
const content = fs6.readFileSync(workspaceJsonPath, "utf-8");
|
|
1332
1335
|
const data = JSON.parse(content);
|
|
1333
1336
|
if (data.folder && typeof data.folder === "string") {
|
|
1334
1337
|
let projectPath = data.folder;
|
|
@@ -1336,7 +1339,7 @@ function scanWorkspaceStorage(ide) {
|
|
|
1336
1339
|
projectPath = projectPath.replace("file://", "");
|
|
1337
1340
|
projectPath = decodeURIComponent(projectPath);
|
|
1338
1341
|
}
|
|
1339
|
-
if (
|
|
1342
|
+
if (fs6.existsSync(projectPath) && fs6.statSync(projectPath).isDirectory()) {
|
|
1340
1343
|
projects.push({
|
|
1341
1344
|
name: path10.basename(projectPath),
|
|
1342
1345
|
path: projectPath,
|
|
@@ -1360,11 +1363,11 @@ var scanIdeProjects = async () => {
|
|
|
1360
1363
|
const seenPaths = /* @__PURE__ */ new Set();
|
|
1361
1364
|
const addProject = (projectPath, ide) => {
|
|
1362
1365
|
try {
|
|
1363
|
-
const resolvedPath =
|
|
1364
|
-
if (
|
|
1366
|
+
const resolvedPath = fs6.realpathSync(projectPath);
|
|
1367
|
+
if (fs6.existsSync(resolvedPath) && fs6.statSync(resolvedPath).isDirectory() && !seenPaths.has(resolvedPath)) {
|
|
1365
1368
|
const isIdeProjectsDir = Object.values(IDE_PROJECTS_PATHS).some((ideDir) => {
|
|
1366
1369
|
try {
|
|
1367
|
-
return
|
|
1370
|
+
return fs6.realpathSync(ideDir) === resolvedPath;
|
|
1368
1371
|
} catch {
|
|
1369
1372
|
return false;
|
|
1370
1373
|
}
|
|
@@ -1387,30 +1390,30 @@ var scanIdeProjects = async () => {
|
|
|
1387
1390
|
}
|
|
1388
1391
|
for (const [ide, dirPath] of Object.entries(IDE_PROJECTS_PATHS)) {
|
|
1389
1392
|
if (ide === "cursor") continue;
|
|
1390
|
-
if (
|
|
1391
|
-
const projects =
|
|
1393
|
+
if (fs6.existsSync(dirPath)) {
|
|
1394
|
+
const projects = fs6.readdirSync(dirPath);
|
|
1392
1395
|
projects.forEach((project) => {
|
|
1393
1396
|
const projectPath = path10.join(dirPath, project);
|
|
1394
1397
|
try {
|
|
1395
|
-
const stats =
|
|
1398
|
+
const stats = fs6.lstatSync(projectPath);
|
|
1396
1399
|
let actualPath = null;
|
|
1397
1400
|
if (stats.isSymbolicLink()) {
|
|
1398
|
-
actualPath =
|
|
1401
|
+
actualPath = fs6.realpathSync(projectPath);
|
|
1399
1402
|
} else if (stats.isFile()) {
|
|
1400
1403
|
try {
|
|
1401
|
-
let content =
|
|
1404
|
+
let content = fs6.readFileSync(projectPath, "utf-8").trim();
|
|
1402
1405
|
if (content.startsWith("~/") || content === "~") {
|
|
1403
1406
|
content = content.replace(/^~/, HOME);
|
|
1404
1407
|
}
|
|
1405
1408
|
const resolvedContent = path10.isAbsolute(content) ? content : path10.resolve(path10.dirname(projectPath), content);
|
|
1406
|
-
if (
|
|
1407
|
-
actualPath =
|
|
1409
|
+
if (fs6.existsSync(resolvedContent) && fs6.statSync(resolvedContent).isDirectory()) {
|
|
1410
|
+
actualPath = fs6.realpathSync(resolvedContent);
|
|
1408
1411
|
}
|
|
1409
1412
|
} catch {
|
|
1410
1413
|
return;
|
|
1411
1414
|
}
|
|
1412
1415
|
} else if (stats.isDirectory()) {
|
|
1413
|
-
actualPath =
|
|
1416
|
+
actualPath = fs6.realpathSync(projectPath);
|
|
1414
1417
|
}
|
|
1415
1418
|
if (actualPath) {
|
|
1416
1419
|
addProject(actualPath, ide);
|
|
@@ -1825,7 +1828,19 @@ var rpcHandlers = {
|
|
|
1825
1828
|
return { success: true, diff };
|
|
1826
1829
|
}
|
|
1827
1830
|
};
|
|
1831
|
+
var INITIAL_RECONNECT_DELAY = 1e3;
|
|
1832
|
+
var MAX_RECONNECT_DELAY = 6e4;
|
|
1833
|
+
var BACKOFF_MULTIPLIER = 2;
|
|
1828
1834
|
var reconnectTimeout = null;
|
|
1835
|
+
var reconnectAttempts = 0;
|
|
1836
|
+
function getReconnectDelay() {
|
|
1837
|
+
const delay = Math.min(
|
|
1838
|
+
INITIAL_RECONNECT_DELAY * Math.pow(BACKOFF_MULTIPLIER, reconnectAttempts),
|
|
1839
|
+
MAX_RECONNECT_DELAY
|
|
1840
|
+
);
|
|
1841
|
+
const jitter = delay * 0.25 * (Math.random() * 2 - 1);
|
|
1842
|
+
return Math.floor(delay + jitter);
|
|
1843
|
+
}
|
|
1829
1844
|
var connectToUserStreams = async (serverUrl) => {
|
|
1830
1845
|
const userId = getUserId();
|
|
1831
1846
|
if (!userId?.userId) {
|
|
@@ -1846,7 +1861,8 @@ var connectToUserStreams = async (serverUrl) => {
|
|
|
1846
1861
|
}
|
|
1847
1862
|
});
|
|
1848
1863
|
ws.on("open", () => {
|
|
1849
|
-
|
|
1864
|
+
reconnectAttempts = 0;
|
|
1865
|
+
console.log(pc4.cyan("connected to user streams"));
|
|
1850
1866
|
if (reconnectTimeout) {
|
|
1851
1867
|
clearTimeout(reconnectTimeout);
|
|
1852
1868
|
reconnectTimeout = null;
|
|
@@ -1857,7 +1873,7 @@ var connectToUserStreams = async (serverUrl) => {
|
|
|
1857
1873
|
const message = JSON.parse(event.toString());
|
|
1858
1874
|
if (message._tag === "rpc_call") {
|
|
1859
1875
|
const { requestId, method, input } = message;
|
|
1860
|
-
console.log(
|
|
1876
|
+
console.log(pc4.gray(`> ${method}`));
|
|
1861
1877
|
const handler = rpcHandlers[method];
|
|
1862
1878
|
if (!handler) {
|
|
1863
1879
|
ws.send(JSON.stringify({
|
|
@@ -1868,7 +1884,6 @@ var connectToUserStreams = async (serverUrl) => {
|
|
|
1868
1884
|
message: `Unknown RPC method: ${method}`
|
|
1869
1885
|
}
|
|
1870
1886
|
}));
|
|
1871
|
-
console.log(pc2.yellow(`Unknown RPC method: ${method}`));
|
|
1872
1887
|
return;
|
|
1873
1888
|
}
|
|
1874
1889
|
try {
|
|
@@ -1878,7 +1893,6 @@ var connectToUserStreams = async (serverUrl) => {
|
|
|
1878
1893
|
requestId,
|
|
1879
1894
|
data: result
|
|
1880
1895
|
}));
|
|
1881
|
-
console.log(pc2.green(`RPC completed: ${method}`));
|
|
1882
1896
|
} catch (error) {
|
|
1883
1897
|
const rpcError = error._tag ? error : {
|
|
1884
1898
|
_tag: "RpcError",
|
|
@@ -1889,7 +1903,7 @@ var connectToUserStreams = async (serverUrl) => {
|
|
|
1889
1903
|
requestId,
|
|
1890
1904
|
data: rpcError
|
|
1891
1905
|
}));
|
|
1892
|
-
console.log(
|
|
1906
|
+
console.log(pc4.red(` ${method} failed`));
|
|
1893
1907
|
}
|
|
1894
1908
|
return;
|
|
1895
1909
|
}
|
|
@@ -1908,25 +1922,38 @@ var connectToUserStreams = async (serverUrl) => {
|
|
|
1908
1922
|
}
|
|
1909
1923
|
}
|
|
1910
1924
|
} catch (parseError) {
|
|
1911
|
-
console.error(
|
|
1925
|
+
console.error(pc4.red(`parse error`));
|
|
1912
1926
|
}
|
|
1913
1927
|
});
|
|
1914
1928
|
ws.on("close", (code, reason) => {
|
|
1915
|
-
|
|
1916
|
-
|
|
1929
|
+
const delay = getReconnectDelay();
|
|
1930
|
+
reconnectAttempts++;
|
|
1931
|
+
console.log(pc4.gray(`user streams disconnected, reconnecting in ${Math.round(delay / 1e3)}s...`));
|
|
1917
1932
|
reconnectTimeout = setTimeout(() => {
|
|
1918
1933
|
connectToUserStreams(serverUrl).catch((err) => {
|
|
1919
|
-
console.error(
|
|
1934
|
+
console.error(pc4.red(`reconnection failed`));
|
|
1920
1935
|
});
|
|
1921
|
-
},
|
|
1936
|
+
}, delay);
|
|
1922
1937
|
});
|
|
1923
1938
|
ws.on("error", (error) => {
|
|
1924
|
-
console.error(
|
|
1939
|
+
console.error(pc4.red(`stream error: ${error.message}`));
|
|
1925
1940
|
});
|
|
1926
1941
|
return ws;
|
|
1927
1942
|
};
|
|
1928
1943
|
|
|
1929
1944
|
// src/server.ts
|
|
1945
|
+
var INITIAL_RECONNECT_DELAY2 = 1e3;
|
|
1946
|
+
var MAX_RECONNECT_DELAY2 = 6e4;
|
|
1947
|
+
var BACKOFF_MULTIPLIER2 = 2;
|
|
1948
|
+
var reconnectAttempts2 = 0;
|
|
1949
|
+
function getReconnectDelay2() {
|
|
1950
|
+
const delay = Math.min(
|
|
1951
|
+
INITIAL_RECONNECT_DELAY2 * Math.pow(BACKOFF_MULTIPLIER2, reconnectAttempts2),
|
|
1952
|
+
MAX_RECONNECT_DELAY2
|
|
1953
|
+
);
|
|
1954
|
+
const jitter = delay * 0.25 * (Math.random() * 2 - 1);
|
|
1955
|
+
return Math.floor(delay + jitter);
|
|
1956
|
+
}
|
|
1930
1957
|
var toolExecutors = {
|
|
1931
1958
|
editFile: editFiles,
|
|
1932
1959
|
deleteFile,
|
|
@@ -1949,12 +1976,13 @@ function connectToServer(serverUrl = DEFAULT_SERVER_URL) {
|
|
|
1949
1976
|
}
|
|
1950
1977
|
});
|
|
1951
1978
|
ws.on("open", () => {
|
|
1952
|
-
|
|
1979
|
+
reconnectAttempts2 = 0;
|
|
1980
|
+
console.log(pc4.cyan("connected to server"));
|
|
1953
1981
|
});
|
|
1954
1982
|
ws.on("message", async (data) => {
|
|
1955
1983
|
const message = JSON.parse(data.toString());
|
|
1956
1984
|
if (message.type === "tool_call") {
|
|
1957
|
-
console.log(
|
|
1985
|
+
console.log(pc4.gray(`> ${message.tool}`));
|
|
1958
1986
|
try {
|
|
1959
1987
|
const executor = toolExecutors[message.tool];
|
|
1960
1988
|
if (!executor) {
|
|
@@ -1966,17 +1994,16 @@ function connectToServer(serverUrl = DEFAULT_SERVER_URL) {
|
|
|
1966
1994
|
id: message.id,
|
|
1967
1995
|
result
|
|
1968
1996
|
}));
|
|
1969
|
-
console.log(pc2.green(`tool call completed: ${message.tool}`));
|
|
1970
1997
|
} catch (error) {
|
|
1971
1998
|
ws.send(JSON.stringify({
|
|
1972
1999
|
type: "tool_result",
|
|
1973
2000
|
id: message.id,
|
|
1974
2001
|
error: error.message
|
|
1975
2002
|
}));
|
|
1976
|
-
console.error(
|
|
2003
|
+
console.error(pc4.red(` ${message.tool} failed: ${error.message}`));
|
|
1977
2004
|
}
|
|
1978
2005
|
} else if (message.type === "rpc_call") {
|
|
1979
|
-
console.log(
|
|
2006
|
+
console.log(pc4.gray(`> rpc: ${message.method}`));
|
|
1980
2007
|
try {
|
|
1981
2008
|
const handler = rpcHandlers[message.method];
|
|
1982
2009
|
if (!handler) {
|
|
@@ -1988,29 +2015,30 @@ function connectToServer(serverUrl = DEFAULT_SERVER_URL) {
|
|
|
1988
2015
|
id: message.id,
|
|
1989
2016
|
result
|
|
1990
2017
|
}));
|
|
1991
|
-
console.log(pc2.green(`rpc call completed: ${message.method}`));
|
|
1992
2018
|
} catch (error) {
|
|
1993
2019
|
ws.send(JSON.stringify({
|
|
1994
2020
|
type: "tool_result",
|
|
1995
2021
|
id: message.id,
|
|
1996
2022
|
error: error.message
|
|
1997
2023
|
}));
|
|
1998
|
-
console.error(
|
|
2024
|
+
console.error(pc4.red(` rpc failed: ${message.method}`));
|
|
1999
2025
|
}
|
|
2000
2026
|
}
|
|
2001
2027
|
});
|
|
2002
2028
|
ws.on("close", () => {
|
|
2003
|
-
|
|
2004
|
-
|
|
2029
|
+
const delay = getReconnectDelay2();
|
|
2030
|
+
reconnectAttempts2++;
|
|
2031
|
+
console.log(pc4.gray(`disconnected, reconnecting in ${Math.round(delay / 1e3)}s...`));
|
|
2032
|
+
setTimeout(() => connectToServer(serverUrl), delay);
|
|
2005
2033
|
});
|
|
2006
2034
|
ws.on("error", (error) => {
|
|
2007
|
-
console.error(
|
|
2035
|
+
console.error(pc4.red(`connection error: ${error.message}`));
|
|
2008
2036
|
});
|
|
2009
2037
|
return ws;
|
|
2010
2038
|
}
|
|
2011
2039
|
async function main() {
|
|
2012
2040
|
const serverUrl = DEFAULT_SERVER_URL;
|
|
2013
|
-
console.log(
|
|
2041
|
+
console.log(pc4.gray("starting ama..."));
|
|
2014
2042
|
connectToServer(serverUrl);
|
|
2015
2043
|
await connectToUserStreams(serverUrl);
|
|
2016
2044
|
startHttpServer();
|
|
@@ -2049,37 +2077,37 @@ function getCodeServerBin() {
|
|
|
2049
2077
|
}
|
|
2050
2078
|
function isCodeServerInstalled() {
|
|
2051
2079
|
const binPath = getCodeServerBin();
|
|
2052
|
-
return
|
|
2080
|
+
return fs6.existsSync(binPath);
|
|
2053
2081
|
}
|
|
2054
2082
|
async function installCodeServer() {
|
|
2055
2083
|
const { ext } = getPlatformInfo();
|
|
2056
2084
|
const downloadUrl = getDownloadUrl();
|
|
2057
2085
|
const tarballPath = path10.join(AMA_DIR, `code-server.${ext}`);
|
|
2058
|
-
if (!
|
|
2059
|
-
|
|
2086
|
+
if (!fs6.existsSync(AMA_DIR)) {
|
|
2087
|
+
fs6.mkdirSync(AMA_DIR, { recursive: true });
|
|
2060
2088
|
}
|
|
2061
|
-
if (!
|
|
2062
|
-
|
|
2089
|
+
if (!fs6.existsSync(CODE_DIR)) {
|
|
2090
|
+
fs6.mkdirSync(CODE_DIR, { recursive: true });
|
|
2063
2091
|
}
|
|
2064
|
-
if (!
|
|
2065
|
-
|
|
2092
|
+
if (!fs6.existsSync(STORAGE_DIR)) {
|
|
2093
|
+
fs6.mkdirSync(STORAGE_DIR, { recursive: true });
|
|
2066
2094
|
}
|
|
2067
|
-
console.log(
|
|
2068
|
-
console.log(
|
|
2095
|
+
console.log(pc4.cyan(`Downloading code-server v${CODE_SERVER_VERSION}...`));
|
|
2096
|
+
console.log(pc4.gray(downloadUrl));
|
|
2069
2097
|
const response = await fetch(downloadUrl);
|
|
2070
2098
|
if (!response.ok) {
|
|
2071
2099
|
throw new Error(`Failed to download code-server: ${response.statusText}`);
|
|
2072
2100
|
}
|
|
2073
2101
|
const buffer = await response.arrayBuffer();
|
|
2074
|
-
await
|
|
2075
|
-
console.log(
|
|
2102
|
+
await fs6.promises.writeFile(tarballPath, Buffer.from(buffer));
|
|
2103
|
+
console.log(pc4.cyan("Extracting code-server..."));
|
|
2076
2104
|
await execAsync3(`tar -xzf ${tarballPath} -C ${CODE_DIR}`);
|
|
2077
|
-
await
|
|
2105
|
+
await fs6.promises.unlink(tarballPath);
|
|
2078
2106
|
const binPath = getCodeServerBin();
|
|
2079
|
-
if (
|
|
2080
|
-
await
|
|
2107
|
+
if (fs6.existsSync(binPath)) {
|
|
2108
|
+
await fs6.promises.chmod(binPath, 493);
|
|
2081
2109
|
}
|
|
2082
|
-
console.log(
|
|
2110
|
+
console.log(pc4.green("\u2713 code-server installed successfully"));
|
|
2083
2111
|
}
|
|
2084
2112
|
async function killExistingCodeServer() {
|
|
2085
2113
|
try {
|
|
@@ -2099,26 +2127,77 @@ async function killExistingCodeServer() {
|
|
|
2099
2127
|
} catch {
|
|
2100
2128
|
}
|
|
2101
2129
|
}
|
|
2130
|
+
async function setupDefaultSettings() {
|
|
2131
|
+
const userDir = path10.join(STORAGE_DIR, "User");
|
|
2132
|
+
const settingsPath = path10.join(userDir, "settings.json");
|
|
2133
|
+
if (!fs6.existsSync(userDir)) {
|
|
2134
|
+
fs6.mkdirSync(userDir, { recursive: true });
|
|
2135
|
+
}
|
|
2136
|
+
const defaultSettings = {
|
|
2137
|
+
// Disable signature verification for Open VSX extensions
|
|
2138
|
+
"extensions.verifySignature": false,
|
|
2139
|
+
// Theme settings
|
|
2140
|
+
"workbench.colorTheme": "Min Dark",
|
|
2141
|
+
"workbench.startupEditor": "none",
|
|
2142
|
+
// Editor settings
|
|
2143
|
+
"editor.fontSize": 14,
|
|
2144
|
+
"editor.fontFamily": "'JetBrains Mono', 'Fira Code', Menlo, Monaco, 'Courier New', monospace",
|
|
2145
|
+
"editor.minimap.enabled": false,
|
|
2146
|
+
"editor.wordWrap": "on",
|
|
2147
|
+
// UI settings
|
|
2148
|
+
"window.menuBarVisibility": "compact",
|
|
2149
|
+
"workbench.activityBar.location": "top"
|
|
2150
|
+
};
|
|
2151
|
+
let existingSettings = {};
|
|
2152
|
+
if (fs6.existsSync(settingsPath)) {
|
|
2153
|
+
try {
|
|
2154
|
+
const content = await fs6.promises.readFile(settingsPath, "utf-8");
|
|
2155
|
+
existingSettings = JSON.parse(content);
|
|
2156
|
+
} catch {
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
const mergedSettings = { ...defaultSettings, ...existingSettings };
|
|
2160
|
+
mergedSettings["workbench.colorTheme"] = "Min Dark";
|
|
2161
|
+
mergedSettings["extensions.verifySignature"] = false;
|
|
2162
|
+
await fs6.promises.writeFile(settingsPath, JSON.stringify(mergedSettings, null, 2));
|
|
2163
|
+
console.log(pc4.green("ama code-server settings configured"));
|
|
2164
|
+
}
|
|
2165
|
+
async function installExtensions() {
|
|
2166
|
+
const binPath = getCodeServerBin();
|
|
2167
|
+
const extensions = [
|
|
2168
|
+
"castrogusttavo.min-theme"
|
|
2169
|
+
];
|
|
2170
|
+
for (const ext of extensions) {
|
|
2171
|
+
try {
|
|
2172
|
+
console.log(pc4.cyan(`ama installing extension: ${ext}...`));
|
|
2173
|
+
await execAsync3(`"${binPath}" --user-data-dir "${STORAGE_DIR}" --install-extension ${ext}`);
|
|
2174
|
+
console.log(pc4.green(`ama extension ${ext} installed`));
|
|
2175
|
+
} catch (error) {
|
|
2176
|
+
console.log(pc4.yellow(`ama failed to install extension ${ext}`), error);
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2102
2180
|
async function startCodeServer(cwd) {
|
|
2103
2181
|
const binPath = getCodeServerBin();
|
|
2104
2182
|
const workDir = cwd || process.cwd();
|
|
2105
|
-
if (!
|
|
2106
|
-
throw new Error("code-server is not installed. Run installCodeServer() first.");
|
|
2183
|
+
if (!fs6.existsSync(binPath)) {
|
|
2184
|
+
throw new Error("ama code-server is not installed. Run installCodeServer() first.");
|
|
2107
2185
|
}
|
|
2108
2186
|
await killExistingCodeServer();
|
|
2187
|
+
await setupDefaultSettings();
|
|
2188
|
+
await installExtensions();
|
|
2109
2189
|
const workspaceStoragePath = path10.join(STORAGE_DIR, "User", "workspaceStorage");
|
|
2110
|
-
path10.join(STORAGE_DIR, "User", "globalStorage");
|
|
2111
2190
|
try {
|
|
2112
|
-
if (
|
|
2113
|
-
await
|
|
2191
|
+
if (fs6.existsSync(workspaceStoragePath)) {
|
|
2192
|
+
await fs6.promises.rm(workspaceStoragePath, { recursive: true, force: true });
|
|
2114
2193
|
}
|
|
2115
2194
|
const stateDbPath = path10.join(STORAGE_DIR, "User", "globalStorage", "state.vscdb");
|
|
2116
|
-
if (
|
|
2117
|
-
await
|
|
2195
|
+
if (fs6.existsSync(stateDbPath)) {
|
|
2196
|
+
await fs6.promises.unlink(stateDbPath);
|
|
2118
2197
|
}
|
|
2119
2198
|
} catch {
|
|
2120
2199
|
}
|
|
2121
|
-
console.log(
|
|
2200
|
+
console.log(pc4.cyan(`ama starting code-server`));
|
|
2122
2201
|
const codeServer = spawn(
|
|
2123
2202
|
binPath,
|
|
2124
2203
|
[
|
|
@@ -2137,19 +2216,19 @@ async function startCodeServer(cwd) {
|
|
|
2137
2216
|
stdio: ["ignore", "pipe", "pipe"]
|
|
2138
2217
|
}
|
|
2139
2218
|
);
|
|
2140
|
-
console.log(
|
|
2219
|
+
console.log(pc4.green(`ama code-server running at http://localhost:8081/?folder=${encodeURIComponent(workDir)}`));
|
|
2141
2220
|
return codeServer;
|
|
2142
2221
|
}
|
|
2143
2222
|
if (process.env.AMA_DAEMON === "1") {
|
|
2144
2223
|
(async () => {
|
|
2145
2224
|
try {
|
|
2146
2225
|
if (!isCodeServerInstalled()) {
|
|
2147
|
-
console.log(
|
|
2226
|
+
console.log(pc4.gray("setting up code-server..."));
|
|
2148
2227
|
try {
|
|
2149
2228
|
await installCodeServer();
|
|
2150
2229
|
} catch (error) {
|
|
2151
|
-
console.error(
|
|
2152
|
-
console.log(
|
|
2230
|
+
console.error(pc4.red(`code-server install failed: ${error.message}`));
|
|
2231
|
+
console.log(pc4.gray("continuing without code-server..."));
|
|
2153
2232
|
}
|
|
2154
2233
|
}
|
|
2155
2234
|
if (isCodeServerInstalled()) {
|
|
@@ -2157,16 +2236,16 @@ if (process.env.AMA_DAEMON === "1") {
|
|
|
2157
2236
|
const projectDir = process.cwd() || os3.homedir();
|
|
2158
2237
|
await startCodeServer(projectDir);
|
|
2159
2238
|
} catch (error) {
|
|
2160
|
-
console.error(
|
|
2239
|
+
console.error(pc4.red(`code-server start failed: ${error.message}`));
|
|
2161
2240
|
}
|
|
2162
2241
|
}
|
|
2163
2242
|
await main();
|
|
2164
2243
|
} catch (error) {
|
|
2165
|
-
console.error("
|
|
2244
|
+
console.error(pc4.red("daemon error"));
|
|
2166
2245
|
process.exit(1);
|
|
2167
2246
|
}
|
|
2168
2247
|
})();
|
|
2169
2248
|
} else {
|
|
2170
|
-
console.error("
|
|
2249
|
+
console.error(pc4.red("this script should only be run as a daemon"));
|
|
2171
2250
|
process.exit(1);
|
|
2172
2251
|
}
|